Я борюсь с записью фрейма стека исключений поверх моих локальных / автоматических / стековых переменных.
Я использую FreeRTOS 8.2.1 и Microchip ASF для SAM4L Разработка с Eclipse MCU 2018/09 и Segger J-Link 6.40.
[EDIT]
Первый раз в l oop, r7 имеет другое значение (0x200044D0), которое выглядит как правильное значение (то же, что и SP). Теперь я думаю, что r7 изменяется во время ожидания в очереди сообщений RTOS, что происходит в верхней части l oop (но не в первый раз!)
for(;;){
if(WaitTx(MSG_WAIT_TIME)){ calls xQueuePeek(...)
do{
>> First time here, r7 has the value 0x200044D0
>> Subsequent times, r7 has the value 0x200044B0
// Keep sending data until no more data
MsgBlock_t *tosend = BuildFrame(MSG_MAX_LEN);
if(tosend){
[/ EDIT ]
У меня есть поток RTOS с верхним уровнем l oop. Две локальные переменные в функции потока становятся забитыми. Устанавливая точку наблюдения для одной из переменных, я вижу, как она запускается при выполнении второй инструкции обработчика прерываний. Дамп памяти показывает, что кадр стека исключений записан в 32 байтах стека потока. Самые низкие 5 суммированных значений соответствуют регистрам r0-r3, r12. Предположительно, остальные 3 соответствуют оригинальному lr, p c и xpsr. Значения выглядят правильно. Код:
TC02_Handler:
00013f84: push {r0, r1, r2, r4, r5, r6, r7, lr}
2141 tc_get_status(TC, BOARD_TC_CH_CMX);
00013f86: movs r1, #2 <<< Watchpoint triggers halt here
00013f88: ldr r0, [pc, #132] ;
Регистры:
r0 = 0x0 == Memory location 0x200044B0
r1 = 0x8 == Memory location 0x200044B4
r2 = 0x0 == Memory location 0x200044B8
r3 = 0x2000aab0 == Memory location 0x200044BC
r4 = 0x2000cd10
r5 = 0x0000cee3
r6 = 0x200044b0
r7 = 0x200044b0
r8-r11 all 0xa5a5a5a5 (RTOS fills stack with this value at startup)
r12= 0x6 == Memory location 0x200044C0
sp = 0x2000e3f8 (nowhere near where exception frame was stacked)
lr = 0xfffffffd
Память:
0x200044B0: 00000000 00000008 00000000 2000AAB0
0x200044C0: 00000006 0000CECB 0000CECC 01000000
---
0x2000E3F8: 00000000 00000008 00000000 2000CD10
0x2000E408: 0000CEE3 200044B0 200044B0 FFFFFFFD
Я не понимаю, что когда точка наблюдения срабатывает при входе для обработчика указатель стека указывает на совершенно другое место. Кадр стека исключений записывается в местоположения с 0x200044B0 по 0x200044CF, но указатель стека (после того, как точка наблюдения останавливает микро) имеет значение 0x2000E3F8.
Первая инструкция обработчика исключений отправляет r0-r2, r4-r7 и лр. Эти значения помещаются в ячейку стека, на которую указывает sp в 0x2000E3F8 - 0x2000E417
Должен ли указатель стека указывать на нижнюю часть кадра стека исключений при входе в обработчик исключений?
Некоторые другие подсказки, которые могут иметь отношение
Отладчик ищет неправильный адрес для этих автоматических c переменных. Отладчик «думает», что мои переменные должны находиться в местах 200044E4 и 200044E8.
Когда код получает к ним доступ, они загружаются из местоположений 200044C0 и 200044C4. Доступ к ним осуществляется как смещение от r7.
ldr r0,[r7,#16] (r7 is 0x200044B0).
and
ldr r0,[r7,#20] (r7 is 0x200044B0).
- Во время выполнения поврежденного потока указатель стека имеет значение 0x200044d0, но r7 (который, я думаю, используется как «указатель кадра» ") имеет значение 0x200044b0. Кадр стека исключений размещен правильно в соответствии со значением sp.
Спасибо