Linker script .relocate section's first symbol, _srelocate, is incorrect (GCC Bug?)

社会主义新天地 提交于 2019-12-02 00:27:25
nonsensickle

I had long ago discovered the answer to my own question but it seems that it is still a little unclear in my edits so allow me to formalize it here.

The issue is that due to a bug in GCC the linker inserts an additional TMC_END symbol taking up 4 bytes in between my _etext and _srelocate symbols. This is incorrect because this symbol has nothing to do with the code that I'm writing and I'm not even using this functionality. I had discovered and explained this in my other SO question.

Workaround:

Atmel's sample code, rightly, assumes that if your code is running out of Flash memory your _srelocate symbol's address and _etext symbol's address will be different, one having an address starting with 0x004... and the other with 0x20....

If your code is running out of RAM, this means that you have a bootloader that copies the relevant sections into the correct memory location, hence the _etext symbol's address will also reside in RAM and be equal to the _srelocate symbol's address.

Therefore Atmel is trying to make sure that the _srelocate section always resides in RAM.

Due to the bug in GCC the solution was to change the code to check if the _srelocate symbol's address is already in RAM, like this:

// I can't remember what #define Atmel has for SRAM so I'm just going to
// use this one for the purposes of my example.
#define SRAM_START_ADDRESS 0x20000000

void Reset_Handler(void)
{
    uint32_t *pSrc, *pDest, Size;

    /* Initialize the relocate segment */
    pSrc = &_etext;      // Could either be in Flash or SRAM depending on your configuration.
    pDest = &_srelocate; // Always in SRAM or there's something strange going on...

    if ((intptr_t)pSrc < (intptr_t)SRAM_START_ADDRESS) { // <<<< Changed code here <<<<
        // We enter here only if pSrc is pointing to a location in Flash.
        // If that's the case, we need to copy the memory from Flash to SRAM.
        for (; pDest < &_erelocate;) {
            *pDest++ = *pSrc++;
        }
    }

    /* Clear the zero segment */
    for (pDest = &_szero; pDest < &_ezero;) {
        *pDest++ = 0;
    }

    /* Set the vector table base address */
    pSrc = (uint32_t *) & _sfixed;
    SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);

    if (((uint32_t) pSrc >= IRAM_ADDR) && ((uint32_t) pSrc < IRAM_ADDR + IRAM_SIZE)) {
        SCB->VTOR |= (1UL) << SCB_VTOR_TBLBASE_Pos;
    }

    /* Initialize the C library */
    __libc_init_array();

    /* Branch to main function */
    main();

    /* Infinite loop */
    while (1);
}

And that worked for my situation. From what I can see this bug was fixed and the fix has since been reverted so it is unlikely that you will have it fixed in your Atmel Studio.

I'm not sure if this is your issue, but if you are using SAM-BA to copy your code to SRAM, the SAM-BA boot program uses the first 2048 (0x800) bytes of SRAM for variables and its stack. Perhaps that is why your relocate section is getting stomped on (there are ISRs and other code still running while you copy the code, and these need their own SRAM).

All the SAM-BA applet examples get copied to 0x20000800 for this reason.

I don't know how else you'd place your code in SRAM, aside from implementing something similar to SAM-BA, in which case you'd also need your own section of SRAM for data.

Here is the linker script for the applets for the SAM4S16 part:

/* ----------------------------------------------------------------------------
 *         SAM Software Package License
 * ----------------------------------------------------------------------------
 * Copyright (c) 2012, Atmel Corporation
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ----------------------------------------------------------------------------
 */

/*------------------------------------------------------------------------------
 *      Linker script for running in internal SRAM on the SAM4S16
 *----------------------------------------------------------------------------*/

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)

/* Memory Spaces Definitions */
MEMORY
{
    romcodesram (W!RX) : ORIGIN = 0x20000000, LENGTH = 0x800
    sram (W!RX) : ORIGIN = 0x20000800, LENGTH = 0x0001F800 /* sram, 128K - sizeof(romcodesram) */
}

SECTIONS
{
    /* startup code in the .isr_vector */
    .text :
    {
        . = ALIGN(4);
        _stext = .;
        KEEP(*(.isr_vector .isr_vector.*))
        *(.mailbox)
        *(.text .text.*)
        *(.rodata .rodata.*)
        *(.ramfunc .ramfunc.*)
        *(.glue_7)
        *(.glue_7t)
        *(.gcc_except_table)
        *(.rodata .rodata*)
        *(.gnu.linkonce.r.*)
        . = ALIGN(4);
        _etext = .;
    } > sram

    /* data */
    .data :
    {
        . = ALIGN(4);
        _sidata = .;
        _sdata = .;

        *(.data)
        *(.data.*)
        . = ALIGN(4);
        _edata = .;
    } > sram

    .bss (NOLOAD) : {
        _szero = .;
        *(.bss)
        . = ALIGN(4);
        _ezero = .;
    } >sram

    /* Stack in SRAM */
    _sstack = 0x2001FFF0;
}
. = ALIGN(4);
end = .;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!