Code hangs when reaching UART API call

cphus wrote on Wednesday, September 19, 2012:

Hello freeRTOS,

This is my first experience ever with an RTOS. I managed to build a custom freeRTOS project for this board
The MCU is LPC1768 and the version of freeRTOS I use is 7.1.1. Compiler is from CodeSourcery Lite (arm-none-eabi-gcc v4.5.2)

I modified a blinking example that succesively blinks four led’s to blink another four in another task at an another rate just to see that the task switching mechanism works.
Then I tried to output something on UART in one of the tasks but the code hangs and the LED’s don’t blink anymore.
I must state that the code for UART is from another example for this particular board that works: I tested it with minicom - so nothing is wrong with the driver…

Next, I’ll reproduce the code from main.c. Note at the end of function vHB1 the calls for initializing the UART 0 and sending a string on it. I have intentionately put it at the end to see that the led’s blink in the order 0-1-2-3-2-1 and then hang.

/* ---- Include Files ---------------------------------------------------- */
#include "stdio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "serial.h"
/* ----------------------------------------------------------------------- */
#define 	HEARBEAT_PRIORITY		( tskIDLE_PRIORITY + 1 )
#define		HEARTBEAT_STACK_SIZE	configMINIMAL_STACK_SIZE
#define LED_0 ( 1UL << 0UL )
#define LED_1 ( 1UL << 1UL )
#define LED_2 ( 1UL << 2UL )
#define LED_3 ( 1UL << 3UL )
#define LED_4 ( 1UL << 4UL )
#define LED_5 ( 1UL << 5UL )
#define LED_6 ( 1UL << 6UL )
#define LED_7 ( 1UL << 7UL )
static unsigned long gLed[] = { LED_0, LED_1, LED_2, LED_3, LED_4, LED_5, LED_6, LED_7 };
/***************************************************************************
*
*   Initialize the GPIO pin that the LED is connected to.
*
***************************************************************************/
static void LED_Init( void )
{
	LPC_GPIO2->FIODIR = LED_0 | LED_1 | LED_2 | LED_3 | LED_4 | LED_5 | LED_6 | LED_7;
	LPC_GPIO2->FIOCLR = LED_0 | LED_1 | LED_2 | LED_3 | LED_4 | LED_5 | LED_6 | LED_7;
}
/***************************************************************************
*
*   Turns the LED on or off. On the robovero, driving the pin low turns the
*   LED on.
*
***************************************************************************/
static void SetLED( unsigned led, unsigned value )
{
	if( value )
		LPC_GPIO2->FIOSET = gLed[led];
	else
		LPC_GPIO2->FIOCLR = gLed[led];
}
/***************************************************************************
*
*   Initializes the chip.
*
***************************************************************************/
static void InitHardware( void )
{
	/* Disable peripherals power. */
	LPC_SC->PCONP = 0;
	/* Enable GPIO power. */
	LPC_SC->PCONP = PCONP_PCGPIO;
	/* Disable TPIU. */
	LPC_PINCON->PINSEL10 = 0;
	if ( LPC_SC->PLL0STAT & ( 1 << 25 ) )
	{
		/* Enable PLL, disconnected. */
		LPC_SC->PLL0CON = 1;
		LPC_SC->PLL0FEED = PLLFEED_FEED1;
		LPC_SC->PLL0FEED = PLLFEED_FEED2;
	}
	/* Disable PLL, disconnected. */
	LPC_SC->PLL0CON = 0;
	LPC_SC->PLL0FEED = PLLFEED_FEED1;
	LPC_SC->PLL0FEED = PLLFEED_FEED2;
	/* Enable main OSC. */
	LPC_SC->SCS |= 0x20;
	while( !( LPC_SC->SCS & 0x40 ) );
	/* select main OSC, 12MHz, as the PLL clock source. */
	LPC_SC->CLKSRCSEL = 0x1;
	LPC_SC->PLL0CFG = 0x20031;
	LPC_SC->PLL0FEED = PLLFEED_FEED1;
	LPC_SC->PLL0FEED = PLLFEED_FEED2;
	/* Enable PLL, disconnected. */
	LPC_SC->PLL0CON = 1;
	LPC_SC->PLL0FEED = PLLFEED_FEED1;
	LPC_SC->PLL0FEED = PLLFEED_FEED2;
	/* Set clock divider. */
	LPC_SC->CCLKCFG = 0x03;
	/* Configure flash accelerator. */
	LPC_SC->FLASHCFG = 0x403a;
	/* Check lock bit status. */
	while( ( ( LPC_SC->PLL0STAT & ( 1 << 26 ) ) == 0 ) );
	/* Enable and connect. */
	LPC_SC->PLL0CON = 3;
	LPC_SC->PLL0FEED = PLLFEED_FEED1;
	LPC_SC->PLL0FEED = PLLFEED_FEED2;
	while( ( ( LPC_SC->PLL0STAT & ( 1 << 25 ) ) == 0 ) );
	/* Configure the clock for the USB. */
	if( LPC_SC->PLL1STAT & ( 1 << 9 ) )
	{
		/* Enable PLL, disconnected. */
		LPC_SC->PLL1CON = 1;
		LPC_SC->PLL1FEED = PLLFEED_FEED1;
		LPC_SC->PLL1FEED = PLLFEED_FEED2;
	}
	/* Disable PLL, disconnected. */
	LPC_SC->PLL1CON = 0;
	LPC_SC->PLL1FEED = PLLFEED_FEED1;
	LPC_SC->PLL1FEED = PLLFEED_FEED2;
	LPC_SC->PLL1CFG = 0x23;
	LPC_SC->PLL1FEED = PLLFEED_FEED1;
	LPC_SC->PLL1FEED = PLLFEED_FEED2;
	/* Enable PLL, disconnected. */
	LPC_SC->PLL1CON = 1;
	LPC_SC->PLL1FEED = PLLFEED_FEED1;
	LPC_SC->PLL1FEED = PLLFEED_FEED2;
	while( ( ( LPC_SC->PLL1STAT & ( 1 << 10 ) ) == 0 ) );
	/* Enable and connect. */
	LPC_SC->PLL1CON = 3;
	LPC_SC->PLL1FEED = PLLFEED_FEED1;
	LPC_SC->PLL1FEED = PLLFEED_FEED2;
	while( ( ( LPC_SC->PLL1STAT & ( 1 << 9 ) ) == 0 ) );
	/*  Setup the peripheral bus to be the same as the PLL output (64 MHz). */
	LPC_SC->PCLKSEL0 = 0x05555555;
}
void vHB1( void * pvParameters )
{
	unsigned int 	led[] = { 0, 1, 2, 3, 2, 1 };
	unsigned int	led_idx = 0;
    /* Setup the LED */
	LED_Init();
	for(;;)
	{
		SetLED(led[led_idx], 1);
		vTaskDelay( 100 / portTICK_RATE_MS );
		SetLED(led[led_idx], 0);
		vTaskDelay( 100 / portTICK_RATE_MS );
		SetLED(led[led_idx], 1);
		vTaskDelay( 100 / portTICK_RATE_MS );
		SetLED(led[led_idx], 0);
		vTaskDelay( 700 / portTICK_RATE_MS );
		led_idx++;
		if( led_idx >=6 )
		{
			led_idx = 0;
            SER_init(0);
            SER_putString(0, "vHB2...\n\r");
		}
	}
}
void vHB2( void * pvParameters )
{
	unsigned int 	led[] = { 7, 6, 5, 4, 5, 6 };
	unsigned int	led_idx = 0;
    /* Setup the LED */
	LED_Init();
	for(;;)
	{
		SetLED(led[led_idx], 1);
		vTaskDelay( 60 / portTICK_RATE_MS );
		SetLED(led[led_idx], 0);
		vTaskDelay( 60 / portTICK_RATE_MS );
		SetLED(led[led_idx], 1);
		vTaskDelay( 60 / portTICK_RATE_MS );
		SetLED(led[led_idx], 0);
		vTaskDelay( 420 / portTICK_RATE_MS );
		led_idx++;
		if( led_idx >=6 )
		{
			led_idx = 0;
		}
	}
}
/***************************************************************************
*
*   main
*
***************************************************************************/
int main( void )
{
	InitHardware();
	xTaskCreate( vHB1,		// Task Function
				 "Heartbeat1", 			// Task Name
				 HEARTBEAT_STACK_SIZE, 	// Stack Size
				 NULL, 					// Parameters
				 HEARBEAT_PRIORITY, 	// Task Priority
				 NULL );				// Place to store task handle
	xTaskCreate( vHB2,		// Task Function
				 "Heartbeat2", 			// Task Name
				 HEARTBEAT_STACK_SIZE, 	// Stack Size
				 NULL, 					// Parameters
				 HEARBEAT_PRIORITY, 	// Task Priority
				 NULL );				// Place to store task handle
	vTaskStartScheduler();
	 /* Will only get here if there was insufficient memory to create the idle
	 * task.  The idle task is created within vTaskStartScheduler().
	 */
	for( ;; )
		;
}

rtel wrote on Wednesday, September 19, 2012:

If it works without the UART, and not with the UART, then it seems likely the issue lies either with your UART functions, or with the interaction between the FreeRTOS API and the UART, or between FreeRTOS and the UART interrupt priorities.  You can read about correct API usage here: http://www.freertos.org/FAQHelp.html and correct interrupt set up here: http://www.freertos.org/RTOS-Cortex-M3-M4.html

There is also an LPC1768 example with functioning UART drivers here: http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_IO/Demo_Applications/LPCXpresso_LPC1769/NXP_LPC1769_Demo_Description.shtml

I can’t comment on your hardware setup, other than to say it seems overly verbose when NXP provide library calls that will do the set up for you.

Do you have stack overflow detection on?

Where is the processor executing when the LEDs stop blinking?

Why are you calling the serial init function more than once?

Regards.

cphus wrote on Wednesday, September 19, 2012:

Thanks for replying,

Do you have stack overflow detection on?
- I activated the stack overflow detection and wrote this handler which should blink an LED if overflow occured but it doesn’t. I also increased the stack size parameter and it doesn’t seem to help

void vApplicationStackOverflowHook(void * pvParameters)
{
    LED_Init();
    while(1)
    {
        SetLED(7,1);
        vTaskDelay(250/portTICK_RATE_MS);
        SetLED(7,0);
        vTaskDelay(250/portTICK_RATE_MS);
    }
}

Where is the processor executing when the LEDs stop blinking?
- I don’t know. The board has a USB J-link SWD debugger but I couldn’t make it work…

Why are you calling the serial init function more than once?
- I know that the initialization should be done before the task’s loop but if I do so the code seems not to execute at all since no LED’s light up. So, putting it where it is now it’s just a way of checking that the code executes well until it reaches the UART initialization function.

If it works without the UART, and not with the UART, then it seems likely the issue lies either with your UART functions

The code for UART is a minimalistic one taken from an example with an SD card for my particular board. It works very well when I load that example - I can create/edit/delete files on the SD card by sending commands via UART0. I reproduce here the relevant part of that driver:

#include "LPC17xx.h"                             /* LPC17xx definitions    */
#include "serial.h"
/*----------------------------------------------------------------------------
  Initialize UART pins, Baudrate
 *----------------------------------------------------------------------------*/
void SER_init (int uart) {
  LPC_UART_TypeDef *pUart;
  if (uart == 0) {                               /* UART0 */
    LPC_PINCON->PINSEL0 |= (1 << 4);             /* Pin P0.2 used as TXD0 (Com0) */
    LPC_PINCON->PINSEL0 |= (1 << 6);             /* Pin P0.3 used as RXD0 (Com0) */
    pUart = (LPC_UART_TypeDef *)LPC_UART0;
  } else {                                       /* UART1 */
    LPC_PINCON->PINSEL4 |= (2 << 0);             /* Pin P2.0 used as TXD1 (Com1) */
    LPC_PINCON->PINSEL4 |= (2 << 2);             /* Pin P2.1 used as RXD1 (Com1) */
    pUart = (LPC_UART_TypeDef *)LPC_UART1;
  }
  pUart->LCR    = 0x83;                          /* 8 bits, no Parity, 1 Stop bit  */
  pUart->DLL    = 9;                             /* 115200 Baud Rate @ 25.0 MHZ PCLK */
  pUart->FDR    = 0x21;                          /* FR 1,507, DIVADDVAL = 1, MULVAL = 2 */
  pUart->DLM    = 0;                             /* High divisor latch = 0         */
  pUart->LCR    = 0x03;                          /* DLAB = 0                       */
}
/*----------------------------------------------------------------------------
  Write character to Serial Port
 *----------------------------------------------------------------------------*/
int SER_putChar (int uart, int c) {
  LPC_UART_TypeDef *pUart;
  pUart = (uart == 0) ? (LPC_UART_TypeDef *)LPC_UART0 : (LPC_UART_TypeDef *)LPC_UART1;
  while (!(pUart->LSR & 0x20));
  return (pUart->THR = c);
}
void SER_putString (int uart, unsigned char *s) {
  while (*s != 0) {
   SER_putChar(uart, *s++);
  }
}

I checked the FreeRTOS_plus_IO UART driver for lpc17xx but for the moment it seems more simple to me to try making the minimalistic UART driver I already use work.

rtel wrote on Wednesday, September 19, 2012:

I activated the stack overflow detection and wrote this handler which should blink an LED if overflow occured but it doesn’t.

The stack overflow hook is called from a context switch - in an interrupt - so you cannot call blocking FreeRTOS API functions.  Your stack overflow hook will probably just crash.

I don’t know. The board has a USB J-link SWD debugger but I couldn’t make it work…

I recommend getting it to work before going any further.  Otherwise you are just left guessing.

Regards.

cphus wrote on Saturday, September 29, 2012:

I managed to configure the debugger to run with CodeBlocks. For the code I gave above the code hanged in HardFault_Handler. But nevermind this code.

I loaded the lpc17xx_uart driver and dependencies into the project and wrote a little task making use of the functions the driver provides. So now I have 2 tasks blipping two rows of led’s and one which should send some message on UART0.
I provide here the UART task.

void vUARTtask(void * pvPatameters)
{
    LPC_UART0_TypeDef UART0;
    LPC_UART_TypeDef * UART = (LPC_UART_TypeDef *) &UART0;
    UART_CFG_Type uart0_configuration = {
        115200,
        UART_PARITY_NONE,
        UART_DATABIT_8,
        UART_STOPBIT_1
        };
    char buf[]="I'm in the UART task!";
    UART_Init(UART, &uart0_configuration );
    while(1)
        {
            UART_Send(UART, buf, sizeof(buf), NONE_BLOCKING );
            vTaskDelay(500/portTICK_RATE_MS);
        }
}

I create it in main like this (priority the same with other tasks):

 xTaskCreate( vUARTtask,
                 "UART0",
                 1000,
                 NULL,
                 UART_PRIORITY,
                 NULL );

I can clearly follow  the code with the debugger until it reaches the char by char sending piece of code. Everything seems to be fine, I even checked the characters it sends and they’re correct. However I see nothing in minicom.

As far as I can tell it shouldn’t be but is there somehing wrong with the code?

rtel wrote on Saturday, September 29, 2012:

There is nothing obviously wrong with the code.

What does the NON_BLOCKING mean in the UART_Send() call?

Regards.

cphus wrote on Saturday, September 29, 2012:

When using UART in BLOCKING mode, a time-out condition is used via defined symbol UART_BLOCKING_TIMEOUT.

The difference between BLOCKING and NONE_BLOCKING is that in NONE_BLOCKING mode if the “tx register” does not empty withing some time the transmitter continues with the next character while in BLOCKING mode it stays there until the register empties. This is for avoiding infinite loops i guess.

But I tried both of them and in either of the cases i cannot see anything in minicom.

Anyway, thanks for helping.

cphus wrote on Saturday, October 06, 2012:

I found a LPC7xx CMSIS UART example and it seems to work. Well, no quite. I can see junk in minicom (baud and other settings are like in the code!).

Here is the task code, just for reference:

void vUARTtask(void * pvPatameters)
{
    LPC_UART_TypeDef *UARTx = (LPC_UART_TypeDef *) LPC_UART0;
    /* UART Configuration structure variable */
    UART_CFG_Type UARTConfigStruct;
    /* UART FIFO configuration Struct variable */
    UART_FIFO_CFG_Type UARTFIFOConfigStruct;
    /* Pin configuration for UART0 */
    PINSEL_CFG_Type PinCfg;
    /*
     * Initialize UART0 pin connect (Port 0, pins 2 and 3)
     */
    PinCfg.Funcnum = 1;
    PinCfg.OpenDrain = 0;
    PinCfg.Pinmode = 0;
    PinCfg.Pinnum = 2;
    PinCfg.Portnum = 0;
    PINSEL_ConfigPin(&PinCfg);
    PinCfg.Pinnum = 3;
    PINSEL_ConfigPin(&PinCfg);
    /* Initialize UART Configuration parameter structure to default state:
     * Baudrate = 9600bps
     * 8 data bit
     * 1 Stop bit
     * None parity
     */
    UART_ConfigStructInit(&UARTConfigStruct);
    /* Set Baudrate to 115200 */
    UARTConfigStruct.Baud_rate = 115200;
    /* Initialize UART0 peripheral with given to corresponding parameter */
    UART_Init(UARTx, &UARTConfigStruct);
    /* Initialize FIFOConfigStruct to default state:
     * 				- FIFO_DMAMode = DISABLE
     * 				- FIFO_Level = UART_FIFO_TRGLEV0
     * 				- FIFO_ResetRxBuf = ENABLE
     * 				- FIFO_ResetTxBuf = ENABLE
     * 				- FIFO_State = ENABLE
     */
    UART_FIFOConfigStructInit(&UARTFIFOConfigStruct);
    /* Initialize FIFO for UART0 peripheral */
    UART_FIFOConfig(UARTx, &UARTFIFOConfigStruct);
    /*  Enable UART Transmit */
    UART_TxCmd(UARTx, ENABLE);
    char string[]="Hello, says freeRTOS!";
    while(1)
    {
        UART_Send(UARTx, (uint8_t *)string, strlen(string), BLOCKING);
        SetLED(7,1);
        vTaskDelay(500/portTICK_RATE_MS);
        SetLED(7,0);
        vTaskDelay(500/portTICK_RATE_MS);
    }
}

It seems that there is more stuff to configure than I previously thought.

I know it’s more like related to the CMSIS than to freeRTOS but do you have a clue why this would happen?

rtel wrote on Sunday, October 07, 2012:

Didn’t you say it was working when you were not using the RTOS, but now you are saying it was not configured?

Well, again, there is nothing obviously wrong.  If the data coming out of the UART is garbled then baud rate is the most likely cause.  Have a look at the library function where it calculates the baud rate settings.  Most likely it will be using the speed of the clock signal to either the processor or the UART (or both) in the calculation, and if it is using an incorrect speed, then the baud rate calculation will also be incorrect.

Regards.

cphus wrote on Sunday, October 07, 2012:

There are 4 scenarios here.
1. I did use a firmware without RTOS with a custom serial library and it worked
2. I used freeRTOS togheter with that custom serial library and the execution ended in HardFault_Handler
3. I used freeRTOS with Cortex-M3 CMSIS serial library (namely lpc17xx_uart) but i did not have any example so I did not well configured the UART. In this case I did not see anything in the computer serial monitor.
4. I found an example of how to use the CMSIS and now I see stuff coming but it’s junk.

Starting from what you said about the clock calculation I searched through the code and indeed that is the problem. The thing is, my code had an hardware initialization function (given somewhere in the comments above) which changes registers related to clock and other stuff, messing up everything. The CMSIS routines should (in my opinion) derive the clock by reading the appropriate registers.

Anyway it works now.
Thanks Mr. Barry