Closed hreintke closed 1 year ago
(Note, you should update because this file was changed for the 3.2.1 release to clean it up and handle the IRQ stuff automatically.)
This is basically an artifact of the way FreeRTOS was patched^Whacked in to the core. In the plain SDK case, if the mutex is already locked on this core then we're in some bad state. There's no idea of "waking up" the holding process, because there are no processes. Only core0, core1 and core0irq, core1irq contexts. If the mutex is locked on the other core we can make forward progress so will block until it's available.
--edit start--
In this case it seems like you got a task swapped out while holding the mutex, only to swap in another which tries to grab the mutex but fails, since the swapped-out task has it. I think in the FreeRTOS case this will happen even if they're not on the same core.
So actually, this will happen even if the other task is not swapped out. It will be running with the lock and this code will see it and not do the "am I on the same core" check the main core does and immediately bail. So it's actually handling things worse than the basic core stuff at this point...
--edit end--
And, there is no check in the FromISR whether the mutex is taken.
I thought the underlying call will block in the SMP FreeRTOS, so there is no need to do anything special. If you try to grab a mutex in an ISR that someone else already has, and you're on the same core, well then that's gonna be a bad time...
--edit 2--
https://www.freertos.org/xSemaphoreTakeFromISR.html
Yup, it can fail so your change looks like the start of a good idea. It still needs some work, however, because the GiveFromISR needs to do some magic stuff if there was a prio inversion per: https://www.freertos.org/a00124.html . That's actually a significant change to the core proper because it can't be isolated in the wrapper. The return from ISR itself needs that new call portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
--edit end
Still investigating, but what are your thoughts about this ?
I'll need to think about this, but feel free to do a PR. I made certain assumptions while using this RAII model in the core which I can guarantee are true in the case where FreeRTOS behaves exactly as base SDK. Conceptually, I think you're right and we can use the FreeRTOS priority inversion stuff to handle the case w/o punting.
Re: portYieldFromISR, it looks like this is a nice to have but not 100% necessary call, per the (old) discussion at https://www.freertos.org/FreeRTOS_Support_Forum_Archive/May_2009/freertos_What_if_portYIELD_FROM_ISR_not_used_3282756.html
If there was someone else holding the mutex during an ISR, to me it looks like you could have a lower prio task running until the next task switch. Not the most correct, but not going to crash. And requiring no core changes outside the CoreMutex.
Looks like what you've already done is good enough to go to a PR, I think!
My primary remarks on Coremutex in ISR were on __freertos_mutex_take_from_isr(m);
without checking result.
If it returns false, the mutex is not taken but the CoreMutex object sets acquired to true.
And on __freertos_mutex_try_take(m)) which only tries and not waits until the mutex is taken.
I am not sure a portYieldFromISR is necessary.
In several documentation I read : From FreeRTOS V7.3.0 pxHigherPriorityTaskWoken is an optional parameter and can be set to NULL.
Will check what that really means by checking the code.
If it needs to check the pxHigherPriorityTaskWoken, there could be something like __freertos_mutex_give_from_isr_yield
which does the xSemaphoreGiveFromISR
and the 'portYieldFromISR`
Or.. add the portYieldFromISR to the __freertos_mutex_give_from_isr anywway.
It's the tradeoff between 1/ possible additional portYieldFromISR and 2/ possible lower prio task running until the next task switch
I will make a PR, try to do this weekend.
Closed by #1481 and #1484
Hi,
Working with the FreeRTOS library at the moment.
Running with Picoprobe(CMSIS-DAP) as upload method and Pico SDK as USB stack, so using 2 USB ports.
Noticed that I do not get all Serial.printf(...) data on the USB port.
This is my current smallest testprogram :
Which gives (varying) results like :
In this case, all output from led16 task is lost.
Found the reason for this behavior :
In SerialUSB there is in the write function :
And in CoreMutex.cpp :
For freertos, there is a
__freertos_mutex_try_take(m)
-> it failes when the mutex is not available. The is no (blocking) wait to get the mutex.And, there is no check in the FromISR whether the mutex is taken.
Expected something like :
Running with this code I get the expected output :
Still investigating, but what are your thoughts about this ?