找回密码
 立即注册
首页 业界区 安全 FreeRTOS的软件定时器的源码分析

FreeRTOS的软件定时器的源码分析

仄谦 2025-7-14 20:29:04
一、软件定时器的特性


  • 定时器的关键成员:周期、回调函数
  • 定时器的指定类型:一次性、可自动重载定时器
  • 定时器的状态:运行、休眠
  • FreeRTOS的软件定时器基于Tick中断实现,但是由于实时系统不允许在内核、中断中执行不确定时间的代码,因此定时器函数被放到了RTOS守护任务中实现
二、RTOS守护任务


  • 优先级:configTIMER_TASK_PRIORITY,默认是2,高于IDLE任务
  • 消息队列的长度:configTIMER_QUEUE_LENGTH,默认是10,40字节
  • 用户调用定时器函数,通过专用的定时器消息队列,发送给RTOS守护任务,在RTOS守护任务中读消息队列,并执行相应的定时器处理函数
  • prvTimerTask在调用vTaskStartScheduler时被创建
三、prvTimerTask任务
  1. static void prvTimerTask( void *pvParameters )
  2. {
  3.   TickType_t xNextExpireTime;
  4.   BaseType_t xListWasEmpty;
  5.   for( ;; )
  6.   {
  7.     xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty );        // 从pxCurrentTimerList获得下一个定时器到期时间,升序排列,头表示第一个到期的定时器
  8.     prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty );    // 定时器到期执行prvProcessExpiredTimer,没到期则有时间限制的等待xTimerQueue(最多等xNextExpireTime - xTimeNow)  
  9.     prvProcessReceivedCommands();                                    // 处理接收命令,非阻塞循环读取队列xTimerQueue,处理message,包括启动定时器、停止定时器。修改定时器、删除定时器
  10.   }
  11. }
  12. static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow )
  13. {
  14.   // 定时器到期了,将定时器从 pxTimer->xTimerListItem队列中移除
  15.   // 如果自动重载,则重新计算超时时间,再把timer加入队列,并通过xTimerGenericCommand函数发送tmrCOMMAND_START_DONT_TRACE命令
  16.   // 最后执行定时器的回调函数
  17. }
复制代码
四、定时器相关函数
  1. TimerHandle_t xTimerCreate(        const char * const pcTimerName,                            // 定时器名称
  2.                                                                 const TickType_t xTimerPeriodInTicks,   // 定时器周期
  3.                                                                 const UBaseType_t uxAutoReload,         // 是否自动重载
  4.                                                                 void * const pvTimerID,                 // ID
  5.                                                                 TimerCallbackFunction_t pxCallbackFunction )  // 回调函数
  6. {
  7.   Timer_t *pxNewTimer;
  8.   pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );          // 分配空间
  9.   prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );  // 初始化
  10.   return pxNewTimer;
  11. }
  12. static void prvInitialiseNewTimer(        const char * const pcTimerName,
  13.                                                                         const TickType_t xTimerPeriodInTicks,
  14.                                                                         const UBaseType_t uxAutoReload,
  15.                                                                         void * const pvTimerID,
  16.                                                                         TimerCallbackFunction_t pxCallbackFunction,
  17.                                                                         Timer_t *pxNewTimer )
  18. {
  19.   prvCheckForValidListAndQueue();
  20.   pxNewTimer->pcTimerName = pcTimerName;
  21.   pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
  22.   pxNewTimer->uxAutoReload = uxAutoReload;
  23.   pxNewTimer->pvTimerID = pvTimerID;
  24.   pxNewTimer->pxCallbackFunction = pxCallbackFunction;
  25.   vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );    // 初始化链表节点
  26. }
  27. // 定时器删除函数
  28. #define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) )
  29. // 定时器复位函数
  30. #define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
  31. // 定时器启动函数
  32. #define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
  33. // 定时器停止函数
  34. #define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) )
  35. // 定时器更改定时周期函数
  36. #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 )释放空间

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册