Что может вызвать исключение ARM MemManage со всеми битами в регистре MMSFR, равными нулю? - PullRequest
0 голосов
/ 08 сентября 2018

Я работаю над кодом Ethernet на устройстве STM32F429 ARM Cortex M4 и сталкиваюсь с ситуацией, когда у меня возникает исключение MemManage, причина которого оказывается очень трудно отследить. Из того, что я понимаю, исключение MemManage вызвано некоторым нарушением MPU, таким как попытка выполнить код в защищенном пространстве регистров 0xE0000000 и выше. В документации Cortex M4, которую я прочитал, указано, что причина исключения должна быть зафиксирована в битах регистра MMSFR и что адрес ошибки может быть записан в регистре MMFAR при определенных обстоятельствах.

Меня расстраивает то, что исключение MemManage генерируется со всеми битами в регистре MMSFR, равными нулю. Я выполняю инструкцию точки останова, как только вводится обработчик исключений, так что я почти уверен, что MMSFR не очищается случайно. Кроме того, нигде в моем коде я даже не использую MPU, и он должен быть в состоянии по умолчанию при включении питания. Наконец, я могу преднамеренно создать исключение MemManage в другом месте моего кода, и биты MMSFR правильно идентифицируют возникшую проблему. Разматывая стек из исключения, единственное, что необычно в ПК, это то, что он находится в середине кода, который вызывается на раннем этапе для инициализации ОСРВ, но не должен выполняться позже, когда возникает исключение. Я пытаюсь определить, как ПК достиг того значения, которое он имел, но его трудно изолировать.

Есть ли у кого-то идеи, почему исключение MemManage может возникать без установки битов MMSFR? Или предложения по методам, позволяющим лучше понять обстоятельства, возникающие в моем коде непосредственно перед возникновением исключения.

Ответы [ 3 ]

0 голосов
/ 08 сентября 2018

Дважды проверьте, что полученное вами исключение на самом деле является MemManage, а не чем-то другим (например, если вы используете общий обработчик для нескольких типов исключений). Другая возможность состоит в том, что вы получаете неточную ошибку, и информация об исходной ошибке была отклонена. Из Руководство по отладке FreeRTOS :

Ошибки ARM Cortex-M могут быть точными или неточными. Если IMPRECISERR бит (бит 2) устанавливается в регистре состояния BusFault (или BFSR, который доступен для байта по адресу 0xE000ED29), то ошибка неточный.

...

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

0 голосов
/ 09 сентября 2018

Я наконец разыскал проблему.Это был код, выполняющий функцию обратного вызова в структуре, но указатель на структуру был нулевым указателем.Смещение функции обратного вызова в структуре соответствует смещению обработчика исключений MemManager в таблице векторов от нулевого адреса.Таким образом, обработчик MemManager вызывался не с помощью исключения, а с помощью простого вызова функции.Вот почему стек выглядел сбивающим с толку меня - я ожидал увидеть кадр стека исключений, а не простой кадр стека вызовов функций.

Подсказка для меня - биты состояния исключения в PSR ([8-0]) все нули (благодаря предложению от cooperised ), которое указывает, что мое исключение MemManager фактически не вызывалось как исключение.Затем я вернулся оттуда, чтобы понять, какой код отвечает за вызов обработчика как вызова функции.Мое ошибочное предположение состояло в том, что единственный способ, которым обработчик MemManager мог быть достигнут, был через исключение - со значением PSR и фреймом стека без исключения, являющимися основными подсказками, которые я игнорировал.

0 голосов
/ 08 сентября 2018

Мой инстинкт (не обязательно точный!) Заключается в том, что здесь что-то не так. Нет причины, по которой исключение MemManage не должно точно регистрировать причину его вызова, и ваше упоминание о том, что ПК был где-то, не должно было указывать на то, что что-то пошло не так задолго до входа в исключение. Исходя из этого, я думаю, вы узнаете больше, если определите , где исключение, а не попытаетесь определить причину из типа исключения.

Я бы начал с проверки значения в LR в той точке, которую вы определили, что имеет место исключение. Это не обязательно скажет вам, где произошла поломка ПК, но сообщит вам, где был выпущен последний BL до возникновения проблемы, так что это может помочь определить границы проблемы. Также может оказаться полезным проверить биты состояния исключения в PSR ([8-0]), чтобы подтвердить тип ошибки. (MemManage - 0x004.)

...