This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP432P401R: Missing UART Reveive Interupt

Part Number: MSP432P401R

I am building a RS-232 tester so it is sending and receiving constantly RS-232 bytes at various baud rates.

One in a while, I am missing a UART0 receive interrupt (UCA0IFG & UCRXIFG)
Using a logic analyser, I noticed that the missing interupt always occurs during an I2C interupt service (UCB0IFG & UCTXIFG0).

Any suggestions?

  • I'm not quite sure what I2C has to do with an RS-232 tester (but it's not my program).

    That said, this sounds suspiciously like erratum USCI43 (SLAZ610O). The wording there seems a bit odd (reading the IFG register reads all the flags, not just the one you're interested in), but the description could fit. The workaround seems to be to use interrupts, which might be intended mean to use UCB0IV rather than reading the IFG directly.
  • I am sending 500 bytes out on UART0 ... they are received by UART2 and loopbacked back ....to be finally received back at UART0.
    I collect statistics on latency, loss, etc... and send the statistics it out to a beaglebone black via I2C. The beaglebone handles the Web Gui.

    I have 4 interupt routines. One for the UARTA0, UARTA3, I2CB0 and a TA0 .
    The UARTA0 has TX and RX interupts enabled.
    The UARTA3 has only RX interupt enabled.
    The I2C has Stop and TX enabled.
    The Timer had a CCIE enabled.

    The missing UART0 RX interupt always seems to occur microseconds around the I2CB0 TX interupt.
    I hope this helps clarify my problem.

    I will search for the erratum you described.
    Thanks
  • Ah, OK -- two different ports, but their operations tend to be closely linked in time.

    The Errata sheet is available at the top of the Product page (next to the Datasheet link). As I mentioned, I find the wording of that Erratum somewhat odd, but its existence (it was added rather recently) suggests that there's a Something in your vicinity.

    Of course, it's also possible to get such a symptom with software. If you have some relevant code fragments you can post, someone here might be able to spot a (e.g.) race condition that would cause such trouble.
  • Here is the relevant code for the UART and the I2C interrupt routines.
    The missing UART0 interupt is always in or around the I2C TX interupt

    //
    // Configure UART0
    //
    P1SEL0 |= BIT2 | BIT3; // Set P1.2 and P1.3 as UART TX and RX

    // 115200 BAUD : SCLK, UCBR=6, UCBRS=0x20 | UCOS16=1 | UCBRF=8
    UCA0CTLW0 |= UCSWRST; // Put eUSCI in reset
    UCA0CTLW0 |= UCSWRST | UCSSEL_2; //SMCLK 12Mhz maintaining reset mode
    UCA0BRW = 6;
    UCA0MCTLW = 0x2000 | UCOS16 | 0x0080;

    UCA0CTLW0 &= ~UCSWRST; // Initialize eUSCI
    UCA0IFG &=~ (UCTXIFG | UCRXIFG); // clear interupt flag
    UCA0IE |= (UCRXIE | UCTXIE); // Enable USCI_A0 RX TX interrupt

    //
    // Configure I2C
    //
    P1SEL0 |= BIT6 | BIT7; // Set pint P1.6 and P1.7 as I2C pins

    UCB0CTLW0 |= UCSWRST;
    UCB0CTLW0 = UCMODE_3 | UCSYNC; //i2cmode and Synchronous
    UCB0I2COA0 = 0x18 | UCOAEN ; //Slave address 0x18
    UCB0CTLW0 &= ~UCSWRST;

    UCB0IFG &= ~ UCTXIFG0;
    UCB0IE |= UCSTPIE | UCTXIE0; // Enable STP interrupt & TX only

    void EUSCIA0_IRQHandler(void)
    {
    if (UCA0IFG & UCRXIFG) //RX a Byte
    {
    RX1 = UCA0RXBUF;
    //
    // <my Rx Code here>
    }
    if (UCA0IFG & UCTXIFG) //Ready to TX another Byte
    {
    if (++TX1_Frame_Index < 5) { //total of 5 bytes to send
    UCA0TXBUF = TX1_Frame[TX1_Frame_Index];
    }
    else{
    UCA0IFG &=~ UCTXIFG; // Clear interrupt, nothing else to send for now
    }
    }
    }

    void EUSCIB0_IRQHandler(void)
    //
    // I2C is in slave mode, it will receive a byte from the master and respond with 11 bytes
    //
    {
    if (UCB0IFG & UCSTPIFG) //I2C Stop, a Byte Received
    {
    UCB0IFG &= ~ UCSTPIFG; // Clear Stop interrupt
    I2C_Byte_Received = UCB0RXBUF;
    PTxData = (unsigned char *)Bone_I2C_TxData; // Start of TX buffer
    I2C_TX_Sent_Count= 0;
    }
    if (UCB0IFG & UCTXIFG0) //Ready to TX another I2C Byte
    {
    if (++I2C_TX_Sent_Count < 12) // 11Bytes to transmit
    {
    UCB0TXBUF = *PTxData++; // Transmit data at address PTxData
    }
    else //Done Transmitting
    {
    // Else load a dummy byte which does not get clocked out
    // as the STOP bit will get triggered on the last byte
    // since the TXBUF is double buffered
    UCB0TXBUF = 0;
    }
    }
    }
  • > UCA0IFG &=~ UCTXIFG; // Clear interrupt, nothing else to send for now

    I recommend you Not do this. Turn off (more generally: actively manage) UCTXIE instead. This read/modify/write sequence invites a race which can lose an (unrelated) IFG which happens just at the right time. Writing TXBUF clears TXIFG atomically (similarly for RXBUF/RXIFG, but you're doing that correctly here); if you don't want to do that, turn off TXIE instead.

    This is not just a theoretical concern -- I've seen maybe 10 people trip over this in the past year or so. In most cases it's the other way around: losing TXIFG (much more visible) when clearing RXIFG, but the principle is the same. It's also more frequent at high bit rates, but the race is always there.
  • Thank You, I am disabling the UCTXIE and it solved the problem.
    I also clear the Stop Interrupt flag in the I2C : UCB0IFG &= ~ UCSTPIFG;
    IS this something that I should also avoid doing... It has not caused any issues so far.
  • I have to suppose that a similar race can happen in I2C mode, though I've never seen a report of it (admittedly weak criterion).

    It may be that as a practical matter I2C operation is much more orderly, reducing the probability down to "theoretical concern". E.g., what other IFG could be anticipated immediately following a STPIFG (I suspect "none"), and would it be noticed if it were lost?

    I expect TI's answer would be to use the UCB0IV, which does operate atomically. But adopting the IV in UART mode would require another (third) strategy for managing TXIFG and RXIFG. (Of course, nothing says you can't: use the IV for I2C mode and not use it for UART mode.)

**Attention** This is a public forum