Top.Mail.Ru

STM32 и FreeRTOS. Быстрый старт для микроконтроллера STM32F4.

Помните, мы работали с операционной системой реального времени 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 есть три папки:

FreeRTOS

Заходим в первую - Demo. Там куча папок, но нас интересует только одна, а именно - CORTEX_M4F_STM32F407ZG-SK. Берем из этой папки файл FreeRTOSConfig.h и копируем к нам в проект. На этом все, переходим дальше - а именно к папке Source. Из нее, а также из вложенной папки Include нам нужны абсолютно все файлы, а вот из папки portable лишь некоторые, заходим в эту папку:

Использование FreeRTOS

Нам нужны две - RVDS и MemMang. В первой из них заходим в папку ARM_CM4F и забираем оба, имеющихся там файла. Из MemMang берем файл heap_2.c и его тоже копируем к нам в проект.

Вот, что мы получаем в итоге:

Проект для FreeRTOS

Кроме уже упомянутых файлов, тут есть файл 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!

Подписаться
Уведомить о
guest

50 комментариев
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии
INA
INA
10 лет назад

Добрый вечер!
Ещё раз большое Вам спасибо за очень хорошие статьи!
Я опять к Вам за помощью. 😉
Прочёл две статьи:
http://we.easyelectronics.ru/electro-and-pc/stm32-uip-enc28j60.html
http://we.easyelectronics.ru/MrMisha/webserver-na-stm32enc28j60uiprtos.html
http://zeroelectronics.ru/practics/enc28j60-uip-na-stm32.html

Вроде всё написано просто и доходчиво.
Но при практической сборке проекта он (проект) опять-таки выдаёт кучу ошибок.
В Ваших статьях не упущены важные моменты, поэтому по ним учиться гораздо проще и понятнее.
Не могли бы Вы написать статью и про подключение ENC28J60 и uIP к уже созданному проекту STM32F4 + FreeRTOC?

INA
INA
10 лет назад

Ок!
Я пока попытаюсь с этим разобраться.
Может что-нибудь получится. 🙂

Nemo
Nemo
10 лет назад

Жаль в FreeRTOS нет "abstract device drivers" как в ChibiOS/RT

http://www.chibios.org/dokuwiki/doku.php

INA
INA
10 лет назад

Запустил uIP в связке с ENC28J60 и FreeRTOS на STM32F407IG. Девайс пингуется, WEB интерфейс из примера тоже работает. Следующая задача - научиться управлять девайсом через WEB. Хотя бы просто по-включать - по-выключать светодиоды.

INA
INA
10 лет назад

Ок!
Пока собираю платку для нормального теста и отладки. На проводках уже стало не удобно.

FreshMan
FreshMan
10 лет назад

мне вот как простому обывателю весьма интерестно, зачем на такой шустренький МК ставить ОС ?
ведь там и так есть где конем разгулятся )))
растолкуйте, пАжалуйста )))

Nemo
Nemo
10 лет назад

1.Проще писать и оталживать и поддерживать код в большых проэктах.
2. Проще,понятние и мощнее программа написана с исользованием RTOS:
например опрос клавыатруры,вывод на дисплей, Wi-Fi, Ethernet, карта памяти, опрос датчиков и управление исполнительными устройствами.

INA
INA
10 лет назад

Собрал платку, запустил IP стек от LifeLover-а (пришлось немного переделать под STM32), помигал светодиодом... В общем, первоначальная задача выполнена. Теперь хочу сделать полноценный WEB интерфейс для управления и мониторинга портов процессора. Универсальный модуль для удалённого управления какими-нибудь устройствами или механизмами и получения информации о их состоянии.

Alexander
Alexander
10 лет назад

Сделал всё как описано, но при компиляции port.c выдаёт ошибку:
Source\port.c(671): error: #20: identifier "SystemCoreClock" is undefined.
При этом SystemCoreClock в файле FreeRTOSConfig.h определён\---- #ifdef __ICCARM__
#include
extern uint32_t SystemCoreClock;
#endif
Подскажите пожалуйста.

INA
INA
10 лет назад

#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 1
//#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configCPU_CLOCK_HZ ( ( unsigned long )168000000)
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
//#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )
//#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75 * 1024 ) )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 18 * 1024 ) )
//#define configMAX_TASK_NAME_LEN ( 10 )
#define configMAX_TASK_NAME_LEN ( 16)
//#define configUSE_TRACE_FACILITY 1

Алексей
Алексей
10 лет назад

