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
bme280 bmp280 gps mpu-6050 options stm32 ssd1331 ssd1306 eb-500 3d-printer soldering tim mpu-9250 dma watchdog piezo exti web raspberry-pi docker ngnix solar bluetooth foc html css brushless flask dc-dc capture gpio avr rs-232 mpx4115a atmega mongodb st-link barometer pwm nvic git java-script programmator dht11 hih-4000 pmsm encoder max1674 smd sensors rtc adc lcd motor timer meteo examples i2c usb flash sms rfid python esp8266 servo books bldc remap eeprom bkp battery ethernet uart usart displays led websocket nodemcu wifi
Архіви