Priorities are not observed (apparently)

I’m using FreeRTOS 8.0.1 on an ARM Cortrex M4F (NRF52832) I have the following issue: There is a writing task SM (priority 2, sorry for the name, it actually means ‘System Manager’ 🙂 ) and a reading task NI (priority 1). The reading task sometimes needs to read a lot of data from our storage. However, it does this in bursts, taking a mutex, reading a block, and releasing the mutex again. The writing task should have precidence over the reading task. However this does not seem to happen. The reading task does not seem to want to yield to the writing task. At some point the writing task will not be able to get the mutex within a reasonable limit. In that case the writing tasks writes an error message and does a busy waiting loop. There are no mutex besides the read and write mutex (and the SPI mutex below). But all should be released once the task have completed the read and/or write operation. I’ve looked through the code and every branch is covered. Two observations, see SystemView screenshot. First the SM task indicates it wants to run (-300 us), but does not seem to get to run! second the NI wants to run, and does get to run. Why? MS task has higher priority and should run first. Second, even though the SM task has a higher priority, the NI task still gets time from FreeRTOS. Any insights welcome. Sysview screenshot

Priorities are not observed (apparently)

I can’t see the SystemView image at the moment. Have you read the section “Mutexes and Task Scheduling” in the book that can be downloaded here: https://www.freertos.org/Documentation/RTOS_book.html – it starts on page 256 in my copy. I don’t think it is exactly what you are seeing, as it refers to the case where both tasks have the same priority, but it may give you some ideas. Does the writing task block anywhere else? Or just on the Mutex?

Priorities are not observed (apparently)

Hi Richard, No both tasks have different priority. Its like pre-emption isn’t happening, though the kernel was configured as such and uses 32 kHz RTC for ticks. From the attachment you can see where the mutex is released. At this point the SM task goes into ready, which is exactly what should happen, except that that it does not go into running. The NI task just keeps running and starts loading the next block of data, at which point the SM task can no longer acquire the lock, as it missed the window of oppertunity. I can ‘hack’ it by introducing a 1 tick delay after the release of the mutex by the NI task. This will cause the SM task to actually start running. If I do an explicit taskYield() it does seem to help, but it doesn’t always work. The portYield is written like this: ~~~ /* Scheduler utilities. */

define portYIELD() do

{ /* Set a PendSV to request a context switch. */ SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; __SEV(); /* Barriers are normally not required but do ensure the code is completely within the specified behaviour for the architecture. */ __DSB(); __ISB(); }while (0) ~~~

Priorities are not observed (apparently)

Hi Richard, I seem to not have replied to this post, as was my intention. See reply below. Cheers, Vincent

Priorities are not observed (apparently)

This does not look like our code – see the implementation of portYIELD() on line 81 (at the time of writing) https://sourceforge.net/p/freertos/code/HEAD/tree/trunk/FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h Where did the FreeRTOS port come from? What else is different from the official port?

Priorities are not observed (apparently)

Hi Richard, This is part of the nRF5x SDK from Nordic Radio. Looking at the code, though written differently, it does do the same thing. Much has changed, but technically it seems very similar. I have attached the complete portmacro file. What would prevent FreeRTOS from preempting after the release of the lock? And why is it different when using a delay? Regards, Vincent

Priorities are not observed (apparently)

What would prevent FreeRTOS from preempting after the release of the lock? And why is it different when using a delay?
The only thing would be if you were in a critical section or the scheduler was suspended (vTaskSuspendAll()) – but you are not supposed to call API functions when either of those are the case. We have lots of tests to check tasks run in the correct order. Normally the only time things happen in a way users don’t expect is when the two tasks have the same priority – hence the book chapter.