Вызов функции 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
}
}