GCC alias to function outside of translation unit -AKA- is this even the right tool for the job?

StackOverflow https://stackoverflow.com/questions/7649979

Question

I'm working with FreeRTOS on an STM32 (Cortex-M3), and using the CMSIS library from ST to bootstrap everything.

The CMSIS library defines the weak symbol SVC_Handler in the startup ".s" file. It must be overridden somewhere in order to get your ISR in the interrupt vector table. FreeRTOS defines vPortSVCHandler, which is the ISR I want to have handle the SVC interrupt.

I would like to "glue" the two together using my application code (i.e. w/o modifyng FreeRTOS or the CMSIS source code). I thought an alias would be the right tool for the job, so I tried this (in a separate source file, main.c):

void SVC_Handler(void) __attribute__ ((alias ("vPortSVCHandler")));

That results in: error: 'SVC_Handler' aliased to undefined symbol 'vPortSVCHandler'

Turns out, according to GCC documentation here http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html, in order to use the alias attribute, you cannot alias a symbol outside of the translation unit. So I thought I'd try to extern the symbol into main.c like so:

extern void vPortSVCHandler( void ) __attribute__ (( naked ));
void SVC_Handler(void) __attribute__ ((alias ("vPortSVCHandler")));

This generates the same error. Any suggestions???

I would really like to avoid modifying either of the libraries. I know I could write a function SVC_Handler that simply calls vPortSVCHandler, but that could add unnecessary overhead to the ISR (possibly depending on optimization settings). Note: The FreeRTOS examples accomplish this via a custom startup file. I'm looking for a way to do this from C or my linker script.

  • Compiler Version: gcc version 4.5.2 (Sourcery G++ Lite 2011.03-42)
  • Target: arm-none-eabi
Était-ce utile?

La solution

You should be able to do this either with a linker script, or by passing the appropriate option to the linker, eg. for ld, --defsym=SVC_Handler=vPortSVCHandler

See the binutils documentation for more information on the ld --defsym option, and assignments in linker scripts

Autres conseils

I think the problem with alias is, that it expects a declared and defined function, since it is just an alias. You want to use it as a forward-declaration of another function. I got a similar thing to work like that:

void SVC_Handler(void) asm("vPortSVCHandler");

This renames the entry point of the SVC_Handler, and if you then do not define it, it should find vPortSVCHandler.

See: https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html

Another solution that I gleaned from one of the FreeRTOS examples is to add the following to your FreeRTOSConfig.h ...

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names - or at least those used in the unmodified vector table. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

The original file is from FreeRTOS/Demo/CORTEX_M0_LPC1114_LPCXpresso/RTOSDemo/Source/FreeRTOSConfig.h which also integrates the CMSIS system clock into the config. A very nice starting point for a CMSIS/FreeRTOS project.

I'm pretty sure SVC handler is only used by FreeRTOS at initial startup, so adding an indirection exception handler isn't going to hurt performance (but its ugly). Best ask this on the FreeRTOS forum, response there is usually great.

Hope this helps, Best Regards, Dave

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top