lpcware

UART Problem

Discussion created by lpcware Employee on Jun 15, 2016
Content originally posted in LPCWare by lmoreira on Fri May 18 01:05:27 MST 2012
Hi Guys,
I have a program that at this point is sending and receiving a packet of data via the USART. I was using interrupts previously but at some stage I decided to try it without the interrupts, but decided that I would like to use them again. the problem is that now that i reinstated the interrupts, the program is not working properly.
The program seems to have the interrupts for the USART disabled but I am clearly enabling them on the UartInit() function which I call at the program startup. It will simply not enter the ISR handler function.

Theres my code for usart.c:

#include "LPC13xx.h"
#include "dataBufferHandler.h"
#include "usart.h"

#define SystemFrequency SystemCoreClock

extern volatile Queue *qAvailableBuffers;

extern volatile Queue *qRXPacketBReady;

uint32_t UARTTxEmpty = 1;

volatile uint8_t  rxTempData;

volatile uint32_t rxTemp;


volatile uint32_t state = 0;

//****************** Added 02/03/12*******
uint32_t flag = 0;
volatile MultiBuffer *usartRxBuffer;
volatile uint32_t rxBufferCount = 0;        // keeps track of number of chars available.

//*******************************************************
//********************Added 19/03/12*********************

extern volatile Queue qRXPacketReady;


