FreeRTOS内有croutine这个驱动,但是,这个怎么翻译,我也不太明白,暂且脑补成协程,就是co-routine,这个用起来跟任务比较类似,只不过他调用每个东西,都像一个函数一样,不像一个任务,就是说,任务是Cortex-A的话,这协程能做的就是Cortex-M的,他们并不能吃多少内存,也不能干太多什么事.但是协程一样要调度的,受任务控制,一般在IDLE任务里面搞.通常的表达是这样的.
void vApplicationIdleHook( void )
{
for( ;; )
{
vCoRoutineSchedule();
}
}
当然,如果Idle里面还有别的任务,可就不能死循环了.当然,其他任务也把时间片全用了,那我自然也没机会执行.当然,要做这个,需要打开configUSE_CO_ROUTINES开关.协程时间准确性也比较差.比如我闪烁一个LED灯.
void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
crSTART( xHandle );
for( ;; )
{
if(uxIndex == 0)
{
GPIO_ToggleBits(GPIOG, GPIO_Pin_13);
crDELAY( xHandle, 500 );
}
else if(uxIndex == 1)
{
GPIO_ToggleBits(GPIOG, GPIO_Pin_14);
crDELAY( xHandle, 1000 );
}
}
crEND();
}
发现,这个程序必须有两个参数,一个是xHandle,自己的句柄,另一个是uxIndex,传入的参数.是Index,所以,只能按数字传.协程必须以crSTART开始,以crEND结束,协程内的延迟,使用crDELAY.实验效果就是,主任务Task并不受干扰,LED还能正常闪烁.完整程序如下,忽略IO初始化.
#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"
void vApplicationIdleHook( void )
{
vCoRoutineSchedule();
}
static void vTask1( void *pvParameters )
{
portTickType xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();
for( ;; )
{
printf("Hello 3000!");
vTaskDelayUntil( &xLastWakeTime, ( 3000 / portTICK_RATE_MS ) );
}
}
static void vTask2( void *pvParameters )
{
portTickType xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();
for( ;; )
{
printf("Hello 2000!");
vTaskDelayUntil( &xLastWakeTime, ( 1000 / portTICK_RATE_MS ) );
}
}
void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
crSTART( xHandle );
for( ;; )
{
if(uxIndex == 0)
{
GPIO_ToggleBits(GPIOG, GPIO_Pin_13);
crDELAY( xHandle, 500 );
}
else if(uxIndex == 1)
{
GPIO_ToggleBits(GPIOG, GPIO_Pin_14);
crDELAY( xHandle, 1000 );
}
}
crEND();
}
int main(void)
{
xTaskCreate( vTask1, ( const char * ) "vTask1", 1000, NULL, 1, NULL );
xTaskCreate( vTask2, ( const char * ) "vTask2", 1000, NULL, 1, NULL );
xCoRoutineCreate( vFlashCoRoutine, 0, 0 );
xCoRoutineCreate( vFlashCoRoutine, 0, 1 );
vTaskStartScheduler();
for(;;);
}
协程非常简单,而且优先级很低,适合做后台应用.