Помните, мы работали с операционной системой реального времени FreeRTOS? Вот эти статьи - ссылка. Там мы использовали микроконтроллеры STM32 серии STM32F10x, и вот теперь пришло время разобраться с работой FreeRTOS на контроллерах STM32F4. Собственно, приступаем к делу!
И для начала необходимо скачать архив с FreeRTOS. Текущей версией является версия 7.5.3, ее и скачиваем. Получаем стомегабайтный архив с кучей файлов, и сейчас будем разбираться, что же делать дальше.
Время традиционной вставки: поскольку компания STMicroelectronics прекратила поддержку библиотеки SPL, которая использовалась в этом курсе, я создал новый, посвященный работе уже с новыми инструментами, так что буду рад видеть вас там - STM32CubeMx. Кроме того, вот глобальная рубрика по STM32, а также статья на смежную тему из нового курса: STM32CubeMx. Быстрый старт с FreeRTOS для STM32.
Создаем в Keil'е новый проект. Я буду использовать плату STM32F4Discovery для экспериментов, поэтому выбрал при создании проекта контроллер STM32F407VG. Но принципиальной разницы тут нет. Создадим несколько папок для файлов проекта, например, вот так:
В папках CMSIS и SPL будут файлы соответствующих библиотек, в папки Source и Header я поместил все файлы, необходимые для использования FreeRTOS. Давайте смотреть, какие же это файлы. Итак, в скачанном архиве с FreeRTOS есть три папки:
Заходим в первую - Demo. Там куча папок, но нас интересует только одна, а именно - CORTEX_M4F_STM32F407ZG-SK. Берем из этой папки файл FreeRTOSConfig.h и копируем к нам в проект. На этом все, переходим дальше - а именно к папке Source. Из нее, а также из вложенной папки Include нам нужны абсолютно все файлы, а вот из папки portable лишь некоторые, заходим в эту папку:
Нам нужны две - RVDS и MemMang. В первой из них заходим в папку ARM_CM4F и забираем оба, имеющихся там файла. Из MemMang берем файл heap_2.c и его тоже копируем к нам в проект.
Вот, что мы получаем в итоге:
Кроме уже упомянутых файлов, тут есть файл main.c - в него мы поместим наш собственный код. Как раз его написанием сейчас и займемся. Только не забудьте добавить файлы из SPL и CMSIS в проект, я на этом останавливаться не буду, поскольку это уже далеко не первый наш проект для STM32F4, все есть в предыдущих статьях )
Итак, подключаем все нужные нам файлы:
/***************************************************************************************/ #include "stm32f4xx.h" #include "stm32f4xx_conf.h" #include "system_stm32f4xx.h" #include "portmacro.h" #include "FreeRTOSConfig.h" #include "FreeRTOS.h" #include "croutine.h" #include "task.h" #include "queue.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_rcc.h" /***************************************************************************************/
Сразу же объявляем переменные:
/***************************************************************************************/ GPIO_InitTypeDef port; uint32_t state; /***************************************************************************************/
Важным моментом является то, что нам необходимо определить некоторые функции, без которых проект не соберется. Сделать это нужно обязательно, пусть даже в данном примере это будут просто функции - "заглушки":
/***************************************************************************************/ void vApplicationIdleHook(void) { } /***************************************************************************************/ void vApplicationMallocFailedHook(void) { for(;;); } /***************************************************************************************/ void vApplicationStackOverflowHook(xTaskHandle pxTask, signed char *pcTaskName) { (void)pcTaskName; (void)pxTask; for(;;); } /***************************************************************************************/ void vApplicationTickHook(void) { } /***************************************************************************************/
Давайте в этом проекте создадим задачу, которая будет вызываться через равные промежутки времени и изменять состояние светодиода. Соответственно, этот светодиод, а точнее ножку контроллера, нам нужно настроить:
/***************************************************************************************/ void vFreeRTOSInitAll() { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); GPIO_StructInit(&port); port.GPIO_Mode = GPIO_Mode_OUT; port.GPIO_Pin = GPIO_Pin_12; port.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &port); } /***************************************************************************************/
Тут все понятно, обычная работа с портами ввода-вывода. Настраиваем вывод PD12 на работу в режиме выхода. Далее пишем код нашей задачи:
/***************************************************************************************/ void vLedTask(void *pvParameters) { while(1) { if (state == 0) { GPIO_SetBits(GPIOD,GPIO_Pin_12); state = 1; } else { GPIO_ResetBits(GPIOD,GPIO_Pin_12); state = 0; } } vTaskDelete(NULL); } /***************************************************************************************/
Осталось совсем немного, а именно функция main():
/***************************************************************************************/ int main() { vFreeRTOSInitAll(); xTaskCreate(vLedTask, (signed char*)"LedTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); vTaskStartScheduler(); } /***************************************************************************************/
Тут всего лишь вызываем функцию инициализации и создаем задачу, как и при использовании FreeRTOS для STM32F10x (ссылка на этот материал в самом начале сегодняшней статьи).
Теперь собираем проект и прошиваем микроконтроллер. В отладчике можно видеть, как меняется состояние светодиода. Собственно, это все, что я хотел сегодня рассказать, теперь мы можем использовать FreeRTOS и на контроллерах STM32F4!