Stm32 не работает while

Русские Блоги

[STM32] Исключение класса неисправности _ помните отладочное решение проблемы HardFault в STM32

1. Базовые знания

Исключение класса неисправности
Существует несколько системных исключений, предназначенных для обработки ошибок. Неисправности в CM3 можно разделить на следующие категории:

  • Неисправности автобуса
  • Ошибки управления памятью
  • Ошибки использования
  • Жесткая вина

Таблица 7.8 Регистр состояния неисправности шины (BFSR), адрес: 0xE000_ED29
Таблица 7.9 Регистр состояния сбоя управления памятью (MFSR), адрес: 0xE000_ED28
Таблица 7.10 Регистр состояния ошибки использования (UFSR), адрес: 0xE000_ED2A
Таблица 7.11 Регистр состояния аппаратной неисправности Адрес: 0xE000_ED2C

1.1 Неисправности шины

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

  • z выборка, обычно называемая «прерывание предварительной выборки» (прерывание предварительной выборки)
  • z Чтение / запись данных, обычно называемое «прерывание данных»

Выполнение следующих действий в CM3 может вызвать исключение шины:

  • Действие стека PUSH на начальном этапе обработки прерывания. Вызывается «ошибка стека»
  • Прервать действие POP стека в конце обработки. Называется «Ошибка извлечения»
  • Когда процессор запускает последовательность (последовательность) обработки прерывания после считывания вектора. Это редкий частный случай, который классифицируется как серьезная неисправность.

1.3 Ошибки управления памятью

Сбои управления памятью в основном связаны с MPU, и часто причина в том, что определенное посещение нарушает стратегию защиты, установленную MPU. Кроме того, определенные незаконные обращения, такие как попытка получить инструкции в неисполняемой области памяти, вызовут ошибку MemManagefault, и она сработает, даже если нет MPU. Распространенные причины сбоев MemManage следующие:

  • Получил доступ к адресу за пределами зоны действия настройки MPU.
  • Запись данных в область только для чтения
  • Уровень пользователя получил доступ к адресу, доступ к которому разрешен только на уровне привилегий

1.4 Ошибки использования

Использование. Случаи возникновения ошибок могут быть следующими:

  • Выполнил неопределенную команду
  • Выполнение инструкций сопроцессора (Cortex-M3 не поддерживает сопроцессоры, но вы можете использовать программное обеспечение для моделирования работы сопроцессора с помощью механизма исключения сбоя, чтобы его можно было легко переносить между другими процессорами Cortex)
  • Попытайтесь войти в состояние ARM (поскольку CM3 не поддерживает состояние ARM, поэтому при переключении будет сгенерирована ошибка использования. Программное обеспечение может использовать этот механизм, чтобы проверить, поддерживает ли процессор состояние ARM)
  • Неверный возврат прерывания (недопустимое / неправильное значение включено в LR)
  • При использовании нескольких инструкций загрузки / сохранения адрес не выравнивается. Кроме того, установив соответствующий управляющий бит NVIC, неисправность может возникнуть в следующих ситуациях:
  • Делитель равен нулю
  • Любые несогласованные посещения

1,5 серьезная ошибка

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

В NVIC есть регистр состояния аппаратной неисправности (HFSR), который указывает причину аппаратной неисправности. Если это не вызвано выборкой вектора, процедура обслуживания аппаратного сбоя должна проверить другие регистры состояния сбоя, чтобы окончательно определить, кто подал прошение.

2. Классический случай

UCOS-II используется в проекте STM32F103, и возникает фатальная проблема: когда запускается только uCOS-II, программа работает нормально.После включения функции USB (или любой другой программы с прерываниями с высоким приоритетом) программа запускается через некоторое время. Мертвый, время случайное.

Запустите программу через keil, остановитесь, когда она выйдет из строя, и увидите смерть в HardFault_Handler:

Это означает, что произошла аппаратная ошибка.
Посмотрите на регистр в это время:

Читайте также:  Не работает emission blender

Обратите внимание на LR, это странное значение 0xFFFFFFF5, мы введем его позже. Теперь, когда произошла аппаратная ошибка, вы можете посмотреть регистр исключений (меню Peripherals-> Core Peripherals-> Fault Reports): (Это быстрее для просмотра, и есть метод для просмотра через регистр позже)

