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 中的任何位置复制初始化数据。