I am having trouble understanding my compiler. We use the Scons utility to compile ARM code for an M0+ processor (on Windows, if it matters. It's an ARMCC compile) I am trying to capture the address of the stack pointer during an interrupt using the answer to this question.
For my compiler, I get the following: Error: #20: identifier "asm" is undefined
The only way that I was able to get it to (mostly) compile was with the following:
void IRQHandler_real( uint32_t *sp )
{
// Do some work
}
__asm void IRQHandler( void )
{
MOV R0,SP
ADDS R0, #1
LDR R1, =IRQHandler_real //<<-- This line fails
BX R1
}
The error code is
Error: A1516E: Bad symbol 'IRQHandler_real', not defined or external
Replacing the last two assembly lines with BL IRQHandler_real
results in the same error.
This answer explains that inline assembly is extremely compiler dependent, so I haven't been able to find an example that matches my code.
I read here that I need an "extern C" call, but I haven't yet found details on what that looks like.
I double checked my syntax of the compiled processor code, and it looks identical to the commands that I am using. I think that the symbol is not defined at the time when the assembly is evaluated. I just haven't figured out how to define and link the symbols.
TL:DR, I need to call a C function from ARM assembly, but I haven't gotten past the compiler.
It seems like the compiler is evaluating the ARM code separately from and after all C code is evaluated. I fixed it by importing the function
with the IMPORT
command. My final code looks like this:
IMPORT IRQHandler_real
PUSH { R4, lr }
MOV R4, SP; The compiler does this from the C code, I'm assuming to avoid a hardware limitation.
MOV R0, R4
BL IRQHandler_real
POP { R4, PC }
ENDP
This works for ARMCC 5.6. I think that most of the documentation out there is for GCC ARM (asm("statement");
). I am still getting Warning: #667-D: "asm" function is nonstandard
, so I will gladly accept a "more correct" answer if one exists.