2012-07-04 3 views
1

Я хотел бы создать инструмент отладки, который поможет мне отлаживать лучшее приложение. Я работаю голыми костями (без ОС). используя встроенный верстак IAR на SAM3 Atmel.вызов стека в ARM cortex m3

У меня есть сторожевой таймер, который вызывает определенный IRQ в случае тайм-аута (это будет заменено программным сбросом при выпуске). В обработчике IRQ я хочу распечатать (UART) трассировку стека, где точно произошло тайм-аут сторожевого таймера.

Я посмотрел в Интернете, и я не нашел реализации этой функции.

У кого-нибудь есть идея, как подойти к подобным вещам?

EDIT: Хорошо, мне удалось захватить обратный адрес из стека, поэтому я точно знаю, где произошел тайм-аут WDT. Развертывание всего стека не так просто, как только оно появляется, потому что каждая функция подталкивает в стек различное количество локальных переменных.

код я в конечном итоге это (для других, кто может найти ПОЛЕЗНЫЕ)

void WDT_IrqHandler(void) 
{ 
    uint32_t * WDT_Address; 
    Wdt *pWdt = WDT ; 
    volatile uint32_t dummy ; 
    WDT_Address = (uint32_t *) __get_MSP() + 16 ; 
    LogFatal ("Watchdog Timer timeout,The Return Address is %#X", *WDT_Address); 
    /* Clear status bit to acknowledge interrupt */ 
    dummy = pWdt->WDT_SR ; 

} 

ответ

1

Должно быть довольно прямолинейно следовать за выполнением. Не программно в вашем isr ...

Мы знаем из ARM ARM, что на Cortex-M3 он толкает xPSR, ReturnAddress, LR (R14), R12, R3, R2, R1 и R0 в стеке. управляет lr, чтобы он мог обнаружить возврат от прерывания, а затем вызывает точку входа, указанную в таблице векторов. если вы реализуете свой isr в asm для управления стеком, вы можете иметь простой цикл, который отключает источник прерывания (отключает wdt, что бы это ни заняло некоторое время), затем переходит в цикл, чтобы сбросить часть стек.

Из этого дампа вы увидите адрес lr/return, функцию/инструкцию, которая была прервана, из разборки вашей программы вы можете увидеть, что компилятор поставил в стек для каждой функции, вычесть это в каждый этап и идти так далеко, как вам нравится, или пока вы печатали содержимое стека.

Вы также можете сделать копию стека в плунжере и проанализировать его позже, а не делать такие вещи в isr (копия все еще занимает слишком много времени, но менее навязчива, чем ожидание на uart).

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

2

Я слышал, как меня зовут? :)

Возможно, вам понадобится крошечный бит встроенной сборки. Просто определите формат фреймов стека и в каком регистре хранится обычный указатель стека и передайте соответствующие значения в переменные C, из которых вы можете форматировать строки для вывода в UART.

Это не должно быть слишком сложно, но, конечно, (будучи довольно низкоуровневым) вам нужно обратить внимание на детали.

Как и в случае "non-exception"; не уверен, действительно ли ARM имеет разные стеки для обычного кода и исключений.

3

Чтобы сделать это с помощью ARM, вам необходимо сообщить своему компилятору о создании кадров стека. Например, с помощью gcc проверьте опцию -mapcs-frame. Возможно, это не тот, который вам нужен, но это будет началом.

Если у вас этого нет, будет «невозможно развернуть» стек, потому что вам потребуется для каждой функции точное использование стека в зависимости от параметров и локальных переменных.

Если вы ищете какой-нибудь пример кода, вы можете проверить dump_stack() в источниках ядра Linux и найти обратно связанную часть кода, выполненную для ARM.

0

Ваш сторожевой таймер может срабатывать в любой точке, даже если стек не содержит достаточной информации для размотки (например, пространство стека было выделено для разлива регистров, но регистры еще не скопированы).

Для корректно оптимизированного кода вам требуется информация об отладке, период. Все, что вы можете сделать из сторожевого таймера, - это регистр и дамп стека в формате, который достаточно читается машиной, чтобы разрешить преобразование в дамп ядра для gdb.

3

ARM определяет пару разделов .ARM.exidx и .ARM.extbl, которые содержат достаточно информации для разворачивания стека без символов отладки. Эти разделы существуют для обработки исключений, но вы также можете использовать их для выполнения backtrace. Добавьте -funwind-tables, чтобы заставить GCC включить эти разделы.

Смежные вопросы