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

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

сброс не желателен, т.к. состояние части периферии нужно сохранить.

Так что мешает вызывать соотв. функцию, которая переинициализирует нужную периферию и в т.ч. NVIC.

Эта же функция должна вызывается при сбросе.

Вот тут я подробно описал как делаю нечто подобное, никакого колхоза, все прозрачно:

https://electronix.ru/forum/index.php?s=&am...t&p=1508140

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


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

Мешает то что если из обработчика прерывания просто передать управление стартовому коду (без system reset), то ненулевой IPSR не сбросится и часть прерываний будет перманентно заблокировано.

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


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

Мешает то что если из обработчика прерывания просто передать управление стартовому коду (без system reset), то ненулевой IPSR не сбросится и часть прерываний будет перманентно заблокировано.

А почему реально не сделать программный сброс (system reset)? Ведь содержимое внутреннего ОЗУ при этом вроде бы не теряется.

 

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


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

"сброс текущего приоритета прерываний без шаманства со стеком."

Рафинированное шаманство ;)

 

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


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

Мешает то что если из обработчика прерывания просто передать управление стартовому коду (без system reset), то ненулевой IPSR не сбросится и часть прерываний будет перманентно заблокировано.

Без формирования необходимого стекового фрейма тут не обойтись. Собственно именно такую операцию и выполняет таск-шедулер любой ОС, висящий на PendSV.

Вы можете сделать по образу и подобию:

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

Далее - в Вашем ISR возбуждаете это прерывание программно (через соотв. регистры NVIC) и штатно выходите из ISR.

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

Никаких запретов прерываний, никакого шаманства - всё штатными средствами.

 

PS: Хотя лучше всё-таки подумать - зачем именно нужно так переходить, без сброса периферии. Это, имхо, идеологически неправильный подход ;)

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


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

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

На случай аварий - системой уже предусмотрено несколько стандартных аппаратных прерываний разного уровня. От мягких программных, до жёстких системных.

 

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

 

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

 

Модуль защиты MPU - на самом деле замечательная вещь, на M4-M7 без него никак. Дело в том что ядро обрабатывает программный код на конвейере, дополнительно - сам код собирается для внеочередного исполнения. GCC знает про MPU, и умеет использовать его настройки. Например для линейной области памяти управления почти всей периферией (0x40000000 - (0.5G)) - запрет кеша, сквозная запись, запрет обратной записи, запрет исполнения кода, ожидать выполнения физической записи. В этом случае состояние периферии будет меняться программой - как задумал пользователь, но не как удобно GCC. Дополнительно - конвейер команд будет сбрасываться при обнаружении обращения к области периферии - чтоб ни одна сволочь вперёд очереди не проскочила (типа я только спросить).

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

 

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

 

Ну и всё скопом по порядку:

Reset_Handler - стартовый адрес прошивки

NMI_Handler - неизвестное прерывание Default_Handler, любое из неопределённых

HardFault_Handler - отказы: шины, арбитра памяти, сбой чтения вектора прерываний.

MemManage_Handler - ошибка доступа к памяти, срабатывание правил MPU

BusFault_Handler - чтение/запись по недопустимому адресу

UsageFault_Handler - прерывание специально для пользователя, можно оформить как критическую секцию

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

SVC_Handler - крутое прерывание пользователя из разряда - пусть весь мир подождёт

DebugMon_Handler - запуск кода отладчика на ядре мк в момент контрольной точки, остановка ядра после кода - для считывания данных отладчиком

пусто

PendSV_Handler - типа удобная функция для переключения контекста, я так не думаю

SysTick_Handler - самый примитивный таймер во всей системе, он даже не полностью 32 бита.

 

/* External Interrupts */

WWDG_IRQHandler - сторожевая собака, гавкает когда перестают ходить строем

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


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

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

 

Итог - кроме как через стек возврата не сделать. Вопрос решен.

 

AVI-crak, Да, MPU хорошо сделали. Главное просто и все что надо есть. Хотя еще не пробовал с ним работать.

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


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

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

Да, забыл указать, что для описанного метода желательно править Process stack и возврат из этого ISR тогда будет идти в Thread mode.

Можно конечно и Main stack править, но тогда нужно перед возвратом из этого ISR сделать запрет прерываний и fault-ов.

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


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

Вот читаю, вижу интересные мудрёные решения, но вопрос остается прежний - чем не угодил традиционный System Reset с предварительным сохранением нужных данных в ОЗУ/FLASH/EEPROM?

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

А если девайс еще и напрямую управляет опасной "силой", то я бы стопитсот раз подумал.

Имхо, лучше лишний раз "передернуть" все железо, чем так нагло влезать в стек подобного девайса ;)

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


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

Имхо, лучше лишний раз "передернуть" все железо, чем так нагло влезать в стек подобного девайса ;)

Чтобы не ресетить девайс - нужно изначально закладывать архитектуру здоровой OS, с отдельным стеком прерываний и куче стеков задач. В этом случае запуск/отключение и управление уровнем прерывания - осуществляется через активную задачу, которая вызывает системное прерывание с заведомо максимальным уровнем.

Без блокировки!!!

 

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

 

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

 

Глубокий сон - весьма специфическое требование, его трудно выполнить качественно, всегда придётся идти на компромисс. Гораздо чаще делают более простой вариант - сохраняют только данные объявленные как статические - в энергонезависимой памяти. С копированием их в память при запуске и сохранением перед отключением.

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


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

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

Ну, обычно существующие ОS под cortex именно так и реализованы :)

Но что-то мне подсказывает, что в данном случае OS вообще не используется ...

 

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

Вы прям озвучили мои мысли :)

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


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

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

Никто уровни и очереди не правит. Еще раз - задача выполнить reset, но не всего и сразу, а выборочный. Включая сброс NVIC. Чтобы часть периферии и данных в RAM остались нетронутыми.

 

Чтобы не ресетить девайс - нужно изначально закладывать архитектуру здоровой OS

Вы эту ОС будете переустанавливать/обновлять без ресета?

Действия при аварии электропитания тоже предполагаются без ресета?

 

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


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

Включая сброс NVIC.

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

Сбросить ядро (или весь МК) можно программно, но все МК делают это по-разному.

В частности, ST умеет делать полноценный аппаратный сброс (как будто дернули внешний NRST) программно через system reset .

 

 

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


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

Чтобы часть периферии и данных в RAM остались нетронутыми.

Дык не трогайте данные в RAM - они и останутся нетронутыми. Ресет содержимое SRAM не затрагивает. Для пущей безопасности нужный кусок SRAM защитите CRC или еще каким образом.

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


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

Дык не трогайте данные в RAM - они и останутся нетронутыми. Ресет содержимое SRAM не затрагивает. Для пущей безопасности нужный кусок SRAM защитите CRC или еще каким образом.

Не прокатит - ТС не желает сбрасывать всю периферию :laughing:

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

Практически всю периферию можно переинициализировать заново, нельзя тока нормально сбросить NVIC, т. к. NVIC является частью ядра.

Но NVIC тоже можно переинициализировать, пусть это и будет неким колхозом.

 

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

После чего модуль "сообщает", что это сброс был выполнен или это невозможно выполнить в данный момент.

 

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

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


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

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

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

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

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

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

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

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

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

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