EmbeddedRelated.com
Forums
Memfault Beyond the Launch

uart0 lpc1768 freertos

Started by Matthew Partyka January 12, 2012
Hello, I have sent posted to the group yesterday (seems to not have worked
first time around) - so if repeat please discard

Im having trouble with my UART functions, the send seems to be working fine
but when receive the buffer does not seem to be empty and is resent as if
there was a interrupt triggered every time there is a send. (hence going
back to the vUAR0RX function)

-so my question is: Should Queues be used instead of semaphores in a
situation like this?

code is from nxp examples and Freertos form the examples that came with the
freertos book

Thanks for your help
Matthew

#define configKERNEL_INTERRUPT_PRIORITY 255
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xa0, or
priority 5. */

code:

char UARTBuffer [] = {'w','o','r','k','\0','\n','\r'};
char UARTBuffer1 [] = {'I','g','o','t','\0','\n','\r'};

#define UART0HW_INTERRUPT_ID (5)

#define UARTCLEAR_INTERRUPT() NVIC_ClearPendingIRQ(UART0_INTERRUPT_ID)

#define UART0_INTERRUPT_PRIORITY (5)

xSemaphoreHandle xUART0Semaphore;

volatile uint32_t UART0Status;
volatile uint8_t UART0TxEmpty = 1;
volatile uint8_t UART0Buffer[BUFSIZE];
volatile uint32_t UART0Count = 0;

/* Initialisation routine for the UART.*/
void vUART0_IRQHandler (void);
uint32_t UARTInit( uint32_t baudrate );
void UARTSend( uint8_t *BufferPtr, uint32_t Length );

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++heart
beat
static void heart_beat(void *pvParameters){
for(;;){
LPC_GPIO1->FIOPIN |= 1 << 29;
sleep(500);
LPC_GPIO1->FIOPIN &= ~(1 << 29);
sleep(500);
}
}

static void TxTest (void *pvParameters){
for(;;){
UARTSend( (uint8_t *)UARTBuffer, 7 );
sleep (5000);
}
}

static void vUART0RX(void *pvParameters){
for(;;){
while( xSemaphoreTake( xUART0Semaphore, portMAX_DELAY ) != pdPASS ); //wait
for UART0 interupt to wake this task up
for(;;){
UARTSend( (uint8_t *)UART0Buffer, 1 );
UART0Buffer [1] = 0;
sleep (5000);
xSemaphoreTake( xUART0Semaphore, 0 );
}
}
}
void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char
*pcTaskName)
{
//to do add overflow function

}

int main(void)
{
SystemInit();
LPC_SC->PCONP |= ( 1 << 15 ); // power up GPIO for heart beat
LPC_GPIO1->FIODIR |= 1 << 29; // puts P1.29 into output mode., for heart
beat
UARTInit(38400); //boud rate
vSemaphoreCreateBinary( xUART0Semaphore );
xSemaphoreTake( xUART0Semaphore, 0 );
if((xUART0Semaphore != NULL))
{
xTaskCreate( vUART0RX, "Handler", 240, NULL, 4, NULL );
xTaskCreate( heart_beat, "Periodic", 240, NULL, 1, NULL );
xTaskCreate( TxTest, "Periodic", 240, NULL, 1, NULL );
vTaskStartScheduler();
}
//if loop exits schdula has failed
for (;;);
}
void vApplicationIdleHook( void )
{
for (;;);
}
void vUART0_IRQHandler (void)
{
uint8_t IIRValue, LSRValue;
uint8_t Dummy = Dummy;

portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
IIRValue = LPC_UART0->IIR;
IIRValue >>= 1; /* skip pending bit in IIR */
IIRValue &= 0x07; /* check bit 1~3, interrupt identification */
if ( IIRValue == IIR_RLS ) /* Receive Line Status */
{
LSRValue = LPC_UART0->LSR;
/* Receive Line Status */
if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
{
/* There are errors or break interrupt */
/* Read LSR will clear the interrupt */
UART0Status = LSRValue;
Dummy = LPC_UART0->RBR; /* Dummy read on RX to clear
interrupt, then bail out */
return;
}
if ( LSRValue & LSR_RDR ) /* Receive Data Ready */
{
/* If no error on RLS, normal ready, save into the data buffer. */
/* Note: read RBR will clear the interrupt */
UART0Buffer[UART0Count] = LPC_UART0->RBR;
UART0Count++;
if ( UART0Count == BUFSIZE )
{
UART0Count = 0; /* buffer overflow */
}
}
}
else if ( IIRValue == IIR_RDA ) /* Receive Data Available */
{
/* Receive Data Available */
UART0Buffer[UART0Count] = LPC_UART0->RBR;
UART0Count++;
if ( UART0Count == BUFSIZE )
{
UART0Count = 0; /* buffer overflow */
}
else{
xSemaphoreGiveFromISR( xUART0Semaphore, &xHigherPriorityTaskWoken );
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}

}
else if ( IIRValue == IIR_CTI ) /* Character timeout indicator */
{
/* Character Time-out indicator */
UART0Status |= 0x100; /* Bit 9 as the CTI error */
}
else if ( IIRValue == IIR_THRE ) /* THRE, transmit holding register empty
*/
{
/* THRE interrupt */
LSRValue = LPC_UART0->LSR; /* Check status in the LSR to see if
valid data in U0THR or not */
if ( LSRValue & LSR_THRE )
{
UART0TxEmpty = 1;
}
else
{
UART0TxEmpty = 0;
}
}

}
uint32_t UARTInit( uint32_t baudrate ){
uint32_t Fdiv;
uint32_t pclkdiv, pclk;
LPC_PINCON->PINSEL0 &= ~0x000000F0;
LPC_PINCON->PINSEL0 |= 0x00000050; /* RxD0 is P0.3 and TxD0 is P0.2 */
/* By default, the PCLKSELx value is zero, thus, the PCLK for
all the peripherals is 1/4 of the SystemFrequency. */
/* Bit 6~7 is for UART0 */
pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03;
switch ( pclkdiv ) {
case 0x00:
default:
pclk = SystemCoreClock/4;
break;
case 0x01:
pclk = SystemCoreClock;
break;
case 0x02:
pclk = SystemCoreClock/2;
break;
case 0x03:
pclk = SystemCoreClock/8;
break;
}
LPC_UART0->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
Fdiv = ( pclk / 16 ) / baudrate ; /*baud rate */
LPC_UART0->DLM = Fdiv / 256;
LPC_UART0->DLL = Fdiv % 256;
LPC_UART0->LCR = 0x03; /* DLAB = 0 */
LPC_UART0->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
NVIC_EnableIRQ(UART0_IRQn);
LPC_UART0->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART0
interrupt */
return (TRUE);
}
void UARTSend( uint8_t *BufferPtr, uint32_t Length ){
LPC_UART0->IER = IER_THRE | IER_RLS; /* Disable RBR */
while ( Length != 0 )
{
/* THRE status, contain valid data */
while ( !(UART0TxEmpty & 0x01) );
LPC_UART0->THR = *BufferPtr;
//UART0TxEmpty = 0; /* not empty in the THR until it shifts out */
BufferPtr++;
Length--;
}
LPC_UART0->IER = IER_THRE | IER_RLS | IER_RBR; /* Re-enable RBR */
return;
}
/******************************************************************************/


