Position inpdeped code for bootloader.

Hello,

I'm creating a custom OTA firmware update on cc2640 chip from TI. (Cortex M3)
For this reason two memory regions are reserved for firmware images.
The problem is, the code works only if it is stored in one of the regions. (According to the Linker File)
If the code is stored in the second region, it does not start at all.

In IAR Compiler the -ropi (the same as PIE/PIC in GCC) works correctly.

The Linker Script is the following:

/* Entry Point */
ENTRY( ResetISR )

/* System memory map */
MEMORY
{
	CRC (RX)		: ORIGIN = 0x00001000, LENGTH = 0x00000004
	OHD (RX)		: ORIGIN = 0x00001004, LENGTH = 0x0000000C
	INT_VEC (RX)	: ORIGIN = 0x00001010, LENGTH = 0x000000C8
	FWU_DESCR (RX)	: ORIGIN = 0x000010D8, LENGTH = 0x00000040
	APP_DESCR (RX)	: ORIGIN = 0x00001118, LENGTH = 0x00000040
	FLASH (RX)      : ORIGIN = 0x00001158, LENGTH = 0x0000AF2F
	CONFIG (RX)		: ORIGIN = 0x0001E000, LENGTH = 0x00001000
	SRAM (RWX)      : ORIGIN = 0x20000000, LENGTH = 0x00005000
	/* Application can use GPRAM region as RAM if cache is disabled in the CCFG
	(DEFAULT_CCFG_SIZE_AND_DIS_FLAGS.SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM = 0) */
	GPRAM (RWX) 	: ORIGIN = 0x11000000, LENGTH = 0x2000
}

/*. Generate a link error if heap and stack don’t fit into RAM .*/
_Min_Heap_Size = 0x800;
_Min_Stack_Size = 0x800;

/*. Highest address of the stack. Used in startup file .*/
_estack = ORIGIN(SRAM) + LENGTH(SRAM); /*end of SRAM .*/


REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_CONFIG", CONFIG);
REGION_ALIAS("REGION_BSS", SRAM);
REGION_ALIAS("REGION_DATA", SRAM);
REGION_ALIAS("REGION_STACK", SRAM);
REGION_ALIAS("REGION_HEAP", SRAM);
REGION_ALIAS("REGION_ARM_EXIDX", FLASH);
REGION_ALIAS("REGION_ARM_EXTAB", FLASH);


/* Section allocation in memory */

SECTIONS
{

      /*
     * UDMACC26XX_CONFIG_BASE below must match UDMACC26XX_CONFIG_BASE defined
     * by ti/drivers/dma/UDMACC26XX.h
     * The user is allowed to change UDMACC26XX_CONFIG_BASE to move it away from
     * the default address 0x2000_0400, but remember it must be 1024 bytes aligned.
     */
    UDMACC26XX_CONFIG_BASE = 0x20000400;

    /*
     * Define absolute addresses for the DMA channels.
     * DMA channels must always be allocated at a fixed offset from the DMA base address.
     * --------- DO NOT MODIFY -----------
     */

    DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x30);
    DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x40);
    DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x70);
    DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x90);
    DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x100);
    DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x110);
    DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x270);
    DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x290);

    /*
     * Allocate SPI0, SPI1, ADC, and GPTimer0 DMA descriptors at absolute addresses.
     * --------- DO NOT MODIFY -----------
     */
    UDMACC26XX_dmaSpi0RxControlTableEntry_is_placed = 0;
    .dmaSpi0RxControlTableEntry DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0RxControlTableEntry)} > REGION_DATA

    UDMACC26XX_dmaSpi0TxControlTableEntry_is_placed = 0;
    .dmaSpi0TxControlTableEntry DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD)  : AT (DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0TxControlTableEntry)} > REGION_DATA

    UDMACC26XX_dmaADCPriControlTableEntry_is_placed = 0;
    .dmaADCPriControlTableEntry DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaADCPriControlTableEntry)} > REGION_DATA

    UDMACC26XX_dmaGPT0APriControlTableEntry_is_placed = 0;
    .dmaGPT0APriControlTableEntry DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaGPT0APriControlTableEntry)} > REGION_DATA

    UDMACC26XX_dmaSpi1RxControlTableEntry_is_placed = 0;
    .dmaSpi1RxControlTableEntry DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1RxControlTableEntry)} > REGION_DATA

    UDMACC26XX_dmaSpi1TxControlTableEntry_is_placed = 0;
    .dmaSpi1TxControlTableEntry DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1TxControlTableEntry)} > REGION_DATA

    UDMACC26XX_dmaADCAltControlTableEntry_is_placed = 0;
    .dmaADCAltControlTableEntry DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaADCAltControlTableEntry)} > REGION_DATA

    UDMACC26XX_dmaGPT0AAltControlTableEntry_is_placed = 0;
    .dmaGPT0AAltControlTableEntry DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaGPT0AAltControlTableEntry)} > REGION_DATA


	.SHADOW_CRC :
	{
		KEEP(*(.SHADOW_CRC))
	} > CRC = 0xFF

	.IMAGE_HEADER :
	{
		KEEP(*(.IMAGE_HEADER))
	} > OHD = 0xFF

	.intvec :
	{
		KEEP(*(.vectors))
	} > INT_VEC = 0xFF

	.firmwareDescr :
	{
		KEEP(*(.firmwareDescr))
	} >  FWU_DESCR = 0xFF

	.applicationDescr :
	{
		KEEP(*(.applicationDescr))
	} >  APP_DESCR = 0xFF

	.text : {
        CREATE_OBJECT_SYMBOLS
        *(.text)
        *(.text.*)
        . = ALIGN(0x4);
        __init_array_start = .;
        KEEP (*(.init_array*))
        __init_array_end = .;
        *(.init)
        *(.fini*)
    } > REGION_TEXT AT> REGION_TEXT = 0xFF

    PROVIDE (__etext = .);
    PROVIDE (_etext = .);
    PROVIDE (etext = .);

    .rodata : {
        *(.rodata)
        *(.rodata.*)
    } > REGION_TEXT AT> REGION_TEXT = 0xFF

    .data :
    {
		_ldata = LOADADDR(.data);
        _data = .;
        *(vtable)
        *(.data)
        *(.data*)
        _edata = .;
    } > REGION_DATA AT > REGION_TEXT  = 0xFF
		
		.config (NOLOAD):
		{
			*(.config)
		} > REGION_CONFIG AT > REGION_CONFIG = 0xFF

    .ARM.exidx : {
        __exidx_start = .;
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
        __exidx_end = .;
    } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX

    .ARM.extab : {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB

    .bss : {
        __bss_start__ = .;
        *(.shbss)
        _bss = .;
        *(.bss)
        *(.bss.*)
        *(COMMON)
        . = ALIGN (4);
        _ebss = .;
        __bss_end__ = .;
    } > REGION_BSS AT> REGION_BSS

    .heap : {
        __heap_start__ = .;
        end = __heap_start__;
        _end = end;
        __end = end;
        . = . + _Min_Heap_Size;
        KEEP(*(.heap))
        __heap_end__ = .;
        __HeapLimit = __heap_end__;
    } > REGION_HEAP AT> REGION_HEAP

    .stack (NOLOAD) : ALIGN(0x8) {
        _stack = .;
        __stack = .;
        KEEP(*(.stack))
        . += _Min_Stack_Size;
        _stack_end = .;
        __stack_end = .;
    } > REGION_STACK AT> REGION_STACK
}


