xSemaphoreTake in a critical section

I’m having an issue where vListInsert is getting stuck in an infinite loop (pxIterator->pxNext = pxIterator, and xValueOfInsertion = pxIterator->pxNext->xItemValue), and I believe I’ve traced the issue down to a call to xSemaphoreTake() that occurs while in a critical section.

This is a 3rd party library that sets/gets some GPIO pins to control wake/sleep for a module. and it does so while in a critical section. The problem is that in my hardware the GPIOs are connected via an I2C based IO expander and the calls to set/get those pins involve a mutex to protect access to the I2C bus.

Is there any safe way to allow this, or do I need to figure out a way to exit the critical section before taking/giving the mutex?

The fundamental problem you are going to run into is that while you are in a critical section, you task can not block if the semaphore isn’t available, nor will the I2C bus generate the interrupts it should be using to operate on.

If you have the code for the 3rd party library, I would look at it and try to figure out why they want the critical section, and perhaps change it as needed. If not, you might check with them why they are doing such a thing, as user mode critical sections really need to be kept short to avoid problems, and calling outside code (like however they are asking for the GPIO) isn’t really a good thing.

If you really need to “break out”, of the critical section, that can be done (assuming you know how the enter it in the first place) but if you don’t know why it is there, that opens you to unknown consequences.

Thanks, that helps.

I do have the source and am looking now to see if/why this is needed. I’ve been pretty underwhelmed by the quality of it so far, so it wouldn’t surprise me to find there’s no good reason for it. It’s in a driver event handler routine, so I suspect it may be to keep other components of the module interface in sync. If so I may be able to accomplish the same thing via temporarily elevating priorites.

The other option is to use a mutex to protect the resources.

I think it may be due to it not differentiating between simply masking the interrupt from its module and stopping all context switching. The glue fuction it uses first masks the pin responsible for reading the interrupt coming from the module, then calls taskENTER_CRITICAL();

Since this is in an event handler, I think I may be able to modify it to simply mask the interrupt and leave context switching alone. There may be some issues with that too though.

As best I can tell, this was only an issue in one spot. Is there a way to set a hook or similar to report when an illegal action is performed inside of a critical section?

I assume by “illegal action” you mean calling a FreeRTOS API with non-zero block time. If yes, there is no assert to catch this as of now. Critical sections should be few and should be very short and deterministic and therefore, grepping for taskENTER_CRITICAL and reviewing the code can be a viable way to catch such violations.