Reg:Longer strings in UART library

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Reg:Longer strings in UART library

388 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Microembedded on Tue Aug 12 01:52:30 MST 2014

Hi all,

I am using a UART library to send and receive data.While i use shorter strings to capture the input data in the receive pin,the function works well.The UART Buffer is displaying the correct data.To be exact if receive more than 16 bytes of data the buffer gets corrupted and sometimes it behaves well and sometimes it misses the first character and last 5 characters.I am tring to send 20 bytes of data to the UART of LPC1227 through my PC.Kindly advice.

#define BUFSIZE  100
volatile uint8_t  UARTBuffer0[100];

I am giving below the UART portion of the code.

/*****************************************************************************
** Function name:UART_IRQHandler
**
** Descriptions:UART interrupt handler
**
** parameters:None
** Returned value:None
**
*****************************************************************************/
void UART0_IRQHandler(void)
{
  uint8_t k,IIRValue, LSRValue;
  uint8_t Dummy = Dummy;

  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 */
      UARTStatus0 = 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 */
      UARTBuffer0[UARTCount0++] = LPC_UART0->RBR;
      if (UARTCount0 == BUFSIZE)
      {
        UARTCount0 = 0;/* buffer overflow */

      }
    }
  }
  else if (IIRValue == IIR_RDA)/* Receive Data Available */
  {
    /* Receive Data Available */
    UARTBuffer0[UARTCount0++] = LPC_UART0->RBR;
    if (UARTCount0 == BUFSIZE)
    {
      UARTCount0 = 0;/* buffer overflow */
    }
  }
  else if (IIRValue == IIR_CTI)/* Character timeout indicator */
  {
    /* Character Time-out indicator */
    UARTStatus0 |= 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)
    {
      UARTTxEmpty0 = 1;
    }
    else
    {
      UARTTxEmpty0 = 0;
    }
  }
  return;
}

/*****************************************************************************
** Function name:UART_IRQHandler
**
** Descriptions:UART interrupt handler
**
** parameters:None
** Returned value:None
**
*****************************************************************************/
void UART1_IRQHandler(void)
{
  uint8_t IIRValue, LSRValue;
  uint8_t Dummy = Dummy;

  IIRValue = LPC_UART1->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_UART1->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 */
      UARTStatus1 = LSRValue;
      Dummy = LPC_UART1->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 */
      UARTBuffer1[UARTCount1++] = LPC_UART1->RBR;
      if (UARTCount1 == BUFSIZE)
      {
        UARTCount1 = 0;/* buffer overflow */
      }
    }
  }
  else if (IIRValue == IIR_RDA)/* Receive Data Available */
  {
    /* Receive Data Available */
    UARTBuffer1[UARTCount1++] = LPC_UART1->RBR;
    if (UARTCount1 == BUFSIZE)
    {
      UARTCount1 = 0;/* buffer overflow */
    }
  }
  else if (IIRValue == IIR_CTI)/* Character timeout indicator */
  {
    /* Character Time-out indicator */
    UARTStatus1 |= 0x100;/* Bit 9 as the CTI error */
  }
  else if (IIRValue == IIR_THRE)/* THRE, transmit holding register empty */
  {
    /* THRE interrupt */
    LSRValue = LPC_UART1->LSR;/* Check status in the LSR to see if
valid data in U0THR or not */
    if (LSRValue & LSR_THRE)
    {
      UARTTxEmpty1 = 1;
    }
    else
    {
      UARTTxEmpty1 = 0;
    }
  }
  return;
}

