Вызов функции C из функции ARM, определенной с помощью __asm

У меня проблемы с пониманием моего компилятора. Мы используем утилиту Scons для компиляции кода ARM для процессора M0+ (в Windows, если это имеет значение. Это компиляция ARMCC). Я пытаюсь захватить адрес указателя стека во время прерывания, используя ответ на этот вопрос.

Для моего компилятора я получаю следующее: Error: #20: identifier "asm" is undefinedЕдинственный способ, которым я смог получить его (главным образом), был следующим:

  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
  }

Код ошибки

  Error: A1516E: Bad symbol 'IRQHandler_real', not defined or external

Замена двух последних сборочных линий BL IRQHandler_real приводит к той же ошибке.

Этот ответ объясняет, что встроенная сборка сильно зависит от компилятора, поэтому я не смог найти пример, соответствующий моему коду.

Я прочитал здесь, что мне нужен вызов "extern C", но я еще не нашел подробностей о том, как это выглядит.

Я дважды проверил мой синтаксис скомпилированного кода процессора, и он выглядит идентично командам, которые я использую. Я думаю, что символ не определен во время оценки сборки. Я просто не понял, как определить и связать символы.

TL: DR, мне нужно вызвать функцию C из сборки ARM, но я не прошел мимо компилятора.

2 ответа

Решение

Похоже, что компилятор оценивает код ARM отдельно от и после того, как весь код C будет оценен. Я исправил это, импортировав функцию с IMPORT команда. Мой окончательный код выглядит так:

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

Это работает для ARMCC 5.6. Я думаю, что большая часть документации для GCC ARM (asm("statement");). Я все еще получаю Warning: #667-D: "asm" function is nonstandardпоэтому я с радостью приму "более правильный" ответ, если таковой существует.

Если ваш компилятор является компилятором C++, вам нужно использовать extern "C", например так;

extern "C" {
  void IRQHandler_real( uint32_t *sp )
  {
     // Do some work
  }
}
Другие вопросы по тегам