6. STM32. Программирование STM32F103. NVIC
NVIC (Nested vectored interrupt controller) - модуль контроля прерываний. Он выполняет следующие функции:
- разрешает / запрещает прерывание
- назначает приоритет прерываний (от 0 до 15. 0 - максимальной приоритет, 15 - минимальный приоритет)
- автоматически сохраняет данные при выполнении одиночных или вложенных прерываний.
Существуют прерывания приоритет которых изменить невозможно:
Номер | Прерывание | Приоритет | Описание |
---|---|---|---|
1 | Reset_Handler | -3(найвищий) | Reset |
2 | NMI_Handler | -2 | NMI переривання |
3 | HardFault_Handler | -1 | Аварійні стани |
The table below gives the allowed values of the pre-emption priority and subpriority according to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function ============================================================================================================================ NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description ============================================================================================================================ NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption priority | | | 4 bits for subpriority ---------------------------------------------------------------------------------------------------------------------------- NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption priority | | | 3 bits for subpriority ---------------------------------------------------------------------------------------------------------------------------- NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption priority | | | 2 bits for subpriority ---------------------------------------------------------------------------------------------------------------------------- NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption priority | | | 1 bits for subpriority ---------------------------------------------------------------------------------------------------------------------------- NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption priority | | | 0 bits for subpriority ============================================================================================================================В зависимости от того, какая группа установлена, будет доступно разное количество приоритетов и субприоритетив.
Приоритеты позволяют реализовать механизм вложенных прерываний, тогда как субприоритет определяют последовательность обработки прерываний с одинаковым приоритетом при одновременном срабатывании.
То есть, если мы установили NVIC_PriorityGroup_0, согласно таблице мы можем установить прерываниям только один приоритет NVIC_IRQChannelPreemptionPriority = 0 и назначить разным прерываниям субприоритет NVIC_IRQChannelSubPriority от 0 до 15. А это значит, что обработка прерываний не будет прерываться другим прерыванием, поскольку у всех одинаковый приоритет. А субприоритет NVIC_IRQChannelSubPriority определяет только последовательность обработки при одновременном срабатывании прерываний.
Если установим NVIC_PriorityGroup_1, мы можем одним прерываниям (более приоритетным) установить NVIC_IRQChannelPreemptionPriority = 0, а менее приоритетным NVIC_IRQChannelPreemptionPriority = 1. К тому же всем прерываниям мы можем установить субприоритет от 0 до 7, который определяет порядок обработки при одновременном поступлении прерываний с одинаковым приоритетом. В этом случае прерывания с приоритетом 0 (высоким) смогут прерывать обработку прерывания с приоритетом 1. А если одновременно возникнут прерывания с одинаковым приоритетом, то первым будет обработано то, у которого выше субприоритет. В предыдущей статье мы выполняли настройки прерывания USART1_IRQn следующим образом:
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
Как видим, мы установили
NVIC_IRQChannelPreemptionPriority = 0;
NVIC_IRQChannelSubPriority = 0;
В нашем примере работало только одно прерывание и нам было все равно, что мы укажем. Иногда случается так, что, когда прилетает какое-то очень важное прерывание, надо бросить все, даже если идет обработка не слишком важного прерывания, и быстро заняться тем, без обработки которого - просто конец. Кстати, я столкнулся с этим на контроллерах Atmega и я не смог решить эту проблему, потому что там не было приоритетов прерываний и, в конце концов, окончательно перешел на микроконтроллеры STM.
Давайте рассмотрим пример настройки двух прерываний с одинаковыми приоритетами и различными субприоритетамы:
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
В этом примере мы установили NVIC_IRQChannelSubPriority = 1; для EXTI0_IRQn. А это значит, что когда EXTI0_IRQn и USART1_IRQn произойдут одновременно, первым будет обработано USART1_IRQn. Но ни одно из этих прерываний не сможет прервать обработку другого, потому что у них одинаковый приоритет NVIC_IRQChannelPreemptionPriority = 0;
Теперь рассмотрим пример, когда EXTI0_IRQn и EXTI1_IRQn имеют больший приоритет и имеют право прервать обработку USART1_IRQn:
/* Set NVIC Priority Group */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
Мы установили NVIC_PriorityGroup_1. Согласно выше приведенной таблицы мы можем установить два приоритета. В данном случае различные субприоритеты логично устанавливать только для прерываний с одинаковым приоритетом. Что мы и сделали для EXTI0_IRQn и EXTI1_IRQn. Теперь EXTI0_IRQn или EXTI1_IRQn могут прервать обработку USART1_IRQn. Но не могут прервать обработку друг друга потому что у них одинаковый приоритет. А если EXTI0_IRQn и EXTI1_IRQn возникнут одновременно, тогда первым будет обработан EXTI0_IRQn - у него выше субприоритет.
Примерно так работают приоритеты прерываний в STM32.
Если вы считаете, что одновременное поступление прерываний вещь очень маловероятная, я Вас разочарую: это происходит чаще, чем Вы могли себе представить. Когда говорят об одновременном поступлении прерываний, имеется в виду не человеческое восприятие одновременности, как мы себе его представляем, а то, как это воспринимает микроконтроллер. Для микроконтроллера одновременное поступление происходит довольно часто. Например, вы в программе запретили обработку прерываний и Ваша программа что-то весьма важное довольно долго делала, а за это время поступило 3 различных прерывания. И вот вы разрешаете обработку прерываний. Микроконтроллер бросается обрабатывать их, а там торчит 3 флажки от прерываний. Для микроконтроллера это одновременное срабатывание прерываний. Такая же ситуация может произойти когда идет обработка прерывания и за это время поступает несколько других прерывания с таким же или меньшим приоритетом. После завершения обработки микроконтроллер видит несколько прерываний которые нужно обработать и для него это одновременное поступление прерываний.
P.S. Через NVIC можно задавать адрес таблицы векторов прерываний. См. функцию NVIC_SetVectorTable. Это нам понадобится значительно позже, если мы доберемся до своего bootloader-a.
Памятка
Все прерывания и их номера описаны в файле stm32f10x.h. Ищите typedef enum IRQn.Желаю успехов!
Смотри также:
- 1. STM32. Программирование STM32F103. Тестовая плата. Прошивка через последовательный порт и через ST-Link программатор
- 2. STM32. Программирование. IDE для STM32
- 3. STM32. Программирование STM32F103. GPIO
- 4. STM32. Программирование STM32F103. Тактирование
- 5. STM32. Программирование STM32F103. USART
- 6. STM32. Программирование STM32F103. NVIC
- 7. STM32. Программирование STM32F103. ADC
- 8. STM32. Программирование STM32F103. DMA
- 9. STM32. Программирование STM32F103. TIMER
- 10. STM32. Программирование STM32F103. TIMER. Захват сигнала
- 11. STM32. Программирование STM32F103. TIMER. Encoder
- 12. STM32. Программирование STM32F103. TIMER. PWM
- 13. STM32. Программирование STM32F103. EXTI
- 14. STM32. Программирование STM32F103. RTC
- 15. STM32. Программирование STM32F103. BKP
- 16. STM32. Программирование STM32F103. Flash
- 17. STM32. Программирование STM32F103. Watchdog
- 18. STM32. Программирование STM32F103. Remap
- 19. STM32. Программирование STM32F103. I2C Master
- 20. STM32. Программирование STM32F103. I2C Slave
- 21. STM32. Программирование STM32F103. USB
- 22. STM32. Программирование STM32F103. PWR
- 23. STM32. Программирование STM32F103. Option bytes
- 24. STM32. Программирование STM32F103. Bootloader
- STM32. Скачать примеры
- System Workbench for STM32 Установка на Ubuntu
- Keil uVision5 – IDE для STM32
- IAR Workbench – IDE для STM32
- Управление бесколлекторным двигателем постоянного тока (BLDC) с помощью STM32
- Управление PMSM с помощью STM32
Error: L6218E: Undefined symbol NVIC_Init (referred from main.o).
Какие варианты решения могут быть?
Заранее Спасибо
Додати коментар
Недавні записи
- 🇺🇦 FOC Board STM32F103RB 🧩
- STM32 Motor control SDK - керування оборотами мотора за допомогою потенціометра 📑
- Flask✙Gunicorn✙Nginx➭😎
- STM32 Motor control SDK - програмне керування обертами мотора
- STM32 Motor control SDK - як створити перший проект
- Vue SVG. Приклад побудови живого параметричного креслення
- Вимірювання моменту мотора
- Vue SVG - компонент. Приклад 📑
- Flask + Vue 🏁 Финальный пример 🏁
- Flask, CORS, JSON-файл. Пример#6
Tags
bldc brushless stm32 motor web html css flask atmega foc git java-script pmsm raspberry-pi python websocket mongodb esp8266 nodemcu st-link tim timer docker ngnix programmator ssd1331 ssd1306 wifi uart meteo bme280 bmp280 i2c gps mpu-6050 mpu-9250 sensors 3d-printer options usb barometer remap watchdog flash eeprom rtc bkp encoder pwm servo capture examples dma adc nvic usart gpio books battery dc-dc sms max1674 avr lcd dht11 piezo rs-232 rfid solar exti bluetooth eb-500 displays ethernet led smd soldering mpx4115a hih-4000
Архіви