interrupt priority что это

Interrupt priority что это

Примечание: информация в этой статье относится к вложенности приоритетов при использовании FreeRTOS на платформах Cortex-M3, Cortex-M4, Cortex-M4F и Cortex-M7. Она не относится к ядрам Cortex-M0 или Cortex-M0+ cores, в которых нет регистра BASEPRI.

[Доступные уровни приоритета]

[Приоритет вытеснения и субприоритет]

Большинство систем по умолчанию следует желаемой конфигурации, за исключением библиотеки драйверов STM32. Если Вы используете STM32 вместе с STM32 driver library, то убедитесь, что все биты приоритета назначены на биты preempt priority, путем вызова NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); перед запуском RTOS.

[Инверсная взаимосвязь числовых значений приоритетов]

Между нумерацией приоритетов аппаратуре Cortex-M и настройкой логической нумерации приоритетов FreeRTOS существует инверсная взаимосвязь. Если у Cortex-M чем меньше числовое значение приоритета прерывания, тем у него приоритет выше, то у FreeRTOS большему числовому приоритету задачи соответствует более высокий приоритет.

Это не интуитивный аспект приоритезации прерываний ARM Cortex-M, потому что не совпадает с большинством не ARM Cortex-M3 архитектур микроконтроллеров.

Приоритет прерывания Cortex-M по умолчанию равен 0. Это значит самый высокий логический приоритет. Таким образом, никогда не оставляете приоритет по умолчанию для ISR, который использует вызовы interrupt safe RTOS API.

[Внутреннее представление приоритетов Cortex-M]

У регистров приоритета Cortex-M всего есть место для максимум 8 бит приоритета. Если, в качестве примера, микроконтроллер реализует только 3 бита из этих восьми, то используются только 3 старшие бита:

На следующей картинке показано, как значение 5 (в двоичной форме 101) сохраняется в регистре приоритета прерывания микроконтроллера, в котором реализованы только 3 бита приоритета. Диаграмма показывает, почему значение 5 (двоичное 00000101) может рассматриваться как 191 (двоичное 10111111), когда 3 бита приоритета сдвинуты в требуемую позицию, и остальные биты установлены в 1:

На следующей картинке показано, как значение 5 (двоичное 101) сохраняется в регистре приоритета прерывания микроконтроллера, в котором реализованы 4 бита приоритета. Диаграмма показывает, почему значение 5 (двоичное 00000101) может рассматриваться как 95 (двоичное 01011111), когда 4 бита приоритета сдвинуты в требуемую позицию, и остальные биты установлены в 1:

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

Макросы настроек configMAX_SYSCALL_INTERRUPT_PRIORITY и configKERNEL_INTERRUPT_PRIORITY можно найти в файле FreeRTOSConfig.h. Необходимо, чтобы значения приоритетов в них были сдвинуты так, как того требует сама архитектура ядра ARM Cortex-M – они должны быть уже сдвинуты к самым старшим значащим битам байта. По этой причине configKERNEL_INTERRUPT_PRIORITY, которое должно быть установлено в самый низкий уровень приоритета, установлено в 255 (двоичное 11111111) хедера FreeRTOSConfig.h, поставляемого с каждым официальным демо FreeRTOS. Есть несколько причин, почему значение указанно таким способом: ядро RTOS обращается к аппаратуре ARM Cortex-M3 напрямую (без использования каких-либо библиотечных функций сторонних производителей), реализация ядра RTOS появилась раньше реализации большинства библиотечных функций, и эта схема использовалась первыми библиотеками ARM Cortex-M3, вышедшими на рынок.

[Критические секции]

BASEPRI это битовая маска. Установка BASEPRI в определенное значение маскирует все прерывания, у которых приоритет равен этому значению и ниже (логически). Поэтому нельзя использовать BASEPRI для маскирования прерываний, у которых приоритет 0.

