FreeRTOS tasks are not context switching

12,888

Solution 1

FreeRTOS is a priority based pre-emptive scheduler, tasks of equal priority that do not yield processor time will be round-robin scheduled. Relying on round-robin scheduling is seldom suitable for real-time tasks, and depending on the configured time slice, that may mess up your timing. Time-slicing may even be disabled.

Your tasks must enter the Blocked state waiting on some event (such as elapsed time) to allow each other to run as intended.

That said, entering the exception handler rather than simply one task starving another or not running with the intended timing is a different matter. For that you will need to post additional information, though your first approach should be to deploy your debugger.

Solution 2

The absolute first thing to check is your "tick" interrupt. Often interrupts are not enabled, timers aren't set up right, clocks are not configured properly in the #pragma's that set up the PIC32.. and all those issues manifest themselves first in a lack of a "tick".

This is the #1 cause of not task switching: if you're not getting the tick interrupt. That's where the normal pre-emptive task switching happens.

Assuming you're using the "off the shelf demo", in MPLAB, set a breakpoint in the void vPortIncrementTick( void ) function (around line 177 in FreeRTOS\Source\portable\MPLAB\PIC32MX\port.c) and run your code. If it breakpoints in there, your timer tick is working.

Solution 3

Do you have a round-robin scheduler? Are your tasks sleeping for any length of time, or just yielding (or busy waiting)?

A very common gotcha in embedded OSs is that the scheduler will frequently not attempt to schedule multiple processes of the same priority fairly. That is, once A yields, if A is runnable A may get scheduled again immediately even if B has not had any CPU for ages. This is very counterintuitive if you're used to desktop OSs which go to a lot of effort to do fair scheduling (or at least, it was to me).

If you're running into this, you'll want to make sure that your tasks look like this:

for (;;)
{
  led(on); sleep(delay);
  led(off); sleep(delay);
}

...to ensure that the task actually stops being runnable between blinks. It won't work if it looks like this:

for (;;)
{
  led(on);
  led(off);
}

(Also, as a general rule, you want to use normal priority rather than high priority unless you know you'll really need it --- if you starve a system task the system can behave oddly or crash.)

Solution 4

Are you sure both tasks are well registered and the scheduler has been launched?

Something like the following code would do the job:

xTaskCreate( yourFirstTask, "firstTask", STACK_SIZE, NULL, TASK_PRIORITY, NULL );
xTaskCreate( yourSecondTask, "secondTask", STACK_SIZE, NULL, TASK_PRIORITY, NULL );
vTaskStartScheduler();

You can also add an application tick hook to see if the tick interruption occurs correctly or if there is a problem with the tick timer.

Solution 5

There are standard demo tasks that just blink LEDs in the FreeRTOS/Demo/Common/Minimal/flash.c source file. The tasks created in that file are included in the standard PIC32 demo application (which targets the Microchip Explorer16 board).

In its very simplest form, a task that just toggles and LED every 500ms would look like this:

/* Standard task prototype, the parameter is not used in this case. */    
void vADummyTask( void *pvParameters )
{
const portTickType xDelayTime = 500 / portTICK_RATE_MS;

    for( ;; )
    {
        ToggleLED();
        vTaskDelay( xDelayTime );
    }        
}
Share:
12,888
Laz
Author by

Laz

Tinkering..

Updated on June 22, 2022

Comments

  • Laz
    Laz about 2 years

    I'm using FreeRTOS port for PIC32 microcontroller on the PIC32MX starter kit. Was just playing with tasks but the tasks aren't context switching. Here are my main config settings:

    #define configMAX_PRIORITIES    ( ( unsigned portBASE_TYPE ) 5 )
    #define configKERNEL_INTERRUPT_PRIORITY         0x01
    #define configMAX_SYSCALL_INTERRUPT_PRIORITY    0x03
    #define configTICK_RATE_HZ              ( ( portTickType ) 100 )
    

    Now I have two tasks defined which blink two LEDs. Both have priority of 4(highest). Under normal operation the LEDs should alternatively blink for each 100 ticks. But this doesn't happen. The second LED blinks for 100 ticks and the control goes to the general exception handler. Why does this happen? Seems like there is no scheduling at all.

  • semaj
    semaj over 13 years
    Be sure to check the return values of xTaskCreate to make sure the task creation did not fail for lack of sufficient memory for the task's stack space.