При разработке электронных устройств до поры до времени (иногда довольно долго) удается обходиться без использования операционной системы. Но наступает момент, когда разрабатываемый девайс должен выполнять огромное количество различных функций или, например, должен обеспечивать возможность добавления новой задачи позднее. В этих случаях обойтись без RTOS (операционная система реального времени, ОСРВ) становится невозможно. Как раз про RTOS эта статья, а точнее про ее установку и использование для микроконтроллеров STM32.
Сразу скажу, что я остановил свой выбор на FreeRTOS – эта ОСРВ портирована на огромное количество архитектур, что является, безусловно, большим плюсом. Есть в сети очень хороший мануал на русском языке, там правда очень много букв, но зато все описано максимально подробно и понятно.
Время традиционной вставки: поскольку компания STMicroelectronics прекратила поддержку библиотеки SPL, которая использовалась в этом курсе, я создал новый, посвященный работе уже с новыми инструментами, так что буду рад видеть вас там - STM32CubeMx. Кроме того, вот глобальная рубрика по STM32, а также статья на смежную тему из нового курса: STM32CubeMx. Быстрый старт с FreeRTOS для STM32.
Итак, в чем же кроется основная идея ОСРВ?
Операционная система реального времени позволяет организовать множество разнообразных задач и обеспечивает их поочередное выполнение и при этом учитывает приоритет каждой задачи. Также благодаря RTOS можно замутить запуск какой-либо задачи через определенные промежутки времени (причем обеспечивается высокая точность временных интервалов). Задачи могут обмениваться информацией друг с другом при помощи реализованной в RTOS очереди. И наконец, при необходимости возможно легким движением руки добавлять все новые и новые задачи. Конечно же, есть и минусы, связанные в основном с тем, что RTOS занимает довольно много памяти. Но эта проблема актуальна скорее для более старых моделей AVR и других контроллеров с небольшими объемами памяти. Так что нас это не будет сильно волновать.
Что можно сказать конкретно про FreeRTOS... FreeRTOS – операционная система с открытым исходным кодом. Можно абсолютно бесплатно и без проблем скачать ее последнюю версию (что кстати необходимо сделать, поскольку мы скоро перейдем к созданию проекта под FreeRTOS). Написана библиотека на C с наличием небольших ассемблерных вставок. Опять же, очень советую прочитать мануал на нее. Там и про различные типы многозадачности, про ОСРВ в целом, про организацию прерываний, про разделение процессорного времени между задачами. В общем, почитать стоит. Мы же рассмотрим практические аспекты установки FreeRTOS, естественно по ходу процесса постараюсь по максимуму объяснять, что и зачем делается. Итак, приступаем...
Для начала дружно скачаем FreeRTOS. У меня, например, FreeRTOS v.7.1.0, по-моему, это последняя версия (на момент написания статьи). Копируем папку с FreeRTOS куда-нибудь поближе к проекту. Именно копируем а не вырезаем/вставляем, поскольку сейчас мы будем удалять из нее то, что нам пока не нужно )
Скопировали, продолжаем…
Я создал в папке с проектом пару папок – Header_Files и Source_Files для заголовочных файлов и файлов с исходным кодом соответственно. Пусть пока для простоты все файлы, которые понадобятся для запуска RTOS лежат там.
Заходим в папку FreeRTOSV7.1.0\FreeRTOSV7.1.0\Demo и удаляем оттуда все, кроме папки CORTEX_STM32F103_Keil. Заходим в единственную оставшуюся папку и обращаем наше внимание на файл FreeRTOSConfig.h. Копируем его в папку header’ов. Давайте его сразу же и отредактируем. Открываем и копируем в этот файл следующие строки:
#define xPortSysTickHandler SysTick_Handler #define xPortPendSVHandler PendSV_Handler #define vPortSVCHandler SVC_Handler
Давайте разбираться, что мы сделали. А всего лишь переопределили обработчики прерываний для того, чтобы прерывания из FreeRTOS попали в вектор прерываний.
Папка FreeRTOSV7.1.0\FreeRTOSV7.1.0\Source – копируем из нее все .c файлы в STMProjects\FreeRTOS\Source_Files. Аналогично, файлы из FreeRTOSV7.1.0\FreeRTOSV7.1.0\Source\include помещаем в STMProjects\FreeRTOS\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:
В настройках проекта прописываем все пути к файлам, присутствующим в проекте, а также не забываем про USE_STDPERIPH_DRIVER:
И, наконец, создадим практический пример! Давайте сделаем традиционное мигание диодом, но уже с использованием ОСРВ. Для начала надо подключить файлы:
#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, вот тут, например). Запускаем программу:
Все работает четко по плану )
Подведем итог. Мы установили FreeRTOS, разобрались с ее работой и даже создали небольшую программку с применением ОСРВ. В следующей статье тоже будем писать под FreeRTOS, но это будет что-нибудь посложнее и поинтереснее. Также вот ссылка на еще один пример организации работы программы с операционной системой.
P. S. Вот, кстати, хорошее описание FreeRTOS на русском - ссылка.
Спасибо за FreeRTOS, если не сложно поделитель ссылочкой на подробный мануал по этой ОС.
Он у меня вообще на работе на компе лежит где-то, сейчас поищу в интернете, если найду, обязательно добавлю ссылочку
Отличий мануал!
Не подскажите какой размер получился этого примера?
На другом компе примеры все у меня..На днях доберусь до него, посмотрю размер обязательно)
18.1 кБ
Собираетесь ли Вы написать статью FreeRTOS + прерывания?
Очень интересно...Например сейчас создаю драйвер для ультр.зв. сенсора HS-SR04, там информация зашифрована в временных интервалах, и чтобы нормально работать думаю использовать внешние прерывания (ловля начала и окончания импульса)
Раз есть интерес, то могу написать ) Но не в самое ближайшее время, сейчас задачи в основном под AVR, ни на что другое времени не остается...
на картинке с деревом проекта нет heap_2.c ,Без него не видит vPortFree и еще одно имя
Ага, в тексте написал, а на картинке забыл указать
Очень хорошая статья. Большое спасибо!
Есть одна просьба: при создании проекта точно по описанию в статье компилятор ругается на "state" и "port". Последний решается вставкой кода GPIO_InitTypeDef port в самом начале функции void vFreeRTOSInitAll() , а вот как победить "state" что-то не нашёл.
Ну, надо объявить, например uint8_t state
Просто я думал, что state имеет отношение к FreeRTOS. Как-то относится непосредственно к ОСРВ. Первый раз занимаюсь сборкой ОСРВ, поэтому "придираюсь" к каждой мелочи. 🙂
Да ничего, вполне нормальный вопрос))
Пробовал собрать 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 пока пустой, есть только инклюды. Никак не могу понять, что ему не нравится. 🙁
Похоже, что файлы не подцепились к проекту..
Все файлы подключил к проекту, все пути указал... Не пойму, что ему надо?... Кейл пятый поставил, хотя и в предыдущем не получалось собрать ОСРВ для STM32F4. Мне нужно именно с F4 поработать, а получается какая-то фигня. Опыта мало, не могу понять в каком направлении копать.
Я могу попробовать под F4 сделать завтра пример с rtos, если успею
Был бы очень благодарен Вам. Очень трудно найти ошибку, если на неё указывает линкёр (по крайней мере мне). С STM32 занимаюсь всего неделю и всех хитростей пока не знаю.
Всё, с установкой, вроде как разобрался. Установил FreeRTOS на STM32F407IG. Просто нужно было уделить особое внимание файлу FreeRTOSConfig.h - от него очень много зависит.
Теперь хочу подключить ENC28J60 и модули RS232 и RS485. Надеюсь, не будет больших проблем с решением этой задачи. 🙂
Если что, вот - https://microtechnics.ru/mikrokontroller-stm32f4-i-freertos/ =) Чуть опоздал 🙂
Тем не менее, ещё раз спасибо! Из Вашей статьи узнал важные моменты насчёт создания функций (пустых), на отсутствие которых ругался линкёр. Это очень важная для меня информация.
Ещё раз большое спасибо!
Не за что)
Большое спасибо за Ваш труд, в результате которого появилась серия статей, помогающих в освоении 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
Похоже, что в файлах freertos1.c и test.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_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
Вот так вот ругается...
Разобрался. Сделал пустой проект в Кейле по описанию на этом же сайте, потом добавил файлы FreeRTOS к проекту - все собралось без ошибок.
Даже не успел ответить =) Хорошо, что заработало )
Спасибо за статьи! Неплохо было бы выкладывать рабочие проекты к статьям - думаю, это было бы большим плюсом.
Подскажите пожалуйста
патаюсь поморгать диодом т.к. судя по всму не работает функция:
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 переключает каждую мс, независимо от наличия задержки в теле функций, в этом скорее всего и проблема. Можно поставить брейкпоинты на сброс и выставление бита и посмотреть в отладчике доходит ли вообще программа до этих строк
Кажется это отличная статья, но у меня напрочь отказывается собираться проект. Видимо по своей неопытности, я не очень понимаю где то место поближе к проекту и как правильно вырезать на фиг. Не могли бы вы выложить ссылку на проект? много вопросов сразу бы отпало. Спасибо
Хорошо, поищу проект завтра, если не найду, сделаю заново и выложу
Готово - http://rusfolder.com/39426226
Класс! Теперь разобрался. Спасибо
=)
Подскажите, пожалуйста сколько нужно оперативки для использования 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'ках, а так в разы ее меньше. Может нужно настройки какие применить?
Ага, сам сразу и допер. в FreeRTOSConfig.h есть параметр #define configTOTAL_HEAP_SIZE ( ( size_t ) (10 * 1024 ) )
Поставил 5*1024, соответственно размер уменьшился в два раза. все скомпилировалось со всеми стеками и web страничкой. как найду пропавший модуль с enc28, отпишусь заработало ли
И сам код было бы интересно посмотреть )))
портировал на F3 и тыкает он меня в это:
RTOS.axf: Error: L6218E: Undefined symbol vTaskStartScheduler (referred from main.o).
RTOS.axf: Error: L6218E: Undefined symbol xTaskGenericCreate (referred from main.o).
где бы я мог накосячить?
Как вариант - какого-то includ'а не хватает
Здравствуйте. Спасибо за ваши труды. Ваши статьи очень помогают по усвоению STM32. Но в данной статье обнаружились ошибки. Использовал Keil 5. Проект не соберётся по двум причинам:
1 - инклуды #include "task.h" и #include "queue.h" должны располагаться под #include "FreeRTOS.h".
2 - определить переменные GPIO_InitTypeDef port;
uint8_t state;
С уважением, Евгений.
Не могли бы Вы дать ссылку на мануал по FreeRTOS, а то та, что в конце статьи, не рабочая.
А с TNKernel не было опыта?
Неа
Спасибо! Хорошая статья!
А что делать тем у кого в загруженной FreeRTOS в папке DEMO нет папки CORTEX_STM32F4XX_Keil, а проект хочется запустить именно на чипе из этой серии? Конкретнее есть у меня плата STMF4 Discovery. Хочу на ней поиграться...
Вот небольшой пример для FreeRTOS на F4 - https://microtechnics.ru/mikrokontroller-stm32f4-i-freertos/
Здравствуйте, реализовал данный пример на stm32f4, при отладке залетает в Default_Handler, подскажите пожалуйста в чём может быть ошибка, проект отправлю на почту. Заранее спасибо.