Функции FreeRTOS API, которые безопасны для вызова из ISR, используют BASEPRI для реализации критических секций, безопасных для прерываний (interrupt safe critical sections). BASEPRI устанавливается в configMAX_SYSCALL_INTERRUPT_PRIORITY, когда происходит вход в критическую секцию, и в 0, когда происходит выход из критической секции. Получено множество сообщений об ошибках (bug report), которые утверждают, что BASEPRI должно быть возвращено в свое оригинальное значение при выходе, не просто установлено в 0, но Cortex-M NVIC никогда не примет прерывание, у которого (логический) приоритет ниже текущего выполняемого прерывания – независимо от того, что установлено в BASEPRI. Реализация, которая всегда устанавливает BASEPRI в 0, будет выполнять код быстрее, чем та реализация, которая сохраняет и затем восстанавливает значение BASEPRI (при включенном оптимизаторе компилятора).

Здесь в качестве примеров показаны назначения приоритетов прерываний блоков USART6 и Ethernet микроконтроллера STM32F407xx. Для упрощения здесь приведены только части заголовков и модулей, касающиеся только настройки приоритетов прерывания.

[FreeRTOSConfig.h]

Конфигурационный файл FreeRTOS:

[settings.h]

Мои настройки приоритета для прерываний аппаратуры USART6 и Ethernet:

[stm32f4xx_hal_usart.c]

Конфигурация приоритета прерываний приема USART6:

[ethernetif.c]

Конфигурация приоритета прерываний Ethernet:

Источник

interrupt priority

1 interrupt priority

приоритет прерываний
Характеристика важности, присваиваемая программным прерываниям. Как правило, система может одновременно обслуживать только одно прерывание, однако в некоторых случаях скорость поступления прерываний превышает скорость обслуживания. В подобной ситуации при помощи системных средств управления можно установить такие маски прерываний, которые будут подавлять некоторые прерывания при наличии более важных прерываний.
[Домарев В.В. Безопасность информационных технологий. Системный подход.]

Тематики

Тематики

2 interrupt priority

3 interrupt priority

4 interrupt priority

5 interrupt priority

6 interrupt priority

7 interrupt priority

8 interrupt priority

9 interrupt priority

10 interrupt priority

11 interrupt priority

12 interrupt priority

13 interrupt priority

14 interrupt level

15 приоритет прерывания

16 приоритет прерывания

См. также в других словарях:

Interrupt priority level — The interrupt priority level (IPL) is a part of the current system interrupt state, which indicates the interrupt requests that will currently be accepted. The IPL may be indicated in hardware by the registers in a Programmable Interrupt… … Wikipedia

Interrupt — This article is about computer interrupts. For the study of the effect of disruptions on job performance, see Interruption science. In computing, an interrupt is an asynchronous signal indicating the need for attention or a synchronous event in… … Wikipedia

Interrupt handler — An interrupt handler, also known as an interrupt service routine (ISR), is a callback subroutine in an operating system or device driver whose execution is triggered by the reception of an interrupt. Interrupt handlers have a multitude of… … Wikipedia

Priority inversion — In scheduling, priority inversion is the scenario where a low priority task holds a shared resource that is required by a high priority task. This causes the execution of the high priority task to be blocked until the low priority task has… … Wikipedia

Читайте также:  какой краской можно покрасить кирпич на балконе

Interrupt latency — In Realtime Operating Systems, Interrupt latency is the time between the generation of an interrupt by a device and the servicing of the device which generated the interrupt. For many operating systems, devices are serviced as soon as the device… … Wikipedia

Interrupt request — IRQ redirects here. For the country with the ISO 3166 1 country code, see Iraq. The computing phrase interrupt request (or IRQ) is used to refer to either the act of interrupting the bus lines used to signal an interrupt, or the interrupt input… … Wikipedia

interrupt controller — A chip used to process and prioritize hardware interrupts. In the PC, a programmable interrupt controller responds to each hardware interrupt, assigns a priority, and forwards it to the main processor. See also interrupt request … Dictionary of networking

priority — /praɪˈɒrəti / (say pruy oruhtee) noun (plural priorities) 1. the state of being earlier in time, or of preceding something else. 2. precedence in order, rank, etc. 3. the having of certain rights before another. 4. Computers the position in rank… … Australian-English dictionary

Programmable Interrupt Controller — A Programmable Interrupt Controller (PIC) is a device which allows priority levels to be assigned to its interrupt outputs. When the device has multiple interrupt outputs to assert, it will assert them in the order of their relative priority.… … Wikipedia

