广东湘恒智能科技有限公司
主营产品: 西门子PLC代理商,plc变频器,伺服电机,人机界面,触摸屏,线缆,DP接头
SIEMENS山东省东营市 西门子代理商——西门子华北一级总代理

2.2 创建Daemon任务

软件定时器任务(Daemon任务)的创建是通过xTaskCreate方法来创建,在创建守护任务之前,还要先通过prvCheckForValidListAndQueue函数创建两个列表和一个消息队列:
































BaseType_t xTimerCreateTimerTask( void ){    BaseType_t xReturn = pdFAIL;
   /* 创建列表与消息队列 */    prvCheckForValidListAndQueue();
   if( xTimerQueue != NULL ){        #if( configSUPPORT_STATIC_ALLOCATION == 1 )        ...略去部分代码        #else        {            /* 创建软件定时器任务(守护任务) */            xReturn = xTaskCreate(  prvTimerTask,                                    "Tmr Svc",                                    configTIMER_TASK_STACK_DEPTH,                                    NULL,                                    ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,                                    &xTimerTaskHandle );        }        #endif /* configSUPPORT_STATIC_ALLOCATION */}    else{        mtCOVERAGE_TEST_MARKER();}
   configASSERT( xReturn );    return xReturn;}

创建列表与消息队列的具体函数内容如下:

2.3 创建列表与消息队列

由于系统节拍采用32位变量进行计数,总有一天会溢出,所以软件定时器使用了两个列表:

当前定时器列表pxCurrentTimerList :系统新创建并激活的定时器都会以超时时间升序的方式插入到pxCurrentTimerList列表中。系统在定时器任务中扫描pxCurrentTimerList中的第一个定时器,看是否已超时,若已经超时了则调用软件定时器回调函数,否则将定时器任务挂起。

溢出定时器列表pxOverflowTimerList:在软件定时器溢出的时候使用,作用与pxCurrentTimerList一致。

定时器列表会按照唤醒时间从早到晚挂接在当前定时器列表中,唤醒时间如果溢出了就挂接在溢出定时器列表中。当系统节拍溢出之后,两个列表的功能会进行交换,即当前列表变为溢出列表,溢出列表变为当前列表。

此外,FreeRTOS的软件定时器还使用了一个消息队列xTimerQueue,利用“定时器命令队列”向软件定时器任务发送一些命令,任务在接收到命令就会去处理命令对应的程序,比如启动定时器,停止定时器,复位、删除、改变周期等。

假如定时器任务处于阻塞状态,我们又需要马上再添加一个软件定时器的话,就是采用这种消息队列命令的方式进行添加,才能唤醒处于等待状态的定时器任务,并且在任务中将新添加的软件定时器添加到软件定时器列表中

(注:事件标志组在中断中设置事件标志,实际也是通过队列发送消息给软件定时器任务来执行)
















































/* 检查是否有可用的列表和队列 */static void prvCheckForValidListAndQueue( void ){    /* 进入临界区 */    taskENTER_CRITICAL();{        /* 还没有创建队列 */        if( xTimerQueue == NULL )        {                      /* 初始化定时器列表1 */            vListInitialise( &xActiveTimerList1 );            /* 初始化定时器列表2 */            vListInitialise( &xActiveTimerList2 );            /* 当前定时器列表 */            pxCurrentTimerList = &xActiveTimerList1;            /* 溢出定时器列表 */            pxOverflowTimerList = &xActiveTimerList2;
           #if( configSUPPORT_STATIC_ALLOCATION == 1 )            ...略去部分代码            #else            {                /* 创建定时器消息队列 */                xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );            }            #endif
           #if ( configQUEUE_REGISTRY_SIZE > 0 )            {                if( xTimerQueue != NULL )                {                    vQueueAddToRegistry( xTimerQueue, "TmrQ" );                }                else                {                    mtCOVERAGE_TEST_MARKER();                }            }            #endif /* configQUEUE_REGISTRY_SIZE */        }        else        {            mtCOVERAGE_TEST_MARKER();        }}    taskEXIT_CRITICAL();}

既然消息队列是用来处理软件定时器的一些操作指令的,那这些在哪里呢?其实就是软件定时器的一些API函数,如下。


展开全文
相关产品
拨打电话 微信咨询 发送询价