Подключаем FreeRTOS к Миландр.
Миландр и FreeRTOS. Как установить и настроить FreeRTOS на микроконтроллере Миландр. Описание процесса настройки и использования.

О полезности операционных систем реального времени можно говорить часами, ровно как и о их вреде. Но раз уж читаете эту запись, значит RTOS
вам действительно нужна.
Здесь не будет описания как пользоваться FreeRTOS
. Всё что будет затронуто - это запуск на микроконтроллере 1986ВЕ92У
(К1986ВЕ92QI
) фирмы Миландр. В принципе данный гайд аналогичен для 91, 93 и 94 чипа.
Если разобраться, и разложить всё по пунктам, то можно привести всю задачу к нескольким простым шагам:
- скачиваем
FreeRTOS
и распаковываем; - создаем проект в
Keil
(я использую версию 5); - подключаем операционную систему;
- настраиваем и пользуемся.
Тем у кого нет желания или времени читать предлагаю перейти сразу в конец статьи и скачать проект для 1986ВЕ92У
с подключенной операционной системой. В тестовой программе мигают четыре светодиода с разной частотой. Думаю этого вполне достаточно для переработки проекта под свои нужды.
Скачиваем FreeRTOS.
Наверно самый простой пункт нашего плана. Для этого нужно перейти на сайт www.freertos.org и скачать последнюю версию, на данный момент это версия 10. Или можно нажать на эту ссылку и загрузить сразу.
Теперь остается распаковать архив и приступить к изучению внутренностей, но это чуть позже.
Создаем проект в Keil.
Здесь должно быть всё понятно, открывает keil и создаём новый проект для микроконтроллера 1986ВЕ92У
.
Подключаем операционную систему.
Вот теперь самое интересное. Пришло время взглянуть на внутренности папки FreeRTOS
, именно её, папку с именем FreeRTOS-Plus
оставим на потом (в данном примере она нам не нужна).
У нас есть две папки:
Demo
- здесь хранятся примеры под разные платформы.Source
- здесь исходники операционной системы, именно эта папка нам и нужна.
Начинаем процесс подключения.
В папке с нашим проектом создаем папку rtos
(для большего порядка, хотя этого можно и не делать) и в неё копируем все содержимое папки Source
за исключением папки portable
, из которой нам нужны только несколько файлов. А именно:
- один из файлов кучи, в моем случае
heap_4.c
изportable\MemMang\
. Подробнее об этих файлах можно почитать на официальном сайте www.freertos.org. port.c
- из папкиportable\RVDS\ARM_CM3\
portmacro.h
- из той же папки
Файлы \*.c
копируем в папку rtos, а файлы\*.h
в поддиректорию \rtos\include\
Настраиваем ...
Теперь необходимо подготовить файл конфигурации операционной системы FreeRTOSConfig.h
, его можно взять в папке \Demo\CORTEX_STM32F103_Keil\
, настроив его под свои нужды или воспользоваться моим файлом (подробности как и с файлами heap_*.c
можно почитать на сайте операционки).
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include <stdint.h>
#include "MDR32Fx.h"
extern uint32_t SystemCoreClock;
#define configCPU_CLOCK_HZ (SystemCoreClock)
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configTOTAL_HEAP_SIZE ((size_t)(10 * 1024))
#define configMINIMAL_STACK_SIZE ((unsigned short)130)
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configMAX_PRIORITIES (5)
#define configUSE_PREEMPTION 1
#define configIDLE_SHOULD_YIELD 1
#define configMAX_TASK_NAME_LEN (10)
#define configUSE_TIMERS 0
#define configTIMER_TASK_PRIORITY (2)
#define configTIMER_QUEUE_LENGTH 5
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2)
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_QUEUE_SETS 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_16_BIT_TICKS 0
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_eTaskGetState 1
#ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#define xPortSysTickHandler SysTick_Handler
#include "freertos_evr.h"
#endif /* FREERTOS_CONFIG_H */
Теперь пробуем собрать прошивку. Но ничего не получается, появляются несколько ошибок:
.\obj\cantest.axf: Error: L6200E: Symbol PendSV_Handler multiply defined (by port.o and mdr32f9qx_it.o).
.\obj\cantest.axf: Error: L6200E: Symbol SVC_Handler multiply defined (by port.o and mdr32f9qx_it.o).
.\obj\cantest.axf: Error: L6200E: Symbol SysTick_Handler multiply defined (by port.o and mdr32f9qx_it.o).
Что в принципе и понятно в файле mdr32f9qx_it.с
описаны функции PendSV_Handler()
, SVC_Handler()
и SysTick_Handler()
, которые использует операционная система. Нужно просто удалить из файла, что мы и сделаем.
Теперь можно видеть желанную строку с информацией об удачной сборке
FromELF: creating hex file...
".\obj\cantest.axf" - 0 Error(s), 0 Warning(s).
Build Time Elapsed: 00:00:03
... и пользуемся.
Как принято, тестовой программой будет мигание светодиода, благо на отладочной палате (LDM-K1986BE92QI
) с микроконтроллером их четыре штуки. Если нет отладочной платы думаю вы разберетесь что делать дальше.
void vLed1(void *argument)
{
while(1)
{
PORT_SetBits(MDR_PORTB, PORT_Pin_0);
vTaskDelay(1000);
PORT_ResetBits(MDR_PORTB, PORT_Pin_0);
vTaskDelay(1000);
}
}
void vApplicationIdleHook (void)
{
}
int main(void)
{
init ();
xTaskCreate(vLed1, "1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
// Запускаем диспетчер и понеслась.
vTaskStartScheduler();
}
Собираем, заливаем и видим мигание примерно раз в секунду.
Надеюсь вы не забыли инициализировать вывод микроконтроллера ответственный за вывод сигнала на светодиод? Кстати эти выводы находятся в порте B
, на котором висит JTAGA
, так что внимательнее.
void PORT_init ( void )
{
PORT_InitTypeDef PORT_InitStructure;
// Запуск тактирования порта контроллера
RST_CLK_PCLKcmd( RST_CLK_PCLK_PORTB, ENABLE);
PORT_InitStructure.PORT_Pin = PORT_Pin_0 | PORT_Pin_1 | PORT_Pin_2 | PORT_Pin_3;
PORT_InitStructure.PORT_OE = PORT_OE_OUT;
PORT_InitStructure.PORT_FUNC = PORT_FUNC_PORT;
PORT_InitStructure.PORT_MODE = PORT_MODE_DIGITAL;
PORT_InitStructure.PORT_SPEED = PORT_SPEED_FAST;
PORT_Init(MDR_PORTB, &PORT_InitStructure);
}
Как видим, установка FreeRTOS
довольно проста и понятна. Однако в некоторых моментах возникают трудности и если нет сил и возможности их преодолеть самостоятельно, лучше спросить у знающих, а не рвать на себе волосы.
Исходники проекта можно взять здесь.