Advanced Programmable Interrupt Controller — In computing, an Advanced Programmable Interrupt Controller (APIC) is a more complex Programmable Interrupt Controller (PIC) than Intel s original types such as the 8259A. APIC devices permit more complex priority models, and Advanced IRQ… … Wikipedia

End of interrupt — An End Of Interrupt (EOI) is a signal sent to a Programmable Interrupt Controller (PIC) to indicate the completion of interrupt processing for a given interrupt. An EOI is used to cause a PIC to clear the corresponding bit in the In Service… … Wikipedia

Источник

Начинаем изучать Cortex-M на примере STM32, часть 2

Данная статья является продолжением цикла по программированию микроконтроллеров на базе ядра Cortex-M.
Первую статью можно прочитать здесь:
Начинаем изучать Cortex-M на примере STM32
Задачей статей является подробное описание особенностей, возникающих при программировании МК. Материал не предназначен для желающих за 10 минут запустить пример мигания светодиодом. Я постараюсь подробно описать то, что часто скрывают от новичков, чтобы их не напугать.

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

Основной акцент сделан на изучение документации на ядро Cortex-M и документации на конкретный контроллер.
На этот раз речь пойдет про прерывания, а так же будут затронуты некоторые вопросы архитектуры памяти и структуры прошивки МК.

Несколько слов про документацию ARM

По не совсем ясным для меня причинам, нельзя зайти на сайт ARM и скачать полную документацию на ядро Cortex-M4. Да и на Cortex-M3 тоже нельзя.
Придется почитать несколько документов.
1. Изучение придется начать с Cortex ™-M3 TechnicalReference Manual Revision: r1p1 — самой первой ревизии технической спецификации на ядро Cortex-M3
2. Во всех дальнейших ревизиях и описании Cortex ™-M4 TechnicalReference Manual описаны лишь общие данные и изменения относительно предыдущего документа.
Так что прошу не удивляться ссылкам на спецификации другого ядра.

Interrupt and Events

Прежде всего необходимо разобраться с тем, что такое прерывания.
В МК Cortex-M есть два понятия, которые часто путают Interrupt и Event.
Event — это событие (аппаратное или программное), на которое могут реагировать ядро или периферийные блоки. Одним из вариантов реакции может быть — прерывание.
Interrupt — это прерывание работы программы и переход управления в специализированный участок обработчик прерывания.

Взаимосвязь между Event и Interrupt заключается в следующем:
Каждый Interrupt вызывается Event, но не каждый Event вызывает Interrupt.
Помимо прерываний, события могут активировать и другие возможности МК.

Управление и обработка прерываниями производится контроллером приоритетных векторных прерываний NVIC (Nested Vectored Interrupt Controller). Контроллер прерываний часть ядра Cortex-M. Документацию на этот контроллер необходимо начинать изучать с Cortex ™-M3 TechnicalReference Manual Revision: r1p1

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

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

Как это работает?

Данный пост не претендует на абсолютную полноту, я советую изучить раздел прерываний в Cortex™-M3 Technical Reference Manual. Поскольку эта часть ядра не претерпела изменений, ее описание дано в первой ревизии r1p1 на ядро Cortex-M3.

Вход в прерывание и выход из него

При инициации прерывания NVIC переключает ядро в режим обработки прерывания. После перехода в режим обработки прерывания регистры ядра помещаются в стек. Непосредственно во время записи значения регистров в стек осуществляется выборка начального адреса функции обработки прерывания.

В стек перемещается регистр регистр статуса программы ( Program Status Register (PSR)), счетчик программы (Program Counter (PC)) и регистр связи (Link Register (LR) ). Описание регистров ядра приведено в Cortex-M4 Generic User Guide. Благодаря этому, запоминается состояние, в котором находилось ядро перед переходом в режим обработки прерываний.

Также сохраняются регистры R0 — R3 и R12. Эти регистры используются в инструкциях для передачи параметров, поэтому, помещение в стек делает возможным их использование в функции обработки прерывания, а R12 часто выступает в роли рабочего регистра программы.

По завершении обработки прерывания все действия выполнятся в обратном порядке: извлекается содержимое стека и, параллельно с этим, осуществляется выборка адреса возврата.

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

Вложенность прерываний

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

Читайте также:  какой клуб открыт сейчас

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

