AnsweredAssumed Answered

Kinetis K10 UART reads the same byte twice

Question asked by Barry Jones on Feb 3, 2016
Latest reply on Feb 3, 2016 by Barry Jones

This has been driving me nuts all day. I have a custom PCB I've designed using a K10 to take serial packets of data from a PC and route them out to one of the other four UARTs on the K10. It also receives packets from those other UARTs to parcel up and feed back to the PC. I'm talking to the PC at 115200 baud, and everything works fine if I only have one slave device hooked to one of the other UARTs. When several are hooked up, I occasionally get the same byte twice. I'm using interrupts, (no DMA), have looked through a lot of example source code and studied the documentation without finding an answer. Here's hoping someone can offer a suggestion. Here's the IRQ handling code:


#define GET_UART_DATA(channel) \

    { \

    s_UartRXBuffers[channel][s_UartRXWriteIdx[channel]++] = UART_D_REG(UART__base_ptr_tbl[channel]) & s_DataMask[channel];     /* Read data from UART buffer.*/ \

    s_UartRXWriteIdx[channel] &= UART_BUF_MASK; /* account for wrap; */ \

    }

 

PE_ISR(Uart3_ISR)

{

   volatile uint8 StatReg = UART_PDD_ReadInterruptStatusReg(UART3_BASE_PTR); // Read status register

  if (StatReg & (UART_S1_NF_MASK | UART_S1_OR_MASK | UART_S1_FE_MASK | UART_S1_PF_MASK))  // Is any error flag set?

  {

    (void)UART_PDD_GetChar8(UART3_BASE_PTR);                // Dummy read 8-bit character from receiver to clear the rdrf bit

    if (StatReg & UART_S1_RDRF_MASK)              // Is the receiver's interrupt flag set?

    {

        StatReg &= ~(uint8)UART_S1_RDRF_MASK;    // Clear the receive data flag to discard the erroneous data

        // Reading an empty data register to clear one of the flags makes FIFO pointers misaligned. RX FIFO flush reinitialises pointers.

        UART_PDD_FlushFifo(UART3_BASE_PTR, UART_PDD_RX_FIFO_FLUSH ); /* Flush RX FIFO */

    }

  }

  else if (StatReg & UART_S1_RDRF_MASK)              // Is the receiver's interrupt flag set?

    GET_UART_DATA(3);

  if( (StatReg & UART_S1_TC_MASK) && (UART_C2_REG(UART3_BASE_PTR) & s_TXIRQMask[3]) ) // Transmit complete flag and correct interrupt enabled??

    UartTXIRQHandler(3);                     // If yes, then invoke the TX irq service routine.

}

 

This is just the latest iteration of the code, I've tried all sorts of things and this is how it's ended up.
As an example of the problem : one of the peripherals I'm talking to sends me a packet like this: 0x02, 0x31, 0xd7, 3f, b7
When things go wrong (once every several hundred packets) I see this in my RX buffer: 0x02, 0x31, 0x31, 0xd7, 3f, b7
Any suggestions, good, bad, or completely crazy gladly accepted:
Cheers,

Outcomes