Is there any way to free a semaphore from a priority 0 interrupt?

Hi there,
I work with a freeRTOS system that runs on a STM H7, generated with Cubemx.

I would like to release a semaphore (in User code Tload_Timer_IrqProcess) from the “TIM1 update interrupt”, i.e. the freeRTOS heart:

/**
  * @brief This function handles TIM1 update interrupt.
  */
void TIM1_UP_IRQHandler(void)
{
  /* USER CODE BEGIN TIM1_UP_IRQn 0 */

  /* USER CODE END TIM1_UP_IRQn 0 */
  HAL_TIM_IRQHandler(&htim1);
  /* USER CODE BEGIN TIM1_UP_IRQn 1 */
	
	// trigger tload events
	Tload_Timer_IrqProcess();
	
  /* USER CODE END TIM1_UP_IRQn 1 */
}

This does not work because the timer-interrupt has a priority of 0, but the call of freertos-systemcalls is probably only allowed up to the value “LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY”.
If I call the semaphore function from the timer interrupt, I get stuck in queue.c at this point:
tASSERT_IF_INTERRUPT_PRIORITY_INVALID();

Hmmm… I commented out that spot and my program then works fine.

It worries me as I’m probably breaking an important system requirement which will then hit badly elsewhere.

Is there any way to free a semaphore from a priority 0 interrupt?

Thank you very much for tipps,
friendly regards
recently

How did you release the semaphore from within an ISR? Did you use the FromISR variant, like xSemaphoreGiveFromISR()?

There are some useful comments in semphr.h, and on freertos.org, of course.

Please also read these comments.
There have been many posts about this subject.

Can you not change the priority of this interrupt? See here for explanation - Understanding priority levels of ISR and FreeRTOS APIs - #16 by aggarg

@htibosch: yes
@aggarg: I don`t want to change the realtime priority of the freertos heart

Isn’t there a way to service a semaphore from a high priority interrupt?

well you MUST not call a FreeRTOS API fn from an ISR above max sys call, it will not work. The only option you have is to raise MAX SYSCALL to include pri 0.

@RAc:

  • Yes, I already know that this does not work, but it works when I comment out the
    “tASSERT_IF_INTERRUPT_PRIORITY_INVALID();” in queue.c.

  • You can`t raise LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY to 0, cubemx limits this to 1…6

Actually, it only appears to work, but you can be sure to experience random and unpredictable crashes. The critical section shield is vital to ensure coherency of the system data structures.

Yes RAc, thats the reason why I`m asking here …

And what I also don’t like is when I change LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY in cubemx, then a lot of interrupts are suddenly shifted to 1, I couldn’t be responsible for the effects. I just want to free up a semaphore and not launch a major attack on the system…

Just don’t do it (freeing a semaphore) this way as it’s not possible. Free it somewhere else in task context if you really, really want to do it (why ?).
For me it seems odd to even think of doing potentially lengthy resource management in an ISR (callback) besides the fact that an ISR is a very restricted context where many things are not possible (in a safe way).

1 Like

@recently : Please do not confuse Cube MX restrictions and FreeRTOS restrictions. You should ask in the partner forum about the Cube quirks…

Who is right now, RAc or Hartmut? RAc says set Max syscall to 0 (only option), Hartmut says it doesn’t work at all (although I can already see it working with my illegal hack).

As people have said, it just isn’t possible to directly do this, and something seems wrong with your design to need it.

That said, if you really need to do this, one trick that can be done is to have your high priority task trigger some other ‘unused’ interrupt, with a reasonable priority and do the operation in that ISR. That interrupt doesn’t need to be in any way ‘related’ to the function you are doing, just preferably some interrupt you aren’t using and can set the pending bit for.

Oh… that sounds very interesting. How can I trigger a interrupt from another interrupt ? I never did that before… maybe a bit more specific?

There is an NVIC function call to set the interrupt pending bit.

Actually, I failed to notice that you actually wish to delete the semaphore in the ISR, that never occurred to me. I thought you intended to release (give) it. If the former, Hartmut is right: Do not even think about it. If the latter, my elaboratons are correct (though I am fairly certain that Hartmut would not oppose them).