|
Понижение приоритета прерывания "на лету"?, Выход из прерывания без выхода из него. |
|
|
|
Feb 23 2011, 14:08
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Добрый день! Предположим, имеется прерывание высокого приоритета. ISR (процедура обработки прерывания), обслужив быстренько себя (например, установив/сбросив флаги), должна затем запустить некоторый процесс. Запуск процесса предполагает каждый раз некую инициализацию, которая длится долго (например, расчеты). Таким образом, если вызвать процедуру запуска процесса непосредственно из ISR, то это будет блокировать всю систему. Конечно, можно установить в ISR лишь некий флажок, проанализировать его в синхронном цикле программы и оттуда запустить процесс. Идея, однако, в том, чтобы еще внутри ISR как бы сделать вид, что ISR завершена, и спокойно вызвать процедуру: Код void xxx_IRQn(void) {
// быстрое и короткое действие самообслуживания .. // понижение "приоритета" до уровня основной программы .. // вызов длительного действия, которое может быть прервано другими ISR InitSomeProcess();
// выход из ISR .. } Для тех, кто имел дело с 51-ми процессорами, там был такой трюк: в ISR можно вызвать (call) инструкцию RETI, что приводило к "переводу" системы на уровень приоритета основной программы, после чего выполнять действия, которые могли уже быть прерваны иными ISR: Код void xxx_Vector(void) interrupt INTERRUPT_XXXX
// быстрое и короткое действие самообслуживания .. // понижение "приоритета" до уровня основной программы call _RETI
// вызов длительного действия, которое может быть прервано другими ISR InitSomeProcess();
// выход из ISR _RETI: RETI } Предполагаю, что где-то надо покрутиться с NVIC. Но не соображу пока, как. P.S. Извините, если разжевываю вопрос как для "чайников": зачастую читаю тут вопросы и не могу врубиться, а что же спрашивают и куда хотят. Кому все сразу понятно, читайте через строку  . TIA
|
|
|
|
|
Feb 23 2011, 14:58
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(GetSmart @ Feb 23 2011, 15:24)  Для этих целей существуют софтовые прерывания. Им назначается обычно самый низкий (или какой угодно) приоритет и внутри нужного прерывания вызывается это софтовое прерывание. В зависимости от приоритета и архитектуры проца оно либо мгновенно вызовется, либо по выходу из текущего прерывания, либо по выходу из всех прерываний, если юзаются вложенные прерывания или много запросов на прерывания.
Непонятно какая архитектура АРМ интересует и какой конкретно проц. Извините, не указал: речь о Cortex-Mx. Насколько помнится, как раз SVI (ранее - SWI) прервать нельзя, что и используется для работы с разделяемыми ресурсами. Использовать некий незанятый ресурс для генерации прерывания низкого приоритета, как это предлагает _dem, можно, если есть свободный. А если все использовано? (некоторые малые Cortex-M0 имеют не шибко много периферии). Все же хочется решить вопрос в рамках "основной" системы.
Сообщение отредактировал KnightIgor - Feb 23 2011, 14:59
|
|
|
|
|
Feb 23 2011, 15:06
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
В кортексах минимум 240 прерываний IRQ. обычно первые до 60 задействованы. Остальные можно делать софтовыми. Вот пример вызова Код NVIC->STIR = ???_IRQn ???_IRQn - любой номер IRQ, хоть из периферийных, хоть из свободных. Команда обычно ставится в конце или около конца основного ISR.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Feb 24 2011, 09:42
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(GetSmart @ Feb 23 2011, 17:03)  Да ладно. Я читал о контроллере прерываний ядра Кортекс-М. Может быть задействовано 68. Остальные не подключены к периферии, но программно вызываются. Проверил на железе (STM32F103RB): к сожалению, НЕ вызываются, точнее - вообще не разрешаются прерывания. В указаном процессоре максимальный номер IRQn = 42 (в отладчике - KEIL - максимальный индекс 42+16=58). Я попробовал разместить вектор как IRQn = 43 (расширил Startup). Код размещается, все путем (почти - ниже расскажу, что странно). Однако при попытке разрешить прерывание (записать соответствующий бит в нужный регистр NVIC_ISERx) бит НЕ хочет устанавливаться, ни программно (ассемблер смотрел), ни напрямую (в окне отображения содержимого памяти в отладчике). То есть, такое впечатление, что само железо затянуло бит на "0", и всё. Соответственно, запись NVIC->STIR = 43 ничего не вызывает. Вот если подготовить и дернуть таким образом IRQn из существующих (< 43), то да, работает. Такие дела... Теперь о странностях размещения кода. Например, берем обработчик прерывания от, скажем, USART1. Компилируем, смотрим карту памяти (*.MAP). Видим: USART1_IRQHandler 0x08000f47 Thumb Code 164 serial.o(.text)Смотрим содержимое таблицы векторов (память под отладчиком, секция RESET, начиная с 0x08000000). По адресу 0x080000D4 (USART1_IRQn = 37, то есть по адресу 0x08000000+4*(37.+ 16.)) и правда видим: 0x080000D4: 47 0F 00 08 ... Идем в текст программы, ставим точку останова на USART1_IRQHandler, запускаем, дожидаемся, когда щелкнет, смотрим и видим... 0x08000F46 B5 10 push {r4, lr}Обратите внимание, что адрес на единицу меньше значения в таблице векторов и карте памяти! Это как? Жук KEIL'а?
Сообщение отредактировал KnightIgor - Feb 24 2011, 09:45
|
|
|
|
|
Feb 24 2011, 09:50
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(KnightIgor @ Feb 24 2011, 12:42)  Обратите внимание, что адрес на единицу меньше значения в таблице векторов и карте памяти! Это как? Жук KEIL'а? Это наследство от более ранних процессоров ARM. Например, ARM7TDMI умеет исполнять наборы инструкций ARM и THUMB, переключаясь между соответствующими режимами. Так вот, там есть инструкция BX addr, которая прыгает на нужный адрес и переключает режим в зависимости от содержимого младшего бита addr (0 - ARM, 1 - THUMB). Cortex-M3 понимает только THUMB (даже Thumb-2), и, видимо, поэтому Keil генерит адреса для перехода с установленным младшим битом. Дополнение. Cortex-M3 Technical Reference Manual говорит так: Цитата Vector table entries are ARM/Thumb interworking compatible. This causes bit [0] of the vector value to load into the EPSR T-bit on exception entry. Creating a table entry with bit [0] clear generates an INVSTATE fault on the first instruction of the handler corresponding to this vector.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|