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.

MSP430FR5969: microcntroller irregular function

Other Parts Discussed in Thread: MSP430FR5969

Hi,

I am having a custom circuit in which uart(UCA1), and counter(TIMERA0, TIMERA1) with TIMERB0 as timer module are used simultaneously.

TIMERB0 module is used to create a one-second interrupt and TIMERA0 and TIMERA1 are used to count the external pulse and UART(UCA1) is used to transmit and receive data at second interval,

most of the time the operation is working fine, but at the irregular interval, the transmitted data is missed and the count value also exceed the provided external pulses , how to resolve this 

  • Hi Sasi,

    I would begin troubleshooting this problem by not using TIMERA0 and TIMERA1. Use only TIMERB0 to generate the 1second interval and in your code where you would normally read the TIMERA0 and TIMERA1 values, instead setup and increment a variable then transmit the value instead of the timer results.  This will help rule out issues with the TIMERA0,A1.

    Also, can you try reducing the code to the absolute smallest size possible and see if it demonstrates the issue.  This means removing everything else in your code except the basic functionality: TIMERB0 to generate 1sec timing and UCA1 to send data.  That's all. Doing this may help uncover an issue that has nothing to do with TIMERB0 or UCA1.

    If you still see the issue, then this points to perhaps something in the method you are using to transmit the data. Can you share the section of your code that does the transmission? 

  • Hi Dennis,

    As per your suggestion, i did run only the counter and uart so everything is working fine when i try to run the full code issue persists, as the design is complete it is impossible to change the microcontroller, Is there any possible way to solve this issue.?

    In this project, two ISR is used one is for TIMERB0 and the other is for UARTA1 if two peripherals get interrupted at the same duration will any of the interrupts fall, 

    If one of the ISR takes 10 ms to complete its overall operation will the other routine wait and execute?

  • Hi sasi,

    Ok, this helps narrow the problem down.

    No concern about two different interrupts occurring at the same time.  Looking at the MSP430FR5969 datasheet, table 6-4, the TIMERB has a higher priority than UART1.  This means should both interrupts occur at exactly the same time, the interrupt controller will acknowledge the TIMERB interrupt and jump to the TIMERB ISR.  Meanwhile, the UART1 interrupt will remain in a pending state (waiting) until TIMERB ISR is complete, then UART1 ISR is called.

    Since we know the TIMERB interrupt occurs every one second, then the UART1 ISR must be the one that takes up to 10ms to complete, which makes sense since it takes some time to transmit the data. Perhaps sharing your code at this point makes sense.  Can you do this?

  • Hi Dennis, 

    I have attached the UART configuration and receive program

    /* GPIO initialize */
    uint8_t looper9;
    P2SEL1 = 0x67; /* uart_A0 RS485_1 gpio pins set & uart_A1 RS485_2 gpio pins set*/
    PJDIR = 0x30; /* Buffer IC disabled */
    PJOUT = 0x20;
    P3DIR = 0x80;
    P3OUT = 0x00;

    /* UART Module initialize for 12Mhz */

    UCA1CTLW0 = 0x0081; /* SMclk selected for UART */
    UCA1BRW = 0x0006; /* prescaler set for baud rate generator */
    UCA1MCTLW = 0x2081; /* oversampling baud rate generation set for 115200 baud rate */
    UCA1CTLW0 = 0x0080; /* Uart modules locked */
    UCA1IE = 0x0001;


    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_A1_VECTOR
    __interrupt void USCI_A1_ISR(void)
    #endif

    {
    receive_buf[0] = UCA1RXBUF;
    UCA1IE = 0x0000; /* Uart interrupt disabled */
    (void)uart_interrupt(receive_buf);
    UCA1IE = 0x0001;
    }

    void uart_interrupt(uint8_t receive_buff[])
    {

    uint8_t looper16=0U,rx_buf_1=0U; /* initializing buffer leads to drop of registers */
    int_16t int_reg;
    uint16_t int_reg1;
    int_reg = UCA1IFG;
    int_reg1 = (uint16_t)int_reg & 0x0001U;
    while((rx_buf_1 != 0x21U))
    {
    looper16++;
    while(!(int_reg1 == 0x0001U)) /* polling is done to create perfect reception */
    {
    int_reg = UCA1IFG;
    int_reg1 = (uint16_t)int_reg & 0x0001U;
    }
    rx_buf_1 = (uint8_t)UCA1RXBUF & 0xFFU; /* receive data for rs485_1 */
    receive_buff[looper16] = rx_buf_1; /* Read buffer */
    int_reg1 = 0U;
    }
    if(looper16 > 3U)
    {
    (void)command(receive_buff);
    }
    else
    {
    (void)delay_loop(30);
    }
    (void)delay_loop(300);
    P3OUT = 0x00; /* To reset receive enable pin */

    }

  • Hi Sasi,

    I reviewed the portion of the code you provided.  I don't see any major problem that would cause the issue you have. It's a little confusing to understand fully what is happening here so you might want to look at some of the UART examples for the MSP430FR5969 in the TI Resource Explorer and see if you can adapt that to work for you.  You also might want to look at the MSP430 Driverlib UART functions.

  • Hi Dennis,

    In this code sometimes code gets stuck in the flag status check function, so these discrepancies take place, I assume that it is due to external noise because when we replaced our USB to rs485 module(DTECH) converter with CSL42xx – USB to RS485 Converter most of the problem solved

  • Hi Sasi,

    Can you take an oscilloscope measurement of the noise on the UART RX pin?

  • Hi Dennis

    while connecting the DTECH cable the reset takes place but it is rare, data is stored in a NAND flash at a second once interval which also disrepteddata142933 23-11-22.xlsx

  • Hi Sasi,

    So you are seeing the device reset when you disconnect/connect the communications cable?

  • Hi Dennis,

    yes, the device reset and most of the problems are related to device disconnecting and connect of communication cables

  • Hi Sasi,

    It sounds like when you connect/disconnect the cable, you are causing some type of voltage spike.

    What I would suggest is monitor the MSP430 VDD as close to the MSP430 as possible.  The best location would be on the 0.1 bypass capacitors near the MSP430.  Then connect/disconnect the cable and see what VDD does?  Does the voltage drop?  Is there noisy or spike?  Then do the same on the MSP430 RST pin.

  • Hi Sasi,

    Do you have an update.  Were you able to monitor VDD and the RST pin and see any disturbances?

  • Hi Dennis,

    I have monitored VDD, the voltage shift is not measurable considerably it reduces from 3.3v to 3.2 v, i am trying to check at the reset pin

  • Hi Dennis,

    I am unable to monitor the reset pin, but I have a doubt I am sure the external interface generates noise that disturbs the microcontroller but the reset is due to software watchdog timer reset only, which means the microcontroller hangs or falls out of routine for a particular interval, what could be the cause of such hangs does memory overflow or multiple interrupts will cause such hangs

  • Hi sasi,

    Ok, we are making progress. 

    Since the WDT must be reset periodically, I agree it sounds like you code gets stuck in a routine.  My suggestion would be to look at any routine that "blocks" or waits for something to happen, like and change in an IO pin, or waiting for the next byte to be received in the UART.  Look through all of your code where you have some form of a "while(1)" loop.

     If that doesn't help zero in on the problem, the other thing you can do is strip down the code to the absolute bare minimum, but still demonstrates this issue.  Many times you will uncover the problem using this method.

  • Hi Dennis,

    As i have shared above a code sample to receive UART data, in that code a while condition is used to verify uart receive flag, some times code gets stuck here in the whole program, if it is done separately no such issue takes place

    while(!(int_reg1 == 0x0001U)) /* polling is done to create perfect reception */
    {
    int_reg = UCA1IFG;
    int_reg1 = (uint16_t)int_reg & 0x0001U;
    }

  • Hi sasi,

    I have reformatted your code and re-posting for convenience and of others that may follow this thread.

    My first comment has to do with your polling inside an interrupt ISR. As you are finding out, it is really bad practice to poll on anything inside an interrupt ISR.  If the polling gets stuck, your code will either hang, or if you are using the WDT, the device will eventually reset.

    I'm not sure exactly what you are trying to do, but I would suggest that your code in the ISR should only read the received byte from the UCA1RXBUF, update your receive_buff[], then exit the ISR.  Do all the processing of the byte or buffer back in main.  This way the UART interrupt is ready to generate another interrupt when the next byte is received.

    To help me understand what the UART is receiving, can you describe the expected data and what you are trying to do with it?

    __interrupt void USCI_A1_ISR(void)
    {
        receive_buf[0] = UCA1RXBUF;
        UCA1IE = 0x0000; /* Uart interrupt disabled */
        (void)uart_interrupt(receive_buf);
        UCA1IE = 0x0001;
    }
    
    void uart_interrupt(uint8_t receive_buff[])
    {
        uint8_t looper16=0U,rx_buf_1=0U; /* initializing buffer leads to drop of registers */
        int_16t int_reg;
        uint16_t int_reg1;
        int_reg = UCA1IFG;
        int_reg1 = (uint16_t)int_reg & 0x0001U;
        
        while((rx_buf_1 != 0x21U))
        {
            looper16++;
            
            while(!(int_reg1 == 0x0001U)) /* polling is done to create perfect reception */
            {
                int_reg = UCA1IFG;
                int_reg1 = (uint16_t)int_reg & 0x0001U;
            }
            rx_buf_1 = (uint8_t)UCA1RXBUF & 0xFFU; /* receive data for rs485_1 */
            receive_buff[looper16] = rx_buf_1; /* Read buffer */
            int_reg1 = 0U;
        }
        
        if(looper16 > 3U)
        {
            (void)command(receive_buff);
        }
        else
        {
            (void)delay_loop(30);
        }
        
        (void)delay_loop(300);
        
        P3OUT = 0x00; /* To reset receive enable pin */
    
    }

  • Hi Dennis,

    I have to receive commands of different lengths, so after receiving the first byte I disabled ISR and use the polling method to receive the upcoming characters. this is the flow, right now I m trying to rewrite the program as per your suggestion. 

**Attention** This is a public forum