У меня такая же проблема с port c (..\FreeRTOS\Source_Files\port.c(671): error: #20: identifier "SystemCoreClock" is undefined). Пока не разобрался. Если кто в курсе, то буду благодарен за помощь

Алексей
Алексей
10 лет назад

Прописал в файле port.c выше написанный код. Проект компилится, прошивается, светодиод загорается, и больше ничего не происходит, никакой реакции на нажатие кнопки и тому подобное... Заранее благодарю за ответ!

Алексей
Алексей
10 лет назад

Немного ошибся с файлом. Надо было внести изменения в файл FreeRTOSConfig.h как написано выше. Все компилится и загружается, но светодиод по прежнему горит статично и не моргает (

Алексей
Алексей
10 лет назад

Буду очень признателен, если кто-то поделится готовым рабочим проектом FreeRTOS+STM32F4DISCOVERY (мигание светодиодом)!!!! Плиз!!! 😉

INA
INA
10 лет назад

Если у Вас всё компилится, то нужно создать саму задачу Task мигания светодиодом, а потом запустить шедулер. Перед функцией бесконечного цикла (for(;;)). Это делается в основном файле проекта (а вообще, кому как больше нравится).

Алексей
Алексей
10 лет назад

Я сделал все так как написано в этой статье. Все компилится, но светодиод не горит и никак не реагирует. Хм... Интересно, в чем же загвоздка?

Алексей
Алексей
10 лет назад

Просьба к автору выложить архив проекта. Было бы очень здорово!!! -;)

Артур
Артур
10 лет назад

У меня светодиод горит, но не мигает . Может быть это из-за того что мы не выставили период мигания? Как и где лучше это задать ? Заранее благодарю.

Артур
Артур
10 лет назад

Может быть проблема в том, что мы не установили период мигания диодами? У меня проект запустился , но тоже не мигают.

Алексей
Алексей
10 лет назад

Гутен морген! Вот можно поморгать через такую функцию

void Delay(uint32_t a) //Функция задержки
{
uint32_t i;
for (i=0; iBSRRL = GPIO_BSRR_BS_12; // Установили на выводе 1
Delay(3000000);
GPIOD->BSRRH = (GPIO_BSRR_BR_12 >> 16);// Установили 0
Delay(3000000);
}
vTaskDelete(NULL);
}

Алексей
Алексей
10 лет назад

Текст неправильно отформатировался

Алексей
Алексей
10 лет назад
Алексей
Алексей
10 лет назад

Что за фигня с отображением комментариев? Короче, пишите e-mail, сброшу на почту

INA
INA
10 лет назад

функция мигания светодиодом...
void vTask_led0(void *pvParameters)
{
for (;;)
{
GPIO_ToggleBits(GPIOA,led0);
vTaskDelay(200);
}
}

создаём задачу мигания светодиодом...
xTaskCreate( vTask_led0, ( signed char * ) "led0", configMINIMAL_STACK_SIZE*2, NULL, 1, ( xTaskHandle * ) NULL);

запускаем шедулер...
vTaskStartScheduler();

Антон Бауер
Антон Бауер
10 лет назад

в демо примере платы STM32F3 Discovery в main.c есть такие строки:
/** @addtogroup STM32F3-Discovery_Demo
* @{
*/
что это за колдовство в комментариях? объясните начинающему, пожалуйста...

Антон Бауер
Антон Бауер
10 лет назад

вообще не похоже, ну да бох с ним.
спасибо за ответ, в любом случае.
Еще хотел спросить, компилятор выдает
Error: L6218E: Undefined symbol assert_param (referred from stm32f30x_rcc.o).
и много предупреждений вроде все файлы подключил вроде:
..\..\Libraries\STM32F30x_StdPeriph_Driver\src\stm32f30x_spi.c(1337): warning: #223-D: function "assert_param" declared implicitly
в компиляторе с99 тоже задействовал..
что ему не так, а?

Антон Бауер
Антон Бауер
10 лет назад

Действительно, все работает. Спасибо!

avgustmen
avgustmen
10 лет назад

Приветствую. Работаю в Eclipse.
Вставил в main функции-заглушки:
void vApplicationIdleHook( void )
void vApplicationMallocFailedHook( void )
void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )
void vApplicationTickHook( void )

но при сборке проекта выдаются ошибки:

