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.

MSP430FR60471: UART stops receiving data after certain duration

Part Number: MSP430FR60471
Other Parts Discussed in Thread: MSP430FR6047

Hi,

I am working with eUCSIA3 uart of MSP430FR6047. My device is running with 100ms period. I am sending some frames(around 80 bytes each) over serial communication (python script). I am able to send and receive data for around 600 frames and after that the uart stops responding, uart interrupt isn't getting fired. Even if i restart pyserial, issue continuous. But when i restart the debugger the device starts to receive the data. 

UART configuration

void ESP_UART_INIT()
{
// Configure USCI_A3 for UART mode
UCA3CTLW0 = UCSWRST; // Put eUSCI in reset
UCA3CTLW0 |= UCSSEL__ACLK; // CLK = ACLK
UCA3BRW = 3; // 9600 baud
UCA3MCTLW |= 0x5300; // 32768/9600 - INT(32768/9600)=0.41
// UCBRSx value = 0x53 (See UG)
UCA3CTLW0 &= ~UCSWRST; // Initialize eUSCI
UCA3IE |= UCRXIE; // Enable USCI_A0 RX interrupt
//Configure RX interrupt to receive UART messages
}

eUSCI registers when device stops responding 

I have done some research but could not find whats going wrong. I am new to this so any lead would be really appriciated. 

Best Regards,

