onfig (NVIC_PriorityGroup_4);
Правила обробки переривання без поділу на підгрупи:
виклик переривання з більш високим пріоритетом призупиняє виконання поточного обробника;
- виконання функції обробки переривання не може бути перервано викликом з тим же або більш низьким рівнем пріоритету;
при одночасному виклику кілька переривань будуть оброблені в порядку пріоритету, при однаковому пріоритеті за зростанням номера переривання (порядкові номери задаються у файлі STM32F4xx. h);
У нашому проекті задаємо наступні пріоритети переривань (0-означає максимально можливий пріоритет):
) переривання отримання даних від модуля Sim900 по USART_2 (файл Sim900. c) _InitStructure. NVIC_IRQChannelPreemptionPriority=0;
) переривання таймера TIM3 запуску перетворень АЦП (після закінчення встановленої витримки часу відбувається переривання, у програмі переривання виконується запуск перетворення, установка пріоритету у файлі ADC. c) _InitStructure. NVIC_IRQChannelPreemptionPriority=4;
) переривання при отриманні даних по USB (файл usb_bsp. c) _InitStructure. NVIC_IRQChannelPreemptionPriority=0;
) переривання після натискання кнопок, і управлінню з брелока (файл app. c) _InitStructure. NVIC_IRQChannelPreemptionPriority=4;
Найнижчий пріоритет у переривань TIM3 і переривань після натискання кнопок, і ці переривання мають однаковий пріоритет, щоб вони не припиняли один одного. А найвищі пріоритети мають обробники переривань по USB - при програмуванні конфігурації пристрою та отримання повідомлення по Sim900. Такі настройки вибрані тому що самими пріоритетними завданнями є конфігурування пристрою по USB, при цьому передача інформації між ПК і МК не повинно перериватися низькопріоритетне перериваннями, і отримання повідомлень по GSM зв'язку яке виконуватиме управління сигналізацією.
Пріоритет завдань не має ніякого відношення до пріоритету переривань. Завдання не виконуються під час виконання обробників переривань. Ядро FreeRTOS дозволяє за допомогою макросредства config MAX_SYSCALL_INTERRUPT_PRIORITY задати найбільший пріоритет переривання, з обробника якого можна викликати API функції FreeRtos. Що-б захистити виконання поточного коду завдання від переривань використовуються критичні секції - це ділянки коду, під час виконання якого заборонені переривання процесора, і не відбувається переривання контексту кожен квант часу, а також заборонено переривання системного таймера SysTick.
Визначимо в нашому проекті
# define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 3
т.е. на всі переривання з пріоритетом до 3 (це переривання USB і переривання отримання інформації модулем Sim900) не впливають критичні секції, так що нічого що робить ядро ??в поточний момент, не завадить виконанню поточного обробника. Наприклад в задачі" LED1 виконується ініціалізація Sim900 наступним чином:
vTaskLED1 (void * pvParameters)
{_ CRITICAL ();// Входжу в критичну секцію_Sim900 (2,4,0);// Передаємо дві команди AT_Sim900 (0,1,0);// Передаємо команду відключення еха_Sim900 (8,13,0);// Включаємо текстовий режім_CRITICAL ();// Виходимо з критичної секції
..........
}
У наведеному вище прикладі при вході в критичну секцію - коли виконується ініціалізація SIM900 забороняємо переривання по TIM3 (запуску АЦП перетворення), і переривання брелока. Також критичні секції використовуються при відправці SMS повідомлення (задача OtpravSms ) - у цей момент виконується послідовність з декількох команд переривати виконання яких не можна.
.4 Функції обробників переривань
Розглянемо деякі фрагменти коду для декількох функцій обробників переривань (файл stm32fxxx_it. c):
) Переривання по таймеру виконуються кожні 2,5 мілісекунди, в обробнику переривання виконується аналіз становища ключів мультиплексора каналів сигналізації, і залежно від поточного положення перемикаються мультиплексори на наступні входи. Після того як завершиться кожне перетворення АЦП, DMA зберігає значення напруг по каналах в глобальному масиві (оголошеному в app. C): __IO uint16_t ADC3ConvertedValue [16]. Таким чином повний цикл вимірів по всіх каналах завершиться після чотирьох перетворень 4 * 2.5=10 мсек.
TIM3_IRQHandler (void)
{
......... (DMA_GetCurrDataCounter (DMA2_Stream0) == 0x10)//масив порожній
{ gt; BSRRH=GPIO_BSRR_BS_7;// Перемикаємо мультиплексор gt; BSRRH=GPIO_BSRR_BS_8;