реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Понижение приоритета прерывания "на лету"?, Выход из прерывания без выхода из него.
KnightIgor
сообщение Feb 23 2011, 14:08
Сообщение #1


Знающий
****

Группа: Участник
Сообщений: 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. Извините, если разжевываю вопрос как для "чайников": зачастую читаю тут вопросы и не могу врубиться, а что же спрашивают и куда хотят. Кому все сразу понятно, читайте через строку wink.gif.

TIA
Go to the top of the page
 
+Quote Post
_dem
сообщение Feb 23 2011, 14:11
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970



А зачем так извращаться ?

В конце концов, если так хочеться, настройте какой-то таймер, на single shot, интервал 0 - 1 мкс, задайте ему прерывание с низким приоритетом, и в вашем обработчике запускайте таймер.

Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 23 2011, 14:14
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



По-моему, описанное достигается очень просто: для запуска "процесса" устанавливаем флаг запроса прерывания для этого процесса. Этому прерыванию можно присвоить любой подходящий приоретет.
Только сейчас заметил: _dem предложил что-то очень похожее. Только даже таймер не нужен. Просто использовать "незанятое" прерывание.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 23 2011, 14:24
Сообщение #4


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Для этих целей существуют софтовые прерывания. Им назначается обычно самый низкий (или какой угодно) приоритет и внутри нужного прерывания вызывается это софтовое прерывание. В зависимости от приоритета и архитектуры проца оно либо мгновенно вызовется, либо по выходу из текущего прерывания, либо по выходу из всех прерываний, если юзаются вложенные прерывания или много запросов на прерывания.

Непонятно какая архитектура АРМ интересует и какой конкретно проц.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Feb 23 2011, 14:58
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 23 2011, 15:06
Сообщение #6


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



В кортексах минимум 240 прерываний IRQ. обычно первые до 60 задействованы. Остальные можно делать софтовыми.

Вот пример вызова
Код
NVIC->STIR = ???_IRQn

???_IRQn - любой номер IRQ, хоть из периферийных, хоть из свободных.
Команда обычно ставится в конце или около конца основного ISR.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 23 2011, 15:45
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(GetSmart @ Feb 23 2011, 18:06) *
В кортексах минимум 240 прерываний IRQ. обычно первые до 60 задействованы. Остальные можно делать софтовыми.

Поправка: не более 240 прерываний. В разных МК - по-разному. Например, в STM32F101 - 68 штук.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 23 2011, 16:03
Сообщение #8


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Да ладно. Я читал о контроллере прерываний ядра Кортекс-М.
Может быть задействовано 68. Остальные не подключены к периферии, но программно вызываются.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 23 2011, 16:44
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(GetSmart @ Feb 23 2011, 19:03) *
Может быть задействовано 68. Остальные не подключены к периферии, но программно вызываются.

Можно цитату? В железе проверять лень...
Я ответа на этот вопрос в документации не нашёл. Был под впечатлением, что число прерываний конфигурируется при синтезе ядра. Приблизительно так же, как число возможных уровней приоритета.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Feb 23 2011, 17:35
Сообщение #10


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(KnightIgor @ Feb 23 2011, 16:08) *
Предположим, имеется прерывание высокого приоритета. ISR (процедура обработки прерывания), обслужив быстренько себя (например, установив/сбросив флаги), должна затем запустить некоторый процесс...


Это типичная схема вытеснения в RTOS. Работает идеально на всех современных архитектурах.

Оформляете свой процесс в виде задачи и ставите в его начале ожидание семафора.
В процедуре прерывания если нужно запустить процесс происходит восстановление не в контекст прерванной задачи, а в контекст задачи процесса, а именно в то место в ядре RTOS где задача вашего процесса остановилась в ожидания семафора.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Feb 23 2011, 20:57
Сообщение #11


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(AlexandrY @ Feb 23 2011, 18:35) *
Это типичная схема вытеснения в RTOS. Работает идеально на всех современных архитектурах.

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

А если я не использую RTOS? Меня механизм как таковой интересует.
Go to the top of the page
 
+Quote Post
Aaron
сообщение Feb 24 2011, 07:21
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007



Цитата(KnightIgor @ Feb 23 2011, 23:57) *
А если я не использую RTOS? Меня механизм как таковой интересует.

я использую protothreads - как раз "готовый механизм без использования RTOS" sm.gif http://www.sics.se/~adam/pt/
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Feb 24 2011, 09:42
Сообщение #13


Знающий
****

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 24 2011, 09:50
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 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.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 24 2011, 11:27
Сообщение #15


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



KnightIgor, с нечётными адресами всё так и должно быть.

По поводу софтового запроса. Его всегда можно повесить на ту периферию, которая в проекте не задействована.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 6th July 2025 - 13:40
Рейтинг@Mail.ru


Страница сгенерированна за 0.01505 секунд с 7
ELECTRONIX ©2004-2016