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. Тестова плата. Прошивка через UART та через 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
Очень ясно и доходчиво) спасибо)
Велике Дякую. Нарешті розібрався.
Tags
web java-script bmp280 adc bldc stm32 rs-232 programmator 3d-printer flash pwm sms motor docker raspberry-pi meteo gps ngnix bme280 timer ssd1331 mpu-6050 bkp battery rfid st-link tim mpx4115a ssd1306 encoder atmega pmsm wifi options rtc examples nvic soldering mongodb esp8266 books lcd foc flask barometer bluetooth ethernet brushless uart watchdog servo gpio solar git remap dma usart eb-500 smd nodemcu sensors displays html python capture dht11 led i2c eeprom piezo exti websocket max1674 usb dc-dc avr hih-4000 css mpu-9250
Архіви