Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC17xx NVIC - Как заблокировать все IRQ с приоритетом ниже нужного?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
GetSmart
Всем привет.
Кто уже близко познакомился с этим NVIC?
Допустим я раздал всем своим прерываниям приоритеты. Некоторым даже одинаковые (нескольким уартам).
Возникла задача на короткое время запрещать все прерывания с приоритетом ниже (со значением выше...) некоторого, оставляя работать самые приоритетные. Что-то вроде имитации залёта в какое-то прерывание среднего уровня, когда блокируются прерывания с приоритетами ниже и равного текущему. Всё аналогично, но без залёта в прерывание и чисто программным путём. Да ещё так, чтобы никакая логика NVIC не сбивалась и никакие запросы не терялись, а только откладывались на попозже.

Вот. Кто подскажет?
_Артём_
Если не ошибаюсь, то нужно смотреть в описание Base Priority Mask Register.
ViKo
__set_BASEPRI(0x60); // Disable interrupts with priority 0x60-0xFF using CMSIS
GetSmart
Это могут быть не те приоритеты. Программно раздаваемые приоритеты насколько мне не изменяет память всего лишь пятибитовые.
aaarrr
Цитата(GetSmart @ Apr 25 2012, 22:54) *
Это могут быть не те приоритеты. Программно раздаваемые приоритеты насколько мне не изменяет память всего лишь пятибитовые.

А других нет sm.gif Разрядность приоритетов implementation defined, биты в поле задействуются от MSB вниз.
sysel
Цитата(GetSmart @ Apr 25 2012, 22:54) *
Это могут быть не те приоритеты. Программно раздаваемые приоритеты насколько мне не изменяет память всего лишь пятибитовые.

В Cortex-M3 могут быть реализованы 3 - 8 бит (старших) приоритетов (в зависимости от производителя). В LPC17xx производителем реализованы 5 бит (старших).
Т.е. когда Вы задаёте приоритет "NVIC_SetPriority (SPI_IRQHandler, 3)", в регистр приоритета прерывания SPI записывается значение "3 << (8-5)", т.е. 0x18. (см. реализацию NVIC_SetPriority в файте core_cm3.h). А когда Вы пишите в регистр BASEPRI, нужно самому делать эти "3 << (8-5)".
Т.е. чтобы запретить прерывания приоритетом ниже или равным 3, нужно вызвать __set_BASEPRI(0x18).
Советую прочесть книжку "The definitive guide to the ARM CORTEX-M3 second editition", толклвая и понятным языком написана.
GetSmart
Ладно, допустим BASEPRI то, что мне нужно. И устанавливать его нужно приоритетом, сдвинутым на 3. Хотя, довольно странно, т.к. функции из общего файла CMSIS.

А отменять фильтрацию приоритета как? Вот картинка из мануала LPC17xx, в которой написано, что запись 0 игнорируется. Если записать в BASEPRI значение 255, то 255 приоритет (255 & 0xf8 => 248) будет заблокирован. То есть это уже "криво".
aaarrr
Цитата(GetSmart @ Apr 25 2012, 23:51) *
А отменять фильтрацию приоритета как? Вот картинка из мануала LPC17xx, в которой написано, что запись 0 игнорируется.

Записью нуля как раз.

Лучше обратиться к первоисточнику:
Цитата
When this register is cleared to 0, it has no effect on the execution priority.
KRS
есть еще полезный алиас
BASEPRI_MAX
запись в него позволяет только увеличить приоритет, т.е. запись значения больше чем есть BASEPRI игнорируется.
ViKo
Из той же книжки:
BASEPRI
A register of up to 8 bits (depending on the bit width implemented for priority level).
It defines the masking priority level. When this is set, it disables all interrupts of
the same or lower level (larger priority value). Higher priority interrupts can still be
allowed. If this is set to 0, the masking function is disabled (this is the default).

Насчет сдвигов, по-моему, sysel не прав, и ничего сдвигать не нужно (потому и работает на любом процессоре, независимо от количества битов в регистрах приоритета):
As with other priority-level registers, the formatting of the BASEPRI register is affected
by the number of implemented priority register widths. For example, if only 3 bits are imple-
mented for priority-level registers, BASEPRI can be programmed as 0x00, 0x20, 0x40 … 0xC0,
and 0xE0

Посмотрел core_cm3.h на функции работы с приоритетами прерываний. Действительно, приоритеты записываются со сдвигом.
Посмотрел в core_cm3.c на функции работы с BASEPRI. Сдвигов не видно.
Что это, если не косяк программистов? "Моя твоя не понимай?"
sysel
Цитата(ViKo @ Apr 26 2012, 08:29) *
Насчет сдвигов, по-моему, sysel не прав, и ничего сдвигать не нужно (потому и работает на любом процессоре, независимо от количества битов в регистрах приоритета):
As with other priority-level registers, the formatting of the BASEPRI register is affected
by the number of implemented priority register widths. For example, if only 3 bits are imple-
mented for priority-level registers, BASEPRI can be programmed as 0x00, 0x20, 0x40 … 0xC0,
and 0xE0

