问题
有两种创建定时器的方式,刚开始我把定时器作为局部变量来使用。
后来出于业务需求,需要把定时器作为全局变量来使用,就出现了下面的问题。
// 创建周期性定时器,周期为1s(手动)
TimerHandle_t countdown_timer;
countdown_timer = xTimerCreate("CountdownTimer", pdMS_TO_TICKS(1000), pdTRUE, (void *)0, CountdownTimerCallback);
void Ctrl_Task_Func(void *argument)
{
while(1)
{
}
}
这样就报错:
…\App\task_ctrl.c(13): error: #77-D: this declaration has no storage class or type specifier
…\App\task_ctrl.c(13): error: #147: declaration is incompatible with “TimerHandle_t countdown_timer” (declared at line 12)
…\App\task_ctrl.c(13): error: #59: function call is not allowed in a constant expression
解决
// 创建周期性定时器,周期为1s(手动)
TimerHandle_t countdown_timer;
void Ctrl_Task_Func(void *argument)
{
countdown_timer = xTimerCreate("CountdownTimer", pdMS_TO_TICKS(1000), pdTRUE, (void *)0, CountdownTimerCallback);
while(1)
{
}
}
像这样,把定时器创建放在任务函数中,就没有任何错误。这是为啥呢?
查阅资料发现:
-
xTimerCreate()
是 FreeRTOS 中的 API,用于创建定时器。它不能在全局作用域中调用。FreeRTOS 的定时器需要与 RTOS 的调度和内存管理配合工作,而它在调用时需要保证任务调度环境已经初始化好(如系统时钟、调度器等),而这些通常只在任务调度启动之后才可用。 -
countdown_timer
是在全局作用域声明的,但如果它在声明时直接调用xTimerCreate()
,编译器会把xTimerCreate()
当成一个不符合全局变量声明规则的函数调用,因为它应该在任务或初始化阶段进行,而不是在全局声明部分。
因此,不要在全局作用域中调用 xTimerCreate(),应该在任务中进行调用。