cancel
Showing results for 
Search instead for 
Did you mean: 

osSemaphoreRelease hangs the MCU?

RafaelS
Associate III

Hello,

I am having trouble releasing a semaphore on the STM32H745I-DISCO.

The context is as follows: I need to capture a breakline on UART2. When the interrupt triggers, I need to read a character and, depending on the received character, either send characters back or do nothing.

To avoid executing the handling code inside the interrupt, I have placed it inside a task with an osSemaphoreWait. My idea is that when the breakline interrupt occurs, the osSemaphoreRelease line should be executed, releasing the semaphore and running the code that manages UART communication.

 

main.c

 

 

int main(void){
  osSemaphoreDef(LIN_breakSem);
  LIN_breakSem = osSemaphoreCreate(osSemaphore(LIN_breakSem), 1);
  osSemaphoreWait(LIN_breakSem, osWaitForever);//here decrements de counter to 0

  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 512);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  osThreadDef(LIN_breakTask, LIN_break_fn, osPriorityNormal, 0, 512);
  LIN_breakTaskHandle = osThreadCreate(osThread(LIN_breakTask), (void *)LIN_breakSem);
  osKernelStart();
  while(1){}
}

void LIN_break_fn(void const * argument)
{
  while(1){
  osSemaphoreId LIN_breakSem = (osSemaphoreId) argument;
  vuelve:
  if (LIN_breakSem != NULL){
    printf("LIN_breakSem = %d\n", LIN_breakSem);
  }else{
    printf("LIN_breakSem == NULL\n");
    osDelay(5000);
    goto vuelve;
  }
  osSemaphoreWait(LIN_breakSem, osWaitForever);
  /*Manage the communication*/
  osSemaphoreWait(LIN_breakSem, osWaitForever);
}

 

 

stm32h7xx_it.c

 

 

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */
	char flagtmp=0;
	USART_TypeDef *U = USART2;
	uint32_t isrflags = U->ISR; // status
	if (isrflags & USART_ISR_LBDF) {
		U->ICR = UART_CLEAR_LBDF;
		flagtmp = 1;
	}

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */
  if(flagtmp){
	  printf("LIN_breakSemInt = %d\n", LIN_breakSem);
	  printf("releasing...\n");
	  //osSemaphoreRelease(LIN_breakSem);
	  int status = osSemaphoreRelease(LIN_breakSem);
	  printf("Status = %x\n", status);
	  flagtmp = 0;
  }
  /* USER CODE END USART2_IRQn 1 */
}

 

 

The problem is that when the osSemaphoreRelease in line 19 is executed inside the interrupt, the microcontroller hangs.


I attach the code: as you can see in the interrupt code after release is printed the status of osSemaphoreRelease but here the MCU hangs and nothing more is printed :')

Any idea?

Thanks.

2 REPLIES 2
gbm
Principal

1. I cannot see osKernelInit() call in your code

2. Is it CMSIS_OS1 or CMSIS_OS2? If 2 - osSemaphoreAcquire() should be used instead of SemaphoreWait. OS1 calls usually fail when mixed with OS2.

3. For any service (like osSemaphoreRelease) to be called from an ISR, the interrupt priority MUST NOT not be higher (so for Cortex-M numerically LOWER) than OS call priority. With CubeMX, the call priority is 5 by default, so the numeric value of UART ISR must be >= 5.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
RafaelS
Associate III

Hello @gbm.

 

1. I have forgot to copy the osKernelStart(); in the post

2. I use CMSIS_V1.

3. I will test incrementing the interrupt priority

 

Thank you!!