回顾prvProcessTimerOrBlockTask()函数,定时器定时时间还没到,将当前任务挂起,直到定时器到期才唤醒或者收到命令的时候唤醒:
/* 队列为空 */ if( pxQueue->uxMessagesWaiting == (UBaseType_t )0U ) { /*将任务插入等待接收队列项而阻塞的事件列表,并加入延时列表进行阻塞延时 */ vTaskPlaceOnEventListRestricted( &(pxQueue->xTasksWaitingToReceive ), xTicksToWait,xWaitIndefinitely ); } /* 队列不为空 */ else { mtCOVERAGE_TEST_MARKER(); } /* 解锁队列*/ prvUnlockQueue(pxQueue);}3.3处理命令队列中接收的消息
用户将需要处理的定时器命令发送到定时器的消息队列, Daemon任务每次执行期间回去读取并执行,下面看看该函数的具体内容:
/*消息队列接收*/ while( xQueueReceive( xTimerQueue,&xMessage, tmrNO_DELAY ) != pdFAIL ) { #if ( INCLUDE_xTimerPendFunctionCall == 1) { /* 命令码小于等于0(事件标志组中断中置位的命令)*/ if( xMessage.xMessageID < ( BaseType_t) 0 ) { const CallbackParameters_t *const pxCallback = &(xMessage.u.xCallbackParameters ); configASSERT( pxCallback);
/* 执行回调函数 */ pxCallback->pxCallbackFunction(pxCallback->pvParameter1, pxCallback->ulParameter2 ); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /*INCLUDE_xTimerPendFunctionCall*/
/* 命令码大于等于0 (软件定时器命令)*/ if( xMessage.xMessageID >= (BaseType_t ) 0 ) { /* 定时器句柄 */ pxTimer =xMessage.u.xTimerParameters.pxTimer;
/*定时器队列项包含该定时器 */ if( listIS_CONTAINED_WITHIN(NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE) { /* 移除该定时器 */ ( void )uxListRemove( &( pxTimer->xTimerListItem ) ); } else { mtCOVERAGE_TEST_MARKER(); }
traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID,xMessage.u.xTimerParameters.xMessageValue);
/* 获取当前时间,并判断是否需要切换定时器列表,如果需要则切换 */ xTimeNow =prvSampleTimeNow( &xTimerListsWereSwitched);
/* 消息类型 */ switch( xMessage.xMessageID) { /* 定时器启动或者复位 */ casetmrCOMMAND_START : case tmrCOMMAND_START_FROM_ISR: case tmrCOMMAND_RESET : casetmrCOMMAND_RESET_FROM_ISR : casetmrCOMMAND_START_DONT_TRACE : /*计算超时时间,超时时间没过加入活跃列表,超时时间已过返回pdTrue */ if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue +pxTimer->xTimerPeriodInTicks, xTimeNow,xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE ) { /*在加入列表前已经超时,执行对应的回调函数 */ pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer); traceTIMER_EXPIRED( pxTimer);
/*如果是周期定时器*/ if( pxTimer->uxAutoReload == ( UBaseType_t )pdTRUE ) { /* 发送消息,通知守护任务将定时器插入当前列表*/ xResult =xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE,xMessage.u.xTimerParameters.xMessageValue +pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY); configASSERT(xResult ); (void ) xResult; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } break;
/* 停止定时器 */ case tmrCOMMAND_STOP: case tmrCOMMAND_STOP_FROM_ISR : /* 定时器已经从活跃列表中移除,什么都不做 */ break;
/* 改变定时器周期 */ casetmrCOMMAND_CHANGE_PERIOD : casetmrCOMMAND_CHANGE_PERIOD_FROM_ISR : /*取出新的频率 */ pxTimer->xTimerPeriodInTicks =xMessage.u.xTimerParameters.xMessageValue; configASSERT( ( pxTimer->xTimerPeriodInTicks >0 ) );
/*计算超时时间,超时时间没过则加入活跃列表 */ ( void) prvInsertTimerInActiveList( pxTimer, ( xTimeNow +pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); break;
/* 删除定时器 */ casetmrCOMMAND_DELETE : #if( (configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && (configSUPPORT_STATIC_ALLOCATION == 0 ) ) { /* 释放软件定时器内存*/ vPortFree( pxTimer); } #elif(( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && (configSUPPORT_STATIC_ALLOCATION == 1 ) ) { if(pxTimer->ucStaticallyAllocated == ( uint8_t )pdFALSE ) { /* 释放软件定时器内存 */ vPortFree( pxTimer); } else { mtCOVERAGE_TEST_MARKER(); } } #endif /*configSUPPORT_DYNAMIC_ALLOCATION */ break;
default : /* Don'texpect to get here. */ break; } } }}