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
Очень ясно и доходчиво) спасибо)
Велике Дякую. Нарешті розібрався.
Недавні записи
- LCD Display ST7567S (IIC)
- Розпізнавання мови (Speech recognition)
- Selenium
- Комп'ютерний зір (Computer Vision)
- Деякі думки про точність вимірювань в електроприводі
- Датчики Холла 120/60 градусів
- Модуль драйверів напівмосту IGBT транзисторів
- Драйвер IGBT транзисторів на A316J
- AS5600. Варіант встановлення на BLDC мотор
- DC-DC для IGBT драйверів ізольований 2 W +15 -8 вольт
Tags
battery soldering java-script ngnix adc rs-232 flask esp8266 watchdog web exti solar mongodb rtc sms pwm usart books ethernet smd git websocket meteo css python dc-dc displays led ssd1306 eeprom gpio barometer max1674 mpx4115a brushless motor mpu-6050 timer sensors remap servo bldc atmega pmsm 3d-printer flash encoder examples dma raspberry-pi tim ssd1331 piezo mpu-9250 rfid eb-500 foc bme280 gps nvic dht11 bluetooth hih-4000 stm32 st-link docker uart avr html wifi bmp280 bkp nodemcu options usb lcd programmator i2c capture
Архіви