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.

MSP432P4111: eUSCI - UART Start Bit interrupt questions

Part Number: MSP432P4111

G'Day all,

I posted on the forum earlier today regarding a way of detecting the start of a DMA based UART receive (here - getting GPIO interrupt off a pin setup as UART Rx).  That first approach didn't work, so I'm looking at another.

The MSP432 eUSCI (UART mode) has a start bit interrupt that I thought might give me a way of detecting start of reception.  Unfortunately I found documentation and actual operation confusing and I hoped you could clarify.

  • Section 24.3.16 of SLAU356I says that the Tx interrupt and Rx interrupts must be off for DMA work but it doesn't say anything about the start bit interrupt so I assume that there will be no bad interaction between the DMA and the start bit interrupt.  Is that true?

  • Section 24.3.15.3 (the section about the UART) talks about UCSTTIFG being a "start BYTE" received interrupt, but the register descriptions (section 24.4.10 for the interrupt enables, section 24.4.11 for the flags) call UCSTTIE/UCSTTIFG a "start BIT" interrupt.  Can you confirm which is the correct description?  When should this interrupt fire?
  • In the MSP432 Peripheral Driver Library Users guide (DriverLib users guide - can't find a web link, but it gets installed along with SimpleLink, e.g. hereC:/ti/simplelink_msp432p4_sdk_3_20_00_06/docs/driverlib/msp432p4xx/MSP432_DriverLib_Users_Guide-MSP432P4xx-4_30_01_01.pdf).  The descriptions around the UART interrupts seem a bit confused. Compare the following sections
    • 28.3.3.1 - UART_clearInterruptFlag(module, mask)  
      • description of  mask -> points to EUSCI_A_UART_enableInterrupt()  
      • NOTE: This is not a correct API function name (but its close)
    • 28.3.3.2 - UART_disableInterrupt(module, mask)
      • description of mask ->Ored combination of
        • EUSCI_A_UART_RECEIVE_INTERRUPT
        • EUSCI_A_UART_TRANSMIT_INTERRUPT
        • EUSCI_A_UART_RECEIVE_ERRONEOUSCHAR_INTERRUPT
        • EUSCI_A_UART_BREAKCHAR_INTERRUPT
      • NOTE: No mention of startbit or transmit compelete
    • 28.3.3.4 - UART_enableInterrupt(module, mask)
      •  description of mask ->Ored combination of
        • EUSCI_A_UART_RECEIVE_INTERRUPT
        • EUSCI_A_UART_TRANSMIT_INTERRUPT
        • EUSCI_A_UART_RECEIVE_ERRONEOUSCHAR_INTERRUPT
        • EUSCI_A_UART_BREAKCHAR_INTERRUPT
      • NOTE: No mention of startbit or transmit compelete
    • 28.3.3.6 - UART_getEnabledInterruptStatus(module)
      • description of return value -> ORed combination of
        • EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG
        • EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG
      • NOTE: Where did BreakChar and erronouschar go?
      • NOTE: No mention of startbit or transmit compelete
    • 28.3.3.7 - UART_getInterruptStatus(module, mask)
      • description of mask value -> ORed combination of
        • EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG
        • EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG
        • EUSCI_A_STARTBIT_INTERRUPT_FLAG
        • EUSCI_A_TRANSMIT_COMPLETE_INTERRUPT_FLAG
      • NOTE: Only occasion in all interrupt control APIs where the startbit and transmit complete flags are mentioned.
      • NOTE: Where did BreakChar and erronouschar go?
      • description of return value -> ORed combination of
        • EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG
        • EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG
      • NOTE: Where did the startbit and transmit compete go?
      • NOTE: Where did BreakChar and erronouschar go?
      • NOTE: What is the difference between the values with _FLAG at the end, and those without? They seem to be used in mixed ways.

Operation

I've setup my system with a 2Mbaud UART (our use of DMA comes from the high speed of the UART) and a pin toggling whenever the "Start bit" interrupt fires.  The data comes in bursts of 48 characters, so I'd expect 48 interrupts.  That is not what I get.  For each burst, I always seem to get the first toggle on the 3rd character and then after that I get a toggle every 5 or 6 characters, but sometimes it misses one.  Its interesting that I get a toggle after the data burst completes.

My interrupt handler (HWI) looks like this

  uint8_t intStatus_u8;

  intStatus_u8 = MAP_UART_getInterruptStatus(EUSCI_A2_BASE, EUSCI_A_UART_STARTBIT_INTERRUPT_FLAG);

  if (intStatus_u8 & EUSCI_A_UART_STARTBIT_INTERRUPT_FLAG)
  {
    MAP_UART_clearInterruptFlag(EUSCI_A2_BASE, EUSCI_A_UART_STARTBIT_INTERRUPT);
    P4->OUT ^= GPIO_PIN3;
  }

 

Looking in execution graph, we can explain some of the behvaiour. 

  • The missed toggles look like they might occur because another HWI ran.  0x20006640 is an unrelated timer interrupt has the same priority as the start bit interrupt. It is not clear why the start bit interrupt never ran.
  • The failure to toggle on all characters might be due to the turnaround time in the interrupt handler.
  • prior the first interrupt, the device is quiet - why didn't it hit the start bit of the first character (or at least the first character).  Why doesn't the start bit interrupt ever trigger on the first character?

Cheers

Julian

  • Hi,

    We will look into it and get back to you ASAP. Please bear with us.

    Thanks,

    PM

  • Hi Julian,

    As you mention in your post, the documentation around the UART peripheral is a bit confusing. 

    However, given your goal of detecting the start of a UART transmission in order to implement a timeout, there are other approaches to resolving the problem that do not involve low-level manipulation of the UART registers, nor the needed experimenting and debug to determine what how to use the UART start interrupt.

    I'm assuming that the UART start bit/byte interrupt would have triggered a timer that cancelled the UART transfer once a defined amount of time has elapsed. Please correct my assumption if I'm wrong.

    The easiest thing to do would be to set a timer after you setup a UART RX DMA transfer. If the timeout occurs, you would simply mark the transfer as cancelled and clean up the UART + DMA state. Now, the downside of this method is that you will also timeout if no data was received, and you will need to repeatedly re-setup the UART after every timeout, even if there was no activity on the interface.

    It sounds like what instead you want is a mechanism where the timeout will only start counting down once the first byte is received. This may be possible to implement if you examine the underlying DMA transfer state. Looking at section 11.2.4 of the MSP432P4 TRM, you'll see that every DMA channel has a control structure associated with it. This control structure has the source and destination memory addresses of the DMA transfer on that channel, as well as a control word. Most crucially, bits [13:4] of that control word contain the amount of DMA transfer words (ie, bytes for a UART transfer) remaining for that channel. If you were to simply read bits 13:4 of the UART DMA RX register once you have started a transfer, you can start a timer once that number decrements from the starting point.

    What do you think of using that approach instead?

    Regards,

    Michael

  • G'Day Michael,

    >I'm assuming that the UART start bit/byte interrupt would have triggered a timer that cancelled the UARTtransfer once a defined amount of time has elapsed.

    Yep, that is exactly right. 

    I've been thinking about your suggestion and I don't think it quite works for us because we'd have to poll the control word.  Doing that quickly enough to set a decent timeout would be more overhead than we can afford.  In our system a new 48byte packet is transmitted @ 2MBaud every 3mSec (and every packet has a CRC).

    I've come up with another solution that works because of our rigid protocol.  I start a 48byte DMA Rx at some arbitrary time and at the same time I start a timeout timer with a period slightly over 3mSec.  The next Rx start ASAP after the previous Rx completes or times out.

    If an Rx starts in the blank time between packets, then (assuming no data errors) we will receive the packet correctly and its CRC will check out.  The turnaround is guaranteed to complete within the next blank time, and so the next Rx will also start in that blank time and we are locked onto the data being transmitted to us.

    If this Rx starts during a packet, then the data we receive will have some data from this packet and some from the next packet and the CRC check will fail.  It will take some time to turn around and start a new Rx.  I rely on this turnaround time to gradually walk the start time of next Rx along until it falls into a blank period and so we get the case above.

    In the above process, the timeout can only trigger in the case of data errors (e.g. unreliable link) or no data at all (e.g. link broken) so the timeout gives useful info about the status of the link.

    Cheers

    Julian

**Attention** This is a public forum