The Startup function was already updated to copy the .rodata correctly as following:

void
ResetISR(void)
{
    //
    // Final trim of device
    //
    SetupTrimDevice();

    //
    // Copy the data segment initializers from FLASH to SRAM.
    //
    __asm(
        "   ldr     r1, =_ldata \n" // get source
        "   mov     r2, pc\n"       // get program counter
        "   cmp     r1, r2\n"        // compare as difference
        "   it      lo\n" // if then condition. If r2 is greeter than r1
        "   addlo   r1, r1, #45056\n"   // add 0xB000
        "   ldr     r2, =_data\n"       // get start of the ram
        "   ldr     r3, =_edata\n"      // get the data length in the ram
        "   copy_loop:\n"               // start copy loop
        "   ldr     r4, [r1], #4\n"// load a word from the source and
        "   str     r4, [r2], #4\n"// store it to the destination
        "   cmp     r2, r3\n"   // check all bytes are copied
        "   ble     copy_loop\n");  // jump to loop start
    //
    // Zero fill the bss segment.
    //
    __asm("    ldr     r0, =_bss\n"
          "    ldr     r1, =_ebss\n"
          "    mov     r2, #0\n"
          "    .thumb_func\n"
          "zero_loop:\n"
          "        cmp     r0, r1\n"
          "        it      lt\n"
          "        strlt   r2, [r0], #4\n"
          "        blt     zero_loop");

    //
    // Call the application's entry point.
    //
    main();

    //
    // If we ever return signal Error
    //
    FaultISR();
}

The bootloader calles the entry (ResetISR(void)) function of the valid firmware at startup.

All libraries are linked with -fPIC option.

target_link_libraries(${TARGETFILE}} ${LIB_LIST} "-fPIC")

I have used listet options:

Compiler flags :  -O2 -fdata-sections -ffunction-sections -fno-strict-aliasing -nostartfiles -fno-exceptions -mcpu=cortex-m3 -mthumb -g0 -Wall "
Linker flags: -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections  -nostartfiles -mthumb -lc -lm -lgcc -lnosys -u __vector_table"
 Effekt -> Firmware works only at first address (0x1000). Other positions does not works.


Compiler flags :  -O2 -fdata-sections -ffunction-sections -fno-strict-aliasing -nostartfiles -fno-exceptions -mcpu=cortex-m3 -mthumb -g0 -Wall -fPIE "
Linker flags: -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections  -nostartfiles -mthumb -lc -lm -lgcc -lnosys -u __vector_table"
 Effekt -> Firmware does not starts

Compiler flags :  -O2 -fdata-sections -ffunction-sections -fno-strict-aliasing -nostartfiles -fno-exceptions -mcpu=cortex-m3 -mthumb -g0 -Wall -fPIE"
Linker flags: -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections  -nostartfiles -mthumb -lc -lm -lgcc -lnosys -u __vector_table -pie "
 Effekt -> Firmware does not starts. The linker flag -pie causes the binarys to be 3 Times grater as whitout this option.


I have alredy read the "Multiple Application Code with Bootloader" question. Unfortunately, the provided solution does not work for me:

Compiler flags :  -O2 -fdata-sections -ffunction-sections -fno-strict-aliasing -nostartfiles -fno-exceptions -mcpu=cortex-m3 -mthumb -g0 -Wall -fPIC "
Linker flags: -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections  -nostartfiles -mthumb -lc -lm -lgcc -lnosys -u __vector_table -msingle-pic-base -mpic-register=r9"
Effekt -> Firmware does not starts.


Coud someone provide some assistance to correct the mistake?

Parents Reply Children
More questions in this forum