Как раз в этом примете "0x00, 0x20, 0x40 … 0xC0, and 0xE0" и получаем 3 бита приоритета сдвинуты на 5 влево. т.е. значение "0x60" регистра BASEPRI будет соответствовать значению 0x03 в NVIC_SetPriority().

Посмотрите реализацию "NVIC_SetPriority()". Они там сдвигают аргумента на (8 - __NVIC_PRIO_BITS) влево.

Из файла LPC17xx.h
Код
#define __NVIC_PRIO_BITS          5         /*!< Number of Bits used for Priority Levels          */


Из файла core_cm3.h
Код
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
  if(IRQn < 0) {
    SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M  System Interrupts */
  else {
    NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */
}


На самом деле в ядре Cortex-M3 всё логично получается, просто небольшая путанка в CMSIS-ке.
KRS
Цитата(sysel @ Apr 26 2012, 13:53) *
На самом деле в ядре Cortex-M3 всё логично получается, просто небольшая путанка в CMSIS-ке.

поэтому лучше ее и не использовать! она скрывает некоторые особенности которые надо знать!
Причем сам CMSIS довольно низкий уровень и использовать на этом уровне непонятно чей код....



ViKo
Цитата(sysel @ Apr 26 2012, 12:53) *
Как раз в этом примете "0x00, 0x20, 0x40 … 0xC0, and 0xE0" и получаем 3 бита приоритета сдвинуты на 5 влево. т.е. значение "0x60" регистра BASEPRI будет соответствовать значению 0x03 в NVIC_SetPriority().
...
На самом деле в ядре Cortex-M3 всё логично получается, просто небольшая путанка в CMSIS-ке.

В том и путаница, что разные числа нужно задавать для задания приоритета и для маскирования.
По мне логично было бы задавать приоритет 0x60 и маскировать приоритет 0x60 и ниже.

Поддерживаю предыдущего выступающего - использовать только заголовочный файл с описаниями регистров и битов, остальное писать самостоятельно, поглядывая на библиотеку (в крайнем случае, при затыках).
KRS
Цитата(ViKo @ Apr 26 2012, 14:50) *
поглядывая на библиотеку (в крайнем случае, при затыках).

поглядывать полезно, потому что некоторые вещи в документации не сразу понятны! Но код смотреть стоит IMHO исключительно совместно с доками от ARM (DDI0403 arm architecture v7m reference manual и DDI0337 cortex m3 trm)
получается что эту библиотеку можно рассматривать как пример, и разобравшись написать свои функции более высокого уровня и с нормальными именами sm.gif


GetSmart
А для CM0 есть механизм аналогичного ограничения приоритетов?

В файле CMSIS для CM0 нет упоминания Base Priority Mask Register.
_Артём_
Цитата(GetSmart @ Jul 11 2013, 12:29) *
А для CM0 есть механизм аналогичного ограничения приоритетов?

Нет такого механизма. На то он и М0.



Цитата(GetSmart @ Jul 11 2013, 12:29) *
В файле CMSIS для CM0 нет упоминания Base Priority Mask Register.

Только PRIMASK есть.

Может в Cortex-M0+ добавят функциональности...

GetSmart
Цитата(_Артём_ @ Jul 11 2013, 16:30) *
Нет такого механизма. На то он и М0.

Как-то неполиткорректно sm.gif

В ядре столько много понапихано, что какая-то мелочь ни чуть не добавила сложности/потребления. Даже если цифровой компаратор считать сложным, то маскировка приоритетов по И/ИЛИ просто элементарна.
GetSmart
Мало того, в доке на LPC11xx (CM0) LPC81x (CM0+) об NVIC есть пунктик "4 programmable interrupt priority levels with hardware priority level masking", который трудно перевести как блокировка всех IRQ с конфигурируемыми приоритетами (регистром PRIMASK).

Так что, надежда остаётся? sm.gif
_Артём_
Цитата(GetSmart @ Jul 11 2013, 18:00) *
"4 programmable interrupt priority levels with hardware priority level masking", который трудно перевести как блокировка всех IRQ с конфигурируемыми приоритетами (регистром PRIMASK).

Непонятно как надо понимать эту фразу. Прерывание с приоритетом N может прервать прерывание с приритетом N+1. но не наоборот. Это обеспечивает hardware
PRIMASK запрещает/разрешает выполнение всех прерываний с конфигурируемым проиритетом. Не то.
Цитата(GetSmart @ Jul 11 2013, 18:00) *
Так что, надежда остаётся? sm.gif

Толку с неё, если регистр BASEPRI не реализован? sm.gif
GetSmart
Цитата(_Артём_ @ Jul 11 2013, 22:45) *
Прерывание с приоритетом N может прервать прерывание с приритетом N+1. но не наоборот. Это обеспечивает hardware

Такая интерпретация второй части предложения напоминает масло масляное. Наличие нескольких уровней приоритетов в контроллере ВСЕГДА обязывает контроллер их ограничивать в процессе их обслуживания. В то же время "софтвер маскинг" обозначало бы ручное управление разрешением/запретом конкретных прерываний. А вот "хардвер маскинг" обозначает "лазейку" типа BASEPRI или ещё более простую маскировку, но для 4 уровней от неё экономия будет незаметна.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.