/*****************************************************************************
** Function name:ModemInit
**
** Descriptions:Initialize UART0 port as modem, setup pin select.
**
** parameters:location
** Returned value:None
**
*****************************************************************************/
void ModemInit( uint32_t location )
{
  if ( location == 0 )
  {
LPC_IOCON->PIO0_3 &= ~0x07;    /* UART I/O config */
LPC_IOCON->PIO0_3 |= 0x02;     /* UART DTR output */
LPC_IOCON->PIO0_7 &= ~0x07;
LPC_IOCON->PIO0_7 |= 0x02;     /* UART CTS input */
LPC_IOCON->PIO0_0 &= ~0x07;
LPC_IOCON->PIO0_0 |= 0x02;     /* UART RTS output */
LPC_IOCON->PIO0_4 &= ~0x07;
LPC_IOCON->PIO0_4 |= 0x02;     /* UART DSR input */
LPC_IOCON->PIO0_5 &= ~0x07;
LPC_IOCON->PIO0_5 |= 0x02;     /* UART DCD input */
LPC_IOCON->PIO0_6 &= ~0x07;
LPC_IOCON->PIO0_6 |= 0x02;     /* UART RI input */
  }
  else if ( location == 1 )
  {
LPC_IOCON->PIO2_3 &= ~0x07;    /* UART I/O config */
LPC_IOCON->PIO2_3 |= 0x04;     /* UART DTR output */
LPC_IOCON->PIO2_4 &= ~0x07;
LPC_IOCON->PIO2_4 |= 0x04;     /* UART CTS input */
LPC_IOCON->PIO2_0 &= ~0x07;
LPC_IOCON->PIO2_0 |= 0x04;     /* UART RTS output */
LPC_IOCON->PIO2_7 &= ~0x07;
LPC_IOCON->PIO2_7 |= 0x04;     /* UART DSR input */
LPC_IOCON->PIO2_6 &= ~0x07;
LPC_IOCON->PIO2_6 |= 0x04;     /* UART DCD input */
LPC_IOCON->PIO2_5 &= ~0x07;
LPC_IOCON->PIO2_5 |= 0x04;     /* UART RI input */
  }
  LPC_UART0->MCR = 0xC0;          /* Enable Auto RTS and Auto CTS. */
  return;
}

/*****************************************************************************
** Function name:SetupUART_Location
**
** Descriptions:Setup UART0 location
**
** parameters:port number, location
** Returned value:None
**
*****************************************************************************/
void SetupUART_Location(uint32_t portNum, uint32_t location)
{
  if ( portNum == 0 )
  {
if ( location == 0 )
{
  LPC_IOCON->PIO0_1 &= ~0x07;    /* UART0 I/O config */
  LPC_IOCON->PIO0_1 |= 0x02;     /* UART0 RXD LOC0 */
  LPC_IOCON->PIO0_2 &= ~0x07;
  LPC_IOCON->PIO0_2 |= 0x02;     /* UART0 TXD LOC0 */
}
else if ( location == 1 )
{
  LPC_IOCON->PIO2_1 &= ~0x07;    /* UART0 I/O config */
  LPC_IOCON->PIO2_1 |= 0x04;     /* UART0 RXD LOC1 */
  LPC_IOCON->PIO2_2 &= ~0x07;
  LPC_IOCON->PIO2_2 |= 0x04;     /* UART0 TXD LOC1 */
}
  }
  else if ( portNum == 1 )
  {
if ( location == 0 )
{
  LPC_IOCON->PIO0_8 &= ~0x07;    /* UART1 I/O config */
  LPC_IOCON->PIO0_8 |= 0x02;     /* UART1 RXD LOC0 */
  LPC_IOCON->PIO0_9 &= ~0x07;
  LPC_IOCON->PIO0_9 |= 0x02;     /* UART1 TXD LOC0 */
}
else if ( location == 1 )
{
  LPC_IOCON->PIO2_11 &= ~0x07;    /* UART1 I/O config */
  LPC_IOCON->PIO2_11 |= 0x05;     /* UART RXD LOC1 */
  LPC_IOCON->PIO2_10 &= ~0x07;
  LPC_IOCON->PIO2_10 |= 0x05;     /* UART TXD LOC1 */
}
else
{
  LPC_IOCON->PIO2_12 &= ~0x07;    /* UART1 I/O config */
  LPC_IOCON->PIO2_12 |= 0x03;     /* UART RXD LOC1 */
  LPC_IOCON->PIO2_13 &= ~0x07;
  LPC_IOCON->PIO2_13 |= 0x03;     /* UART TXD LOC1 */
}
  }
  else
  {
while ( 1 );
  }
  return;
}