An Engineer's Guide to the LPC2100 Series

On 12/01/2012 17:30, Matthew Partyka wrote:

> Im having trouble with my UART functions, the send seems to be working fine
> but when receive the buffer does not seem to be empty and is resent as if
> there was a interrupt triggered every time there is a send. (hence going
> back to the vUAR0RX function)

I'm not sure I follow. Are you saying each time you send you also get
an Rx interrupt? Do you have some sort of loopback configuration?
> -so my question is: Should Queues be used instead of semaphores in a
> situation like this?

I can't really read the code as the formatting has all been messed up,
but as a general comment - if you have any sort of throughput
requirements it is best to use a semaphore. Have the interrupt place
the data in a circular buffer, then give a semaphore when you want a
task to drain the buffer. A lot of the FreeRTOS demos use queues to
pass data into and out of the an interrupt - but this is done really to
demonstrate queues being used in interrupt, and to test the system by
loading it up. It is not meant to represent an efficient implementation
- but is useful for low throughput applications such as command
interpreters that receive one character at a time.

Regards,
Richard.

+ http://www.FreeRTOS.org
Designed for Microcontrollers.
More than 7000 downloads per month.

Can I attach files on this board? ...I'll give it a shot
im not sure how I can make the code more readable,

On Thu, Jan 12, 2012 at 12:51 PM, FreeRTOS Info wrote:

> **
> On 12/01/2012 17:30, Matthew Partyka wrote:
>
> > Im having trouble with my UART functions, the send seems to be working
> fine
> > but when receive the buffer does not seem to be empty and is resent as if
> > there was a interrupt triggered every time there is a send. (hence going
> > back to the vUAR0RX function)
>
> I'm not sure I follow. Are you saying each time you send you also get
> an Rx interrupt? Do you have some sort of loopback configuration?
> > -so my question is: Should Queues be used instead of semaphores in a
> > situation like this?
>
> I can't really read the code as the formatting has all been messed up,
> but as a general comment - if you have any sort of throughput
> requirements it is best to use a semaphore. Have the interrupt place
> the data in a circular buffer, then give a semaphore when you want a
> task to drain the buffer. A lot of the FreeRTOS demos use queues to
> pass data into and out of the an interrupt - but this is done really to
> demonstrate queues being used in interrupt, and to test the system by
> loading it up. It is not meant to represent an efficient implementation
> - but is useful for low throughput applications such as command
> interpreters that receive one character at a time.
>
> Regards,
> Richard.
>
> + http://www.FreeRTOS.org
> Designed for Microcontrollers.
> More than 7000 downloads per month.
>
>
>


--- In l..., Matthew Partyka wrote:
>
> Can I attach files on this board? ...I'll give it a shot
> im not sure how I can make the code more readable,

Please do not post code.

Please ask questions to help you understand the problem.

You are asking for people to fix your code with no understanding.

don


Memfault Beyond the Launch