Перейти к содержанию
    

stm32 NVIC: сброс маскировки прерываний внутри обработчика

Назрела необходимость (уже давно), разрешить прерывания более низкого приоритета в обработчике высокого приоритета. Способ в лоб - подкорректировав стек и сделать фиктивный возврат из прерывания.

С помощью MRS/MSR как я понял этого не сделать - в документации написано что запись в IPSR игнорируется.

Есть ли какое-то более человеческое решение чем через формирование стека возврата и возврат из прерывания?

 

Собственно, зачем это нужно - в случае аварии вызывается определенный irq. В обработчике нужно сделать некую аварийную последовательность действий, но для этого нужны рабочие обработчики другиз, в т.ч. низкоприоритетных прерываний. Можно конечно приоритеты нужных irq повысить.

Но есть вторая задача - сделать софтовый ресет (разумеется с обнулением стека), в нужную функцию и с разблокированными прерываниями. Например, в bootolader для перепрошивки.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Назрела необходимость (уже давно), разрешить прерывания более низкого приоритета в обработчике высокого приоритета.

Это противоречит самому принципу приоритетов прерываний. Странная необходимость ...

 

Способ в лоб - подкорректировав стек и сделать фиктивный возврат из прерывания.

С помощью MRS/MSR как я понял этого не сделать - в документации написано что запись в IPSR игнорируется.

В режиме handler (обработка прерываний) автоматом включается привилегированный режим, т.е. при остром желании можно влезть в любой стек и нагадить там как положено ))

Обычно это используют лишь в портах RTOS.

 

Есть ли какое-то более человеческое решение чем через формирование стека возврата и возврат из прерывания?

Можно форсить более высокоприоритетное прерывание прямо из текущего обработчика.

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

Для этой цели хорошо подойдет NMI, у него самый высокий приоритет (после Reset).

Можно даже извратиться - вызывать hardfault, например, обращаясь к несуществующей памяти :smile3046:

 

Собственно, зачем это нужно - в случае аварии вызывается определенный irq.

А в чем проблема вызывать некую функцию? К чему городить огород с отдельным прерыванием?

 

Например, в bootolader для перепрошивки.

А вот эта задача реализуется уже несколько иначе. Тут неоднократно поднималась эта тема. Пройдитесь поиском ))

 

 

зы. Подобную задачу я реализую просто: вызываю в случае аварии System Reset (нужно смотреть на его реализацию в каждом семействе МК).

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

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

Это реализована подтяжками соотв. портов МК внешними резисторами.

Остальные обработчики типа HardFault у меня тоже в итоге вызывают System Reset (после анализа и фиксации в журнале событий причины сбоя).

Т.е. любое зависание, срабатывание вотчдога и т. д. всегда сбрасывают проц, что автоматом вырубает все силовые цепи.

Это удобно при отладке и прошивке - пока шьется проц, вырубается всякая опасная "сила", скажем силовые ключи привода мощного мотора, гасится мощной источник для "силы".

В таком решении гарантировано, что ничего никуда не поедет и не сожжет никакие "пробки" )))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

То что колхоз это понятно, но без него не вижу простых решений. Хотя не сильный колхоз. Единственное неудобство - повторный вход в оборванные обработчики прерываний, но это не сильно пугает. Сброс состояний - дело несложное.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Единственное неудобство - повторный вход в оборванные обработчики прерываний, но это не сильно пугает. Сброс состояний - дело несложное.

Все-таки не пойму, чем не годится обычная функция, которая делает всю эту инициализацию?

 

например, обрывается питание и bluetooth подвисает перед прошивкой
Я бы в таком случае поставил ключ на питание блютуса - какой нить подходящий p-mosfet.

Управление им от соотв. gpio. Так и питание батарейки проще экономить (если девайс батарейный).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Так все-таки, чем не годится вызов некой функции, где все это делается?

Она же вызывается при запуске проца однократно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы в таком случае поставил ключ на питание блютуса - какой нить подходящий p-mosfet.

как вариант, только с RC цепочкой. Чтоб вырубался, но не сразу. Но честно не думал что проблемы такого характера могут возникнуть, думаю все-таки правильнее программно решить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

как вариант, только с RC цепочкой. Чтоб вырубался, но не сразу. Но честно не думал что проблемы такого характера могут возникнуть, думаю все-таки правильнее программно решить.

Правильно - как можно надежнее ))

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

В идеале хорошо бы еще мониторить потребляемый ток, чтобы вовремя вырубать мертвые узлы, но такое нужно очень редко ....

 

В одном моем проекте стояла ESP-ка, которая любила иногда подвисать по usart-у. Зная это, я сразу поставил для нее отдельный стабилизатор 3.3В со входом EN.

Это позволило включать ESP-ку только тогда, когда это было нужно, чисто программно. Зависла - передергиваем питание стабилизаатора и начинаем все по-новой.

Фактически производился сброс только модуля, отвечающего за обмен под wifi, а все остальные модули (программные модули) работали в штатном режиме.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так все-таки, чем не годится вызов некой функции, где все это делается?

Она же вызывается при запуске проца однократно.