Можно видеть, что аппаратные ошибки (Hard Faults) вызваны петициями (бит FORCED), а настоящая причина ошибки вызвана ошибками использования, а конкретной причиной ошибки использования является ошибка INVPC. Если вы не используете Keil, Вы также можете узнать причину ошибки, непосредственно просмотрев аномальное значение регистра. Проверьте два руководства: «Техническое справочное руководство по процессору ARM Cortex-M3» и «Общее руководство пользователя устройств Cortex-M3» (можно загрузить непосредственно с официального сайта ARM), адрес регистра SCB (блок управления системой (SCB)) — 0xE000E000 , Адрес регистра статуса HardFault — 0xE000ED2C (HFSR, также доступен на Baidu), проверьте значение соответствующего адреса:

Вы можете видеть, что значение HFSR (0xE000ED2C) равно 0x40000000, а значение UFSR (0xE000ED2A) — 0x0004. Проверьте руководство «Основное руководство пользователя устройств Cortex-M3». Соответствующие биты означают:

Бит FORCED HFSR равен 1, что указывает на то, что причина аппаратной ошибки вызвана петициями. Этот бит 1 указывает, что произошли другие типы исключений, но исключения не могут быть обработаны из-за проблем с приоритетом или проблем включения, поэтому эти исключения обновляются до аппаратных ошибок. аномальный.

Бит INVPC в UFSR равен 1, что означает, что делается попытка загрузить недопустимое значение EXC_RETURN в ПК при возврате аварийного прерывания, что вызывает ошибку использования.

Причина, по которой ошибка использования обновляется до аппаратной ошибки, заключается в том, что бит ошибки использования не включен, а бит USGFAULTENA SHCRS (0xE000ED24, системный обработчик управления и регистр состояний) равен 0.

Используйте keil для перезагрузки программы. Перед запуском программы измените значение 0xE000ED24 на 0x00070000 (временно включите бит USGFAULTENA), а затем запустите снова. Когда программа выйдет из строя, вы увидите, что место сбоя становится UsageFault_Handler (этот шаг необязателен, просто Для проверки понимания механизма исключения).

В это время значение регистра исключений также стало:

Вы можете видеть, что значение HFSR исчезло, только значение UFSR указывает, что произошла ошибка INVPC.

Теперь выясним, почему возникает ошибка INVPC.

Описание ошибок INVPC в «Общем руководстве пользователя устройств Cortex-M3»:

Выше говорилось, что если значение EXC_RETURN незаконно загружено в ПК из-за неправильного контекста или неправильного значения EXC_RETURN, возникнет эта ошибка.

Когда бит INVPC равен 1, значение ПК точки возврата аварийного прерывания, вызвавшего эту ошибку, сохраняется в соответствующем стеке.

Что означает EXC_RETURN:

EXC_RETURN используется для возврата программы из аварийного прерывания.

В соответствии с процессом обработки исключений Cortex-M3, когда возникает исключение, ЦП сначала помещает регистр ядра в текущий стек (если он в настоящее время находится в режиме потока, он помещается в стек PSP, если он в настоящее время находится в режиме обработчика, он помещается в стек MSP), а затем ЦП установит для LR специальное значение, такое как 0xFFFFFFFD, затем переключится в режим обработчика, переключится на стек MSP и, наконец, войдет в процедуру обработки исключений (процедура обработки исключений всегда использует стек MSP). Когда процедура обработки исключений завершена и необходимо вернуться из прерывания, значение LR загружается в ПК (обычно инструкция BX LR, это также может быть MOV PC, инструкция LR или POP <. PC>и другие инструкции. , До тех пор, пока LR может быть назначен ПК), поскольку значение LR равно 0xFFFFFFFD, когда ЦП обнаруживает, что специальное значение загружено в ПК, он знает, что это возврат прерывания, и затем выполняет действие возврата прерывания (и нажимает Действие противоположное: извлечь значение регистра ядра из стека, восстановить в режим потока или режим обработчика и т. Д.).

Здесь это специальное значение (0xFFFFFFFD) — EXC_RETURN. Его характеристика состоит в том, что все верхние 28 бит равны 1, и только нижние 4 бита могут быть изменены. Различные нижние 4 бита представляют различные действия по возврату прерывания.

Читайте также:  Не работают поворотники аварийка работает audi

Это значение автоматически устанавливается ЦП перед вводом обработки исключений, и допустимы только 3 значения:

0xFFFFFFF1 Указывает, что значение регистра восстанавливается из стека MSP при возврате прерывания, и режим обработчика вводится после возврата прерывания, и используется стек MSP (что эквивалентно возврату из прерывания к другому прерыванию).

0xFFFFFFF9 Указывает, что значение регистра восстанавливается из стека MSP при возврате прерывания.После возврата прерывания он переходит в режим потока и использует стек MSP (это используется, когда PSP не используется, а используется только стек MSP).

