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.

Atomic? When to disable global interrupt? I2C and Timer Interrupts

Other Parts Discussed in Thread: MSP430F1611, MSP430F2132

Hi i want to have a rule when to disable global interrupt and how.

Situation:

MSP430F1611:

- I2C Master sending data to I2C Slave every 4 minutes.

- Using TimerB for increasing ticks in every ms  and sec using timer ISR (CCR0 for sec / CCR1 for ms)

- LPM3 + GIE

MSP430F2132:

- I2C Slave receiving data from I2C Master every 4 minutes

- Using TimerA for generating tick in every ms  and sec using timer ISR (CCR0 for sec / CCR1 for ms)

- LPM3 + GIE

Looks like Timer B ISR in I2C Master(1611) is preventing I2C write in weird way.

Or still I have I2C issues.

I2C Master Write And Read function are all implemented by polling I2C IFGs. ( No I2C Interrupt enabled for Master)

And every step is checked and generate reports when ERROR is detected by using timeout  function (Timer A in 1611)

I2C Master Write Flow:

// before initiating the transfer, check bus is busy or not

while (I2CDCTL & I2CBB)

{
    if(i2cTimeOut) { return ERROR_BUS_BUSY;}
}

// after start and stop condition is set ( I used I2CRM = 0 option, so i set them before I load data to buffer)

while((I2CIFG & TXRDYIFG) == 0)

{
    if(i2cTimeOut) { return ERROR_TIMEOUT;}
}

I2CDRB = Data;

// after last byte is loaded to buffer wait for the transfer to be finished

while ((~I2CIFG) & ARDYIFG)

{

   if(i2cTimeOut) { return ERROR_TRANSFER_TIMEOUT;}

}

And while write I2C data to slave, ms Tick timer ISR also running.

And i get ERROR_BUS_BUSY report from time to time.

I cannot re-create the situation. this happens sporadically.

Looks like I2CBB is not reset for some reason.

So i got rid of I2CBB check as I check ARDYIFG for checking transfer completion at the end anyway.

But then i SOMETIMES get ERROR_TRANSFER_TIMEOUT error.

So i thought "ms timer  B ISR" has something to do with this.

So i turned the tick timer off from I2C Master when I2C data is transferring.

This definitely improved the situation but i still get ERROR_TRANSFER_TIMEOUT error once in a while.

Question:

So I read some threads and articles, and this might be something to do with not disabling interrupts while i'm doing critical things.

Critical Sections / Atomic Sections were told. Word read / write is Ok. but other than that something has to be done.

I still do not know whether my problems has to do with critical section protections or I2C modules issues ( esp. i have issues with I2CBUSY / I2CBB / ARDYIFG)

But if i need to set critical sections. what is best way to do this? I'm using CCS 5 

_DINT();

do_criticalthing();

_ENIT();

is this enough? some people are storing SR values before _DINT(); and restore SR after _EINT();

Do you also think ms tick timer ISR can change the I2C hardware states  or IFGs? when the code is waiting for it to be changed?

Sorry for the long question and thank you in advance.

hojun

  • Ho-Jun Song said:
    is this enough? some people are storing SR values before _DINT(); and restore SR after _EINT();

    It might be enough. The SR save is usually done because GIE bit (whcih is set by EINT and cleared by DINT) is located in SR. And not, SR isn't restored after EINT but instead of EINT. So GIE bit returns to previous state. Else if you enter a critical section from inside a critical section, you'd enable interrupts after the inner critical section if it just were doing EINT.

    If you don't have nested critical sections (that means, your critical section is never called while interrupts are disabled), then you don't need it. It is, however, the cleaner way.

    Ho-Jun Song said:
    Word read / write is Ok. but other than that something has to be done.

    A word read or word write, even operations like += or &= on a byte or word variable, are atomic. One processor instruction. No itnerrupt can interrupt them.
    However, when workign on a long value, an interrupt may happen between operatign on the first and second word of the dword value. Normally, this isn't critical too. But if the long value is a counter that is incremented inside the ISR, it may be incremented while you are reading it. With unpredictable results.
    As a rule of thumb, critical sections must be entered whenever you do an operation that needs to be consistent in a whole but might be influenced by an ISR.
    Imagine a ring buffer where you write to it and adjus tthe write counter and in the middle of doing so, teh ISR reads from it to send data and also adjusts the counter. It could lead in bytes not sent. Or even a stalled transfer because the ISR thinks there's nothing more to send and stops while main thinks the ISR isn't done sending and waits.
    And even if there is no conflivting access to variables and buffers, it might jsut be that your main code is timing critical and doesn't bear an ISR interrupting and taking time.

    Normally, I2C shouldn't be sensitive to timing, and if properly implemented, there is no problem with data access too.

    I must admit that I didn't use the USART I2C myself. I found it way to complex to handle when doing simple transfers like 'send one byte then read three'. So I wrote some  bit-banging I2C master macros and lived happily with them :)

  • Thank you Jens-Michael Gross for clarifying SR save.

    Jens-Michael Gross said:
    So I wrote some  bit-banging I2C master macros and lived happily with them :)

    And yes i think for I2C master i'd do implement them all in software.

    USART I2C module has some problems  ( = too hard to be perfect) and i want my system to be much reliable as possible.

    To generate error report on every step and to simulate error condtions, i think automated unclear i2c hardware module is not a good idea.

    Thank you again.

    hojun

**Attention** This is a public forum