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.

Fail-safe I2C driver for the MSP430

I’m trying to develop a fail-safe I2C driver. While I was coding the i2c_write driver I find out that even without the “__bis_SR_register(CPUOFF + GIE);”  but for the i2c_read introducing the “__bis_SR_register(CPUOFF + GIE);  ” it’s a must, otherwise the CPU gets blocked. As an active wait is anyway needed, setting the CPU off or coding something like “while(byte_cntr)” doesn’t make a big difference. On the other hand, I’m worried about the situation that arises when the MSP430 is commanded to read a single byte and a NACK condition occurs. For reading only one byte the code is “UCB0CTL1 |= UCTXSTT;   while (UCB0CTL1 & UCTXSTT);   UCB0CTL1 |= UCTXSTP;   __bis_SR_register(CPUOFF + GIE” (please note that differs from the attached driver code) but setting the STOP command clears the UCNACKIFG bit and the CPU gets blocked if a NACK arises.

 

  • You can go completely wihtout interrupts. Or completely go without active(busy) waiting. The main reason for interrupts is to preserve power on events with a long delay without anything to do.

    You didn't write for which MSP you're coding. There are difference between USART, USI, USCI for 2x/4X and USCI for 5x devices. Especially for 2X/4X USCI, interrupts are differently distributed to the interrupt vectors than you would expect.

    MARIENKA OLIVAR said:
    “UCB0CTL1 |= UCTXSTT;   while (UCB0CTL1 & UCTXSTT);   UCB0CTL1 |= UCTXSTP;   __bis_SR_register(CPUOFF + GIE”

    Not exactly. After the while, you need to check for UCNACKIFG, which indicates a non-responding slave. If it is clear, you can then wait (another while()) for UCRXIFG. It is set, when a byte has been received but before the master has sent an ACK for it. So there's still time to set the UCSTP bit, then read RXBUF. The I2C is finished (idle) when the UCBUSY bit is clear (which should be 1/2 clock cycle after UCSTP is cleared).

  • I’m experiencing problems with the I2C driver and my conclusion is that: the CPU is very susceptible to external noises when LPM0 is activated. If a noise arises while I2C communications when it is in LPM0 it gets blocked, so blocked that even with a TIMER expiration associated with a “ _BIC_SR_IRQ(LPM0_bits);” sometimes still continues blocked. I will re-code all the driver again without using any LPM mode, and see what happens. Any additional feedback is welcome.

     Thanks,

    PD: the piece of code added to the driver for timer expiration is as follows:

     

            TACCR0 = TAR + tTIMEOUT;                               // Time-Out

            TACTL = TASSEL_2 + MC_2;                                               // SMCLK, continuous mode

            TACCTL0 = CCIE;                                   // Enable Time-Out

            TIMEOUT = FALSE;

            UCB0CTL1 |= UCTXSTT +UCTR;                                        // I2C TX, start condition

            __bis_SR_register(CPUOFF + GIE);            // Enter LPM0 w/ interrupts

            if (TIMEOUT)

            {

              UCB0CTL1 |= UCTXSTP;                    // I2C stop condition

            }

            else   while ((UCB0CTL1 & UCTXSTP) && (TIMEOUT == FALSE));                 // Ensure stop condition got sent

            TIMEOUT = FALSE;

            TACTL = 0;                                        // Stop Timer_A

            TACCTL0 = 0;                                // Disable reception

  • MARIENKA OLIVAR said:
    the CPU is very susceptible to external noises when LPM0 is activated.

    Ah, no. Entering LPM just suppresses the generation of the MCLK signal (and therefore stops the cpu). It does not change anything else. If your cod ecrashes, then either your code is wrong or the MSP is defective.

    The latter includes the occurrence of the flash bug in the 54xxA adn 51xx series which causes the internal code fetching latch to lose the MSB when it is not accessed for a certain time. All devices shopped since January this year won't have this bug anymore, but if you have an older one of an affected series... then it won't work properly over extended periods of LPM, unless you do some tricks to 'access' the flash from time to time (e.g. a timer-triggered DMA transfer)

     

    P.s.: what timeout are you generating? I2C does not know about timeouts, and the physical design of the bus does not allow ignoring a condition that will cause a condition that would require a timeout. Either you get an ACK or NACK (and you'll get this immediately, based on the I2C clock) or someone is holding the clock line low. Then you cannot transmit a stop at all and the bus is stalled.
    I don't understand, however, the logic of the code. Either there is a timeout, then you send a stop, or there is no timeout then you wait for no stop condition? Okay, might make sense together with what happens in the ISR.
    However, setting stop when there is no response (no ACK nor NACK) is fruitless. If there is a timeout, then there is no high clock line (else there were no timeout), and without a high clock line, no stop can be sent.

**Attention** This is a public forum