Switching to idle state for a moment instead of switching to higher priority task at once

Hi, I ran into some problem when trying to understand how are tasks in FreeRTOS working. Expected result for given code was:
-only red LED ON → only green LED ON → only blue LED ON → and so on
but after first loop, which was ok instead of green LED switching on after red, there is blue LED (idle task) for a while before that. I wanted to paste link to yt video showing that, but I can’t. There is code:

#include "led.h"
#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "MKV58F24.h"
#include "fsl_debug_console.h"

#include "FreeRTOS.h"
#include "task.h"


#define my_task_PRIORITY (configMAX_PRIORITIES - 1)

static void prvSetupHardware(void);
static void vHelloTask(void *pvParameters);
static void vLEDTask(void *pvParameters);
void vApplicationIdleHook(void);

int main(void) {

    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitBootPeripherals();
    BOARD_InitDebugConsole();

	prvSetupHardware();

    if (xTaskCreate(vLEDTask, "LED_RED", configMINIMAL_STACK_SIZE + 10, "r", 3, NULL) != pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1) ;
    }
    if (xTaskCreate(vLEDTask, "LED_GREEN", configMINIMAL_STACK_SIZE + 10, "g", 2, NULL) != pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1) ;
    }

    vTaskStartScheduler();

    while(1) {

    }
    return 0 ;
}

static void prvSetupHardware(void)
{
	initLed('b');
	initLed('g');
	initLed('r');
}


static void vLEDTask(void *pvParameters)
{
	char color = *((char*)pvParameters);
	for (;;) {
		onLed(color);
		for(int i=8000000;i>0;i--);
		vTaskDelay( 4000 / portTICK_RATE_MS );
	}

	vTaskDelete(NULL);
}

void vApplicationTickHook(void)
{
	offLed('r');
	offLed('g');
	offLed('b');
}


void vApplicationIdleHook(void)
{
	onLed('b');
}

Hi @dloew, what is this code supposed to do?

1 Like

Why are you trying to turn off LEDs in tick hook? Tick hook is called on every tick.

An alternate can be to start with all the LEDs off and toggle them in the tasks:

static void vLEDTask(void *pvParameters)
{
	char color = *((char*)pvParameters);
	for (;;) {
		toggleLed(color);
		vTaskDelay( pdMS_TO_TICKS(4000) );
	}
	vTaskDelete(NULL);
}

void vApplicationTickHook(void)
{
   /* Do nothing. */
}


void vApplicationIdleHook(void)
{
	toggleLed('b');
}

Thanks.

1 Like

To turn off LED’s every tick just to be sure that currently running task switch on specified diode back. Even without that and turning led’s off in every switch context using this code in FreeRTOSConfig.h:

#define traceTASK_SWITCHED_OUT()				\
		offLed('r'); \
		offLed('g'); \
		offLed('b');

effect is the same and there is the same problem.

Hi dloew,

this code is bound to yield indeterministic results unless the busy loop gets optimized away (in which case it is useless anyways). If the loop does not get optimized away, the actual busy time depends on the generated code and the processor speed. If the CPU busy period happens to be longer than the following delay loop, your lower priority task may get starved out.

What actually do you expect to see with this indeterministic setup? What happens if you make the test suite deterministic?

1 Like

Thank You for all answers. I agree that it’s nondeterministic, so there can be some problems. I suppose that there was happening sth like that:
freertos
Following for loop ‘for(int i=8000000;i>0;i–);’ takes about 1s (ON state of LED). I don’t know yet, why after changing it to ‘for(int i=16000000;i>0;i–);’ it’s what I expected (switching to green task at once).