2. Непрерывная обработка прерываний
Эта ситуация может возникнуть в двух случаях: если два прерывания имеют одинаковый приоритет и возникают одновременно, если низкоприоритетное прерывание возникает во время обработки высокоприоритетного.
В этом случае, промежуточные операции над стеком не производятся. Происходит только загрузка адреса обработчика низкоприоритетного прерывания и переход к его выполнению. Отказ от операций над стеком экономит 6 тактов. Переход к следующему прерыванию происходит не за 12 тактов, а всего за 6.

3. Запаздывание высокприоритетного прерывания
Ситуация возникает, если высокоприоритетное прерывание происходит во перехода к обработке низкоприоритетного (за те самые 12 тактов). В этом случае переход к высокоприоритетному прерыванию будет происходить не менее 6 тактов с момента его возникновения (время необходимое для загрузки адреса обработчика прерывания и перехода к нему). Возврат в низкоприоритетное уже описан выше.

Приоритеты прерываний

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

Значение приоритета прерывания задается в регистрах Interrupt Priority Registers (см. Cortex-M4 Generic User Guide). При этом, часть бит отвечает за приоритет группы, в которой находится прерывание, а часть — за приоритет внутри группы.
Настройка распределение бит на приоритет группы или приоритет внутри группы осуществляется с помощью регистра Application Interrupt and Reset Control Register (ВНИМАТЕЛЬНО. см. Cortex-M4 Generic User Guide).

Как вы, наверно, заметили, в Cortex-M4 Generic User Guide сказано, что настройка приоритетов и группировки приоритетов зависят от конкретной реализации implementation defined.
А вот дальше не очень приятная вещь. В Reference manual к МК STM32F407 про NVIC почти нет информации. Но есть ссылка на отдельный документ. Для того, чтобы разобраться с реализацией NVIC в STM32 придется прочитать еще один документ — STM32F3xxx and STM32F4xxx Cortex-M4 programming manual. Вообще говоря, я советую внимательно изучить данный документ и по всем другим вопросам, в нем работа ядра расписана более подробно, чем в документации от ARM.
В нем, уже можно найти:

A programmable priority level of 0-15 for each interrupt. A higher level corresponds to a
lower priority, so level 0 is the highest interrupt priority

Из возможных 8 бит приоритета используются только 4. Но этого вполне достаточно для большинства задач.

Маскирование прерываний

Предположим, что у нас стоит задача запуска ракеты-носителя при нажатии на красную кнопку, но только при условии, что повернут ключ.
Нет совершенно ни какого смысла генерировать прерывание на поворот ключа. А вот прерывание на нажатие красной копки нам понадобится. Для того, чтобы включать/выключать различные вектора прерываний, существует маскирование прерываний.
Маскирование прерывания осуществляется с помощью регистров Interrupt Set-enable Registers.
Если прерывание замаскировано, это не означает, что периферия не генерирует события! Просто NVIC не вызывает обработчик этого события.

Таблица векторов прерываний

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

Расположение векторов прерываний и загрузка МК

• stack top address
• reset routine location
• NMI ISR location
• Hard Fault ISR location.

Из начала флеш памяти ядро считывает значение SP (stack top addres) и PC (reset routine location). Таким образом, автоматически начинает выполняться функция, с адресом считанным в регистр PC. Это может быть, например main.

