GCC 位置独立代码:变量未正确加载
GCC Posistion independent code: Variables are not loaded correctly
该程序在 CC2650 (M3) 上独立运行时运行良好。但它也应用作通过无线电信道加载的固件。为此,需要位置无关代码。问题是,未设置如下所述定义的所有变量。
uint32_t u32Timer_g = 2000;
static DeviceInterfaceStructure_t suInterfaceStructure_g =
{
.timeOut = 0,
.state = STATE_IDLE,
.lastState = STATE_IDLE,
.Config.reconnect = 0,
.Config.lVersion = 0x01,
};
该程序是使用 GCC (gcc-arm-none-eabi-7-2018-q2-update) 使用以下标志编译的:
--asm
-fPIE
-pie
-fno-strict-aliasing
-fdata-sections
-ffunction-sections
-fno-exceptions
并使用以下链接描述文件
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
{
.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 :
{
_text = .;
*(.text*)
*(.rodata)
*(.rodata*)
*(.init)
*(.fini*)
*(.eh_frame*)
_etext = .;
} > FLASH = 0xFF
.ARM.exidx :
{
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
.data :
{
_data = .;
*(vtable)
*(.data)
*(.data*)
_edata = .;
*(.got)
*(.got*)
*(.igot*)
} > SRAM AT > FLASH
_ldata = LOADADDR(.data);
.bss :
{
__bss_start__ = .;
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
__bss_end__ = .;
} > SRAM
/* User_heap_stack section, used to check that there is enough SRAM left */
._user_heap_stack :
{
__heap_start__ = .;
end = __heap_start__;
_end = end;
__end = end;
KEEP(*(.heap))
__heap_end__ = .;
__HeapLimit = __heap_end__;
. = . + _Min_Stack_Size;
} > SRAM
.gpram :
{
} > GPRAM
}
问题是:我哪里做错了???
更新
初始化和重定位:
//*****************************************************************************
void
ResetISR(void)
{
uint32_t *pui32Src, *pui32Dest;
//
// CC26xx PG1 workaround: Check backdoor when coming from POR
//
EnableAndCheckBackdoor();
//
// Final trim of device
//
trimDevice();
//
// Copy the data segment initializers from flash to SRAM.
//
pui32Src = &_etext;
for(pui32Dest = &_data; pui32Dest < &_edata; )
{
*pui32Dest++ = *pui32Src++;
}
//
// 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();
}
即使您独立编译代码位置,您的链接器脚本也不会那样做。您的数据重定位循环使用闪存地址进行数据复制:
pui32Src = &_etext;
您需要修改它以处理 OTA 情况并从 RAM 中的任何位置复制初始化数据。
该程序在 CC2650 (M3) 上独立运行时运行良好。但它也应用作通过无线电信道加载的固件。为此,需要位置无关代码。问题是,未设置如下所述定义的所有变量。
uint32_t u32Timer_g = 2000;
static DeviceInterfaceStructure_t suInterfaceStructure_g =
{
.timeOut = 0,
.state = STATE_IDLE,
.lastState = STATE_IDLE,
.Config.reconnect = 0,
.Config.lVersion = 0x01,
};
该程序是使用 GCC (gcc-arm-none-eabi-7-2018-q2-update) 使用以下标志编译的:
--asm
-fPIE
-pie
-fno-strict-aliasing
-fdata-sections
-ffunction-sections
-fno-exceptions
并使用以下链接描述文件
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
{
.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 :
{
_text = .;
*(.text*)
*(.rodata)
*(.rodata*)
*(.init)
*(.fini*)
*(.eh_frame*)
_etext = .;
} > FLASH = 0xFF
.ARM.exidx :
{
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
.data :
{
_data = .;
*(vtable)
*(.data)
*(.data*)
_edata = .;
*(.got)
*(.got*)
*(.igot*)
} > SRAM AT > FLASH
_ldata = LOADADDR(.data);
.bss :
{
__bss_start__ = .;
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
__bss_end__ = .;
} > SRAM
/* User_heap_stack section, used to check that there is enough SRAM left */
._user_heap_stack :
{
__heap_start__ = .;
end = __heap_start__;
_end = end;
__end = end;
KEEP(*(.heap))
__heap_end__ = .;
__HeapLimit = __heap_end__;
. = . + _Min_Stack_Size;
} > SRAM
.gpram :
{
} > GPRAM
}
问题是:我哪里做错了???
更新 初始化和重定位:
//*****************************************************************************
void
ResetISR(void)
{
uint32_t *pui32Src, *pui32Dest;
//
// CC26xx PG1 workaround: Check backdoor when coming from POR
//
EnableAndCheckBackdoor();
//
// Final trim of device
//
trimDevice();
//
// Copy the data segment initializers from flash to SRAM.
//
pui32Src = &_etext;
for(pui32Dest = &_data; pui32Dest < &_edata; )
{
*pui32Dest++ = *pui32Src++;
}
//
// 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();
}
即使您独立编译代码位置,您的链接器脚本也不会那样做。您的数据重定位循环使用闪存地址进行数据复制:
pui32Src = &_etext;
您需要修改它以处理 OTA 情况并从 RAM 中的任何位置复制初始化数据。