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

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 answer

  • answered 2017-10-11 10:01 Ed King

    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.