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.

MSP430FR2676: Code Project Review - Code going off into the weeds

Part Number: MSP430FR2676


Hello,

I Need a full code review/troubleshooting help but I can't post the code in its entirety to this public space. If someone is willing to private message me for an in-depth code review I could really use the help.

I don't have much of a clue as to what is causing my code to jump out of the program space intermittently which causes my program to freeze and become entirely unusable (unless I restart it).

I have a lot of different pieces at play(Captivate, I2C, SPI, Timers, Interrupts, a Button, and more).

Thanks!

  • Hi Max,

    At one point, I suspect you had portions of the code working but made a change or added something and now its not working, correct?

    If so, do you recall what portions were working together before trouble started?

    I'll send you a private message so you can share with TI internal.

  • Hi Dennis, 

    Yes, this is correct. I started from square one by getting examples to work individually, then one by one adding them together. I believe at this point it has to do with captivate, because many times(certainly not every time) the crash occurs, it mentions the function "CAPT_saveCycleResultsAutoMultiFreq()"  yet I have tried everything I could think to try. But other times it just tells me the program broke at an address.

    I also worry that my peripheral interrupts are simply conflicting, but it's hard to tell.

    I went ahead and sent over all the information in a private message.

    Thanks, 

    Max

  • Here are 3 screenshots of what CCS shows once I pause a debug session during a runaway.

  • Hi Max,

    The Captivate interrupt priority is the lowest on the MSP430, so not conflict with the other peripherals, however, if Captivate goes into a calibration with large value conversion_count, it is possible it can block code execution for some time.  I see from the files you uploaded you are using 250 for the conversion_count so you are good there.  I did notice you have noise immunity enabled.  I would avoid that unless you anticipate your product will be exposed to electrical disturbances through and A.C. line.  For now, try running without it enabled and see it that helps.  That will provide a clue.

    The message indicates the code is stalled in one of the library functions (black box so there is no source code or symbols that would provide additional information).

    Now that I have you project, I'll take a look through it.

    BTW, I like you software state diagrams in your software architecture document.  What tool do you use to generate these?

  • Hi Dennis, 

    I've tried with and without. Without noise immunity, it still freezes, however, the errors all simply say "Break at address "xxxxx" with no debug information available, or outside of program code".

    Also, thank you! The state diagrams in that document are all made using www.lucid.app , Its a very simple and effective with lots of features, highly recommended.

    Debug Without noise immunity enabled:

  • Hi Max, thanks for the lucid tip.  I'll check it out.

    I need a little more description on the faulty behavior.  For example, when you power up the system and don't touch anything it is fine, or after sometime (seconds, mins, etc.) does it freeze?  Or does it work fine until you touch one of the Capacitive touch buttons?

    When it does freeze, if you look at your debugger window you should see a call stack.  Here is an example.

    Can you take a snapshot of yours when it hangs?

  • Dennis, 

    It appears to only actually freeze while I am using the capacitive touch buttons.

    However, even if I do not use any of the capacitive buttons, then I pause the program, it still ends up with a break at an address...Yet when I resume the program again, the program is not frozen (LED driver and capacitive buttons all work temporarily until it freezes up again--until I reset it).

    Here are some screenshots from when it freezes while using the cap touch:

    Here is what happens when I pause the program without touching any capacitive buttons:

        

  • Also, is the CAPT_appSleep() function only necessary if you are using Wake on proximity mode? Because currently, I don't have a reason to go into LPM, so I am running in Active mode only (No wake-on-proximity state handling and therefore no LPM).

  • The CAPT_appSleep( ) in the main loop is there to reduce device power when the CPU has nothing else to do, so you are fine running in active mode.

    Another we can try is changing the compiler's optimization from -03 to none.  You can find this under the project properties, compiler settings.

  • Dennis, 

    My project optimization is already set to "off".

  • Mark, is this only an issue when running in debug mode?  If you remove debugger and cycle power do you see same behavior?

  • Dennis, 

    No, it happens regardless.

  • I have your code running on CAPT-FR2676 with the BSWP panel connected.  I made a couple of changes to your configuration code so I can send output to the GUI. Granted, I don't have SPI, I2C... running, but at least I can confirm the Captivate appears to be working and responding as expected when I touch any of the buttons.

    It appears to only actually freeze while I am using the capacitive touch buttons.

    When a button  detected, you send data to a host using SPI and IC2 to LED driver.  Have you confirmed with scope/logic analyzer that these are working?  or a better question is if you were to monitor the SPI and I2C bus when a button is pressed, do they execute correctly and completely? 

  • Dennis, 

    Oddly enough, I just hooked up my logic analyzer to I2C and once I did that, the freezing stopped. But the moment I disconnect it, it freezes again.

    That at least points us in the direction of I2C being the problem here. But unfortunately, it also means I won't be able to see it with my scope.

  • That's strange.  Typically, adding wires to the I2C bus can make things worse, due to the added capacitance of the wires.  Connecting your analyzer makes it work better makes we want to look into grounding issues.  Are the MSP430 and the I2C devices sharing the same ground? 

    What value resistors do you use for the I2C pull ups?  Are they pulled up to 3.3V or some other voltage?

  • Yes, the ground is shared between the devices.

    The I2C lines were pulled up with 4.7k resistors, however, I just swapped them to try with 3k resistors, but still freezing. Voltage is 3.3V

  • Ok, and with the probes connected to the I2C pins you don't see any other unexpected behaviors?  Are you running the I2C clock at 400KHz or 100KHz?

  • At the moment I am just trying to get 100KHz running, but at 400KHz it still freezes. 

  • No other odd behaviors from what I can tell.

  • Hi Max,

    I thought more about your problem over the weekend.  You have two devices on the I2C bus.  Do either of these devices implement and interrupt pin that the MSP430 responds to?  If so, are you using pull ups on those pins? And if so, can you monitor those interrupt pins instead of the I2C bus.  I won't tell us what is happening on the bus, but give a clue if one device stops generating interrupts.

  • Hi Dennis, 

    One of the I2C devices is an ambient light sensor that does have an interrupt pin, which I will be reading from. However, at the moment I have this sensor commented out from the project since the rest of it is not working yet. 

    The other device is the LED driver which can only be written to so an interrupt pin is of no use here, unfortunately. 

  • Hi Dennis, 

    Have you had a chance to take a further look into this? Still haven't found a solution yet, unfortunately.

  • Hi Max,

    At this point my thinking this is an I2C bus issue. You said early on that you got the individual examples working.

    I started from square one by getting examples to work individually, then one by one adding them together.

    Let's break the problem down and If you go back and just perform I2C (no Captivate), do you still see the behavior when connecting probes to the I2C makes it work and removing the probes causes the I2C to stop? Or does the I2C work by itself? For example, write various values to your LED drivers and see if it responds and changes LEDs, etc.

  • Dennis,

    Ok just tried this, and you are right it is still occurring with captivate commented out of the project.

    This time though I found that the arbitration lost flag (UCALIFG) gets set, causing the bus to stay busy. From what I have read there is no way to handle such a situation but I am not so sure

    Due to some issues with visual lighting in this project, we are removing 1 of the 2 LED drivers and significantly reducing the number of LEDs. I have hopes that this will help with the issue since it seems at least one of the 2 drivers seems to be pulling the SDA line low. From what I have read this seems to be what can cause arbitration to get lost, unless you have any other ideas?

  • Hi Max,

    The UCALIFG bit is an arbitration bit between two masters and shouldn't be getting set.  The MSP is the only I2C master on the buss, correct?  This tells me there must be someone on the buss who is not behaving.  After removing one of the LED drivers, what devices are still connected to the buss?  Are you sure there aren't two slave devices with same addrs?

  • Hi Max,

    What is your status?  Have you discovered anything else that could be useful?

  • Hi Dennis, 

    Sorry for the delay on this, oddly enough our new board revision happened to come in today (only a single led driver now and a reduced number of LEDs). I haven't had too much time to test everything thoroughly yet, but I did have it freeze up on me once, however, I haven't been able to reproduce this.

    I am going to do some thorough testing tomorrow and debug + hook up my logic analyzer. I'll report back tomorrow with my findings.

    To answer your previous questions:

    1) MSP is the only master on the bus.

    2) The LED Driver is currently the only device on the I2C bus. (If I remove the LED driver, then nothing is connected to the bus)

  • Dennis, 

    It appears the same issue is at play here.

    Arbitration is getting lost and the stop flag is being set. I can't seem to find a straight answer anywhere on this. 

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Another Find: 

    When I am debugging with a logic analyzer, the only way I can connect it to the board is through a Flex cable + FPC breakout combo.

    Turns out, leaving my logic analyzer disconnected and the FPC breakout board still connected, the I2C works as it should. So long as the FPC adapter is hooked up to the I2C lines, the I2C communication works fine.

    If I disconnect the breakout board and leave only the flex cable attached, I2C stops working again.

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Conclusion:

    It appears that adding more surface area to the SDA and SCL traces has a positive impact on whatever issue is occurring here...

  • Hi Max,

    This is certainly sounding like this is some type of grounding issue. Did you like for me to look at your PCB layout?

  • Hi Dennis, 

    Yes, if you could that would be great I'll send you updated files in a private message.

  • Dennis, 

    The plot thickens...

    I was able to tie my logic analyzer directly to the board(bypassing the FPC breakout) with some soldering, which allowed me to see the error while it was still attached. Apparently (if this actually is the source of the problem), I'm simply getting a NACK, and it's causing it to freeze.

    If I send a repeated start after getting a NACK, then the MSP430 does try to reinitiate communication, but then it just receives another NACK and halts indefinitely.

    If I send a stop condition upon receiving a NACK, all comms stop immediately and never try to start up again.

    Not really sure what another way to handle a NACK would be. Let me know if you have any ideas.

  • Hi Max,

    If the slave is NACKing then it doesn't recognize the address you are sending.  Double check and make sure it is same.  Also, what code are you using for I2C Master?

  • Hi Dennis,

    Here is the code for the i2c master I am using. I've added some additional code to the NACK flag that seems to allow it to run a lot longer before freezing, but still not out of this yet.

    Also, I approved your request for the Altium access, should be able to view the design now.

    uint8_t i2c_tx_buffer[20]= {0};        // Pointer to TX data
    uint8_t i2c_rx_buffer[20]= {0};        // Pointer to RX data
    
    
    #pragma vector = USCI_B1_VECTOR
    __interrupt void USCIB1_ISR(void)
    {  switch(__even_in_range(UCB1IV,USCI_I2C_UCBIT9IFG))
        {
            case USCI_I2C_UCNACKIFG:
                UCB1CTL1 |= UCTXSTP;
                i2c_tx_byte_counter = 2;
                i2c_transmit_byte = 0;
                i2c_tx_buffer[0] = 0x25;
                i2c_tx_buffer[1] = 0x00;
                //UCB1I2CSA = 0x3C;
                UCB1IFG &= ~UCNACKIE;
                UCB1IE |= UCTXIE | UCNACKIE;
                UCB1CTL1 |= UCTXSTT;
            break;                                      // Vector 4: NACKIFG break;
            case USCI_I2C_UCTXIFG0:                       // Vector 26: TXIFG0 break;
                if (i2c_tx_byte_counter > 0)                                // Check TX byte counter
                {
                        UCB1TXBUF = i2c_tx_buffer[i2c_transmit_byte++];            // Load TX buffer
                        i2c_tx_byte_counter--;                              // Decrement TX byte counter
                }
                else if(i2c_tx_byte_counter == 0)
                {
                        i2c_transmit_byte=0;
                        UCB1CTLW0 |= UCTXSTP;                     // I2C stop condition
                        UCB1IFG &= ~UCTXIFG;                      // Clear USCI_B1 TX int flag
                }
            break;
        }
    }
    
    void i2c_init()
    {
        EUSCI_B_I2C_initMasterParam param = {0};
        param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
        param.i2cClk = CS_getSMCLK();
        param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS;
        param.byteCounterThreshold = 0;
        param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
        EUSCI_B_I2C_initMaster(EUSCI_B1_BASE, &param);
        //Set Master in transmit mode
        EUSCI_B_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
        //Enable I2C Module to start operations
        EUSCI_B_I2C_enable(EUSCI_B1_BASE);
        EUSCI_B_I2C_clearInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT);
        //Enable master transmit interrupt
        EUSCI_B_I2C_enableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT);
    
    }
    
    
    
    void i2c_master_write(uint8_t slave_address, uint8_t register_address, uint8_t data)
    {
            i2c_tx_buffer[0] = register_address;                //add register address to TX buffer
            i2c_tx_buffer[1] = data;
            i2c_transmit_byte=0;
            i2c_tx_byte_counter = 2;                  // Load TX byte counter
            UCB1I2CSA = slave_address;              // configure slave address
            UCB1IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
            UCB1IE &= ~UCRXIE;                       // Disable RX interrupt
            UCB1IE |= UCTXIE | UCNACKIE;             // Enable TX interrupt
    
            //while (UCB1CTLW0 & UCTXSTP);        // Ensure stop condition got sent
            UCB1CTLW0 |= UCTR + UCTXSTT;        // I2C TX, start condition
            __bis_SR_register(GIE); // Enter LPM0 w/ interrupts, and remain in LPM0 until all data is TX'd
    }

  • Hi Max,

    I reviewed your sch and pcb files.  I don't see anything wrong with either.  Looking at your timing diagrams, it appears the slave is clock stretching (delays the ACK) after writing the initial slave address and before the first byte is sent.  I'll take a look at the LED driver datasheet tomorrow.

  • Dennis, 

    I think you're correct that it's a clock issue, the datasheet is very minimal, and haven't found it very helpful, unfortunately.

    Let me know if you can think of any ideas, I'm at quite a loss here. 

  • Dennis,

    I ended up contacting the engineering team at Lumissil (manufacturer of the led driver) and they were very helpful, and we finally figured it out. 

    The I2C lines were noisy, plus the Reset pin line was noisy for the LED driver. So the noisy I2C lines were causing NACKs to occur, but the reset line was the cause of the freezing that was occurring.

    Really appreciate all your help on this though!

    Happy Holidays!

    -Max

  • Hi Max,

    Awesome news!  I'm glad you were able to get to the bottom of this issue.

    Thank you - yes, happy holidays to you as well.

    I'll change the status of this posting to RESOLVED, but if this isn’t the case, please click the "This did NOT resolve my issue" button and reply to this thread with more information.
    If this thread locks, please click the "Ask a related question" button and in the new thread describe the current status of your issue and any additional details you may have to assist us in helping to solve your issues.

**Attention** This is a public forum