State machine program design in FreeRTOS - vTaskStartScheduler in a switch statement

不羁的心 提交于 2019-12-12 04:44:50

问题


I have a program design question in FreeRTOS:

I have a state machine with 4 states, and 6 tasks. In each state, different tasks must be executed, excepting Task1, which is always active:

State 1: Task1, Task2, Task3
State 2: Task1, Task2, Task3, Task4
State 3: Task1, Task5
State 4: Task1, Task6

Task1, Task3, Task4, Task5 and Task6 are periodic, and each one reads a different sensor.
Task2 is aperiodic, it sends a GPRS alarm only if a threshold is reached.

The switching between the states is determined by events from the sensor input of each task.

The initial approach for the design of main() is to have a switch to control the states, and depending on the state, suspend and activate the corresponding tasks:

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;
    }
}

My question is: where should I call vTaskStartScheduler(), in relation with the switch? It seems to me that in this code, once the vTaskStartScheduler is called, the program will never enter the switch statement.

Should I create another task always active to control the state machine, which has the previous while and switch statements inside, such as the following pseudocode?

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

Any advice will be much appreciated...


回答1:


To answer your question, vTaskStartScheduler() will, as the name suggests, start the scheduler. Any code after it will only execute when the scheduler is stopped, which in most cases is when the program ends, so never. This is why your switch won't run.

As you have already eluded to, for your design you could use a 'main' task to control the others. You need to have created this and registered it with the scheduler before calling vTaskStartScheduler().

On a side note, if you do go with this approach, you only want to suspend/resume your tasks on first entry into a state, not on every iteration of the 'main' task.

For example:

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;
}



回答2:


As Ed King metioned, your solution contains a major design flaw. That is - after starting scheduler, no code that's specified after it in the main function will ever execute until the scheduler is stopped.

I suggest implementing your state logic in Idle task (remember to include delays in your tasks not to starve the Idle hook from processing time). Idle task could block and unblock the tasks depending on the current state by menas of semaphores. Remember though, that the Idle hook is a task with a lowest possible priority, so be careful when designing your system. The solution suggested by me may be completely wrong when the tasks consume most of the processing time not allowing the Idle task to switch states.

Alternatively, you can create a superior task as mentioned by Ed King, with the highest priority.

To be honest, everything depends on what the task are really doing.



来源:https://stackoverflow.com/questions/46685292/state-machine-program-design-in-freertos-vtaskstartscheduler-in-a-switch-state

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!