freertos(第五课 softtimer)

freertos提供了soft timer,需要为softtimer挂接callback,当时间到达后,就会触发callback执行。
callback在timer的服务任务中执行的,所以,不能使用可能阻塞任务的API。
一般使用SysTick作为softtimer的基础时钟。
两次触发callback的时间间隔xTimerPeriodInTicks叫做定时周期。

freertos通过一个prvTimerTask任务(Daemon Task)管理softtimer。这个任务是在启动调度器时,自动创建的。
Daemon Task 会在执行期间,轮询软件定时器,如果满足条件,则调用callback。

#define configUSE_TIMERS 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTICK_RATE_HZ 1000

这两个配置宏,使能了软件定时器,并设置了TICK。

类似于linux中的jiffies,freertos中,也会维护一个全局变量xTickCount,作为系统时间。
当用户创建一个softtimer时,freertos会根据用户设置的定时数,在当前jiffies上后延设置的定时数,并填充到softtimer的唤醒时间中。然后将softtimer的控制块插入软件定时器列表。
freertos维护了两个TIMERLIST。
pxCurrentTimerList, pxOverflowTimerList。
新创建的SoftTimer,会以jiffies升序的顺序,插入pxCurrentTimerList.
DaemonTask在运行时,会按顺序扫描pxCurrentTimerList,如果首元超时,则调用首元对应的Callback,如果首元都没有超时,那么其他定时器也一定没有超时,所以这时,DaemonTask挂起。
pxOverflowTimerList作用与之一致。

编写软件定时器的callback时,应该快进快出,不允许阻塞DaemonTask,更不允许死循环。
DaemonTask的任务优先级应该尽量高,从而获得更好的时间响应度。
单次软件定时器的Callback被执行完并返回后,系统会自动删除TIMER,并回收资源。

用户程序通过Timer command queue和 Daemon Task进行通信。
在用户程序中,使用TIMER API,freertos负责将一个command发送到Timer command queue中,当DaemonTask运行时,从command queue中获取命令。

#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)
#define configTIMER_QUEUE_LENGTH
#define configTIMER_STACK_DEPTH

这几个宏,用来配置DaemonTask。

来看看TIMER的控制块。

typedef struct tmrTimerControl{
	const char* pcTimerName;
	ListItem_t xTimerListItem;
	TickType_t xTimerPeriodInTicks;
	UBaseType_t uxAutoReload;

	TimerCallbackFunction_t pxCallbackFunction;
	void* pvTimerID;
}xTIMER;
typedef xTIMER Timer_t;

在xTimerListItem的value中,存放唤醒时间jiffies。

来看看TIMER API。
1)创建。
xTimerCreate(),动态创建一个TIMER对象,并返回句柄。

TimerHandle_t 
xTimerCreate(
			const char* const pcTimerName,
			const TickType_t xTimerPeriodInTicks,
			void * const pvTimerID,
			TimerCallbackFunction_t pxCallbackFunction
			);

2)启动。
xTimerStart,将TIMER启动,并添加到ACTIVELIST中。

BaseType_t xTimerStart(TimerHandle_t xTimer, TickType_t xBlockTime);

BaseType_t 
xTimerStartFromISR(
		TimerHandle_t xTimer, 
		BaseType_t* pxHigherPriorityTaskWoken
		);

3)停止。
xTimerStop,将TIMER停止,并从ACTIVELIST中移除。

BaseType_t xTimerStop(TimerHandle_t xTimer, TickType_t xBlockTime);

BaseType_t 
xTimerStopFromISR(
		TimerHandle_t xTimer, 
		BaseType_t* pxHigherPriorityTaskWoken
		);

4)复位。
xTimerReset,用来复位TIMER。

BaseType_t xTimerReset(TimerHandle_t xTimer, TickType_t xTicksToWait);

BaseType_t 
xTimerResetFromISR(
		TimerHandle_t xTimer, 
		BaseType_t* pxHigherPriorityTaskWoken
		);

5)删除。

BaseType_t xTimerDelete(TimerHandle_t xTimer, TickType_t xTicksToWait);

来看一个具体的例子。

static TimerHandle_t Swtmr1_Handle = NULL;
static TmerHandle_t Swtmr2_Handle = NULL;

// in apptask
Swtmr1_Handle = xTimerCreate(
			(const char*)"AutoReloadTimer",
			(TickType_t)1000,
			(UBaseType_t)pdTRUE,
			(void*)1,
			(TimerCallbackFunction_t)Swtmr1_Callback 
	);

if(Swtmr1_Handle != NULL){
	xTimerStart(Swtmr1_Handle, 0);
}

Swtmr2_Handle = xTimerCreate(
			(const char*)"OneShotTimer",
			(TickType_t)5000,
			(UBaseType_t)pdFALSE,
			(void*)2,
			(TimerCallbackFunction_t)Swtmr2_Callback 
	);

if(Swtmr2_Handle != NULL){
	xTimerStart(Swtmr2_Handle, 0);
}

static void Swtmr1_Callback(void* parameter)
{
	TmrCb_Count1++;
	return;
}

static void Swtmr2_Callback(void* parameter)
{
	TmrCb_Count2++;
	return;
}

对于系统中,一些基于时间事件驱动的操作和行为,用TIMER是比较合适的。
系统负责管理时间点,开发者只需要关注于TIMEEVENT ACTION。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值