Исключение AVR32: ошибка данных шины
Недавно я столкнулся со странным поведением во встроенном программном обеспечении.
Что я получил: Запуск 32-битного контроллера AVR32, запуск программы с внешней SDRAM, так как размер файла слишком велик, чтобы запускать его непосредственно со флэш-памяти микроконтроллера. Из-за карты физической памяти области памяти разделены между:
стек (начало 0x1000, длина 0xF000) ( < 0x1000 защищено MPU)
EBI SDRAM (начало 0xD0000000, длина 0x00400000).
Что происходит: К сожалению, я получил исключение, которое невозможно воспроизвести. Глядя на мою заданную трассировку стека, происходит следующее нерегулярное событие:
Имя: извлечение данных об ошибке шины - Источник события: Шина данных - Сохраненный адрес возврата: Первая незавершенная инструкция
Кроме того, указатель стека имеет допустимое значение, в то время как адрес, где происходит исключение (последняя точка входа для извлечения инструкций), указывает на нирвану памяти (например, 0x496e6372, что-то около 0x5..., 0x6....). Я предполагаю, что это должна быть "Первая незавершенная инструкция", о которой идет речь в руководстве. Однако строка в моем исходном коде всегда одна и та же: доступ к функции-члену из массива данных через указатель.
if(mSomeArray[i])
{
mSomeArray[i]->someFunction(); <-- Crash
}
Дело в том, что при добавлении или удалении другого исходного кода событие исчезает и возвращается снова.
О чем я думал: что-то портит мою память (отображение). Какие ошибки возможны для этого?
- Переполнение буфера?
- Контроллер SDRAM может быть отключен, поэтому он теряет некоторые данные. Это не невозможно, а скорее невероятно
- Стек достаточно большой, я уже проверил это с водяным знаком
- Скорость шины данных и часы AVR установлены правильно
Как решить это: Больше утверждать? К сожалению, я не могу отладить это с помощью AVRStudio. Кто-нибудь намек или идея? Или я что-то упускаю очевидное?
Редактировать:
Упомянутые подходы от пользователей:
- Проверьте адреса указателя функции и записи массива
- Перезапись стекового массива
- Не правильно написанные прерывания
- Неинициализированные указатели
- Проверьте доступ к массиву через
i
на случай аварии - использовать адрес обработчика исключений для несанкционированного доступа к памяти
- использование
snprintf
вместоsprintf
Позднее приложение к ветке: проблема заключалась в неправильном доступе к массиву (был задан неправильный индекс) в старом программном модуле, который не имел ничего общего с моими модулями. Я обнаружил это случайно, это было любопытно, что это не появилось раньше, и мне потребовалось много времени, чтобы найти строку кода. Я отмечаю единственный ответ как правильное решение.
Спасибо всем за ваш вклад.
Берегите себя (своего программного обеспечения;))
1 ответ
Вот несколько идей:
- Проверьте 'i', чтобы убедиться, что оно находится в пределах массива.
- Проверьте адрес указателя функции, который должен быть вызван. У него должен быть адрес в SDRAM.
- Посмотрите, есть ли у чипа адрес обработчика исключений, к которому он перейдет, когда получит доступ к недопустимой памяти. Как только вы там, выведите некоторые отладочные данные
- Если ваш отладчик позволяет, установите точку останова на someFunction(), когда она написана. Это перехватит какую-то другую функцию, когда перезапишет указатель на функцию.