/*****************************************************************************
** Function name:UARTInit
**
** Descriptions:Initialize UARTx port, setup pin select,
**clock, parity, stop bits, FIFO, etc.
**
** parameters:UART port number, baudrate
** Returned value:None
**
*****************************************************************************/
void UARTInit(uint32_t portNum, uint32_t baudrate)
{
  uint32_t i, Fdiv;
  uint32_t regVal;

  if ( portNum == 0 )
  {
UARTTxEmpty0 = 1;
UARTCount0 = 0;
    for ( i = 0; i < BUFSIZE; i++ )
{
  UARTBuffer0 = 0;

}
NVIC_DisableIRQ(UART0_IRQn);

SetupUART_Location( portNum, 0 );/* default is location 0 */

/* Enable UART 0 clock */
LPC_SYSCON->PRESETCTRL |= (0x1<<2);
LPC_SYSCON->SYSAHBCLKCTRL |= (0x1<<12);
LPC_SYSCON->UART0CLKDIV = 0x1;     /* divided by 1 */

LPC_UART0->LCR = 0x83;             /* 8 bits, no Parity, 1 Stop bit */
regVal = LPC_SYSCON->UART0CLKDIV;
Fdiv = ((SystemCoreClock/regVal)/16)/baudrate ;/*baud rate */

LPC_UART0->DLM = Fdiv / 256;
LPC_UART0->DLL = Fdiv % 256;
LPC_UART0->LCR = 0x03;/* DLAB = 0 */
LPC_UART0->FDR = 0x10;/* set to default value: 0x10 */
LPC_UART0->FCR = 0x07;/* Enable and reset TX and RX FIFO. */

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

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

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

#if TX_INTERRUPT
LPC_UART0->IER = IER_RBR | IER_THRE | IER_RLS;/* Enable UART interrupt */
#else
LPC_UART0->IER = IER_RBR | IER_RLS;/* Enable UART interrupt */
#endif
  }
  else
  {
UARTTxEmpty1 = 1;
UARTCount1 = 0;
    for ( i = 0; i < BUFSIZE; i++ )
{
  UARTBuffer1 = 0;
}
NVIC_DisableIRQ(UART1_IRQn);

SetupUART_Location( portNum, 0 );/* default is location 0 */

/* Enable UART 1 clock */
LPC_SYSCON->PRESETCTRL |= (0x1<<3);
LPC_SYSCON->SYSAHBCLKCTRL |= (0x1<<13);
LPC_SYSCON->UART1CLKDIV = 0x1;     /* divided by 1 */

LPC_UART1->LCR = 0x83;             /* 8 bits, no Parity, 1 Stop bit */
regVal = LPC_SYSCON->UART1CLKDIV;
Fdiv = ((SystemCoreClock/regVal)/16)/baudrate ;/*baud rate */

LPC_UART1->DLM = Fdiv / 256;
LPC_UART1->DLL = Fdiv % 256;
LPC_UART1->LCR = 0x03;/* DLAB = 0 */
LPC_UART1->FDR = 0x10;/* set to default value: 0x10 */
LPC_UART1->FCR = 0x07;/* Enable and reset TX and RX FIFO. */

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

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

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

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

/*****************************************************************************
** Function name:UARTSend
**
** Descriptions:Send a block of data to the UART 0 port based
**on the data length
**
** parameters:portNum, buffer pointer, and data length
** Returned value:None
**
*****************************************************************************/
void UARTSend(uint32_t portNum, uint8_t *BufferPtr, uint32_t Length)
{

  while ( Length != 0 )
  {
if ( portNum == 0 )
{
  /* THRE status, contain valid data */
#if !TX_INTERRUPT
  while ( !(LPC_UART0->LSR & LSR_THRE) );
  LPC_UART0->THR = *BufferPtr;
#else
  /* Below flag is set inside the interrupt handler when THRE occurs. */
      while ( !(UARTTxEmpty0 & 0x01) );
  LPC_UART0->THR = *BufferPtr;
      UARTTxEmpty0 = 0;/* not empty in the THR until it shifts out */
#endif
}
else
{
  /* THRE status, contain valid data */
#if !TX_INTERRUPT
  while ( !(LPC_UART1->LSR & LSR_THRE) );
  LPC_UART1->THR = *BufferPtr;
#else
  /* Below flag is set inside the interrupt handler when THRE occurs. */
      while ( !(UARTTxEmpty1 & 0x01) );
  LPC_UART1->THR = *BufferPtr;
      UARTTxEmpty1 = 0;/* not empty in the THR until it shifts out */
#endif
}
BufferPtr++;
Length--;
  }
  return;
}

int main (void)
    {

        while(!)
{
      if ( UARTCount0 != 0 )
              {
                        LPC_UART0->IER = IER_THRE | IER_RLS;
                        UARTSend( 0, UARTBuffer0 ,20);
                        LPC_UART0->IER = IER_THRE | IER_RLS | IER_RBR;
              }
}
}
0 Kudos
5 Replies

351 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Microembedded on Tue Aug 12 07:55:07 MST 2014
HI rocketdawg,

            I couldnt get your last sentence.Did you guess the code takes care of string more than 16 bytes?Any idea why isnt working everytime?or if the code doesnt take care of string of more than 16 bytes any suggestion how to modify the code.Thank you.
0 Kudos

351 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rocketdawg on Tue Aug 12 07:30:18 MST 2014
I do not use that part, but I bet that the data sheet says that the UART has an internal FIFO of 16 bytes.
so the code just happens to work because it was, unbeknownst to you,  using these internal FIFO.
just a guess, but sometimes I guess good.
0 Kudos

351 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Microembedded on Tue Aug 12 06:34:51 MST 2014
But what i cannot understand is that the existing program works fine on some occasions.It works fine on all occasions when input string is less than 16 bytes. Thank you.
0 Kudos

351 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Microembedded on Tue Aug 12 04:52:24 MST 2014
Thanks Martin for your response but the same program is working fine if i send only 16 bytes of data.The problem starts only when i send more than 16 bytes of data to the UART.I am sending 20 bytes of data in the same fashion i am sending 16 bytes of data,then why shouldnt the buffer receive the 20 bytes of data in the same way it receives 16 bytes of data.

     Please can you suggest what change should i do to the code to resolve this issue.Thanks a lot
0 Kudos

351 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by capiman on Tue Aug 12 02:11:34 MST 2014
Hi,

what happens when some characters (e.g. up to 16 bytes) are received?
They get collected in interrupt routine and UARTCount0 is increased, say e.g. to 4.
In your main routine you are sending fixed 20 bytes, even when only 4 bytes were received...

What happens when you receive the remaining bytes?
You send out again 20 bytes, some bytes valid, some of them not...

What happens when you receive more than 20 bytes? Where in UARTBuffer0 are they written by ISR?
Not at the beginning, but somewhere behind the 20 bytes.
Your sending in main always starts at the beginning, even when there was nothing updated.

What happens when you receive some bytes at the end of the buffer, wrap around,
and write the next received byte at the start of the buffer?
Your call to UARTSend in main can't handle such a wrap-around situation...

You are disabling interrupts (RBR) in main. What happens when more data is received,
when you are still in the process of sending out 20 characters (done in main)?

Best regards,

Martin
0 Kudos