状态机程序设计在FreeRTOS-vTaskStartScheduler中的一个switch语句



我在FreeRTOS:中有一个程序设计问题

我有一个状态机,有4个状态和6个任务。在每种状态下,必须执行不同的任务,Task1除外,它始终处于活动状态:

状态1:Task1,Task2,Task3
状态2:Task1,Task2,Task3,Task4
州3:Task1,Task 5
国家4:Task1,任务6

任务1、任务3、任务4、任务5和任务6是周期性的,每个任务读取不同的传感器
Task2是非周期性的,它只有在达到阈值时才会发送GPRS警报。

状态之间的切换由来自每个任务的传感器输入的事件决定。

main()设计的最初方法是有一个开关来控制状态,并根据状态暂停和激活相应的任务:

void main ()
{
/* initialisation of hw and variables*/
system_init(); 
/* creates FreeRTOS tasks and suspends all tasks except Task1*/
task_create();
/* Start the scheduler so FreeRTOS runs the tasks */
vTaskStartScheduler(); 
while(true)
{
switch STATE:
case 1:
suspend(Task4, Task5, Task6);
activate(Task2, Task3);
break;
case 2:
suspend(Task5, Task6);
activate(Task2, Task3, Task4);
break;
case 3:
suspend(Task2, Task3, Task4, Task6); 
activate(Task5);
break;
case 4: 
suspend(Task2, Task3, Task4, Task5);
activate(Task6);
break;
}
}

我的问题是:对于开关,我应该在哪里调用vTaskStartScheduler()?在我看来,在这段代码中,一旦调用vTaskStartScheduler,程序就永远不会进入switch语句。

我应该创建另一个始终处于活动状态的任务来控制状态机吗?状态机中有前面的while和switch语句,例如下面的伪代码?

task_control()
{
while(true)
{
switch STATE:
case 1: 
suspend(Task4, Task5, Task6);  
execute(Task2, Task3); 
and so on...
}
}  

任何建议都将不胜感激。。。

要回答您的问题,顾名思义,vTaskStartScheduler()将启动调度程序。之后的任何代码都只会在调度程序停止时执行,在大多数情况下,这是程序结束时,所以永远不会执行。这就是您的switch无法运行的原因。

正如你已经回避的那样,对于你的设计,你可以使用一个"主要"任务来控制其他任务。在调用vTaskStartScheduler()之前,您需要创建并向调度程序注册它。

顺便说一句,如果你采用这种方法,你只想在第一次进入状态时暂停/恢复你的任务,而不是在"主"任务的每次迭代中。

例如:

static bool s_first_state_entry = true;
task_control()
{
while (true)
{
switch (STATE)
{
case 1:
if (s_first_state_entry)
{  
// Only do this stuff once              
s_first_state_entry = false;
suspend(Task4, Task5, Task6);  
execute(Task2, Task3); 
}
// Do this stuff on every iteration
// ...
break;
default:
break;
}
}
}  
void set_state(int state)
{
STATE = state;
s_first_state_entry = true;
}
正如Ed King所说,您的解决方案包含一个主要的设计缺陷。也就是说,在启动调度程序之后,在主函数中指定的任何代码都不会执行,直到调度程序停止。

我建议在Idle任务中实现您的状态逻辑(记住在任务中包含延迟,以免使Idle钩子无法处理时间)。空闲任务可以根据当前状态通过大量信号量来阻塞和取消阻塞任务。不过,请记住,空闲挂钩是一项优先级尽可能低的任务,因此在设计系统时要小心。当任务消耗了大部分处理时间而不允许空闲任务切换状态时,我提出的解决方案可能是完全错误的。

或者,您可以创建Ed King提到的具有最高优先级的高级任务。

老实说,一切都取决于任务真正在做什么。

最新更新