Tool/software: Code Composer Studio
I have already realized firmware update on the CC2640R2F (Proprietary radio mode) in IAR using -ropi option and it works on all posiible image positions in the flash.
The firmware updater itself uses one of two positions in the Flash where the image can be stored. (0x1000 and 0xC000)
Now the same shall be realized using GCC under CCS (9.3).
The Linker Script is following:
ENTRY( ResetISR )
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
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_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 = 0x20000400;
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);
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
.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 Project is compiled with the following flags:
--asm
-fno-strict-aliasing
-fdata-sections
-ffunction-sections
-fno-exceptions
-fpie
The linker is called with the following flags:
-Wl,--gc-sections
-nostartfiles
-mthumb
-lc
-lm
-lgcc
-lnosys
-u __vector_table
-u g_pfnVectors
-pie
Unfortunately, the image works only if it is loaded from the position 0x1000 (Linker Script Origin). If the code is stored in 0xC000, then the default fault handler is called immidetely.
By means of disassembly I have found, that the _ldata = LOADADDR(.data); is not position indepnedent. And usage of the standart GCC Statup file:
void
ResetISR(void)
{
uint32_t *pSrc;
uint32_t *pDest;
//
// Final trim of device
//
SetupTrimDevice();
//
// Copy the data segment initializers from FLASH to SRAM.
//
pSrc = &_ldata;
for(pDest = &_data; pDest < &_edata; )
{
*pDest++ = *pSrc++;
}
__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");
main();'
FaultISR(); }
Always fails. As workarownd I have added to the data copy a check if the position of the current _data is valid as following (here is C representation, I have used the assembler code instead):
if((uint32_t)pSrc < (uint32_t)get_pc())
{
pSrc+=0xB000;
}
With this workaround the variables are copied correctly. Unfortenately some of the functions still have the wrong addressing...
Could someone infom me, how to change the linker script, so that the realtive adderssing will be used?
Thanks in Advance