Ей нужно по хорошему передать несколько параметров. Плюс как определить что на ребут для определенной цели ушел? В память записать определенную сигнатуру? Но это то же колхоз.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ей нужно по хорошему передать несколько параметров.
Зачем?

Сделайте разные функции для разных задач. Дайте им соотв. имена.

 

Плюс как определить что на ребут для определенной цели ушел?

Я использую модульную структура проекта, каждый модуль нужно инициализировать индивидуально при старте.

Но ничто не мешает принудительно его переинициализировать (скажем, вызвав соотв. SWI).

Каждый модуль у меня "владеет" своими пинами и своими аппаратными узлами (таймеры, цапы и т.п.).

Никто не обращается к одному и тому же аппаратному узлу из разных модулей. Т. е. у всех аппаратных сущностей есть владелец в единственном числе.

Так я точно могу управлять всей системой. Т. е. на этапе проектировки закладывается строгая и очень жесткая иерархия.

Она неизменна в процессе работы всей железки.

Каждый модуль обязан самостоятельно инициализировать "свое" железо (в т.п. числе и пины!).

Общая пока что только инициализация системного таймера и тактовой частоты, но и она скоро "уйдет" в свой модуль (SystemController).

 

В память записать определенную сигнатуру? Но это то же колхоз.

Я совсем запутался ... Какую еще сигнатуру?

Что же на самом деле вы хотите реализовать?

Распишите конкретный пример, а то, может оказаться, что мы толкуем о разных вещах )))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

        RCC->AHBENR=1;// marker for software reset
  
        SysTick->CTRL=0;
        uint32_t* ptr=(uint32_t*)(0x08000000);
        SCB->VTOR=(uint32_t)ptr;
        __set_MSP(*(ptr++));
        __set_BASEPRI(0);
        __set_CONTROL(0);
        NVIC->ICER[0]=0xFFFFFFFF;
        NVIC->ICER[1]=0xFFFFFFFF;
        NVIC->ICER[2]=0xFFFFFFFF;
        NVIC->ICER[3]=0xFFFFFFFF;
        NVIC->ICER[4]=0xFFFFFFFF;
        NVIC->ICER[5]=0xFFFFFFFF;
        NVIC->ICER[6]=0xFFFFFFFF;
        NVIC->ICER[7]=0xFFFFFFFF;
        NVIC->ICPR[0]=0xFFFFFFFF;
        NVIC->ICPR[1]=0xFFFFFFFF;
        NVIC->ICPR[2]=0xFFFFFFFF;
        NVIC->ICPR[3]=0xFFFFFFFF;
        NVIC->ICPR[4]=0xFFFFFFFF;
        NVIC->ICPR[5]=0xFFFFFFFF;
        NVIC->ICPR[6]=0xFFFFFFFF;
        NVIC->ICPR[7]=0xFFFFFFFF;
        void (*start)()=(void(*)())(*ptr);
        start();

 

Вполне доволен таким софтовым ресетом без сброса железа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вполне доволен таким софтовым ресетом без сброса железа.

А приведите пример, когда действительно нужен такой "софтовый ресет"?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я совсем запутался ... Какую еще сигнатуру?

Что же на самом деле вы хотите реализовать?

Распишите конкретный пример, а то, может оказаться, что мы толкуем о разных вещах )))

Мы видимо по разному думаем.

 

Я про то, как передать загрузчику после железного ресета параметры. Это некий квест и тоже с колхозом.

 

Работает примерно так: работает девайс в обычном режиме. Приходит кодограмма на перепрошивку, с дополнительными данными. Независимо от режима он должен ребутнуться, продолжить обмен по этому протоколу (без обрыва и без переинициализации протокола обмена) и прошиться. При этом в этой кодограмме содержатся данные, которые надо передать загрузчику.

То есть загрузчик должен получить содержимое кодограммы и все состояния протокола обмена.

После перепрошивки также без переинициализации протокола обмена запустить основную программу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

После перепрошивки также без переинициализации протокола обмена запустить основную программу.

Имхо, очень сомнительная и где-то даже опасная необходимость ...

Обычно, всякая смена прошивки софта предполагает сброс всего проца. Мне никогда не попадалось обратное.

 

Но, может быть, вы имеете ввиду некие настройки конкретного экземпляра девайса?

У меня такие настройки храняться в внешней EEPROM/FRAM или во внутреннем EEPROM (или FLASH, если нету EEPROM).

При перезапуске приложения все настройки загружаются в ОЗУ и оттуда все работает до очередного сброса.

Также предусмотрены настройки по дефолту, позволяет вернуть девайс соотв. командами к заводским настройкам.

За все это отвечает отдельный модуль Settings, он хранит все изменяемые параметры системы, которые могут быть разные для разных девайсов (в т. ч. серийны номер).

 

Мы видимо по разному думаем.
Это вообще-то справедливо для всех, иначе вообще не были бы нужны форумы :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Специфика такая. Не хочется протокол обмена обрывать, т.к. это вызывает проблемы на главном устройстве, а их решить сложнее чем протокол поддерживать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...