Other Parts Discussed in Thread: MSP430F2252
Tool/software: Code Composer Studio
I am facing a strange issue on the MSP430I2021 eUSCI_A in UART mode.
In my application I use eUSCI_A in UART mode with RX and TX interrupts.
My UART RX interrupt handler stores the received characters in a static buffer or records a possible receive error condition; in both cases the condition flags are always cleared. In my main loop the following function is called to handle the UART reception:
/*! ** \fn short Uart0_GetBuffer( unsigned char *Buff, unsigned short *Len ) ** \brief Get the received packet and the receive condition ** \param Buff The buffer for the received packet ** \param Len The received packet size ** \return UART0_NODATA - no reception ** UART0_ERROR - reception error (framing, parity, overrun) ** UART0_SIDATA - received packet ** UART0_RXDATA - packet reception in progress **/ short Uart0_GetBuffer( unsigned char *Buff, unsigned short *Len ) { short tmp = UART0_NODATA; UCA0IE &= ~UCRXIE; // disable RX interrupt // handle the current receive condition: // - If a packet was received, store it in the buffer and return UART0_SIDATA. // - Else if reception error, return UART0_ERROR. // - Else if packet reception in progress, return UART0_RXDATA. [...] UCA0IE |= UCRXIE; // enable RX interrupt return tmp; }
My issue:
- My application starts and runs for a few seconds (random from 10 to 30 sec), the UART is working properly (receives and transmits), but then a reset occurred.
My application does not use the watchdog and no code optimization. The supply voltage VCC on my board is stable and no external reset occurs. I run with DCO clock with external 20K resistor, MCLK = DCO/2 = 8.192MHz, SMCLK = DCO/4 = 4.096MHz. The UART communication handles packets with size until 30 bytes in both RX and TX directions.
After a day of searching, I found the cause is the RX interrupt disable-enable sequence. Also, letting RX interrupt run without handling the serial communication, I get the same issue with the following function in the main loop:
/*! ** \fn short Uart0_GetBuffer( unsigned char *Buff, unsigned short *Len ) ** \brief Get the received packet and the receive condition ** \param Buff The buffer for the received packet ** \param Len The received packet size ** \return UART0_NODATA - no reception ** UART0_ERROR - reception error (framing, parity, overrun) ** UART0_SIDATA - received packet ** UART0_RXDATA - packet reception in progress **/ short Uart0_GetBuffer( unsigned char *Buff, unsigned short *Len ) { short tmp = UART0_NODATA; UCA0IE &= ~UCRXIE; // disable RX interrupt UCA0IE |= UCRXIE; // enable RX interrupt return tmp; }
So, it looks like a very frequent write access to the UCRXIE bit in the UCA0IE register may generate a reset condition. Why?
Nothing about that is reported in the device erratasheet.
In the meantime I solved disabling (_DINT()) and re-enabling (_EINT()) all the interrupts in the Uart0_GetBuffer() function, instead of the single UART RX interrupt. But I don't like it!
I don't understand this behavior: the same function is running properly on an old application of mine based on the MSP430F2252 and built with IAR compiler (but in that case the peripheral USCI is a little bit different from the eUSCI).
Any idea?
Thank you all.