Top.Mail.Ru
Уведомления
Очистить все

[Решено] Не могу попасть в обработчик исключения

Алексей_Байдин
(@aleksej_bajdin)
Level 0

Всем здравствуйте! Хотел бы найти ответ на свой вопрос. Есть устройство, которое должно быть надежным даже в случае отказа, при возникновения каких либо неучтённых ошибках в программе (и как следствии зависание STM32). Мысль такая, если возникает ошибка, заходим в обработчик исключения, в нем отключаем мотор и все что нужно. На первое время, пока с моими знаниями, хотя бы так. Что дальше будет, для меня пока не важно - главное отключить мотор. Я не могу зайти в обработчики (ни в какие) исключений. Что я для этого сделал:
1) Включил глобальные прерывания:

__enable_irq();

2) Разрешил их как обычные прерывания:

NVIC_EnableIRQ(NonMaskableInt_IRQn);

NVIC_EnableIRQ(HardFault_IRQn);
NVIC_EnableIRQ(MemoryManagement_IRQn);
NVIC_EnableIRQ(BusFault_IRQn);
NVIC_EnableIRQ(UsageFault_IRQn);
NVIC_EnableIRQ(SVCall_IRQn);
NVIC_EnableIRQ(DebugMonitor_IRQn);
NVIC_EnableIRQ(PendSV_IRQn);
NVIC_EnableIRQ(SysTick_IRQn);

3) Переоределил сами обработчики:

extern "C" void HardFault_Handler(void)
{ GPIOB->BSRR |= GPIO_BSRR_BR_5; // выключаем мотор }

ну и так во всех, что есть:
 NonMaskableInt_IRQn     
 HardFault_IRQn       
 MemoryManagement_IRQn    
 BusFault_IRQn      
 UsageFault_IRQn  
 SVCall_IRQn         
 DebugMonitor_IRQn      
 PendSV_IRQn
 SysTick_IRQn

4) искусственно создаю ситуацию появления ошибки. Или обработчик, например Таймера, не переопределю, а он должен попасть туда, или такой командой:

__asm("svc 0");

5) уже под отладчиком я регистр NVIC_ISER0 устанавливаю в 0xFFFFFFFF, что все прерывания разрешить системные (хотя здесь я не уверен что я правильно настраиваю)
Но при созданной ситуации "STMка зависла", я не попадаю ни в один из определённых обработчиков исключений. А попадаю в цикл всем известный Loop

  .section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler

Что я сделал неправильно или что недоделал или в чем не прав и ошибаюсь?

Цитата
Topic starter Размещено : 14.08.2023 15:44
Aveal
(@aveal)
Top level Admin

Тема создана на базе обсуждения в комментариях.

ОтветитьЦитата
Размещено : 14.08.2023 16:52
Эдуард
(@eduard)
Level 4 Moderator

Мы разобрали этот вопрос. Дело оказалось прозаическим.

Если посмотреть файл startup_stm32xxxx.s, который лежит в "/Core/Startup/" мы увидим такие строки

Default_Handler:
Infinite_Loop:
  b Infinite_Loop

Сюда мы попадаем, если прерывание у нас не объявлено, но разрешено.
Потому что в стартовом скрипте стоят заглушки.

 .weak NMI_Handler
  .thumb_set NMI_Handler,Default_Handler

  .weak HardFault_Handler
  .thumb_set HardFault_Handler,Default_Handler

  .weak MemManage_Handler
  .thumb_set MemManage_Handler,Default_Handler

  .weak BusFault_Handler
  .thumb_set BusFault_Handler,Default_Handler

  .weak UsageFault_Handler
  .thumb_set UsageFault_Handler,Default_Handler

Это только часть, остальное можно посмотреть самим.

Вся ошибка возникла когда автор вместо

extern "C" void TIM1_BRK_TIM15_IRQHandler(void)

описал прерывание

extern "C" void TIM1_TIM15_IRQHandler(void)

соответственно у него вызывалось прерывание, которое нужно, но обработчика там не было. И согласно алгоритму всё сваливалось на метку Default_Handler и зацикливалось.

Правда автор не указал это в сообщении.

Но возникает ещё интересная тема. А когда вызываются прерывания, которые указал автор? В документации это как то скудно описано.

Получаем - невнимательность вызвала ошибку, не связанную с другими проблемами, которые могли бы вызвать описанные автором прерывания.

В то же время возникает вопрос: А как себя обезопасить от таких ошибок?

 

ОтветитьЦитата
Размещено : 14.08.2023 16:54
Алексей_Байдин
(@aleksej_bajdin)
Level 0

Добавлю от себя.

Скажу с радостью, что проблема решена. Спасибо людям!

Первое что. Есть некоторые ошибки в понимании происходящего в железе.

__enable_irq();

Обработчики исключений включены по умолчанию, специально я их не отключал. И поэтому здесь эта команда не имеет смысл.

Второе. Я действительно не понимал некоторых вещей. Действительно, если я разрешил прерывание, например Таймера, но не описал его обработчик или описал его с ошибкой (например, вместо TIM6_IRQHandler(void), написал TIM6IRQHandler(void)) просто упустил один символ, то STMка уходит на заглушку, откуда в тот самый Infinity Loop. И с этим ничего не поделаешь. Это уже как говорится моя проблема.

Третье, никакой ошибки здесь нет, поэтому я не входил ни в какие обработчики исключений, в которые хотел.
Ошибка действительно возникала, если я, например специально делил на ноль, что делать нельзя, соответственно я всё-таки входил в обработчик исключения:

extern "C" void HardFault_Handler(void)

Четвертое, если взглянуть на код функции

NVIC_EnableIRQ(HardFault_IRQn);

то там ничего не происходит, так как HardFault_IRQn имеет значение отрицательное, а в функции NVIC_EnableIRQ проверяется по условию на значение больше, чем ноль. И эти команды не имели смысл.

Пятое, читать и еще раз читать Programming manual.

Но остались вопросы:

Есть такой регистр - SHCSR (System handler control and state register). Он виден под отладчиком. Там есть биты:

USGFAULTENA
BUSFAULTENA
MEMFAULTENA

Если переведем документ Programming manual PM0214, то прочитаем следующее для этих трёх битов:

Установит в "1", чтобы разрешить

Под отладчиком, смотря на эти биты, я вижу, что они все сброшены в ноль...
Получается, 3 обработчика исключений:

MemManage_Handler
BusFault_Handler
UsageFault_Handler

запрещены???

ОтветитьЦитата
Topic starter Размещено : 14.08.2023 17:16
Aveal
(@aveal)
Top level Admin
От: @aleksej_bajdin

Получается, 3 обработчика исключений:

MemManage_Handler
BusFault_Handler
UsageFault_Handler

запрещены?

Хм, похоже на то, судя по битам.

ОтветитьЦитата
Размещено : 15.08.2023 20:08
Поделиться: