Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

Task Crash While Waiting for Semaphore

Posted by paulromero on July 27, 2016

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 UART2IRQn and handled by the UART2IRQHandler() interrupt handler. It signals the ModemUARTEventHandler() task with the BTUARTDataSignal semaphore.

The symptoms of the problem are as follow:

1) A UART2 interrupt is generated, UART2IRQHandler() signals MODEMUARTEventHandler() of the event via the BTUARTDataSignal semaphore and the event is successfully handled. At this point MODEMUARTEventHandler() task has called xSemaphoreTake() once.

2) The MODEMUARTEvent_Handler() call xSemaphoreTake() again and crashes as follows:

In the FreeRTOS ListInsert() routine the crash occurs when the following line of code executes:

pxNewListItem->pxPrevious = pXIterator;

The sequence of FreeRTOS calls is as follows:

	SemaphoreTake();
	QueueGenericReceive();
	TaskPlaceOnEventList();
	ListInsert();

The definitions and code I consider relevant follow below.

The relevant UART definitions are as follows:

~~~

define BTUART LPCUART2
define BTIRQ UART2IRQn

~~~

The relevant definitions from FreeRTOSConfig.h are as follows.

~~~

define configMAX_PRIORITIES ( 5 )
define configPRIO_BITS 4 /* 15 priority levels */
define configLIBRARYLOWESTINTERRUPT_PRIORITY 0xf
define configLIBRARYMAXSYSCALLINTERRUPTPRIORITY 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 configKERNELINTERRUPTPRIORITY ( configLIBRARYLOWESTINTERRUPTPRIORITY << (8 - configPRIOBITS) )

/* !!!! configMAXSYSCALLINTERRUPT_PRIORITY must not be set to zero !!!! See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */

define configMAXSYSCALLINTERRUPTPRIORITY ( configLIBRARYMAXSYSCALLINTERRUPTPRIORITY << (8 - configPRIOBITS) )

~~~

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

~~~ unsigned int pri; // // Finally enable the IRQ interrupt. // The priority of SysTickIRQn is 30, and that of TIMER1IRQn is 29 // Set the UART1IRQn to 28 as it is the highest priority less than // that of TIME1IRQn. // // The LPC4088 interrupt priority range is as follows: // // HIGH: 0 - 15 // LOW: 16 - 31 // pri = ((1u << __NVICPRIOBITS) - 2u) - 2u; // SysTickIRQn pri -= 3; NVICSetPriority(BT_IRQ, pri); ~~~

This is the relevant task and semaphore initialization:

~~~ BTUARTDataSignal = xSemaphoreCreateBinary(); // // BTMODEMHANDLERTASK - Highest Priority - Almost // xTaskCreate(ModemUARTEventHandler, (signed char *) "MODEM/UART", configMINIMALSTACKSIZE, NULL, (tskIDLEPRIORITY + 3UL), &task_id); ~~~

This is the relevant portion of the task:

~~~ TASK void ModemUARTEventHandler(void *parm) { INTERTASKMSG 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:

~~~ ROUTINE void UART2IRQHandler(void) { BaseTypet hiprioalert; 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 BTMODEMHANDLERTASK. // portENDSWITCHINGISR(hiprio_alert);

} ~~~


Task Crash While Waiting for Semaphore

Posted by rtel on July 28, 2016

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 (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

Do you have configASSERT() defined? 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.


Task Crash While Waiting for Semaphore

Posted by paulromero on July 28, 2016

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 _NVICPRIOBITS is set to 5 bits in my environment and xSemaporeGiveFromISR(), called from the interrupt handler, correctly signals the ModemUARTHandler() task with BTUARTDataSignal 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 configLIBRARYMAXSYSCALLINTERRUPTPRIORITY 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, configMAXSYSCALLINTERRUPT_PRIORITY, is 40.

In LPC407x8x177x_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.


Task Crash While Waiting for Semaphore

Posted by rtel on July 29, 2016

It isn't so clear how configLIBRARYMAXSYSCALLINTERRUPTPRIORITY 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 configLIBRARYMAXSYSCALLINTERRUPTPRIORITY 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 http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html.

Yes it must be lower than configMAXSYSCALLINTERRUPT_PRIORITY - which means a higher numerical value. See the link above.

NVICSetPriority(irq, (1 << (__NVICPRIO_BITS - 1)) + priority);

Why not just

NVIC_SetPriority(irq, configMAX_LIBRARY_INTERRUPT_PRIORITY + whatever );

Task Crash While Waiting for Semaphore

Posted by paulromero on July 29, 2016

Please clarify the recommendation about NVICSetPriority(). Do you really mean to use configMAXLIBRARYINTERRUPTPRIORITY = 5 or configMAXSYSCALLINTERRUPT_PRIORITY = 40 ?


Task Crash While Waiting for Semaphore

Posted by rtel on July 30, 2016

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).


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists