LPC1114: confusion about UART example

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

LPC1114: confusion about UART example

1,804 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by RA1981 on Sun Mar 27 01:29:37 MST 2011
Hi,

I'm going through the examples provided with the LPCxpresso IDE.
Currently I'm looking at the UART example located in the "UART" folder, sub-folder "driver", file "UART.c".
The interrupt handler has the following RLS (receive line status) section:
  if (IIRValue == IIR_RLS)        /* Receive Line Status */
  {
    LSRValue = LPC_UART->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 */
      UARTStatus = LSRValue;
      Dummy = LPC_UART->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 */
      UARTBuffer[UARTCount++] = LPC_UART->RBR;
      if (UARTCount == BUFSIZE)
      {
        UARTCount = 0;        /* buffer overflow */
      }    
    }
  }
If I understand the LPC11xx User Manual correctly, the only interrupt source for RLS interrupts are the error flags OE, PE, FE and BI of the Line Status Register LSR.
Now, the confusion is about the second if-block which checks the receive data ready flag RDR. If the above mentioned error flags are the only source for a RLS interrupt, the second if-block could never be executed because the condition for the first if-block is true and therefore the ISR is leaved.
What am I missing?

There's also a confusing statement in the user manual regarding the RDA interrupt source:
"Rx data available [B]or[/B] trigger level reached in FIFO (U0FCR[0]=1)"
According to UART FIFO Control Register (U0FCR) description U0FCR[0] (FIFOEnable flag) must not be zero when using the UART. So the above could be missunderstood in a way that the FIFO trigger level is useless...
I [U]think[/U] I can read it as:
"Rx data available[B](U0FCR[0]=0)[/B] or trigger level reached in FIFO (U0FCR[0]=1)"
Am I correct?

Sorry if I'm asking silly questions, but for me it seems NxP user manuals are hard to read, they should be more detailed

Regards,

Ralf
0 Kudos
8 Replies

999 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by researchinnovation on Mon Dec 03 02:09:07 MST 2012

Quote: mindware
simply devised another "packaging method" and did the work in main.
Stuff seems to be working alright.
Thank you for the tip.


Hi..
Can you please share your working code with us.



Thanks & Regards...  :-)
0 Kudos

999 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Wed Nov 23 02:23:31 MST 2011
Hm,

transmitting data from the uart interrupt is not brave - it's ... well ... just asking for problems. An ISR should be simple, very short and especially never poll or wait for a device to finish :eek:

If you end up inside the first IF statement this just means there is some problem with the date received (perhaps you are using the wrong baud rate, number of data bits or a parity error ?).
You could try to loop back the uart port and send a character from you main application (after enabling the interrupt handler) to see if that workd.

I would not unpack the messages inside the interrupt handler.
Instead, just check for an end of packet signature in the interrupt handler and signal your program that a packet is complete - then let the application decode the packet.

The software example program provided in the examples folder should work - I've used that example before with success.

Regards,
[INDENT]Rob
[/INDENT]
0 Kudos

999 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gbm on Wed Nov 23 02:20:58 MST 2011
First, there are many UART interrupt sources - error, modem status change, received data, empty transmit register, timeout when receiving data with FIFO not empty.

Second, 16550-type UART, after which the LPC UARTs were modelled, is an outdated controller withe read-sensitive registers, which makes a proper interrupt servicing techinqe a nightmare. It is possible to write a non-elegant but working code for interrupt-driven transmit (did that a few times), and there are no problems with interrupt-driven reception.

The NXP demo code looks slighly incorrect, but ii ts 90% useable.
0 Kudos

999 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mindware on Tue Nov 22 20:28:12 MST 2011
I gave up playing with the ISR and simply devised another "packaging method" and did the work in main.
Stuff seems to be working alright.
Thank you for the tip.
0 Kudos

999 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Thu Nov 17 18:49:37 MST 2011

Quote:

Any ideas?

UART buffers are a really good idea. They are used to keep ISR short. You are doing a lot of stuff in your UART ISR, even transmitting :eek:

That's brave :)

The rest of the world is probably just processing UART buffer data outside UART ISR in main :rolleyes:
0 Kudos

999 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mindware on Thu Nov 17 18:24:57 MST 2011
Hi guys,

