STM32 с нуля. Установка FreeRTOS.

При разработке электронных устройств до поры до времени (иногда довольно долго) удается обходиться без использования операционной системы. Но наступает момент, когда разрабатываемый девайс должен выполнять огромное количество различных функций или, например, должен обеспечивать возможность добавления новой задачи позднее. В этих случаях обойтись без RTOS (операционная система реального времени, ОСРВ) становится невозможно. Как раз про RTOS эта статья, а точнее про ее установку в среде Keil для контроллеров STM32F10x.

Сразу скажу, что я остановил свой выбор на FreeRTOS – эта ОСРВ портирована на огромное количество архитектур, что является, безусловно, большим плюсом. Есть в сети очень хороший мануал на русском языке, там правда очень много букв, но зато все описано максимально подробно и понятно)

Итак, в чем же фишка ОСРВ?

Операционная система реального времени позволяет организовать множество разнообразных задач и обеспечивает их поочередное выполнение, при этом учитывает приоритет каждой задачи. Также благодаря RTOS можно замутить запуск какой-либо задачи через определенные промежутки времени (причем обеспечивается высокая точность временных интервалов). Задачи могут обмениваться информацией друг с другом при помощи реализованной в RTOS очереди. И наконец, при необходимости возможно легким движением руки добавлять все новые и новые задачи. Конечно же, есть и минусы, связанные в основном с тем, что RTOS занимает довольно много памяти. Но эта проблема актуальна скорее для более старых моделей AVR и других контроллеров с небольшими объемами памяти. Так что нас это не будет сильно волновать )

Что можно сказать конкретно про FreeRTOS..

FreeRTOS – операционная система с открытым исходным кодом. Можно абсолютно бесплатно и без проблем скачать ее последнюю версию (что кстати необходимо сделать, поскольку мы скоро перейдем к созданию проекта под FreeRTOS =) ). Написана библиотека на C с наличием небольших ассемблерных вставок. Опять же, очень советую прочитать мануал на нее. Там и про различные типы многозадачности, про ОСРВ в целом, про организацию прерываний FreeRTOS, про разделение процессорного времени между задачами. В общем, почитать стоит ) Мы же рассмотрим практические аспекты установки FreeRTOS, естественно по ходу процесса постараюсь по максимуму объяснять что и зачем делается. Итак STM32 FreeRTOS..

Для начала дружно скачаем FreeRTOS. У меня, например, FreeRTOS v.7.1.0, по-моему, это последняя версия. Копируем папку с FreeRTOS куда-нибудь поближе к проекту. Именно копируем а не вырезаем/вставляем, поскольку сейчас мы будем удалять из нее то, что нам пока не нужно )

Скопировали, продолжаем…
Я создал в папке с проектом пару папок – Header_Files и Source_Files для header’ов и исходников соответственно. Пусть пока, для простоты, все файлы, которые понадобятся для запуска RTOS лежат там.
Заходим в папку FreeRTOSV7.1.0\FreeRTOSV7.1.0\Demo и удаляем нафиг оттуда все, кроме папки CORTEX_STM32F103_Keil. Заходим в единственную оставшуюся папку и хватаем файл FreeRTOSConfig.h. Копируем его в папку header’ов. В общем, я положил его в STMProjects\FreeRTOS1\Header_Files. Пусть там и живет ) Давайте его сразу же кстати и поправим. Открываем и копируем в этот файл следующие строки:

#define xPortSysTickHandler SysTick_Handler
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler

Давайте разбираться, что мы сделали. А всего лишь переопределили обработчики прерываний для того, чтобы прерывания из FreeRTOS попали в вектор прерываний. Вот и все )

Папка FreeRTOSV7.1.0\FreeRTOSV7.1.0\Source – тащим оттуда все .c файлы поближе к нашему проекту, в STMProjects\FreeRTOS1\Source_Files. Аналогично файлы из FreeRTOSV7.1.0\FreeRTOSV7.1.0\Source\include перетекают в STMProjects\FreeRTOS1\Header_Files.

Теперь проследуем в FreeRTOSV7.1.0\FreeRTOSV7.1.0\Source\portable и там прям таки манит папка под названием Keil. Заходим и видим «Nothing to see here.» Первая мысль – «Нифига себе! А где?..». Но не отчаиваемся, нам намекают посмотреть папку RVDS – заходим в нее, выбираем наше ядро (папка ARM_CM3) и забираем оттуда два файла к нам в проект.

