MPStoering
MPStoering

Reputation: 184

Calling a C function from ARM function defined with __asm

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.

Upvotes: 4

Views: 2677

Answers (2)

MPStoering
MPStoering

Reputation: 184

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.

Upvotes: 1

cleblanc
cleblanc

Reputation: 3688

If your compiler is a C++ compiler you will need to use extern "C" like this;

extern "C" {
  void IRQHandler_real( uint32_t *sp )
  {
     // Do some work
  }
}

Upvotes: 2

Related Questions