После обязательных четырех компонентов, может находиться дальнейшая таблица векторов прерываний. Главное сохранить порядок.
При желании, можно разместить таблицу векторов прерываний в другой области памяти, но тогда, необходимо сообщить NVIC, куда мы передвинули таблицу. За это смещение таблицы векторов отвечает регистр Vector Table Offset Register (см. Cortex-M4 Technical Reference Manual. Это может понадобиться для написание встроенного загрузчика нового ПО (bootloader), но об этом как-нибудь в другой раз.

От теории к практике

ТЗ второго проекта

Пример создается для отладочной платы STM32F4Discovery.
При нажатии на кнопку должен загореться светодиод LED3. При замыкании контактов PC6 и GND загорается светодиод LED5.
В процессе программирования поиграемся с приоритетами прерываний и посмотрим к чему это приведет.

Железная часть

Найдем в документации к плате кнопку и светодиод:

При ненажатой кнопке на пине PA0 будет логический ноль, при нажатии на кнопку на кнопке появится логическая 1 (3.3В).
Светодиод LED3 подключен к пину PD13.
Светодиод LED5 подключен к пину PD14.
Интересней всего с контактом PC6 — он напрямую выведен на штыревой разъем. Нам будет необходимо обеспечить регистрацию логической 1, когда он не закорочен с контактом GND. О том, как это сделать пойдет речь ниже.

Настройка GPIO

Для нашей задачи необходимо настроить пины PD13 и PD14 как выходные. О том, как это делать можно прочитать в предыдущей статье.
С настройкой пина PA0 тоже все достаточно просто — его нужно настроить на вход. Не смотря на то, что после ресчета МК почти все пины настроены на вход, крайне желательно явно прописать эту инициализацию.
С пином PC7 все несколько интереснее. Поскольку он «висит в воздухе», его состояние не определено. Нам же необходимо, чтобы при этом его состояние всегда было «1». Для этого, в блоке GPIO активировать подтяжку. В нашем случае, необходима подтяжка к питанию — PULL UP.
Активация подтяжки осуществляется с помощью регистра GPIO port pull-up/pull-down register.

Прерывания EXTI

Для выполнения нашего «ТЗ» с использованием прерываний, нам необходимо настроить прерывания, которые будут срабатывать при переходе контакта PA0 из состояния «0» в состояние «1», и прерывание при переходе контакта PC6 из состояния «1» в состояние «0».

Hardware interrupt selection
To configure the 23 lines as interrupt sources, use the following procedure:
• Configure the mask bits of the 23 interrupt lines (EXTI_IMR)
• Configure the Trigger selection bits of the interrupt lines (EXTI_RTSR and EXTI_FTSR)
• Configure the enable and mask bits that control the NVIC IRQ channel mapped to the external interrupt controller (EXTI) so that an interrupt coming from one of the 23 lines can be correctly acknowledged.

Нам понадобятся 0 и 6 линии EXTI. Для размаскирования соответствующих линий прерываний необходимо записать в регистр EXTI_IMR значение 0x9.
Для линии PA0, необходима генерация события прерывания по переходу из состояния «0» в состояние «1» — по возрастающему фронту. То есть, необходимо записать 1 в нулевой бит регистра EXTI_RTSR.
Для линии PC6, наоборот, необходима генерация события прерывания по переходу из состояния «1» в состояние «0» — по падающему фронту. То есть, необходимо записать 1 в шестой бит регистра EXTI_FTSR.
На этом настройка блока EXTI закончена. Последний пункт будет реализован при настойке NVIC.

Читайте также:  какой ориентации листа не существует

По мимо этого, необходимо определиться, пин с какого порта подключается к определенной линии EXTI. Делается это с помощью регистров SYSCFG external interrupt configuration register (Reference manual). Эти регистры находятся в System configuration controller, что мне кажется не очень логичным (почему было не включить эту насторойку в EXTI?), но оставим сей факт на совести ST.

Настройка NVIC

Активация обработки определенного вектора прерывания осуществляется с помощью регистров Interrupt set-enable registers (NVIC_ISERx). Описание регистров приведено в Cortex-M4 Generic User Guide. Сама таблицу векторов прерываний для нашего МК приведена в Reference manual (см. Table 61).

Из таблицы можно увидеть, что для 0 линии есть отдельное прерывание, а вот линии с 5 по 9 генерируют одно прерывание на всех.
Кроме того, из таблицы мы узнали номера векторов, необходимых нам прерываний. Теперь нужно записать «1» в 6 бит (активация прерываний линии 0 EXTI) регистра NVIC_ISER0 (адрес 0xE000E100) и в 23 бит того же регистра (активация прерываний линий 5-9).

Настройка приоритетов

Для того, чтобы можно было побаловаться с приоритетами прерываний настроим группы приоритетов так, чтобы 2 бита отвечали за приоритет внутри группы, и 2 бита — за приоритет самой группы. Для этого необходимо записать значение 0х05FA0500 в регистр Application interrupt and reset control register (STM32F3xxx and STM32F4xxx Cortex-M4 programming manual).
Настройка приоритетов осуществляется с помощью регистров Interrupt Priority Registers (STM32F3xxx and STM32F4xxx Cortex-M4 programming manual). Нас будут интересовать регистры Interrupt Priority Register 2 (0xE000E4008) и регистр Interrupt Priority Register 5(0xE000E401C).
Пока не будем изменять приоритеты. Пусть будут одинаковы для обоих прерываний.

Обработка прерываний

Функции обработчики прерываний — ни что иное, как просто функции языка C, который ни чего не получают и не возвращают (и правильно — не от кого и не кому).
Главное правило — обработка прерываний должна осуществляться как можно быстрее. Иначе низкоприоритетные прерывания могут слишком долго ждать.

Если с обработкой прерывания линии 0 EXTI все достаточно просто, то с группой линий 5-9 возникает вопрос — как определить какая линия вызвала прерывание. Узнать это можно проверкой бит регистра Pending register (EXTI_PR) — Reference manual.

Создаем таблицу векторов и располагаем ее в правильном месте

Использование
Располагает таблицу __vector_table в начале секции, объявленной в файле линкера. Сам файл можно посмотреть тут:

Сама секция задается в начале ROM памяти. Адреса можно посмотреть тут (документ, в котором описана адресация флеш памяти STM32):

Комбинация директивы IAR и спецфункции IAR:
Записывает в начале флеша указатель на верхушку стека.

Саму таблицу заполняют адреса функций, реализующий вечный цикл. Исключение сделано только для интересующих нас функций:

В функции, вызываемой при старте, просто производится переход к
Это функция — main(). Сам символ можно переопределить, если возникнет желание:

Переходим к основному файлу

Обратите внимание на то, что значения спецрегистров МК объявлены как volatile. Это необходимо, чтобы компилятор не пытался оптимизировать операции обращения к ним, поскольку это не просто участки памяти и их значения могут изменяться без участия ядра.

Настраиваем группирование приоритетов

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

Включение тактирование используемой периферии

Напомню, что перед началом работы с периферийными блоками необходимо включить их тактирование:

Работать сразу с SYSCFG нельзя, нужно подождать несколько тактов. Но мы и не будем. Займемся инициализацией GPIO.

Инициализация GPIO

Светодиоды инициализируются так же как и в прошлый раз:

Кнопка PA0 и контакт PC7 инициализируются как входные:

Вот только для контакта PC6 необходимо включить подтяжку питания. Активация подтяжки производится с помощью регистра GPIOC_PUPDR:

Настройка EXTI

И так, на нужно настроить следующие параметры — включить прерывания для линий 0 и 6, для линии 0 прерывание по растущему фронту, для линии 6 — прерывание по падающему фронту:

Осталось настроить пины каких портов подключены к линии EXTI (странное решение, например МК stellaris могут генерировать прерывание при любой комбинации пинов, у STM32 с этим сложнее):

Настройка NVIC

Осталось настроить приоритеты прерываний и маскировать их для инициации обработки. Обратите внимание, что регистры NVIC_IPR доступны для побайтового обращения, что значительно упрощает доступ только к необходимым байтам приоритетов отдельных векторов прерываний. Достаточно только сделать сдвиг на величину номера вектора прерывания (см. листинг определений). Еще раз напомним, что EXTI Line 0 имеет 6 номер в таблице векторов, а EXTI line 5_9 — номер 23. У STM32 значение имеют только старшие 4 бита приоритета:

Для демонстрации приоритеты установлены различными.
Теперь можно включить прерывания:

С этого момента нажатие на кнопку и закоротки PC6 и GND будет приводить к вызову функций обработчиков прерываний EXTI_Line0_IntHandler и EXTI_Line6_IntHandler соответственно.

Обработка прерываний

В функциях обработки прерываний в первую очередь необходимо очистить прерывание, после этого можно зажечь светодиоды. Для демонстрации приоритетов прерываний в один из обработчиков добавлен вечный цикл. Если приоритет прерывания с вечным циклом ниже приоритета второго — то оно не сможет быть вызвано. Иначе, оно сможет прервать первое. Я предлагаю вам самим попробовать различные знчения приоритетов прерываний и наглядно увидеть к чему это приводит (ВНИМАНИЕ — не забудьте про группы прерываний!).

Источник

Сказочный портал