Осталось зайти в папку FreeRTOSV7.1.0\Source\portable\MemMang и тащим файл heap_2.c.
Уфф, все, все файлы собрали, создаем новый проект в Keil и приступаем ко второй части Мерлезонского балета )

Нам нужно добавить все файлы в проект – это и CMSIS, и SPL, и FreeRTOS.
FreeRTOS Создание проекта
Теперь в настройках проекта прописываем все пути к файлам, присутствующим в проекте, а также не забываем про USE_STDPERIPH_DRIVER:
STM32 FreeRTOS
Тепеь напишем пример. Давайте сделаем традиционное мигание диодиком, но уже с использованием ОСРВ. Для начала надо подключить файлы:

#include "task.h"
#include "queue.h"
#include "FreeRTOS.h"
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"

Теперь надо настроить нужный нам вывод, на который мы повесим светодиод. Кстати, в мануале на FreeRTOS есть еще и правила, в соответствии с которыми рекомендуется оформлять код.

void vFreeRTOSInitAll()
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_StructInit(&port);
    port.GPIO_Mode = GPIO_Mode_Out_PP;
    port.GPIO_Pin = GPIO_Pin_0;
    port.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &port);
}

Тут все как обычно, включили тактирование, настроили вывод. Двигаемся дальше:

void vLedTask (void *pvParameters)
{
    while(1)
    {
	if (state == 0)
	{
            GPIO_SetBits(GPIOA,GPIO_Pin_0);
	    state = 1;
	}
	else
	{
	    GPIO_ResetBits(GPIOA,GPIO_Pin_0);
	    state = 0;
	}
    }
    vTaskDelete(NULL);	
}

Это задача, которую мы будем выполнять. Тут довольно извращенно реализовано мигание диодом. В конце функции, за пределами цикла, принято вызывать функцию vTaskDelete(NULL), которая удалит задачу в случае выхода из бесконечного цикла.

Теперь осталось только реализовать функцию main().

int main()
{
    vFreeRTOSInitAll();
    xTaskCreate(vLedTask,(signed char*)"LedTask", configMINIMAL_STACK_SIZE,
					NULL, tskIDLE_PRIORITY + 1, NULL);
    vTaskStartScheduler();
}

Сначала вызываем функцию для конфигурирования вывода PA0. А вот дальше интереснее – создаем задачу при помощи функции xTaskCreate().

Рассмотрим этот момент подробнее. Она принимает аргументы:
pvTaskCode — указатель на функцию, реализующую задачу,
pcName — нуль-терминальная (заканчивающаяся нулем) строка, определяющая имя функции – это для наглядности,
usStackDepth — глубина (размер) собственного стека создаваемой задачи, в данном случае мы используем минимально допустимый размер стека, определенный макросом configMINIMAL_STACK_SIZE,
pvParameters— произвольный параметр, передаваемый задаче при ее создании,
uxPriority — определяет приоритет создаваемой задачи, мы берем tskIDLE_PRIORITY + 1 = (приоритет задачи бездействие) + 1,
pxCreatedTask — может использоваться для получения дескриптора (handle) создаваемой задачи, который помещается по адресу pxCreatedTask после успешного создания задачи.

Остается в функции main() вызвать планировщика, и все готово )

Запускаем отладчик и смотрим, что из всего этого вышло. Открываем окошко логического анализатора и настраиваем его на мониторинг вывода РА0. (про это написано в предыдущих статьях по STM32, вот тут, например). Запускаем программу и….:
Keil Пример программы
Диод мигает! Это победа )

Подведем итог. Мы установили FreeRTOS, разобрались с ее работой и даже создали небольшую программку с применением ОСРВ. В следующей статье тоже будем писать под FreeRTOS, но это будет что-нибудь посложнее и поинтереснее )

P.S. Вот кстати хорошее описание FreeRTOS на русском — ссылка

Понравилась статья? Поделись с друзьями!

