坚持再坚持 发表于 2024-3-26 17:19:49

定时器的回调函数和任务的抢占

环境:STM32F407,软件定时器的优先级为“3”,普通任务的优先级为“2”,抢占式任务调度图中黄色是普通任务,在代码开始处反转I/O引脚电平。图中绿色是定时器的回调函数,定时器定时20ms,回调函数执行时间占用7ms。问题:在普通任务执行时,定时器定时时间结束会抢占普通任务,开始执行定时器的回调函数,怎么在回调函数执行的7ms中,普通任务执行了I/O引脚反转,抢占了高优先级的回调函数(在回调函数中不能执行含有主动阻塞的代码)??

坚持再坚持 发表于 2024-3-27 20:08:11

问题查明了,因为软件定时器的回调函数中嵌套了很多程序,在里面使用了vTaskDelay函数,导致守护任务阻塞了。

坚持再坚持 发表于 2024-3-27 20:12:10

“定时器回调函数在定时器服务任务的上下文中执行。 因此, 定时器回调函数永远不试图阻塞是至关重要的 。 例如,定时器回调函数在访问队列或信号时,不得调用 vTaskDelay()、 vTaskDelayUntil(),也不得 指定非零阻塞时间。”---这是FreeRTOS官网给的解释,在不影响守护任务调度的情况下,并且不将守护任务的优先级设定为最低,还是可以使用阻塞函数的吧??

坚持再坚持 发表于 2024-3-28 08:45:30

坚持再坚持 发表于 2024-3-27 20:12
“定时器回调函数在定时器服务任务的上下文中执行。 因此, 定时器回调函数永远不试图阻塞是至关重要的 。...

当FreeRTOS的配置项configUSE_TIMERS被设置为1时,在启动调度器时,会自动创建xTimerCreateTimerTask()任务,此任务的具体代码还没有详细查看,应该只处理与定时器相关的东西。如果此任务的优先级比较高,在不影响其它定时器的情况下,应该还是可以使用阻塞延时函数的吧

eric2013 发表于 2024-3-28 09:50:28

坚持再坚持 发表于 2024-3-27 20:12
“定时器回调函数在定时器服务任务的上下文中执行。 因此, 定时器回调函数永远不试图阻塞是至关重要的 。...

不可以调用。

skyshine 发表于 2024-3-28 15:03:54

为啥要在中断里阻塞延时,改成任务通知或者信号量呗,定时器回调里用任务通知和信号量,出来直接切到目标任务,目标任务就用来死等延时,优先级设置高一点避免被其他任务打断。vTaskDelay()这种延时会把cpu让出来给其他低优先级任务,要避免上面这种情况最好还是死等。

坚持再坚持 发表于 2024-3-29 14:14:29

skyshine 发表于 2024-3-28 15:03
为啥要在中断里阻塞延时,改成任务通知或者信号量呗,定时器回调里用任务通知和信号量,出来直接切到目标任 ...

1、图中一个是普通任务(优先级为2),一个是定时器的回调函数(优先级为3),没有在中断里面阻塞延时;
2、因为普通任务和回调函数都在调用函数A,为了防止函数A的SPI时序被打断,函数A使用了信号量。可能是为了更及时的获取信号量,在获取信号量代码之前先延时了1ms。所以在定时器的回调函数里面会阻塞。
函数A:
         vTaskDelay(M2T(1));
         xSemaphoreTake(s_mlToken, portMAX_DELAY);获取信号量
         SPI相关的代码
          xSemaphoreGive(s_mlToken);释放信号量
其实代码中的延时函数多余了
页: [1]
查看完整版本: 定时器的回调函数和任务的抢占