FreeRTOS的软件定时器的源码分析
一、软件定时器的特性[*]定时器的关键成员:周期、回调函数
[*]定时器的指定类型:一次性、可自动重载定时器
[*]定时器的状态:运行、休眠
[*]FreeRTOS的软件定时器基于Tick中断实现,但是由于实时系统不允许在内核、中断中执行不确定时间的代码,因此定时器函数被放到了RTOS守护任务中实现
二、RTOS守护任务
[*]优先级:configTIMER_TASK_PRIORITY,默认是2,高于IDLE任务
[*]消息队列的长度:configTIMER_QUEUE_LENGTH,默认是10,40字节
[*]用户调用定时器函数,通过专用的定时器消息队列,发送给RTOS守护任务,在RTOS守护任务中读消息队列,并执行相应的定时器处理函数
[*]prvTimerTask在调用vTaskStartScheduler时被创建
三、prvTimerTask任务
static void prvTimerTask( void *pvParameters )
{
TickType_t xNextExpireTime;
BaseType_t xListWasEmpty;
for( ;; )
{
xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); // 从pxCurrentTimerList获得下一个定时器到期时间,升序排列,头表示第一个到期的定时器
prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); // 定时器到期执行prvProcessExpiredTimer,没到期则有时间限制的等待xTimerQueue(最多等xNextExpireTime - xTimeNow)
prvProcessReceivedCommands(); // 处理接收命令,非阻塞循环读取队列xTimerQueue,处理message,包括启动定时器、停止定时器。修改定时器、删除定时器
}
}
static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow )
{
// 定时器到期了,将定时器从 pxTimer->xTimerListItem队列中移除
// 如果自动重载,则重新计算超时时间,再把timer加入队列,并通过xTimerGenericCommand函数发送tmrCOMMAND_START_DONT_TRACE命令
// 最后执行定时器的回调函数
}四、定时器相关函数
TimerHandle_t xTimerCreate( const char * const pcTimerName, // 定时器名称
const TickType_t xTimerPeriodInTicks, // 定时器周期
const UBaseType_t uxAutoReload, // 是否自动重载
void * const pvTimerID, // ID
TimerCallbackFunction_t pxCallbackFunction )// 回调函数
{
Timer_t *pxNewTimer;
pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); // 分配空间
prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );// 初始化
return pxNewTimer;
}
static void prvInitialiseNewTimer( const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
Timer_t *pxNewTimer )
{
prvCheckForValidListAndQueue();
pxNewTimer->pcTimerName = pcTimerName;
pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
pxNewTimer->uxAutoReload = uxAutoReload;
pxNewTimer->pvTimerID = pvTimerID;
pxNewTimer->pxCallbackFunction = pxCallbackFunction;
vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); // 初始化链表节点
}
// 定时器删除函数
#define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) )
// 定时器复位函数
#define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
// 定时器启动函数
#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
// 定时器停止函数
#define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) )
// 定时器更改定时周期函数
#define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) )五、守护任务中对不同定时器函数命令的处理
[*]tmrCOMMAND_START、tmrCOMMAND_RESET、tmrCOMMAND_START_FROM_ISR、tmrCOMMAND_RESET_FROM_ISR、tmrCOMMAND_START_DONT_TRACE(重载),从list移除定时器,调用prvInsertTimerInActiveList将定时器加入pxCurrentTimerList中
[*]tmrCOMMAND_STOP、tmrCOMMAND_STOP_FROM_ISR,从list中移除定时器
[*]tmrCOMMAND_CHANGE_PERIOD、tmrCOMMAND_CHANGE_PERIOD_FROM_ISR,从list移除定时器,更新时间通过prvInsertTimerInActiveList加入list
[*]tmrCOMMAND_DELETE,,从list移除定时器,在vPortFree( pxTimer )释放空间
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]