I'm in the middle of trying to figure this UART out myself. I managed to get to the point where the UART ISR keeps repeating itself(I can see it because I print a string at the routine's end(also trough the UART)for debug purposes).
The thing is that it's repeating itself without anything being sent to the UART RX pin...
All this just by using the example code given for LPCXpresso and some minor,harmless tinkering.
I only used the loopback example and added some code to treat the char that I receive and not place it in the UARTBuffer, but pass it to a switch statement and add it (or not) to a buffer.
As I understood, the interrupt flag gets unset when I read the RBR register.
Here's the code:

volatile uint32_t UARTStatus;
volatile uint8_t  UARTTxEmpty = 1;
volatile uint8_t  UARTBuffer[BUFSIZE];
volatile uint32_t UARTCount = 0;
uint8_t Buf_var[PKGSIZE], Parsable=0, First_char=1, Pos_in_message=0, Write1_personal=0;//za_char;
uint8_t za_char,var_i, message[30];
uint8_t mes_fin[]="\n\rString totally evaluated.\n\r",mes_start[]="\n\rHit the { char.\n\r", mes_stop[]="\n\rHit the end } char.\n\r",mes_char[]="\n\rJust another useful char.\n\r" ;
#if CONFIG_UART_DEFAULT_UART_IRQHANDLER==1
/*****************************************************************************
** Function name:        UART_IRQHandler
**
** Descriptions:        UART interrupt handler
**
** parameters:            None
** Returned value:        None
** 
*****************************************************************************/
void UART_IRQHandler(void)
{
    //LPC_UART->IER = IER_THRE | IER_RLS;  /* Disable RBR */
  uint8_t IIRValue, LSRValue;
  uint8_t Dummy = Dummy;
  uint8_t Error=0;
  IIRValue = LPC_UART->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_UART->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 */
      UARTStatus = LSRValue;
      Dummy = LPC_UART->RBR;    /* Dummy read on RX to clear 
                                interrupt, then bail out */
      Error=1;
      //LPC_UART->IER = IER_THRE | IER_RLS | IER_RBR;    /* Re-enable RBR */
      return;
    }
    if (LSRValue & LSR_RDR)    /* Receive Data Ready */            
    { Error=0;
      /* If no error on RLS, normal ready, save into the data buffer. */
      /* Note: read RBR will clear the interrupt */
      //UARTBuffer[UARTCount++] = LPC_UART->RBR;
    za_char= LPC_UART->RBR;
     // if (UARTCount == BUFSIZE)
     // {
      //  UARTCount = 0;        /* buffer overflow */
     // }
    }
  }
  else if (IIRValue == IIR_RDA)    /* Receive Data Available */
  {    Error=0;
    /* Receive Data Available */
  za_char = LPC_UART->RBR;
 // if  ( (LPC_UART->LSR & LSR_THRE) );
  //LPC_UART->THR = za_char;
  // UARTBuffer[UARTCount++] = LPC_UART->RBR;
   // if (UARTCount == BUFSIZE)
    //{
     // UARTCount = 0;        /* buffer overflow */
    //}
  }
  else if (IIRValue == IIR_CTI)    /* Character timeout indicator */
  {Error=1;
    /* Character Time-out indicator */
    UARTStatus |= 0x100;        /* Bit 9 as the CTI error */
  }
  else if (IIRValue == IIR_THRE)    /* THRE, transmit holding register empty */
  {Error=1;
    /* 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;
    }
  }

  if(!Error)
  {
     if(!Parsable)
          { switch (za_char){
          case '{':
                { UARTSend((uint8_t *)mes_start,(int)strlen((const char *)mes_start));
                  if(First_char==1)
                      {
                            First_char=0;
                            Write1_personal=1; Pos_in_message=0;
                           // LPC_UART->THR = '#';
                            UARTSend((uint8_t * )Buf_var, (int)strlen((const char *)Buf_var));
                            //LPC_UART->THR = '\n';
                            for( var_i=0;var_i<=PKGSIZE;var_i++)
                                  {
                                      Buf_var[var_i]=0;
                                  }
                      }
                    break;
                }
          case '}':
                { UARTSend((uint8_t *)mes_stop,(int)strlen((const char *)mes_stop));
                  if (First_char==0 )
                        {
                            if (Pos_in_message == 5)
                                  {
                                      Parsable=1;
                                  }
                            else
                                  {
                                      for( var_i=0;var_i<=PKGSIZE;var_i++)
                                            {
                                                Buf_var[var_i]=0;
                                            }
                                      First_char=1;
                                      Write1_personal=0;
                                      Pos_in_message=0;
                                  }
                        }

                          break;
                }
          default:
                { UARTSend((uint8_t *)mes_char,(int)strlen((const char *)mes_char));
                  if(First_char==0 && Write1_personal && Pos_in_message<=4 )
                                      {
                                          Buf_var[Pos_in_message++]=za_char;
                                          UARTSend((uint8_t * )Buf_var, (int)strlen((const char *)Buf_var));
                                    }

                }

          }

          }
  }

 // LPC_UART->IER = IER_THRE | IER_RLS | IER_RBR;    /* Re-enable RBR */
  UARTSend((uint8_t *)mes_fin,(int)strlen((const char *)mes_fin));
  return;
}
#endif
Sorry for the crappy code but I'm getting desperate. I'm stuck at this for 2 weeks now and I can't seem to get anywhere.
It usually starts to auto-repeat after I send the first char in.
I'm trying to get the ISR to unpack messages that look like this:
{A1234}
where the brackets are the marks for start and stop, and the actual string that I want to capture in a buffer is A1234(for example).

