Доброе время суток!) Продолжаем изучать микроконтроллеры ARM архитектуры, сегодня пойдет речь о RTOS (OCPB), а в частности про FreeRTOS (тут я добавлю свою ложку дёгтя) и новый зверь ChibiOS. RTOS – операционная система реального времени. Что такое реальное время? Стандарт POSIX 1003.1 даёт следующее определение: «Реальное время в операционных системах — это способность операционной системы обеспечить требуемый уровень сервиса в определённый промежуток времени». Операционная система, реагирующая на событие за определенный, заданный промежуток времени. Операционные системы реального времени делят на два типа — системы жесткого реального времени и системы мягкого реального времени. Операционная система, которая может обеспечить требуемое время выполнения задачи реального времени даже в худших случаях, называется операционной системой жёсткого реального времени. Операционная система, которая может обеспечить требуемое время выполнения задачи реального времени в среднем, называется операционной системой мягкого реального времени.
FreeRTOS – http://www.freertos.org/
Лого freertos
ChibiOS – http://www.chibios.org/
Лого чиби
Какие MCU поддерживают данные оси?
FreeRTOS – наверное самая пушистая, количество платформ просто зашкаливает, вот ссылка ( http://www.freertos.org/RTOS_ports.html ), где подробно перечисляется, какие мсиюшки поддерживает freertos: Actel, Altera, Atmel, NXP,.., ST… и очень много другого.
ChibiOS – не такая пушистая, но потенциал очень велик)
Так какие платформы поддерживает чиби?
ARM Cortex-M0 (ARMv6-M) GCC LPC11xx, LPC11Uxx, STM32F0xx
ARM Cortex-M0 (ARMv6-M) RVCT LPC11xx, LPC11Uxx, STM32F0xx
ARM Cortex-M3 (ARMv7-M) GCC LPC13xx, STM32F1xx, STM32F2xx, STM32L1xx
ARM Cortex-M3 (ARMv7-M) IAR LPC13xx, STM32F1xx, STM32F2xx, STM32L1xx
ARM Cortex-M3 (ARMv7-M) RVCT LPC13xx, STM32F1xx, STM32F2xx, STM32L1xx
ARM Cortex-M4 (ARMv7-ME) GCC STM32F3xx, STM32F4xx
ARM Cortex-M4 (ARMv7-ME) IAR STM32F3xx, STM32F4xx
ARM Cortex-M4 (ARMv7-ME) RVCT STM32F3xx, STM32F4xx
ARM7 GCC AT91SAM7x, LPC214x
MegaAVR GCC ATmega128, AT90CAN128, ATmega328p, ATmega1280
MSP430 GCC MSP430F1611
Power Architecture e200z GCC/HighTec SPC56x (all)
STM8 Cosmic STM8L, STM8S
STM8 Raisonance STM8L, STM8S
Как мы видим это в основном ведущие поставщики микроконтроллеров ST, Atmel и NXP.
Первые примеры будут посвящены вытесняющей многозадачности. Что такое многозадачность? Это свойство операционной системы или среды выполнения обеспечивать возможность параллельной (или псевдопараллельной) обработки нескольких процессов. Истинная многозадачность операционной системы возможна только в распределённых вычислительных системах. Вытесняющая многозадачность – это когда диспетчер каждый системный тик, останавливает задачу(А), и передает управление другой задаче(Б). Обеспечивая тем самым псевдопараллельное выполнение. Сегодня у нас будут два подопытных кролика. Первый STM32F429ZI –DISCO и второй SAM3N-EK.
Для изучения freertos есть, ОЧЕНЬ ПОДРОБНОЕ РУКОВОДСТВО ПО FREERTOS написал Андрей Курниц для журнала «Компоненты и технологии» (http://www.kit-e.ru/articles/micro/2011_2_96.php ). И так начинаем:
STM32F4 + Keil + FreeRTOS
#include "stm32f4xx_hal.h" #include "cmsis_os.h" UART_HandleTypeDef huart5; void SystemClock_Config(void); static void StartThread(void const * argument); static void MX_GPIO_Init(void); static void MX_UART5_Init(void); typedef struct TaskParam_t{ signed long int period; } Task; Task p1, p2; void vTask1(void *pvParameters){ Task *task_period; task_period = (Task *)pvParameters; HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET); for(;;){ HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_13); vTaskDelay(task_period->period); } vTaskDelete(NULL); } void vTask2(void *pvParameters){ Task *period; period = (Task *) pvParameters; HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_SET); for(;;){ HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_14); vTaskDelay(period->period); } vTaskDelete(NULL); } int main(void) { HAL_Init(); SystemClock_Config(); HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); MX_GPIO_Init(); p1.period = 1000; p2.period = 500; xTaskCreate(vTask1, (signed char *) "Task1", configMINIMAL_STACK_SIZE, (void *) &p1, 1, NULL); xTaskCreate(vTask2, (signed char *) "Task2", configMINIMAL_STACK_SIZE, (void *) &p2, 1, NULL); vTaskStartScheduler(); while (1){ } }
STM32F4 + keil + ChibiOS
#include "ch.h" #include "hal.h" static WORKING_AREA(waThread1, 128); static WORKING_AREA(waThread2, 128); static msg_t Thread1(void *arg); static msg_t Thread2(void *arg); typedef struct TaskParam_t{ signed long int period; } Task; Task p1, p2; int main(void){ p1.period = 1000; p2.period = 500; halInit(); chSysInit(); chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, (void *)&p1); chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, (void *)&p2); while(TRUE){ } } static msg_t Thread1(void *arg){ Task *period; period = (Task *) arg; palSetPad(GPIOG, GPIOG_LED4_RED ); while(TRUE){ palTogglePad(GPIOG, GPIOG_LED4_RED); chThdSleepMilliseconds(period->period); } } static msg_t Thread2(void *arg){ Task *period; period = (Task *) arg; palSetPad(GPIOG, GPIOG_LED3_GREEN); while(TRUE){ palTogglePad(GPIOG, GPIOG_LED3_GREEN); chThdSleepMilliseconds(period->period); } }
halInit() – инициализация борды
chSysInit() – инициализация оси и инициализация диспетчера задач
Thread *chThdCreateStatic(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg) – создание потока (создание задачи).
1 – ый аргумент – указатель на выделенную память для задачи
2- ой аргумент – размер памяти, сколько выделили
3- ый аргумент – уровень приоритета для задачи
4- ый аргумент – имя функции
5-ый аргумент – данные передаваемые функции
Проект для чиби
SAM3N-EK+Ateml Studio 6 +FreeRTOS
#include <asf.h> #include "conf_board.h" #define TASK_MONITOR_STACK_SIZE (2048/sizeof(portSTACK_TYPE)) #define TASK_MONITOR_STACK_PRIORITY (tskIDLE_PRIORITY) #define TASK_LED_STACK_SIZE (1024/sizeof(portSTACK_TYPE)) #define TASK_LED_STACK_PRIORITY (tskIDLE_PRIORITY) extern void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char *pcTaskName); extern void vApplicationIdleHook(void); extern void vApplicationTickHook(void); extern void xPortSysTickHandler(void); void SysTick_Handler(void) { xPortSysTickHandler(); } extern void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char *pcTaskName) { } extern void vApplicationIdleHook(void) { } extern void vApplicationTickHook(void) { } typedef struct TaskParam_t{ signed long int period; } Task; Task p1, p2; static void task_led1(void *pvParameters) { Task *period; period = (Task *) pvParameters; for (;;) { LED_Toggle(LED0); vTaskDelay(period->period); } } static void task_led2(void *pvParameters) { Task *period; period = (Task *) pvParameters; for (;;) { LED_Toggle(LED1); vTaskDelay(period->period); } } int main(void) { sysclk_init(); board_init(); p1.period = 1000; p2.period = 500; xTaskCreate(task_led1, (signed char *)"Led1", TASK_LED_STACK_SIZE, (void *) &p1, TASK_LED_STACK_PRIORITY, NULL); xTaskCreate(task_led2, (signed char *)"Led2", TASK_LED_STACK_SIZE, (void *) &p2, TASK_LED_STACK_PRIORITY, NULL); vTaskStartScheduler(); while(1){ } return 0; }
Проект_FreeRTOS_Atmel
Как мы видим применение freertos просто потрясающее, программная реализация просто копи пастом переносится на другую платформу, немного подправив код. Если возникли вопросы, оставляется их в коментах, я обязательно отвечу, а на сегодня все, всем пока!)