仄谦 发表于 2025-7-14 20:29:04

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]
查看完整版本: FreeRTOS的软件定时器的源码分析