A single task doesn't run with a priority other than 0

I’ve struggling with priorities in FreeRTOS. After some research I found that a program with a single task with priority other than 0 (the lowest), does not run! For example:

 xTaskCreateStatic(
          plc_kernel_task,
          ( const portCHAR* ) "PLC",
          TASK_PLC_KERNEL_STACK_SIZE,
          NULL,
          1,
          plc_kernel_task_ram,
          &plc_kernel_task_tcb );

(with: #define configMAX_PRIORITIES 3)

will not run. But if I change its priority to 0, then it runs smoothly.

It gets worst. If I have two tasks, TA and TB, where TA has a priority greater than TB (say (configMAX_PRIORITIES-1) vs tskIDLE_PRIORITY, respectively) neither task run. However, if I swap their priorities ( tskIDLE_PRIORITY vs configMAX_PRIORITIES-1) then both tasks run. TA is the master, and TB is the slave (from a binary semaphore point of view).

It sounds crazy but that’s the problem I’m facing it. Maybe I’m missing something. Any ideas? I could reduce the problem to the one I mentioned, so for the moment ignore the problem with two tasks.

Is there a problem with priorities?

I’m coding my program for the Arduino UNO (ATmega328 port) board on Linux, so I can’t debug (GDB) the program from inside. I’m not using sketches, instead I’m using Arduino-Makefile.

Thanks in advanced!

I will have to say that I have never seen FreeRTOS do other than run the highest priority ready task, unless I have done something to corrupt the FreeRTOS structures.

Do you have stack checking enabled?
Do you have configASSERT defined, and in a way that you can be sure to know if it is triggered?
How do you know that the tasks are not being run?

Yes, the Arduino environment makes things much harder to debug real problems.

Hi Richard,

I will have to say that I have never seen FreeRTOS do other than run the highest priority ready task, unless I have done something to corrupt the FreeRTOS structures.

Many examples in the official documentation use the tskIDLE_PRIORITY.

Do you have stack checking enabled?

I’m using static objects (xTaskCreateStatic()), so there’s no need to check the stack (I think/hope so).

Do you have configASSERT defined, and in a way that you can be sure to know if it is triggered?

No, I don’t, and I’ll do it ASAP.

How do you know that the tasks are not being run?

I’ve started my project blinking LEDs before jumping out to more complicated stuff. And the LED blinks whenever the task’s priority is exactly the lowest (0):

//----------------------------------------------------------------------
//                     plc_kernel_task()
//----------------------------------------------------------------------
static const uint16_t TASK_PLC_KERNEL_STACK_SIZE = 256;
static StaticTask_t plc_kernel_task_tcb;
static StackType_t plc_kernel_task_ram[ TASK_PLC_KERNEL_STACK_SIZE ];
TaskHandle_t main_task_handler;
void plc_kernel_task( void* pvParameters )
{
   pinMode( 13, OUTPUT );
   digitalWrite( 13, HIGH );
   
   TickType_t last_wake_time = xTaskGetTickCount();
   FOREVER
   {
      vTaskDelayUntil( &last_wake_time, pdMS_TO_TICKS( 1000 ) );

      digitalWrite( 13, HIGH );

      vTaskDelay( pdMS_TO_TICKS( 200 ) );

      digitalWrite( 13, LOW );

      Serial.println( ":PLC" );
   }
}


int main(void)
{
   cli();

   xTaskCreateStatic(
         plc_kernel_task,
         ( const portCHAR* ) "PLC",
         TASK_PLC_KERNEL_STACK_SIZE,
         NULL,
         1,                                           // <=== HERE IS THE PROBLEM !!
         plc_kernel_task_ram,
         &plc_kernel_task_tcb );

   // more stuff ...
}

If I set the priority to 0 then the system works (LED and serial output work as expected). But once I change its value to other than 0 (1 or 2), then the systems seems to do nothing. Of course it carries a lot of issues.

Did I discover a bug?

Yes, the Arduino environment makes things much harder to debug real problems.

As hell =)

I’ll try configASSERT and I’ll let you know. Thank you!

I’m using static objects (xTaskCreateStatic()), so there’s no need to check the stack (I think/hope so).

Creating tasks as static objects does NOT guarantee that you don’t overrun your stack. Unless your task has NO local variables and calls no functions (not even standard library functions) you will be using stack and could use too much of it.

Doing all your creation via CreateStatic means you can probably get away with a smaller heap, and don’t need to check for success as much, as it can’t fail due to lack of heap (but it still is good to check, as you still might get failures due to bad parameters).

Hi Richard,

The FreeRTOS functions that check the stack do so based upon the user’s heap, which I’m not using whatsoever. From FreeRTOSConfig.h:

#define configSUPPORT_STATIC_ALLOCATION       1
//#define configSUPPORT_DYNAMIC_ALLOCATION    0
//#define configTOTAL_HEAP_SIZE               (( UBaseType_t )( 1500 ))

#define configMAX_PRIORITIES                  3

As you see, I’ve disabled completely the dynamic support. Dynamic memory allocation is bad, really bad.

In the other side, when compiling the program (that has grown up from the last post) ) I get this:

AVR Memory Usage
----------------
Device: atmega328p

Program:    5822 bytes (17.8% Full)
(.text + .data + .bootloader)

Data:       1255 bytes (61.3% Full)
(.data + .bss + .noinit)

(ATmega328 has 2KB of RAM.)

As I shown in a prev post, the memory stack for my tasks is in boundaries:

static const uint16_t TASK_PLC_KERNEL_STACK_SIZE = 256;
static const uint16_t TASK_MAIN_STACK_SIZE = 128 * 3;

Now let consider that actually there’s a problem with memory, then Why both tasks run whenever their priorities are set to 0? That’s the question. Why don’t they run whenever priorities are set to 1 (for example)?

I think I need to debug this simple program in another microcontroller for which I already have the tools for debugging in Linux. For example, I’ll try it on the LPC1114 from NXP (Eclipse IDE based) to reproduce the bug, and if so, to fix it. Well, I cannot fix it. You’ve read from my other post that hacking the FreeRTOS core is a nightmare =)

The stack check routine do NOT need the stack to come from the heap, but use the base of stack value stored in the TCB, and compare that to the stack pointer, or check the first few bytes to see if the check pattern is still there.

You may be thinking of the basic stack check that some heaps use that compare the main program stack to the current heap top (which don’t work with FreeRTOS after the scheduler is started, since that stack at the end of memory isn’t the one normally being used.

As to why things don’t work, I don’t know, but I do know that the only time I have seen issues with tasks running is either the tasks block themselves, or memory has been corrupted, normally by stack overflow or bad interrupt priorities.

You’re right. I didn’t think it thoroughly: I was thinking when the heap is full. The stack can overflow no matter how the task was created.