/*****************************************************************************
** Function name:        UARTInit
**
** Descriptions:        Initialize UART0 port, setup pin select,
**                clock, parity, stop bits, FIFO, etc.
**
** parameters:            UART baudrate
** Returned value:        None
**
*****************************************************************************/
void UARTInit(void)
{
  uint32_t Fdiv;
  uint32_t regVal;
  uint32_t baudrate = 115200;
  NVIC_DisableIRQ(UART_IRQn);

  LPC_IOCON->PIO1_6 &= ~0x07;    /*  UART I/O config */
  LPC_IOCON->PIO1_6 |= 0x01;     /* UART RXD */
  LPC_IOCON->PIO1_7 &= ~0x07;
  LPC_IOCON->PIO1_7 |= 0x01;     /* UART TXD */
  /* Enable UART clock */
  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
  LPC_SYSCON->UARTCLKDIV = 0x1;     /* divided by 1 */

  LPC_UART->LCR = 0x83;             /* 8 bits, no Parity, 1 Stop bit */
  regVal = LPC_SYSCON->UARTCLKDIV;
  Fdiv = (((SystemFrequency/LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16)/baudrate ;    /*baud rate */

  LPC_UART->DLM = Fdiv / 256;
  LPC_UART->DLL = Fdiv % 256;
  LPC_UART->LCR = 0x03;        /* DLAB = 0 */
  LPC_UART->FCR = 0x07;        /* Enable and reset TX and RX FIFO. */

  /* Read to clear the line status. */
  regVal = LPC_UART->LSR;

  /* Ensure a clean start, no data in either TX or RX FIFO. */
// CodeRed - added parentheses around comparison in operand of &
  while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );
  while ( LPC_UART->LSR & LSR_RDR )
  {
    regVal = LPC_UART->RBR;    /* Dump data from RX FIFO */
  }

  /* Enable the UART Interrupt */
  NVIC_EnableIRQ(UART_IRQn);

#if TX_INTERRUPT
  LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS;    /* Enable UART interrupt */
#else
  LPC_UART->IER = IER_RBR | IER_RLS;    /* Enable UART interrupt */
#endif
  return;
}


/*****************************************************************************
** Function name:        UART_IRQHandler
**
** Descriptions:        UART interrupt handler
**                         It really handles reception of packets
**
** parameters:            None
** Returned value:        None
**
** Notes:
** - I have a bit of a problem with this routine. It seems to have
** to much in it for a interrupt handling routine. I would rather
** prefer if we just incremented/set a flag to denote that there
** are char waiting in the USART RX hardware buffer.
** This will mean that we need to check that flag at regular intervals.
**
** As I add more functionality this routine will create problems because
** I am spending to much time in the interrupt routine.
**
** Thinking about it do I need an interrupt for every character received?
** I don't think so, only if communications on the USART are the priority.
**
*****************************************************************************/

void UART_IRQHandler(void)
{
    volatile uint8_t  rxTempData;

    uint8_t IIRValue, LSRValue;
    uint8_t Dummy = Dummy;

    /******** Added 02/03/12*******/
    if(flag == 0)    /* flag needs to be Global*/
    {
        usartRxBuffer = getElementFromQueue(qAvailableBuffers);
        flag = 1;
    }

    /******************************/

    IIRValue = LPC_UART->IIR;

    IIRValue >>= 1;            /* skip pending bit in IIR, this is OK but may be needed
                               at some other stage*/
    IIRValue &= 0x07;            /* check bit 1~3, interrupt identification by masking the 3 bits*/

    /* One way to check for received data, it also checks for line errors */
    if (IIRValue == IIR_RLS)        /* Receive Line Status check for type of interrupt  */
    {
        LSRValue = LPC_UART->LSR;    /* check if there is any line error */
        /* Receive Line Status */
        if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI))
        {
            /* There are errors or break interrupt, hence we need as minimum
             * clear the interrupts we probably should also dump the data
             * in the buffer*/
            /* Read LSR will clear the interrupt */
            rxTemp = LSRValue;
            Dummy = LPC_UART->RBR;    /* Dummy read on RX to clear
                                    interrupt, then bail out */
            return;    /* needs checking */
        }
    }
    /* This is a modification to the program's previous version, it should work, but needs checking */
    if ((LSRValue & LSR_RDR)|(IIRValue == IIR_RDA))    /* Receive Data Ready | Receive Data Available*/
    {
            /* If no error on RLS, normal ready, save into the data buffer. */

            /* Note: read RBR will clear the interrupt, this is important
             * or else on the next if statement bellow it will again react to the interrupt*/

            /* Receive Data Available */
            rxTempData = LPC_UART->RBR;
            /*Check for startChar
              No checks required, I think. if a Start Char is received
              dump packet and restart. */
            if(rxTempData == TXPSTARTCHAR)
            {
                rxBufferCount = 0;
                state = 1;




                if (state == 0)
                {
                    usartRxBuffer->buffer[rxBufferCount] = rxTempData;
                    rxBufferCount++;
                    state = 1; /*Start character as been received and it is possibly a valid packet */

                    return;
                }
                /*Another Start Char as been received without end of packet. needs error handling */
                if (state == 1)
                {
                    releaseBuffer(usartRxBuffer);
                    rxBufferCount = 0;
                    state = 0;
                    flag = 0;

                }


            }
            if((state == 1)&(rxTempData != TXPENDCHAR))
            {
                rxBufferCount++;
                /*Resulting Data will not include StartChar*/
                usartRxBuffer->buffer[rxBufferCount++] = rxTempData;
                /*Resulting Data will not include StartChar*/
            }
            /*Normal state packet is ready for processing*/
            if((state == 1)&(rxTempData == TXPENDCHAR))
            {
                usartRxBuffer->buffer[rxBufferCount++] = rxTempData;
                usartRxBuffer->buffer[107] = rxBufferCount;
                addElementToQueue(qRXPacketBReady, usartRxBuffer);


                state = 0;
                rxBufferCount = 0;
                flag = 0;
            }
            /* Packet length time out, no error handling for now */
            if(rxBufferCount > MAXPACKETLENGTH)
            {
                releaseBuffer(usartRxBuffer);
                state = 0;
                flag = 0;
            }


    }
    /* Not quiet sure I need this or what actually does */
    else if (IIRValue == IIR_CTI)    /* Character timeout indicator */
    {
        /* Character Time-out indicator */
        rxTemp |= 0x100;        /* Bit 9 as the CTI error */
    }
    /* This is for the TX part probably not needed */
    else if (IIRValue == IIR_THRE)    /* THRE, transmit holding register empty */
    {
        /* THRE interrupt */
        LSRValue = LPC_UART->LSR;        /* Check status in the LSR to see if
                                           valid data in U0THR or not */
        if (LSRValue & LSR_THRE)
        {
            UARTTxEmpty = 1;
        }
        else
        {
            UARTTxEmpty = 0;
        }
    }

    Dummy = LPC_UART->RBR;

}



The UartInit() function is not my original one, in desperation I transplanted the one given on the uart example that came with LPCXpresso as that example works perfectly fine.

Any ideas welcomed.

Best Regards
                   Luis

Outcomes