Can you please give me some advice/pointers to follow?
Any ideas?
What can go so wrong since I don't mess with the flags or anything?


All the best,
mindware

p.s.
If it's not legal to post that code I'm asking a moderator to remove it,please.
0 Kudos

999 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by RA1981 on Mon Mar 28 03:45:51 MST 2011
Hi Larry,


Quote:
I just looked at the code and UM10398 and at first glance it appears that you are correct about this.


:) Thank you for checking it. My first thought was I am missing something ;)


Quote:
I completely agree with you on the state of the user manuals.  NXP  should spend a little more time explaining how to use the peripherals  and provide some code snippets as well.


Indeed. The above U0FCR[0] (FIFOEnable flag) thing is one example. If U0FCR[0] must be set for proper operation no other part of the documentation should leave confusion about it if it's possibly cleared, this leads to missunderstanding and may result in loosing the fun of these nice controllers :(

Still fighting with the UART ISR, but it's getting better... (at least I hope so).

Regards,

Ralf
0 Kudos

999 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Sun Mar 27 11:02:10 MST 2011
Hi Ralf,


Quote: RA1981
If I understand the LPC11xx User Manual correctly, the only interrupt source for RLS interrupts are the error flags OE, PE, FE and BI of the Line Status Register LSR.
Now, the confusion is about the second if-block which checks the receive data ready flag RDR. If the above mentioned error flags are the only source for a RLS interrupt, the second if-block could never be executed because the condition for the first if-block is true and therefore the ISR is leaved.
What am I missing?



I just looked at the code and UM10398 and at first glance it appears that you are correct about this.


Quote:
There's also a confusing statement in the user manual regarding the RDA interrupt source:
"Rx data available [B]or[/B] trigger level reached in FIFO (U0FCR[0]=1)"
According to UART FIFO Control Register (U0FCR) description U0FCR[0] (FIFOEnable flag) must not be zero when using the UART. So the above could be missunderstood in a way that the FIFO trigger level is useless...
I [U]think[/U] I can read it as:
"Rx data available[B](U0FCR[0]=0)[/B] or trigger level reached in FIFO (U0FCR[0]=1)"
Am I correct?



I'm not completely sure about this but as you stated the U0FCR bit 0 is FIFOEn and must be set to enable proper UART operation.  U0FCR is write only and a zero, or transition, of this bit will disable and automatically clear the UART FIFOs. I don't see it as an indicator of any status.  If I'm wrong I hope to be flogged.:)


Quote:

Sorry if I'm asking silly questions, but for me it seems NxP user manuals are hard to read, they should be more detailed :(



I completely agree with you on the state of the user manuals.  NXP should spend a little more time explaining how to use the peripherals and provide some code snippets as well.

Larry
0 Kudos