Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
like image 718
Brian McFarland Avatar asked Oct 04 '11 15:10

Brian McFarland


3 Answers

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

like image 60
Hasturkun Avatar answered Nov 03 '22 09:11

Hasturkun


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

like image 26
Klemens Morgenstern Avatar answered Nov 03 '22 10:11

Klemens Morgenstern


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.

like image 39
goertzenator Avatar answered Nov 03 '22 09:11

goertzenator