Как повесить ARM AT91SAM7X256 Печать
Добавил(а) microsin   

Тут решил собирать разные методы завешивания процессора и/или его переход по прерываниям Abort, Data Abort, Prefetch Abort, Undefined Instruction и методы их устранения (если разобрался, как).

Самый частый способ завешивания программы - ошибки с указателями (неинициализированные, неправильно установленные указатели), или неправильная их интерпретация (например, имеется указатель на указатель, который был раньше обычным указателем, и не везде в программе исправлен код использования этого указателя). Другой самый частый глюк - выход за пределы массива. Такие тупые ошибки я тут не рассматриваю, поскольку они тривиальны и легко выявляются (если, конечно, программа не слишком запутанная).

Очень неприятные ошибки - те, которые трудно исправить (особенно если код чужой). Например, функция библиотеки ведет себя не так, как ожидалось, либо скомпилированный код ведет себя не так, как хотелось бы. Обычно это происходит не потому, что ошибка в библиотеке или компиляторе, а просто недостаточно знаний, как их правильно использовать (хотя бывают и исключения из этого правила). Тогда помогает поиск документации и/или тщательная её разборка. Иногда приходится экспериментировать с разными вариантами кода одного и того же алгоритма.

[Способ 1]

Тут реализована казалось бы невинная идея скопировать в буфер dspdata по нужному адресу 16-битное слово (младшая половина от 32-битного bytecnt):
u8* dspdata;
u32 bytecnt;

bytecnt = 135;
dspdata = malloc(bytecnt);
dspdata[0] = 0xA5;
dspdata[1] = 0xA5;
dspdata[2] = 1;
//тут собственно, должно происходить копирование, а получается зависание.
*(u16*)&(dspdata[3]) = (u16)(bytecnt-2);

Последняя команда, на которой ARM виснет, компилируется в следующий код:
0010D048  E1B00008  MOVS  R0, R8         ;загрузим значение bytecnt, равное 135 (0x00000087), в регистр R0
0010D04C  E2500002  SUBS  R0, R0, #0x2   ;вычтем из R0 число 2, теперь там будет 133 (0x00000085).
0010D050  E1C700B3  STRH  R0, [R7, #+3]  ;запишем младшую половину R0 по адресу R7+3 (R7 у нас указывает на буфер dspdata).

На последней команде (STRH) микроконтроллер вешается (управление попадает на Abort_Handler:), причем непонятно, почему. Решить проблему удалось в обход, используя функцию memcpy.

[Способ 2]

if (crc == *(u16*)(dst->data))
{
    ..
}

Эта конструкция может вызвать Data Abort, если адрес dst->data нечетный, например равен 0x0020D3B1. Вот в такой ассемблерный код компилируется этот оператор if, исключение Data Abort срабатывает при выполнении 3-ей строки (адрес 0x00126370):
00126368  E59F00F0  LDR   R0, [PC, #+240]
0012636C  E1D000B0  LDRH  R0, [R0, #+0]
00126370  E1D611B1  LDRH  R1, [R6, #+17]
00126374  E1500001  CMP   R0, R1
00126378  1A000005  BNE   ??fwupdate_routine_29

Обойти ситуацию удалось, делая побайтовую выборку u16:
reccrc = dst->data[0] + (((u16)(dst->data[1]))<<8);
if (crc == reccrc)
{
    ..
}

Другой пример похожей ошибки (произойдет зависание, если адрес pnt нечетный):

u8* pnt;
*(u16*)pnt = tempCRC; 

[Ссылки]

1. IAR EW ARM: программа вылетает в Abort_Handler.
2. IAR EW ARM: устранение ошибок компиляции.
3. IAR EW ARM: устранение ошибок с отображением регистров.
4. IAR EW ARM: применение #ifndef и #define для разрешения конфликтов включаемых файлов (#include).
5. IAR EW ARM: пути с $PROJ_DIR$ не работают, почему?