cgccarmembedded

Arm Cortex-M7 SAM-E70 x32-ld is keeping both weak and strong function definition


I am trying basic thing with SAM-E70 but proper documentation is not existing and after 6 hours not even GPT could help, so I am asking here. I need to be able to place function directly at vector table. If function is not defined, default weak unused ISR will be used. I can't place ISR functions inside structure. They must be separated. I took Reset_Handler as example:

I have two fp definitions, one in interrupts.c:

__attribute__((weak, section(".pfnReset"))) void (*const interrupts_reset)(void) = UnusedIsrHandler; 

second one in startup_xc32.c:

__attribute__((section(".pfnReset"))) void (*const interrupts_reset)(void) = &Reset_Handler;

this is output form .map file:

 *(.pfnReset.*)
 .pfnReset.interrupts_reset
                0x0000000000400004        0x4 build/default/production/_ext/1083072663/interrupts.o
 .pfnReset.interrupts_reset
                0x0000000000400008        0x4 build/default/production/_ext/1294464586/startup_xc32.o
                0x0000000000400008                interrupts_reset

and this is srec file, from start of vector table (address 400000), the F0FF4520 is address of stack pointer init value, after which both function addresses are placed:

    S2 14 400000 F0FF4520 E5B54000 015B4000 E5B54000 07
                         ^        ^
                         |        |
address of weak function |        |
                                  |
       address of strong function |

finally here is my linker script:

SECTIONS
{
    .vectors :
    {
        . = ALIGN(4);
        _sfixed = .;
        __svectors = .;
        KEEP(*(.pvStack.*))               /* Stack pointer */
        KEEP(*(.pfnReset.*))              /* Reset Vector */
        KEEP(*(.pfnNonMaskableInt.*))     /* Non-Maskable Interrupt */
        KEEP(*(.pfnHardFault.*))            /* Hard Fault */
        KEEP(*(.pfnMemoryManagement.*))     /* Memory Management Fault */
        KEEP(*(.pfnBusFault.*))             /* Bus Fault */
        KEEP(*(.pfnUsageFault.*))           /* Usage Fault */
        KEEP(*(.pfnReservedC9.*))           /* Reserved */
        KEEP(*(.pfnReservedC8.*))           /* Reserved */
        KEEP(*(.pfnReservedC7.*))           /* Reserved */
        ...
        } > VECTOR_REGION

Why the function is not replaced, but both are used? (toolchain XC32 v4.40)


Solution

  • Okay so after many hours I finally run out of ways how to do it wrong. The key was to use EXTERN() command and place both function pointers into section not marked as KEEP. From MPLABĀ® XC32 Assembler, Linker and Utilities User's Guide :

    The EXTERN(symbol symbol ...) command forces symbol to be entered in the output file as an undefined symbol. Doing this may, for example, trigger linking of additional modules from standard libraries. Several symbols may be listed for each EXTERN, and EXTERN may appear multiple times. This command has the same effect as the -u command line option.

    Pity alias do not work across translation units, overwise it would be perfect solution.