Nandkishor

  • Is serial communication the only thing stopped?

    You are probably overrunning a buffer getting the MCU confused. Is the MCU able to process the "frame" before the next one arrives?

    I suggest breaking at frame 590 or so and look to see that all the buffers are getting fully cleared and that you are absolutely ready for the next frame.

  • Is serial communication the only thing stopped?

    Yes.

    You are probably overrunning a buffer getting the MCU confused. Is the MCU able to process the "frame" before the next one arrives?

    i am waiting for the acknowledgement from MCU before sending next frame. And this wait is also sufficient for MCU to process the frame. 

    I suggest breaking at frame 590 or so and look to see that all the buffers are getting fully cleared and that you are absolutely ready for the next frame.

    I am ensuring that the buffers are cleared

  • Then I think you need to share your code. I suggest that you pare it down to a simple non-working example - this often helps you find the issue.

  • Here is the part of the code. 

    From script side:(Host computer)

    I am running one recieve thread receive_data(), 

    def receive_data:
        give required delay for responce to arrive,
        reads the data from serial port,
        autheticate_data()
        
    def authenticate_data:
        validate the data,
        send_data()

    def send_data():
        send data over serial port

    Device side:

    //UART initialization
    void ESP_UART_INIT()

    {
       // Configure USCI_A3 for UART mode
       UCA3CTLW0 = UCSWRST;                    // Put eUSCI in reset
       UCA3CTLW0 |= UCSSEL__ACLK;              // CLK = ACLK
       UCA3BRW = 3;                            // 9600 baud
       UCA3MCTLW |= 0x5300;                    // 32768/9600 - INT(32768/9600)=0.41
                                               // UCBRSx value = 0x53 (See UG)
       UCA3CTLW0 &= ~UCSWRST;                  // Initialize eUSCI
       UCA3IE |= UCRXIE;                       // Enable USCI_A0 RX interrupt
       //Configure RX interrupt to receive UART messages
    }
    //UART interrupt 
    #pragma vector=EUSCI_A3_VECTOR
    __interrupt void USCI_A3_ISR(void)
    {
        switch(__even_in_range(UCA3IV, USCI_UART_UCTXCPTIFG))
        {

            case USCI_NONE: break;
            case USCI_UART_UCRXIFG:
                while(!(UCA3IFG&UCTXIFG));
                g_RxByte = UCA3RXBUF;
                FillBuffer(g_RxByte);

                __no_operation();
                break;
            case USCI_UART_UCTXIFG: break;
            case USCI_UART_UCSTTIFG: break;
            case USCI_UART_UCTXCPTIFG: break;
            default: break;
        }
    }
    #endif

    FillBuffer() description:
    Its an FSM which does the CRC checks on incoming data and fill my ESP buffer accordingly. 
    I have come across some posts saying its not an good idea to have extra/unwanted processing inside an interrupt. But then why would it be happening that I am able to get response for most of the initial frames and then it stops working (just to reiterate UART interrupt not getting fired). Can there be any other reasons for uart not responding?
    Still I will try to move this fill buffer and see if it resolves the issue.  
  • 1) I can think of no good reason to wait on TXIFG being set when responding to a receive interrtupt.

    2) There are lots of reasons why your program would become unresponsive. All having to do with the rest of your code.

    When the program stops responding to data, what is it doing?

  • I guess I should have been more clear. We need a compilable, running example that exhibits the problem that we can run on our MCU's.

  • 1) I can think of no good reason to wait on TXIFG being set when responding to a receive interrtupt.

    Thanks for noticing it. Yes its not necessary. I remove it and i still get the same issue.

    When the program stops responding to data, what is it doing?

    I am having same issue as most of the people mentioned in this thread. https://e2e.ti.com/support/processors-group/processors/f/processors-forum/274366/uart-not-receiving-interrupts. But no one found the root cause of this. 

    I have already attached a reference code for my Rx interrupt. 
    For Tx:

    void SendData(unsigned char buff[],unsigned int tx_len)
    {
        int count=0;

        for(count=0;count<tx_len;count++)
        {
            while (!(UCA3IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
            UCA3TXBUF = buff[count];  //Send buffer data
        }
    }

    This is what I have observed in my case:

    The uart interrupt works fine for 1st 2 to 3 mins and then stops triggering. After uart interrupt stops responding, i pause the debugger and see RXIE and GIE is set but RXIFG is not set. I have attached the screenshot of the registers when uart starts reponding in my 1st message. My other part of the code other interrupts, timers continues to work as expected.  

  • To expand on what Keith said, post a complete program which exhibits this problem. This does two things:

    1) It gives others a chance to see the complete picture making it easier to help you. Better than guessing by a long shot.

    2) While cutting it down, you may notice something and realize what the problem is. Or removing something might make the problem vanish.

  • Does it happen when you are not connected to the debugger?

  • I just did a quick test on my FR2311 Launchpad - which is all I have available.

    Over 3000 seconds I sent about 15000 packets of about 80 bytes - 1 every 200 ms. The device was *not* working under the debugger.

    I had the PC send the frames, and the MCU sent them back after they were all received.

    Some observations.

    80 bytes at 9600 baud is very close to 100 ms

    Here is the MCU program, warts and all (I hate register based programming!):

    Sorry for the text pasting, the code insert did not work for me.

    // WIth added UART Stuff
    #include <msp430.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <float.h>

    char Buffer[100];
    unsigned int BuffIdx = 0;
    volatile bool RXDone = false;

    char TXBuffer[100];
    unsigned int TXBuffIdx = 0;

    int Packet = 0;

    void Init_GPIO();
    void Software_Trim();            // Software Trim to get the best DCOFTRIM value
    #define MCLK_FREQ_MHZ 8                     // MCLK = 8MHz

    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;               // Stop watchdog timer
        Init_GPIO();

        __bis_SR_register(SCG0);                // disable FLL
        CSCTL3 |= SELREF__REFOCLK;              // Set REFO as FLL reference source
        CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_3; // DCOFTRIM=3, DCO Range = 8MHz
        CSCTL2 = FLLD_0 + 243;                  // DCODIV = 8MHz
        __delay_cycles(3);
        __bic_SR_register(SCG0);                // enable FLL
        Software_Trim();             // Software Trim to get the best DCOFTRIM value

        CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz
        // default DCODIV as MCLK and SMCLK source

        P1DIR |= BIT0 | BIT1;                   // set ACLK and LED pin as output
        P1SEL1 |= BIT1;                         // set ACLK pin as second function

        // Set up UART
        // Configure UART pins
        P1SEL0 |= BIT6 | BIT7;                  // set 2-UART pin as second function

        // Configure UART
        UCA0CTLW0 |= UCSWRST;
        UCA0CTLW0 |= UCSSEL__SMCLK;

        // Baud Rate calculation
        // 8000000/(16*9600) = 52.083
        // Fractional portion = 0.083
        // User's Guide Table 17-4: UCBRSx = 0x49
        // UCBRFx = int ( (52.083-52)*16) = 1
        UCA0BR0 = 52;                             // 8000000/16/9600
        UCA0BR1 = 0x00;
        UCA0MCTLW = 0x4900 | UCOS16 | UCBRF_1;

        UCA0CTLW0 &= ~UCSWRST;                    // Initialize eUSCI
        UCA0IE |= UCRXIE | UCTXIE ;                         // Enable USCI_A0 RX and TX interrupt

        PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode
        // to activate previously configured port settings

        __bis_SR_register(GIE);

        // just in case
        strcpy(TXBuffer, "Hello, World!");

        UCA0TXBUF = TXBuffer[TXBuffIdx++];  //Send buffer data


        while (1)
        {

            if (RXDone == true)
            {
                sprintf(TXBuffer, "Packet: %d", Packet++);

                strcat(TXBuffer, Buffer);

                TXBuffIdx = 0;

                UCA0TXBUF = TXBuffer[TXBuffIdx++];  //Send buffer data
                BuffIdx = 0;
                RXDone = false;
            }

        }
    }

    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    {
        switch (__even_in_range(UCA0IV, USCI_UART_UCTXCPTIFG))
        {
        case USCI_NONE:
            break;
        case USCI_UART_UCRXIFG:

            P1OUT ^= BIT0;                      // Toggle P1.0 using exclusive-OR

            if(UCA0RXBUF == 'X')
            {
                RXDone = true;
            }

            Buffer[BuffIdx++] = UCA0RXBUF;
            Buffer[BuffIdx] = '\0';



            __no_operation();
            break;
        case USCI_UART_UCTXIFG:
            if (TXBuffer[TXBuffIdx] != '\0')
                UCA0TXBUF = TXBuffer[TXBuffIdx++];
            break;

        case USCI_UART_UCSTTIFG:
            break;
        case USCI_UART_UCTXCPTIFG:
            break;
        default:
            break;
        }
    }
    void Software_Trim()
    {
        unsigned int oldDcoTap = 0xffff;
        unsigned int newDcoTap = 0xffff;
        unsigned int newDcoDelta = 0xffff;
        unsigned int bestDcoDelta = 0xffff;
        unsigned int csCtl0Copy = 0;
        unsigned int csCtl1Copy = 0;
        unsigned int csCtl0Read = 0;
        unsigned int csCtl1Read = 0;
        unsigned int dcoFreqTrim = 3;
        unsigned char endLoop = 0;

        do
        {
            CSCTL0 = 0x100;                         // DCO Tap = 256
            do
            {
                CSCTL7 &= ~DCOFFG;                  // Clear DCO fault flag
            }
            while (CSCTL7 & DCOFFG);               // Test DCO fault flag

            __delay_cycles((unsigned int) 3000 * MCLK_FREQ_MHZ); // Wait FLL lock status (FLLUNLOCK) to be stable
            // Suggest to wait 24 cycles of divided FLL reference clock
            while ((CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)) && ((CSCTL7 & DCOFFG) == 0))
                ;

            csCtl0Read = CSCTL0;                   // Read CSCTL0
            csCtl1Read = CSCTL1;                   // Read CSCTL1

            oldDcoTap = newDcoTap;               // Record DCOTAP value of last time
            newDcoTap = csCtl0Read & 0x01ff;       // Get DCOTAP value of this time
            dcoFreqTrim = (csCtl1Read & 0x0070) >> 4;       // Get DCOFTRIM value

            if (newDcoTap < 256)                    // DCOTAP < 256
            {
                newDcoDelta = 256 - newDcoTap; // Delta value between DCPTAP and 256
                if ((oldDcoTap != 0xffff) && (oldDcoTap >= 256)) // DCOTAP cross 256
                    endLoop = 1;                   // Stop while loop
                else
                {
                    dcoFreqTrim--;
                    CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim << 4);
                }
            }
            else                                   // DCOTAP >= 256
            {
                newDcoDelta = newDcoTap - 256; // Delta value between DCPTAP and 256
                if (oldDcoTap < 256)                // DCOTAP cross 256
                    endLoop = 1;                   // Stop while loop
                else
                {
                    dcoFreqTrim++;
                    CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim << 4);
                }
            }

            if (newDcoDelta < bestDcoDelta)         // Record DCOTAP closest to 256
            {
                csCtl0Copy = csCtl0Read;
                csCtl1Copy = csCtl1Read;
                bestDcoDelta = newDcoDelta;
            }

        }
        while (endLoop == 0);                      // Poll until endLoop == 1

        CSCTL0 = csCtl0Copy;                       // Reload locked DCOTAP
        CSCTL1 = csCtl1Copy;                       // Reload locked DCOFTRIM
        while (CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1))
            ; // Poll until FLL is locked
    }

    void Init_GPIO()
    {
        P1DIR = 0xFF;
        P2DIR = 0xFF;
        P1REN = 0xFF;
        P2REN = 0xFF;
        P1OUT = 0x00;
        P2OUT = 0x00;
    }

    Here is the C# program on the PC:

    using System.IO.Ports;
    
    namespace PacketExchange
    {
        public partial class Form1 : Form
        {
            static SerialPort mySerialPort = new SerialPort();
    
            string line = "0123456789";
    
            volatile bool STOP = false;
            public Form1()
            {
                InitializeComponent();
    
                string[] names = SerialPort.GetPortNames();
    
                foreach (string s in names)
                {
                    cbPorts.Items.Add(s);
                }
                cbPorts.SelectedIndex = 0;
    
    
            }
    
            private void butOpen_Click(object sender, EventArgs e)
            {
                // Allow the user to set the appropriate properties.
                mySerialPort.PortName = cbPorts.SelectedItem.ToString();
                mySerialPort.BaudRate = 9600;
                mySerialPort.Parity = Parity.None;
                mySerialPort.DataBits = 8;
                mySerialPort.StopBits = StopBits.Two;
    
                // Set the read/write timeouts
                mySerialPort.ReadTimeout = 500;
                mySerialPort.WriteTimeout = 500;
    
                mySerialPort.Open();
            }
    
            private void butStop_Click(object sender, EventArgs e)
            {
                STOP = true;
            }
    
            private void butStart_Click(object sender, EventArgs e)
            {
                DateTime packetsent = DateTime.Now;
                TimeSpan wait;
                int frame = 0;
                DateTime txstart = DateTime.Now;
    
                butStart.Enabled = false;
                STOP = false;
    
                rtbOut.Clear();
    
                while (true)
                {
                    if (STOP == true)
                    {
                        rtbOut.AppendText("STOP!\n");
                        break;
                    }
    
                    string rx = mySerialPort.ReadExisting();
                    if (rx != "")
                    {
                        rtbOut.AppendText(rx);
                    }
    
                    wait = DateTime.Now - packetsent;
    
                    if ((decimal)wait.TotalMilliseconds > numPause.Value)
                    {
                        tbBetween.Text = wait.TotalMilliseconds.ToString("F02");
                        packetsent = DateTime.Now;
                        // Send Packet
                        mySerialPort.WriteLine("Frame: " + frame.ToString());
                        frame++;
    
                        for (int i = 0; i< numPacketSize.Value; i++)
                        {
                            mySerialPort.WriteLine(line);
                        }
    
                        mySerialPort.Write("X");
                        
                        TimeSpan tx = DateTime.Now - txstart;
                        tbtxtime.Text = tx.TotalSeconds.ToString("F03");
    
                        rtbOut.Clear();
                    }
                    Application.DoEvents();
                }
                butStart.Enabled = true;
            }
        }
    }

  • Yes. It happens even when i don't have debugger connected. 

  • To expand on what Keith said, post a complete program which exhibits this problem

    I will try to cut down my program and see if i am able to reproduce the same issue. 

**Attention** This is a public forum