0xFFFFFFFD Указывает, что значение регистра восстанавливается из стека PSP при возврате прерывания.После того, как прерывание возвращается, оно переходит в режим потока и использует стек PSP (это обычное явление, ОС возвращается к пользовательской программе после обработки прерывания).

Можно видеть, что возврат прерывания зависит от значения в LR. В этом проекте значение LR стало 0xFFFFFFF5, что, очевидно, также является значением EXC_RETURN, но это значение отличается от трех вышеупомянутых и является недопустимым, поэтому INVPC вызывается ошибка.

При входе в прерывание значение LR автоматически устанавливается ЦП.В этом нет ничего плохого.Почему значение LR становится недопустимым при выходе из прерывания? Причина только одна: программа обработки прерывания изменяет значение LR, что неверно.

Чтобы найти процедуру обработки прерывания, которая изменяет LR, необходимо найти инструкцию возврата прерывания, которая вызвала UsageFault.

Затем найдите инструкцию, которая вызвала ошибку, согласно сообщению об ошибке UsageFault.

Как упоминалось в описании INVPC, место, вызвавшее ошибку UsageFault, сохраняется в стеке.

Сначала проверьте значение LR (0xFFFFFFF5), 4-й бит равен 1, поэтому используется стек PSP (не обращайте внимания на значение R13 (SP), R13 — это значение стека MSP).

Значение PSP — 0x20000760 (см. Скриншот предыдущего регистра), проверьте значение соответствующей памяти:

Согласно процессу обработки исключений Cortex-M3, при входе в прерывание ЦП сохраняет значение регистра следующим образом:

xPSR (старший адрес)
PC
LR
R12
R3
R2
R1
R0 (младший адрес)

В соответствии с приведенной выше последовательностью соответствующие позиции регистров отмечены на снимке экрана стека PSP.Это состояние ЦП до входа в аварийное прерывание (здесь исключение UsageFault).

Из значения стека PSP видно, что до входа в аварийное прерывание UsageFault значение ПК равно 0x08002200, а значение LR равно 0x08000F59.

В окне дизассемблирования keil щелкните правой кнопкой мыши меню, чтобы выбрать «Показать дизассемблер по адресу . », введите 0x08002200, соответствующая область исходного кода также изменится, вы увидите, что код, вызвавший исключение UsageFault:

Это код в uCOS-II, который является исключением UsageFault, вызванным этим BX LR. Должно быть, значение LR было неправильно изменено, когда оно выполняется до этой точки.

Я по-прежнему ничего не вижу, поднимаюсь на один уровень выше, проверяю код, соответствующий LR, проверяю код 0x08000F58 в окне разборки (обратите внимание, что значение в LR — нечетное число, указывающее, что адрес возврата — инструкция THUMB, а фактический адрес кода — Соответствующий четный адрес 0x08000F58).

Вы можете видеть, что соответствующий ассемблерный код:

Соответствующий исходный код на C:

Итак, чтобы прояснить идею, процесс вызова:
. -> OSCtxSw -> OS_CPU_SR_Restore -> OS_CPU_SR_Restore вызвало исключение UsageFault.

Код OS_CPU_SR_Restore очень прост (см. Выше), он не изменяет значение LR. Итак, продолжаем смотреть на предыдущую функцию OSCtxSw.

Эта функция находится в файле os_cpu_a.asm:

Функция OSCtxSw использует сам LR, и кажется, что она не будет изменять LR случайным образом (иначе она не будет работать сама по себе), и подсказка кажется прерванной.
Но внимательно посмотрите на код OSCtxSw, он действительно возвращается после активации флага PendSV. Чтение кода OS_Sched показывает, что прерывание не будет инициировано немедленно, когда флаг PendSV установлен в OSCtxSw, потому что глобальное прерывание ЦП в это время отключено, и только когда глобальное прерывание включено, прерывание PendSV будет фактически запущено. Когда будет включено глобальное прерывание? Посмотрите на первое предложение OS_CPU_SR_Restore:

MSR PRIMASK, R0, открывается в этом предложении.
Итак, после запуска этого кода будет запущено прерывание PendSV, а инструкция BX LR будет выполняться после возврата прерывания PendSV. Прерывание PendSV — это то место, где uCOS-II действительно выполняет переключение контекста задачи.Он сильно изменит регистры ЦП и, скорее всего, изменит LR.

Читайте также:  Емл 327 не работает

Итак, продолжайте проверять код обработки прерывания PensSV, который также находится в файле os_cpu_a.asm,