/Users/Alexey/Documents/workspace/probeFreeRTOS/Release/../libs/freeRTOS/src/heap_2.c:228: undefined reference to `vApplicationMallocFailedHook'
./libs/freeRTOS/src/tasks.o: In function `prvIdleTask':
/Users/Alexey/Documents/workspace/probeFreeRTOS/Release/../libs/freeRTOS/src/tasks.c:2196: undefined reference to `vApplicationIdleHook'
./libs/freeRTOS/src/tasks.o: In function `xTaskIncrementTick':
/Users/Alexey/Documents/workspace/probeFreeRTOS/Release/../libs/freeRTOS/src/tasks.c:1717: undefined reference to `vApplicationTickHook'
/Users/Alexey/Documents/workspace/probeFreeRTOS/Release/../libs/freeRTOS/src/tasks.c:1730: undefined reference to `vApplicationTickHook'
./libs/freeRTOS/src/tasks.o: In function `vTaskSwitchContext':
/Users/Alexey/Documents/workspace/probeFreeRTOS/Release/../libs/freeRTOS/src/tasks.c:1871: undefined reference to `vApplicationStackOverflowHook'
/Users/Alexey/Documents/workspace/probeFreeRTOS/Release/../libs/freeRTOS/src/tasks.c:1872: undefined reference to `vApplicationStackOverflowHook'

Не могу понять почему функции-заглушки не видны из main при сборке проекта. Прошу дать подсказку.

avgustmen
avgustmen
10 лет назад

Не помогло:
закомментировал строки в tasks.c в которых определяется функция обработки установок, описанных в FreeRTOSConfig.h.
Например, для #define configUSE_IDLE_HOOK 1 в tasks.c было:

#if ( configUSE_IDLE_HOOK == 1 )
{
extern void vApplicationIdleHook( void );

vApplicationIdleHook();
}
#endif /* configUSE_IDLE_HOOK */
стало:

#if ( configUSE_IDLE_HOOK == 1 )
{
extern void vApplicationIdleHook( void );
//Моя правка строчка ниже закомментирована
//vApplicationIdleHook();
}
#endif /* configUSE_IDLE_HOOK */

Так же сделал configUSE_TICK_HOOK 1 в tasks.s и configUSE_MALLOC_FAILED_HOOK 1 в heap_2.c.

проблема с неверной ссылкой на vApplicationStackOverflowHook не решена. При определении в task.c:

extern void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName );

выдает ошибку:

In file included from ../src/main.cpp:6:0:
../libs/freeRTOS/include/task.h:68:44: error: variable or field 'vApplicationStackOverflowHook' declared void
extern void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName );
^
../libs/freeRTOS/include/task.h:68:44: error: 'xTaskHandle' was not declared in this scope
../libs/freeRTOS/include/task.h:68:64: error: expected primary-expression before 'signed'
extern void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName );
^

Максим
Максим
10 лет назад

Добрый день, Aveal,
Есть интересная длительная работа по STM32F4 в Москве
Подробности в почту.
Приличные подборки статей.
Пишите

Alex_Bariskin
Alex_Bariskin
10 лет назад

Спасибо за статью, всё запустил, для пущей наглядности сделал несколько разных "taskов" думаю как это реально с пользой применить.

Александр
Александр
9 лет назад

Возможно кому-то пригодится еще....
Нужно в конце FreeRTOSConfig.h привязать диспетчер к прерыванию таймера.
Мой кусок конфига
..........................................................
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

#endif /* FREERTOS_CONFIG_H */

Николай
Николай
9 лет назад

Всё сделал, всё работает на f4Discovery, только вопрос к Aveal - почему если:
configCPU_CLOCK_Hz = 168000000(168 мГц тактовая), а TICK_RATE_HZ = 1000 (1мс выходит), то при выставлении допустим TaskDelay(500) вот так:

void vLedTask (void *pvParameters)
{
while(1)
{
if (state == 0)
{
GPIO_SetBits(GPIOD,GPIO_Pin_12);
state = 5;
}
else
{
GPIO_ResetBits(GPIOD,GPIO_Pin_12);
state = 0;
}
vTaskDelay(500);
}
vTaskDelete(NULL);
}

то диод моргает с частотой около 3 сек, хотя должно быть раз в секунду (через 500 тиков - гаснет ( state = 0), через 500 снова загорается(state = 1)) (тики по 1 мс)
как пересчитывать тики в реальное время - мс?)
ещё такой же точно вопрос был у парня тут:
http://www.cyberforum.ru/microcontrollers/thread1277104.html

Можете помочь разобраться если не трудно?)Или я что-то не так понимаю?

Salavat
Salavat
9 лет назад

Добрый день. Пытаюсь запустить связку uip+freeRtos+web на камне
stm32l100 . Freertos работает, но как только подключаю остальные библиотеки устройство не работает. Хотя проект компилится в Keil без ошибок. Немог ли ты поделиться готовым рабочим примером.

Николай
Николай
9 лет назад

Уже разобрался..))
Надо было в system_stm32f4xx.c изменить:
#define PLL_M 8 // стояло 25
Здесь 25 нужно заменить на 8 (внешний кварц 8МГц у Дисковери F4)
теперь всё чётко секунду в секунду))
спасибо)

Николай
Николай
9 лет назад

Уже разобрался..))
Надо было в system_stm32f4xx.c изменить:
#define PLL_M 8 // стояло 25
Здесь 25 нужно заменить на 8 (внешний кварц 8МГц у Дисковери F4)
теперь всё чётко секунду в секунду))
спасибо)

SPECTR
SPECTR
9 лет назад

Здоровки.
Недавно поставил freeRTOS на STM32F407VG. Встала она без проблем. Четыре светодиодика мигают параллельно независимо друг от друга. В общем и целом - на лицо параллельность выполнения задач. Чуть позже, изучая очереди и семафоры, столкнулся с одной серьезной проблемой. При использовании API-функций в теле обработчика прерывания (например, функция разблокирования какой-либо задачи из обработчика - xTaskResumeFromISR) происходит зависание. Т.е., входя в обработчик и выполняя какую-либо API-функцию, программа больше никогда не выходит из этого обработчика и все встает. Но при попытке использовать аналоги этих функций в задачах (допустим функция vTaskResume) все работает прекрасно.
В чем кроется проблема? Кто знает, подскажите пожалуйста.

vasa
vasa
9 лет назад

Добрый день!
Кто-нибудь подключал библиотеку USB+SDIO к RTOS? И как это должно выглядеть?
Спасибо!

50
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x