freertos提供了soft timer。
如果使用了soft timer,那么OS中,需要存在一个专门的任务,soft timer task。简称STT。在freertos中,STT就是DaemonTask。任务中,可以设置一个时刻,当时刻到的时候,soft timer task会调用注册的callback,
注意,callback运行在DaemonTask中,不会有独立的任务资源。
所以,在callback中,不能调用任何可能阻塞STT的API。
例如,taskDelay,taskDelayUntil之类的API。
再例如,RPC类的API,访问信号量,访问队列等。
freertos提供了一系列和soft timer相关的API。
这些API,向soft timer command queue发送命令消息。STCQ是不能被用户直接访问的。
例如,
在用户任务中,调用了xTimerReset这个API,
OS执行这个API时,是向STCQ发送一个cmd,当DaemonTask获得CPU后,会从STCQ中获取命令消息,然后解析,执行,并调用callback。
++++++++++++++++++++++++++++++++++++
常用的soft timer相关的API有,
xTimerStart----启动soft timer,开始更新tick counter,并在每个tick,执行STCQ中的命令,检查是否有callback需要被调用。等。
xTimerStop----停止soft timer。
xTimerReset----将tick counter的值归零,但是并不是停止soft timer,而是重新开始计数。
对应的fromisr版本的API,用于ISR中。
++++++++++++++++++++++++++++++++++++
来看看soft_timer_task。
//TimerControl的任务函数
void soft_timer_task(void *pvParameters)
{
u8 key,num;
for(;;)
{
key = KEY_Scan(0);
switch(key)
{
case WKUP_PRES: //当key_up按下的话打开周期定时器
xTimerStart(AutoReloadTimer_Handle,0); //开启周期定时器
printf("开启定时器1\r\n");
break;
case KEY0_PRES: //当key0按下的话打开单次定时器
xTimerStart(OneShotTimer_Handle,0); //开启单次定时器
printf("开启定时器2\r\n");
break;
case KEY1_PRES: //当key1按下话就关闭定时器
xTimerStop(AutoReloadTimer_Handle,0); //关闭周期定时器
xTimerStop(OneShotTimer_Handle,0); //关闭单次定时器
printf("关闭定时器1和2\r\n");
break;
}
num++;
if(num==50) //每500msLED0闪烁一次
{
num=0;
LED0=!LED0;
}
vTaskDelay(10); //延时10ms,也就是10个时钟节拍
}
}
这是一个前台任务,一个输入任务。
扫描按键,根据不同的按键状态,向不同的soft timer内核对象的STCQ发送cmd。
每个soft timer,都有对应于自己的DaemonTask.
DaemonTask运行时,会检查tick counter的计数,如果时间到,则会调用注册到soft timer中的callback。
+++++++++++++++++++++++++++++++++++++++++++
来看看soft timer 和callback的关系。
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建软件周期定时器
AutoReloadTimer_Handle=xTimerCreate((const char* )"AutoReloadTimer",
(TickType_t )1000,
(UBaseType_t )pdTRUE,
(void* )1,
(TimerCallbackFunction_t)AutoReloadCallback); //周期定时器,周期1s(1000个时钟节拍),周期模式
//创建单次定时器
OneShotTimer_Handle=xTimerCreate((const char* )"OneShotTimer",
(TickType_t )2000,
(UBaseType_t )pdFALSE,
(void* )2,
(TimerCallbackFunction_t)OneShotCallback); //单次定时器,周期2s(2000个时钟节拍),单次模式
//创建定时器控制任务
xTaskCreate((TaskFunction_t )timercontrol_task,
(const char* )"timercontrol_task",
(uint16_t )TIMERCONTROL_STK_SIZE,
(void* )NULL,
(UBaseType_t )TIMERCONTROL_TASK_PRIO,
(TaskHandle_t* )&TimerControlTask_Handler);
vTaskDelete(StartTask_Handler); //自删
taskEXIT_CRITICAL(); //退出临界区
}
在创建soft timer的时候,注册了callback。
+++++++++++++++++++++++++++++++++++++++++++
来看看callback。
void AutoReloadCallback(TimerHandle_t xTimer)
{
static u8 tmr1_num=0;
tmr1_num++; //周期定时器执行次数加1
LCD_ShowxNum(70,111,tmr1_num,3,16,0x80); //显示周期定时器的执行次数
LCD_Fill(6,131,114,313,lcd_discolor[tmr1_num%14]);//填充区域
}
void OneShotCallback(TimerHandle_t xTimer)
{
static u8 tmr2_num = 0;
tmr2_num++; //周期定时器执行次数加1
LCD_ShowxNum(190,111,tmr2_num,3,16,0x80); //显示单次定时器执行次数
LCD_Fill(126,131,233,313,lcd_discolor[tmr2_num%14]); //填充区域
LED1=!LED1;
printf("定时器2运行结束\r\n");
}
callback在DaemonTask中被调用执行。
从虚拟CPU的角度看,DaemonTask在tick counter不满足条件时自旋,知道tick counter满足条件时,跳出自旋,开始执行callback。
+++++++++++++++++++++++++++++++++++++++++++++
版权声明:本文为CSDN博主「Huskar_Liu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42418557/article/details/122157431
暂无评论