# Task Crash While Waiting for Semaphore

**URL:** <https://forums.freertos.org/t/task-crash-while-waiting-for-semaphore/6081>\
**Category:** Kernel\
**Created:** [July 27, 2016, 3:40pm UTC](https://forums.freertos.org/t/task-crash-while-waiting-for-semaphore/6081 "2016-07-27T15:40:45Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 27, 2016, 3:40pm UTC](https://forums.freertos.org/t/task-crash-while-waiting-for-semaphore/6081/1 "2016-07-27T15:40:45Z")

</div>

**[paulromero](https://sourceforge.net/u/paulromero/)** wrote on [Wednesday, July 27, 2016](https://sourceforge.net/p/freertos/discussion/382005/thread/caeed4a0/#9623):

Dear Group:

I am having a FreeRTOS problem which I believe is due to incorrect  
interrupt priority configuration.

The generic hardware is the Cortex M4 and the LPC4088 processor running on  
on an Embedded Artist’s LPC4088-32 Developer’s Kit in particular. (i.e. The FreeRTOS  
version is V8.0.1.)

Interrupts generated by LPC4088 UART2 are associated with NVIC interrupt  
UART2\_IRQn and handled by the UART2\_IRQHandler() interrupt handler. It signals  
the Modem\_UART\_Event\_Handler() task with the BT\_UART\_Data\_Signal semaphore.

The symptoms of the problem are as follow:

1. A UART2 interrupt is generated, UART2\_IRQHandler() signals MODEM\_UART\_Event\_Handler()  
of the event via the BT\_UART\_Data\_Signal semaphore and the event is successfully  
handled. At this point MODEM\_UART\_Event\_Handler() task has called xSemaphoreTake()  
once.

2. The MODEM\_UART\_Event\_Handler() call xSemaphoreTake() again and crashes as follows:

The definitions and code I consider relevant follow below.

The relevant UART definitions are as follows:

```auto
#define BT_UART LPC_UART2
#define BT_IRQ UART2_IRQn

```

The relevant definitions from FreeRTOSConfig.h are as follows.

```auto
#define configMAX_PRIORITIES ( 5 )
#define configPRIO_BITS 4 /* 15 priority levels */

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5

/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

```

The priority initialization for the interrupt handler for UART2 is as follows and  
the interrupt handler follows below:

```auto
 unsigned int pri;
	//
	// Finally enable the IRQ interrupt.
	// The priority of SysTickIRQn is 30, and that of TIMER1_IRQn is 29
	// Set the UART1_IRQn to 28 as it is the highest priority less than
	// that of TIME1_IRQn.
	//
	// The LPC4088 interrupt priority range is as follows:
	//
	// HIGH: 0 - 15
	// LOW: 16 - 31
	//
	pri = ((1u << __NVIC_PRIO_BITS) - 2u) - 2u;	// SysTickIRQn
	pri -= 3;
	NVIC_SetPriority(BT_IRQ, pri);

```

This is the relevant task and semaphore initialization:

```auto
	BT_UART_Data_Signal = xSemaphoreCreateBinary();
	//
	// BT_MODEM_HANDLER_TASK - Highest Priority - Almost
	//
	xTaskCreate(Modem_UART_Event_Handler, (signed char *) "MODEM/UART",
				configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY + 3UL),
				&task_id);

```

This is the relevant portion of the task:

```auto
TASK void Modem_UART_Event_Handler(void *parm)
{
	INTERTASK_MSG msg;
	UINT ecause, n;

	vTaskDelay(configTICK_RATE_HZ * 3);

	for(;;)
	  {

		//
		// Wait until the UART #2 interrupt handler signals that data is available.
		//
		xSemaphoreTake(BT_UART_Data_Signal, portMAX_DELAY);

		switch(MU_Event.type)
		{
		case MU_XE_TXFIFO_EMPTY:
			if(MU_Data->mode == FRAME_MODE)
			  {
				msg.event = IEV_BT_FIFO_EMPTY;
				msg.data = NULL;
				msg.length = 0;
				X_SEND_MSG(LINK_HANDLER_TASK, &msg, X_HI_PRIO);
			  }
			else
				atd_tx_stored(TRUE);
			break;
		case MU_XE_RXDATA:
			n = Chip_UART_ReadRB(BT_UART, &MU_Data->rx_ring,
		 	                      (void *) MU_Data->rx_data_buf, BT_MAX_RING_BUF);

			if(MU_Data->mode == FRAME_MODE)
				link_handle_data(MU_Data->rx_data_buf, n);
			else
				atd_rx_data(MU_Data->rx_data_buf, n);

			break;
		case MU_XE_PHY_ERROR:
			ecause = MU_Event.cause;
			bt_rx_phy_error(ecause);
			break;
		default:
			//
			// BUG
			//
			abort();
		}

	  }

}

```

Finally, this is the interrupt handler:

```auto
ROUTINE void UART2_IRQHandler(void)
{
	BaseType_t hi_prio_alert;
	UINT cause;

	MU_Event.type = MU_XE_INVALID;
	MU_Event.cause = 0;

	//
	// Examine te IIR register to determine the interrupt cause.
	//
	cause = Chip_UART_ReadIntIDReg(BT_UART);
	cause &= 0xFF;

	//
	// Ignore a spurious interrupt.
	//
	if( !(cause & UART_IIR_INTSTAT_PEND) )
	  {
		if( (cause & (UART_IIR_INTID_THRE | UART_IIR_INTID_RDA)) ||
		  ( (cause & UART_IIR_INTID_CTI) == UART_IIR_INTID_CTI ) )
		  {
			//
			// In the case of a RBR or THR interrupt, this the following routine
			// manages Ring Buffer and FIFO data transfer transactions.
			//
			// After the data transfer, notify the BT_MODEM_HANLDER_TASK that
			// data is available for reading, or that a data transmission operation
			// is complete.
			//
			Chip_UART_IRQRBHandler(BT_UART, &MU_Data->rx_ring, &MU_Data->tx_ring);
	
			if( cause & UART_IIR_INTID_THRE )
				MU_Event.type = MU_XE_TXFIFO_EMPTY;
			else
				MU_Event.type = MU_XE_RXDATA;
		  }
		else
		if( (cause & UART_IIR_INTID_RLS) == UART_IIR_INTID_RLS )
		  {
			MU_Event.type = MU_XE_PHY_ERROR;
			MU_Event.cause = Chip_UART_ReadLineStatus(BT_UART);
			MU_Event.cause &= 0xFF;
		  }
		else
		  {
			//
			// BUG: Invalid cause.
			//
			abort();
		  }
	
		//
		// Signal the BT_MODEM_HANDLER_TASK of an event.
		//
		xSemaphoreGiveFromISR(BT_UART_Data_Signal, &hi_prio_alert);
	  }
	else
	  {
		//
		// Spurious interrupt
		//
		;
	  }
	//
	// The BT_MODEM_HANDLER_TASK has a higher priority than almost
	// all other tasks which could be executing. If that is the case,
 	// force a context switch to the BT_MODEM_HANDLER_TASK.
	//
	portEND_SWITCHING_ISR(hi_prio_alert);

}

```

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [July 28, 2016, 8:05am UTC](https://forums.freertos.org/t/task-crash-while-waiting-for-semaphore/6081/2 "2016-07-28T08:05:34Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Thursday, July 28, 2016](https://sourceforge.net/p/freertos/discussion/382005/thread/caeed4a0/#37d5):

First, tripple check the value of

```
__NVICPRIOBITS
```
, 

as this has been the cause of some confusion over the years with the NXP headers and documentation mismatching. For example, a quick web search finds it set to 3 in this file: [http://www.keil.com/dd/docs/arm/nxp/lpc43xx/lpc43xx.h](http://www.keil.com/dd/docs/arm/nxp/lpc43xx/lpc43xx.h) (you have it set to 4) and a comment that it has been corrected in this change history: [http://cdn.rowleydownload.co.uk/arm/packages/LPC4300.htm](http://cdn.rowleydownload.co.uk/arm/packages/LPC4300.htm)

Do you have configASSERT() defined? [http://www.freertos.org/a00110.html#configASSERT](http://www.freertos.org/a00110.html#configASSERT) That should assist in finding a priority assignment error - it might be worth updating to a newer version of FreeRTOS to as newer versions have additional assert() points for better error detection.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 28, 2016, 6:23pm UTC](https://forums.freertos.org/t/task-crash-while-waiting-for-semaphore/6081/3 "2016-07-28T18:23:46Z")

</div>

**[paulromero](https://sourceforge.net/u/paulromero/)** wrote on [Thursday, July 28, 2016](https://sourceforge.net/p/freertos/discussion/382005/thread/caeed4a0/#3ab5):

There is a conflict between the number of NVIC interrupt priority bits of the LPC4088 Cortex M4  
processor as defined by NXP versus CMIS3. NXP defines 5 bits and 32 priority levels split  
into two groups–the maskable group is appropriate for use with FreeRTOS. CMIS3 defines 4  
bits and 16 priority levels by necessity.

(i.e. The target environment is an LPC4088 processor on the Embedded Artist’s LPC4088-32  
Developer’s Kit board.)

I am fairly certain that the NXP 5 bit definition is correct.

When \_\_NVIC\_PRIO\_BITS is set to 5 bits in my environment and xSemaporeGiveFromISR(), called from the interrupt handler,  
correctly signals the Modem\_UART\_Handler() task with  
BT\_UART\_Data\_Signal semaphore. In that case the priority  
of SysTickIRQn = 30 and can be computed as follows:

```
(1 << NVIC_PRIO_BITS) - 2;

```

The important FreeRTOSConfig.h definitions should be as follows:

```
#define configPRIO_BITS 5 /* 32 priority levels */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY	0x1f

```

It isn’t clear if configLIBRARY\_MAX\_SYSCALL\_INTERRUPT\_PRIORITY should  
be set but it is set to 5 as in the current configuration and any clues  
would be appreciated. If the value is 5, the encoded value,  
configMAX\_SYSCALL\_INTERRUPT\_PRIORITY, is 40.

In LPC407x\_8x\_177x\_8x.h the value is as follows:

```
#define __NVIC_PRIO_BITS 5 /* !< Number of Bits used for Priority Levels */

```

This seems reasonable since a great deal of Cortex M4 documentation indicates  
there are 32 rather than 15 priority levels. Chapter 5 section 3.5  
of the LPC17xx edition of “Using the FreeRTOS Real Time Kernel” indicates there  
are 32 priority levels. Section 5.5 of the UM10562–The LPC408x/LPC407x User Manual,  
indicates there are 5 interrupt bits and 32 levels as well.

In CMSIS/Include/core\_cm3.h the value is as follows:

```
#define __NVIC_PRIO_BITS 4

```

Best Regards,

Paul R.

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [July 29, 2016, 5:02am UTC](https://forums.freertos.org/t/task-crash-while-waiting-for-semaphore/6081/4 "2016-07-29T05:02:18Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Friday, July 29, 2016](https://sourceforge.net/p/freertos/discussion/382005/thread/caeed4a0/#3ab5/aa65):

> It isn’t so clear how configLIBRARY\_MAX\_SYSCALL\_INTERRUPT\_PRIORITY should  
> be set but it is set to 5 in the current configuration. This is important  
> because the priority of an interrupt that uses xSemaphoreGiveFromISR() must  
> be numerically greater than configLIBRARY\_MAX\_SYSCALL\_INTERRUPT\_PRIORITY  
> if I  
> understand the documentation correctly. Is this right ?

Here is an example for 5 bits:

```
/* Use the system definition, if there is one */
#ifdef __NVIC_PRIO_BITS
  #define configPRIO_BITS __NVIC_PRIO_BITS
#else
  #define configPRIO_BITS 5
#endif

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x1f
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5

/* The lowest priority. */
#define configKERNEL_INTERRUPT_PRIORITY ( 
configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( 
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
```

See [RTOS for ARM Cortex-M](http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html).

Yes it must be lower than configMAX\_SYSCALL\_INTERRUPT\_PRIORITY - which  
means a higher numerical value. See the link above.

> NVIC\_SetPriority(irq, (1 \<\< (\_\_NVIC\_PRIO\_BITS - 1)) + priority);

Why not just

```
NVIC_SetPriority(irq, configMAX_LIBRARY_INTERRUPT_PRIORITY + whatever );
```

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 29, 2016, 2:24pm UTC](https://forums.freertos.org/t/task-crash-while-waiting-for-semaphore/6081/5 "2016-07-29T14:24:54Z")

</div>

**[paulromero](https://sourceforge.net/u/paulromero/)** wrote on [Friday, July 29, 2016](https://sourceforge.net/p/freertos/discussion/382005/thread/caeed4a0/#0d83):

Please clarify the recommendation about NVIC\_SetPriority(). Do you  
really mean to use configMAX\_LIBRARY\_INTERRUPT\_PRIORITY = 5 or  
configMAX\_SYSCALL\_INTERRUPT\_PRIORITY = 40 ?

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [July 30, 2016, 5:32pm UTC](https://forums.freertos.org/t/task-crash-while-waiting-for-semaphore/6081/6 "2016-07-30T17:32:56Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Saturday, July 30, 2016](https://sourceforge.net/p/freertos/discussion/382005/thread/caeed4a0/#0d83/70fc):

I mean you really have to set the parameter to whatever the processor  
actually needs - but you will find, as others have, that different  
documents and source files say different things about what the processor  
actually needs, so you will first have to work that out (which can be  
done by experimentation - you can write 0xff into one of the priority  
registers, then read the value back, and see how many of the bits  
actually got set).
