LPC1769 UART Interrupts ONCE

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

LPC1769 UART Interrupts ONCE

2,579 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gminnucci on Tue Feb 19 14:36:01 MST 2013
Hi everybody,

I have this code below as IRQ handler for UART1 Interrupt.
The fact is that it only interrupt once in receiving mode... :confused:
Could anybody help ?
Thx in advance.
Gus
[FONT=Courier New][SIZE=2]
----------------------------
[B]void UART1_IRQHandler (void)[/B]
{
    uint32_t IIRValue;
    uint16_t Dummy;

  IIRValue = LPC_UART1->IIR;
  IIRValue &= IIR_MASK;
  switch (IIRValue) {    /*-----------------------------------------------------------------------------------------*/
      default:
        case IIR_NO_PENDING:           
      break;  /*-----------------------------------------------------------------------------------------*/
      /* RX Line Status Error */
        case IIR_RLS:                /* RESET: Read LSR */
        COMM1.sr    = LPC_UART1->LSR ;
        COMM1.rdr   = LPC_UART1->RBR;              
      break;  /*-----------------------------------------------------------------------------------------*/
    /* Receive Data Available */
    case IIR_RDA:               
        COMM1.sr    = LPC_UART1->LSR ;
        COMM1.rdr     = LPC_UART1->RBR;

        if (COMM1.sr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) {
        }
        else {
                COMM1.buffer[COMM1.idx++] = COMM1.rdr;
                COMM1.n_paq ++;
            }
        }
    break;
    case IIR_CTOUT:             
        Dummy = LPC_UART1->RBR;
        Dummy |= 0x100;        /* Bit 9 as the CTI error */
    break;
[/SIZE][/FONT]
[FONT=Courier New][SIZE=2][FONT=Courier New][SIZE=2]/*-----------------------------------------------------------------------------------------*/
[/SIZE][/FONT]    case IIR_THRE:                /* RESET: Read IIR o Write THR */
    break;

    case IIR_MSR:      /* RESET: Read MSR (ADD: 0xXXXX XXXX) */
    break;
  }
  return;
}
/*-----------------------------------------------------------------------------------------*/[/SIZE][/FONT]
[FONT=Courier New][SIZE=2]
*****************************************************************************/
[B]uint32_t UART1Init( uint32_t baudrate )[/B]
{
  uint32_t Fdiv, ret;
  uint32_t pclkdiv, pclk;
    /*---------------------------------------------------------------------*/
/* Already Configured */
//        LPC_PINCON->PINSEL4 &= ~0x0000000F;
//        LPC_PINCON->PINSEL4 |= 0x0000000A;    /* Enable RxD1 P2.1, TxD1 P2.0 */

/* By default, the PCLKSELx value is zero, thus, the PCLK [SIZE=2]f[/SIZE]or
        all the peripherals is 1/4 of the SystemFrequency. */
        /* Bit 8,9 are for UART1 */
        pclkdiv = (LPC_SC->PCLKSEL0 >> 8) & 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_UART1->LCR = 0x83;        /* 8 bits, no Parity, 1 Stop bit */
        Fdiv = ( pclk / 16 ) / baudrate ;    /* baud rate */
        LPC_UART1->DLM = Fdiv / 256;
        LPC_UART1->DLL = Fdiv % 256;
        LPC_UART1->LCR = 0x03;        /* DLAB = 0 */
        LPC_UART1->FCR = 0x00;        /* FIFO Control: */

        LPC_UART1->IER = (IER_RBR | IER_RLS | IER_MSR);    /* Enable UART1 interrupt */

        NVIC_EnableIRQ(UART1_IRQn);
[/SIZE][/FONT][SIZE=2][FONT=Courier New]return;
[SIZE=2]}

[/SIZE][/FONT][/SIZE]
0 Kudos
Reply
3 Replies

1,821 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Fklein23 on Fri Oct 10 07:00:52 MST 2014
Ex-Zero:

I added UART0 to my UART interrupt handler, and the code is virtually the same as your quoted code (the variables are even named the same).

QUOTE:
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 */
... and so on
END QUOTE

OK, my handler does UART0, not UART1.

But here is the strange thing I am seeing. This instruction: "IIRValue = LPC_UART0->IIR;" clears the RBR register!!!!
Without breakpoints, the symptom is that the transmit functionality works perfectly, but the receive function doesn't do ANYTHING.
I can see the character sent by the terminal on the oscilloscope, the interrupt fires, but no characters appear in the application's input channel.
WITH breakpoints, I stopped the IRQ handler at this instruction and before reading the IIR register, my watch window shows

LPC_UART0->IIRconst volatile uint32_t196
LPC_UART0->RBRconst volatile uint8_t85 'U'

Then after a single step through THIS instruction: "IIRValue = LPC_UART0->IIR;"

Now my watch windows look like this:

LPC_UART0->IIRconst volatile uint32_t193
LPC_UART0->RBRconst volatile uint8_t0 '\0'

Note that not only does the RBR register get cleared, but the
I have tried several workarounds, because I was concerned that the very existence of the watch window, which displayed the value of the RBR register, might have caused the actual register to clear as if my program had read it. (I get paranoid about stuff like that after 30 years of living with the "errata" of the microprocessor world! :-)

Note not only does the RBR register get cleared by reading the IIR register, but the RX data available bit ALSO clears in the IIR register after reading it.

So I put the "read RBR"  instruction BEFORE the "read IIR" register and set a breakpoint AFTER both instructions. I then hit a key on the terminal and the variable that received the RBR data was ZERO!  ????????

I am not sure what to do. The interrupt handler is virtually identical to yours, and I was assured by my colleagues here that the same handler, when aimed at UART2 works flawlessly.

So my next step is to rewire the breadboard temporarily, to use UART2 instead of UART0 and try the same experiment and see what happens in the UART2 IRQ handler (which is identical to the UART0 handler).

I wonder if UART0 has some known quirks that make it different that UART2 and 3. I know that 0,2 and 3 are different than UART1, but the same method should work for AT LEAST UART0 and 2.

Any thoughts?
Anyone else ever seen this?

Thanks - Frank


0 Kudos
Reply

1,821 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gminnucci on Thu Feb 21 14:44:29 MST 2013
Yes. Is just the basic stuff to acomplish the service.
The problem is that the IRQ service runs Once.
It seems to be ok but....

ideas ?
Thx in advance,
Gus
0 Kudos
Reply

1,821 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Tue Feb 19 15:51:15 MST 2013
Your IRQ handler looks a little bit short :eek: Is there a special reason why you don't use a working sample code like:


Quote:

/*****************************************************************************
** Function name:        UART1_IRQHandler
**
** Descriptions:        UART1 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 */
      UART1Status = 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 */
      UART1Buffer[UART1Count] = LPC_UART1->RBR;
      UART1Count++;
      if ( UART1Count == BUFSIZE )
      {
        UART1Count = 0;        /* buffer overflow */
      }   
    }
  }
  else if ( IIRValue == IIR_RDA )    /* Receive Data Available */
  {
    /* Receive Data Available */
    UART1Buffer[UART1Count] = LPC_UART1->RBR;
    UART1Count++;
    if ( UART1Count == BUFSIZE )
    {
      UART1Count = 0;        /* buffer overflow */
    }
  }
  else if ( IIRValue == IIR_CTI )    /* Character timeout indicator */
  {
    /* Character Time-out indicator */
    UART1Status |= 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 )
    {
      UART1TxEmpty = 1;
    }
    else
    {
      UART1TxEmpty = 0;
    }
  }

}

0 Kudos
Reply