Последний код OS_CPU_PendSVHandler:

Принудительно LR XOR 0x04 до того, как OS_CPU_PendSVHandler вернется, здесь принудительно изменить LR, если вы сделаете ошибку здесь, это вызовет проблемы (вопрос: после того, как ошибка будет сделана здесь, вы должны напрямую вызвать исключение в последнем предложении BX LR, почему Что записано в стеке PSP, так это ошибка в OS_CPU_SR_Restore? Фактически, в то время, когда проблема действительно была локализована, я поймал ошибку в BX LR в OS_CPU_PendSVHandler, но на момент написания этой статьи я поймал ошибку в OS_CPU_SR_Restore) .
Когда возникает ошибка, значение LR равно 0xFFFFFFF5, поэтому перед запуском этого оператора ORR значение LR должно быть 0xFFFFFFF1.

0xFFFFFFF1 является допустимым, это означает, что аварийное прерывание возвращается к другому аварийному прерыванию после возврата. uCOS-II — очень зрелый код, как здесь исправить неправильный LR? См. Описание uCOS-II, OS_CPU_PendSVHandler XOR 0x04 LR перед возвратом, чтобы убедиться, что он использует стек PSP после возврата, то есть он должен гарантировать, что он возвращается к пользовательскому коду. Это означает, что OS_CPU_PendSVHandler должен вводить это прерывание в пользовательском режиме, и он не должен вводить OS_CPU_PendSVHandler (вложенное прерывание) при наличии других прерываний.

Как гарантировать, что OS_CPU_PendSVHandler не войдет, когда есть другие прерывания? Глядя на описание uCOS-II, обнаруживается, что приоритет прерывания PendSV должен быть самым низким, чтобы гарантировать, что OS_CPU_PendSVHandler не войдет, когда есть другие прерывания.

Здесь исходное значение LR равно 0xFFFFFFF1 (позже изменено на 0xFFFFFFF5), что указывает на то, что OS_CPU_PendSVHandler введен в другие прерывания. Тогда что-то не так с приоритетом PendSV.

Проверьте приоритет прерывания PendSV (меню Peripherals -> Core Peripherals -> Nested Vectored Interrupt Controller):

Разумеется, приоритет PendSV не самый низкий, он равен 0 и имеет тот же приоритет, что и другие прерывания.

Очевидно, что пока приоритет Pend System Service не самый низкий, это вызовет указанные выше проблемы.

Проверьте код для установки приоритета PendSV, который также находится в файле os_cpu_a.asm:

OSStartHighRdy устанавливает 0xE000ED20 в 0xFFFF, чтобы установить приоритет PendSV. Просмотрите «Общее руководство пользователя устройств Cortex-M3» и обнаружите, что [23:16] 0xE000ED20 является битом приоритета PendSV. Здесь значение приоритета прерывания неверно.
Значит, виновато неправильное значение NVIC_PENDSV_PRI!

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

После изменения этих двух значений на следующие значения проблема решена:

При правильной работе приоритет PendSV должен быть 15, как показано на рисунке ниже:

А почему эти два значения неверны? Может случиться так, что код uCOS-II скопирован из другого проекта, который не является архитектурой Cotex-M3 (архитектура M1?), Поэтому значение здесь не может быть использовано здесь. Конкретный источник больше недоступен.

По сути, это трагедия, вызванная копированием кода uCOS.

Интеллектуальная рекомендация

Обход последовательности двоичного дерева, обход предварительного порядка (рекурсивный, нерекурсивный), обход среднего порядка (рекурсивный, нерекурсивный), последующий обход (рекурсивный, нерекурсивный)

Справочник статей Обход последовательности двоичного дерева Предзаказ обхода Рекурсивная версия Нерекурсивная версия Упорядоченный обход Рекурсивная версия Нерекурсивная версия Обход после заказа Реку.

iOS- alloc init new

Вы должны создавать объекты каждый день в процессе разработки, но зачем вам нужно alloc init во время инициализации? Что сделали alloc и init? alloc: выделяет память для объекта, позволяет ему не осво.

Python без модуля по имени решение

Иногда запуск программы Python, такие как питон bob.py, клубеньковые ошибки ИМЕНИ «×××», потому что ИМПОРТ ××× произошел. Как решить это? Два случая ана.

1.5.2 Вложенность и область действия функций Python

1. Тернарная операция Результат выполнения условия if else Результат выполнения условия Например: 2. Пространство имен ** Глобальное пространство имен: ** Пространство, созданное для хранения «в.

Источник

Оцените статью