STM32 с нуля. Установка FreeRTOS.: 49 комментариев
  1. Спасибо за FreeRTOS, если не сложно поделитель ссылочкой на подробный мануал по этой ОС.

    • Он у меня вообще на работе на компе лежит где-то, сейчас поищу в интернете, если найду, обязательно добавлю ссылочку

  2. Собираетесь ли Вы написать статью FreeRTOS + прерывания?

    Очень интересно…Например сейчас создаю драйвер для ультр.зв. сенсора HS-SR04, там информация зашифрована в временных интервалах, и чтобы нормально работать думаю использовать внешние прерывания (ловля начала и окончания импульса)

    • Раз есть интерес, то могу написать ) Но не в самое ближайшее время, сейчас задачи в основном под AVR, ни на что другое времени не остается…

  3. на картинке с деревом проекта нет heap_2.c ,Без него не видит vPortFree и еще одно имя

  4. Очень хорошая статья. Большое спасибо!
    Есть одна просьба: при создании проекта точно по описанию в статье компилятор ругается на «state» и «port». Последний решается вставкой кода GPIO_InitTypeDef port в самом начале функции void vFreeRTOSInitAll() , а вот как победить «state» что-то не нашёл.

  5. Просто я думал, что state имеет отношение к FreeRTOS. Как-то относится непосредственно к ОСРВ. Первый раз занимаюсь сборкой ОСРВ, поэтому «придираюсь» к каждой мелочи. 🙂

  6. Пробовал собрать FreeRTOS 7.5 для STM32F407, но что-то не получается. Очень много ошибок выдаёт линкёр. Вот такого плана:
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol pxCurrentTCB (referred from port.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol vTaskSwitchContext (referred from port.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol xTaskIncrementTick (referred from port.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol vTaskSuspendAll (referred from timers.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol xTaskGenericCreate (referred from timers.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol xTaskGetSchedulerState (referred from timers.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol xTaskGetTickCount (referred from timers.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol xTaskResumeAll (referred from timers.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol vApplicationMallocFailedHook (referred from heap_2.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol vTaskMissedYield (referred from queue.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol vTaskPlaceOnEventList (referred from queue.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol vTaskPlaceOnEventListRestricted (referred from queue.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol vTaskPriorityDisinherit (referred from queue.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol vTaskPriorityInherit (referred from queue.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol vTaskSetTimeOutState (referred from queue.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol xTaskCheckForTimeOut (referred from queue.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol xTaskGetCurrentTaskHandle (referred from queue.o).
    .\Release\test_mka1.axf: Error: L6218E: Undefined symbol xTaskRemoveFromEventList (referred from queue.o).

    Сам файл main.c пока пустой, есть только инклюды. Никак не могу понять, что ему не нравится. 🙁

  7. Все файлы подключил к проекту, все пути указал… Не пойму, что ему надо?… Кейл пятый поставил, хотя и в предыдущем не получалось собрать ОСРВ для STM32F4. Мне нужно именно с F4 поработать, а получается какая-то фигня. Опыта мало, не могу понять в каком направлении копать.

  8. Был бы очень благодарен Вам. Очень трудно найти ошибку, если на неё указывает линкёр (по крайней мере мне). С STM32 занимаюсь всего неделю и всех хитростей пока не знаю.

  9. Всё, с установкой, вроде как разобрался. Установил FreeRTOS на STM32F407IG. Просто нужно было уделить особое внимание файлу FreeRTOSConfig.h — от него очень много зависит.
    Теперь хочу подключить ENC28J60 и модули RS232 и RS485. Надеюсь, не будет больших проблем с решением этой задачи. 🙂

  10. Тем не менее, ещё раз спасибо! Из Вашей статьи узнал важные моменты насчёт создания функций (пустых), на отсутствие которых ругался линкёр. Это очень важная для меня информация.
    Ещё раз большое спасибо!

  11. Большое спасибо за Ваш труд, в результате которого появилась серия статей, помогающих в освоении STM32. Также как у INA, при создании проекта точно по описанию в статье компилятор ругался на «state» и «port». Благодаря комментариям внес исправления, но появилась другая проблемка, которую самостоятельно решить не получается:
    STMProjects\FreeRTOS\Sourse_Files\FreeRTOS1.c: 1 warning, 0 errors
    linking…
    .\start.axf: Error: L6200E: Symbol __ARM_use_no_argv multiply defined (by freertos1.o and test.o).
    .\start.axf: Error: L6200E: Symbol main multiply defined (by freertos1.o and test.o).
    Not enough information to list image symbols.
    Not enough information to list the image map.
    Finished: 2 information, 0 warning and 2 error messages.
    «.\start.axf» — 2 Error(s), 1 Warning(s).
    Target not created

  12. Статья хорошая, но проект в кейле собираться не желает…

    .\Header_Files\stm32f10x_type.h(27): error: #256: invalid redeclaration of type name «s32» (declared at line 487 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(31): error: #256: invalid redeclaration of type name «vs32» (declared at line 495 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(35): error: #256: invalid redeclaration of type name «u32» (declared at line 503 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(39): error: #256: invalid redeclaration of type name «uc32» (declared at line 507 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(43): error: #256: invalid redeclaration of type name «vu32» (declared at line 511 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(47): error: #256: invalid redeclaration of type name «vuc32» (declared at line 515 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(53): error: #101: «RESET» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(53): error: #101: «SET» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(53): error: #256: invalid redeclaration of type name «FlagStatus» (declared at line 519 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(53): error: #256: invalid redeclaration of type name «ITStatus» (declared at line 519 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(55): error: #101: «DISABLE» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(55): error: #101: «ENABLE» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(55): error: #256: invalid redeclaration of type name «FunctionalState» (declared at line 521 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(56): warning: #47-D: incompatible redefinition of macro «IS_FUNCTIONAL_STATE» (declared at line 522 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(58): error: #101: «ERROR» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(58): error: #101: «SUCCESS» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(58): error: #256: invalid redeclaration of type name «ErrorStatus» (declared at line 524 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_conf.h(111): warning: #47-D: incompatible redefinition of macro «HSE_Value» (declared at line 528 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(273): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(338): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(357): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(383): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(404): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(568): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(612): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(638): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(664): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(703): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(731): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(770): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(832): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(865): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(882): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(896): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1067): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1098): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1129): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1188): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1219): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1240): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1253): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1285): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1332): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1406): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c(1451): warning: #223-D: function «assert_param» declared implicitly
    compiling stm32f10x_gpio.c…
    .\Header_Files\stm32f10x_type.h(27): error: #256: invalid redeclaration of type name «s32» (declared at line 487 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(31): error: #256: invalid redeclaration of type name «vs32» (declared at line 495 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(35): error: #256: invalid redeclaration of type name «u32» (declared at line 503 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(39): error: #256: invalid redeclaration of type name «uc32» (declared at line 507 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(43): error: #256: invalid redeclaration of type name «vu32» (declared at line 511 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(47): error: #256: invalid redeclaration of type name «vuc32» (declared at line 515 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(53): error: #101: «RESET» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(53): error: #101: «SET» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(53): error: #256: invalid redeclaration of type name «FlagStatus» (declared at line 519 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(53): error: #256: invalid redeclaration of type name «ITStatus» (declared at line 519 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(55): error: #101: «DISABLE» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(55): error: #101: «ENABLE» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(55): error: #256: invalid redeclaration of type name «FunctionalState» (declared at line 521 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(56): warning: #47-D: incompatible redefinition of macro «IS_FUNCTIONAL_STATE» (declared at line 522 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(58): error: #101: «ERROR» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(58): error: #101: «SUCCESS» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(58): error: #256: invalid redeclaration of type name «ErrorStatus» (declared at line 524 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_conf.h(111): warning: #47-D: incompatible redefinition of macro «HSE_Value» (declared at line 528 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(111): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(178): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(286): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(308): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(324): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(346): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(361): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(377): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(397): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(420): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(437): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(466): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(486): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(554): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(613): warning: #223-D: function «assert_param» declared implicitly
    STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c(632): warning: #223-D: function «assert_param» declared implicitly
    compiling system_stm32f10x.c…
    .\Header_Files\stm32f10x_type.h(27): error: #256: invalid redeclaration of type name «s32» (declared at line 487 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(31): error: #256: invalid redeclaration of type name «vs32» (declared at line 495 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(35): error: #256: invalid redeclaration of type name «u32» (declared at line 503 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(39): error: #256: invalid redeclaration of type name «uc32» (declared at line 507 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(43): error: #256: invalid redeclaration of type name «vu32» (declared at line 511 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(47): error: #256: invalid redeclaration of type name «vuc32» (declared at line 515 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(53): error: #101: «RESET» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(53): error: #101: «SET» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(53): error: #256: invalid redeclaration of type name «FlagStatus» (declared at line 519 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(53): error: #256: invalid redeclaration of type name «ITStatus» (declared at line 519 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(55): error: #101: «DISABLE» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(55): error: #101: «ENABLE» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(55): error: #256: invalid redeclaration of type name «FunctionalState» (declared at line 521 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(56): warning: #47-D: incompatible redefinition of macro «IS_FUNCTIONAL_STATE» (declared at line 522 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(58): error: #101: «ERROR» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(58): error: #101: «SUCCESS» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(58): error: #256: invalid redeclaration of type name «ErrorStatus» (declared at line 524 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_conf.h(111): warning: #47-D: incompatible redefinition of macro «HSE_Value» (declared at line 528 of «CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    compiling FreeRTOS1.c…
    .\Header_Files\FreeRTOSConfig.h(127): warning: #1-D: last line of file ends without a newline
    .\Header_Files\stm32f10x_type.h(27): error: #256: invalid redeclaration of type name «s32» (declared at line 487 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(31): error: #256: invalid redeclaration of type name «vs32» (declared at line 495 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(35): error: #256: invalid redeclaration of type name «u32» (declared at line 503 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(39): error: #256: invalid redeclaration of type name «uc32» (declared at line 507 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(43): error: #256: invalid redeclaration of type name «vu32» (declared at line 511 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(47): error: #256: invalid redeclaration of type name «vuc32» (declared at line 515 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(53): error: #101: «RESET» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(53): error: #101: «SET» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(53): error: #256: invalid redeclaration of type name «FlagStatus» (declared at line 519 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(53): error: #256: invalid redeclaration of type name «ITStatus» (declared at line 519 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(55): error: #101: «DISABLE» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(55): error: #101: «ENABLE» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(55): error: #256: invalid redeclaration of type name «FunctionalState» (declared at line 521 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(56): warning: #47-D: incompatible redefinition of macro «IS_FUNCTIONAL_STATE» (declared at line 522 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_type.h(58): error: #101: «ERROR» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(58): error: #101: «SUCCESS» has already been declared in the current scope
    .\Header_Files\stm32f10x_type.h(58): error: #256: invalid redeclaration of type name «ErrorStatus» (declared at line 524 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    .\Header_Files\stm32f10x_conf.h(111): warning: #47-D: incompatible redefinition of macro «HSE_Value» (declared at line 528 of «.\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h»)
    FreeRTOS1.c(11): error: #20: identifier «port» is undefined
    FreeRTOS1.c(22): error: #20: identifier «state» is undefined
    FreeRTOS1.c(33): warning: #111-D: statement is unreachable
    Target not created

    Вот так вот ругается…

  13. Разобрался. Сделал пустой проект в Кейле по описанию на этом же сайте, потом добавил файлы FreeRTOS к проекту — все собралось без ошибок.

  14. Спасибо за статьи! Неплохо было бы выкладывать рабочие проекты к статьям — думаю, это было бы большим плюсом.

  15. Подскажите пожалуйста
    патаюсь поморгать диодом т.к. судя по всму не работает функция:
    vTaskDelay( 5 / portTICK_RATE_MS );

    Возможно необхадимо что либо в FreeRTOSConfig.h подправить что бы использовать эту функцию?

    У меня 2 задачи, одна подает напряжание на вывод другая убирает. Если использовать taskYIELD();
    в конце каждой задачи то вроде как работает- диод горит тусклее.

    • Функция должна работать по идее. Если она нужна, чтобы посмотреть моргает ли диод, то 5 миллисекунд маловато

      • Вот мой код:

        *
        *
        *

        void vLedTestSet (void *pvParameters)
        {
        for (;;)
        {
        GPIOB->BSRR =GPIO_BSRR_BS5; // Выставили бит 5. GPIO_BSRR_BS5 это битмаска
        vTaskDelay( 250 / portTICK_RATE_MS );
        //taskYIELD();
        }
        }

        void vLedTestClear (void *pvParameters)
        {
        for (;;)
        {
        GPIOB->BSRR =GPIO_BSRR_BR5; // Сбросили бит 5.
        vTaskDelay( 250 / portTICK_RATE_MS );
        }
        }

        int main(void)

        {
        InitAll();
        xTaskCreate(vLedTestSet,(signed char*)»LedSet», configMINIMAL_STACK_SIZE,NULL, tskIDLE_PRIORITY + 1, NULL);
        xTaskCreate(vLedTestClear,(signed char*)»LedClear», configMINIMAL_STACK_SIZE,NULL, tskIDLE_PRIORITY + 1, NULL);

        vTaskStartScheduler();

        }

        может тут я что то не так делаю???

        • Ну смотри ) Задачу freertos переключает каждую мс, независимо от наличия задержки в теле функций, в этом скорее всего и проблема. Можно поставить брейкпоинты на сброс и выставление бита и посмотреть в отладчике доходит ли вообще программа до этих строк

  16. Кажется это отличная статья, но у меня напрочь отказывается собираться проект. Видимо по своей неопытности, я не очень понимаю где то место поближе к проекту и как правильно вырезать на фиг. Не могли бы вы выложить ссылку на проект? много вопросов сразу бы отпало. Спасибо

  17. Подскажите, пожалуйста сколько нужно оперативки для использования FreeRTOS? Дело в том, что в самом тупом примере с мигание одного светодиода heap2 сжирает практически весь ее запас (у меня 16КБ)

    Module ro code ro data rw data
    —— ——- ——- ——-
    D:\projects\IAR_ARM\start_discovery\FreeRTOS\Demo\CORTEX_STM32L152_IAR\Debug\Obj: [1]
    heap_2.o 300 6 10 264
    list.o 152
    main.o 316 20 12
    port.o 224 4 4
    portasm.o 124
    queue.o 1 018
    startup_stm32l1xx_md.o 476
    stm32l1xx_gpio.o 194
    stm32l1xx_it.o 18
    stm32l1xx_rcc.o 36
    system_stm32l1xx.o 368
    tasks.o 2 032 12 256
    ————————————————-
    Total: 5 258 42 10 536

    не очень наглядный листинг. в общем 10 264 байт уходит под обслуживание heap2. если задачу усложнить, причем довольно существенно — добавляем ip стек с возможностью одновременного подключения 40 клиентов, всякой статистикой и прочим, то heap2 отъедает 16,5КБ. В принципе, считаю это не большим увеличением по сравнению с многократным усложнением программы.
    Вот я и спрашиваю, действительно ли heap2 должен по умолчанию съедать столько оперативки? Ведь запускают же как-то FreeRTOS даже на AVR’ках, а так в разы ее меньше. Может нужно настройки какие применить?

  18. Ага, сам сразу и допер. в FreeRTOSConfig.h есть параметр #define configTOTAL_HEAP_SIZE ( ( size_t ) (10 * 1024 ) )
    Поставил 5*1024, соответственно размер уменьшился в два раза. все скомпилировалось со всеми стеками и web страничкой. как найду пропавший модуль с enc28, отпишусь заработало ли

  19. портировал на F3 и тыкает он меня в это:
    RTOS.axf: Error: L6218E: Undefined symbol vTaskStartScheduler (referred from main.o).
    RTOS.axf: Error: L6218E: Undefined symbol xTaskGenericCreate (referred from main.o).
    где бы я мог накосячить?

  20. Здравствуйте. Спасибо за ваши труды. Ваши статьи очень помогают по усвоению STM32. Но в данной статье обнаружились ошибки. Использовал Keil 5. Проект не соберётся по двум причинам:
    1 — инклуды #include «task.h» и #include «queue.h» должны располагаться под #include «FreeRTOS.h».
    2 — определить переменные GPIO_InitTypeDef port;
    uint8_t state;
    С уважением, Евгений.

  21. Не могли бы Вы дать ссылку на мануал по FreeRTOS, а то та, что в конце статьи, не рабочая.

  22. Спасибо! Хорошая статья!
    А что делать тем у кого в загруженной FreeRTOS в папке DEMO нет папки CORTEX_STM32F4XX_Keil, а проект хочется запустить именно на чипе из этой серии? Конкретнее есть у меня плата STMF4 Discovery. Хочу на ней поиграться…

  23. Здравствуйте, реализовал данный пример на stm32f4, при отладке залетает в Default_Handler, подскажите пожалуйста в чём может быть ошибка, проект отправлю на почту. Заранее спасибо.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *