• TI Thinks Resolved

MSP430F5524: UCBBUSY being continuously set

Intellectual 520 points

Replies: 12

Views: 278

Part Number: MSP430F5524

I am using I2C Module 0 (UCB0) to communicate with two slaves - EEPROM(24LC64) and a temperature sensor(Si7060). I2C Write and Reads from the temperature sensor are being done continuously. Occasional I2C reads are failing as they do not respond in time, but it is okay by me as the next reads work.

But After 10-15 min(one in 10000 or more reads), the UCBBUSY bit gets set. The SDA line is continuously held low. My code is waiting in a while loop for the bit to get cleared which is not happening and thus the code gets stuck. Writes are working fine. I have used the same code which was being used for I2C Module 1(UCB1) which is having no problem.

(1) Why is this happening? I have observed on a CRO that the CLK signal is looking like a sine wave. Is the insufficient hold time leading to the slave pulling the data line low to signal an ACK and never releasing it? In this case changing I2C clock frequency solve the issue, right? Current clock frequency is about 133KHz(16Mhz/120)

(2)When the UCBBUSY is getting set I tried resetting the I2C Module by doing 

UCB0CTL1 = UCSWRST;

__delay_cycles(1000);

UCB0CTL1 &= ~UCSWRST;

Though this reset the module and the SDA line back to the high voltage level, this is leading to unsuccessful I2C Reads continuously in certain cases. Is what I have attempted to correct? If not, how else can I solve this problem?

We are in a critical stage during production. Any help would be dearly appreciated. Please find the code attached.

Thanks

Abhisheki2cCode.c

  • You say that the clock signal looks like a sine. The rise time is controlled by your resistor pullup. The fall time depends on the ability of the MSP430 output to pull it low. If both rise and fall times are long, then you have excessive capacitance on the line.

    Missing from your code is initialization for the I/O pins. You might want to double check that.

  • In reply to David Schultz36:

    Hi David

    Do you think the hold time is more of a problem rather than the rise or fall time? Any idea why the hold time is less?

    This is the initialisation I am doing in main.c:

    P3SEL  |=  (MCU_UCB0_SDA|MCU_UCB0_SCL);   // where MCU_UCB0_SDA = 0x1, MCU_UCB0_SCL=0x2

    Given that we cannot change the hardware design now, can you think of any other firmware hack through which I could solve the problem? Failed I2C reads are okay. I just don't want the SDA line to be continuously held low.

    Thanks

    Abhishek

  • In reply to Abhishek Veeraraghavan:

    I suggest that you read TI's slva689 and verify that you are meeting the I2C signal rise and fall time specifications. If not, you will have to change something. (Pullup resistors and/or F5524 output drive strength.)

    Perhaps a slower clock will be enough.

  • In reply to David Schultz36:

    Hi David

    I shall try reading that. What do you mean by changing FF24 output drive strength?

    I want to report something that I observed today. I tried outputting a series of log statements onto PuTTY through UART  in the read,write functions. Eg: Start sent, ACK received, write successful etc. On doing this I was able to successfully run the code for 2-3 hours at a stretch. Now this leads me to conclude that adding delay through __delay_cycles( ) might well be  a suitable workaround to the issue I am facing. The CPU clock speed is 16MHz. This could be too fast for the slave to respond to, right? The I2C clock speed is about 133KHz , so that should be fine. Could I get your opinion on this? In your comment on a slower clock doing the trick, were you referring to the CPU clock or the I2C clock?

    Thanks

    Abhishek

  • In reply to Abhishek Veeraraghavan:

    See the description in the manual on the drive strength register. (PxDS)

    I cannot follow that middle part very well. It sounds as though you are pausing in the middle of the I2C transaction to send data over a separate serial port. This would alter the inter-character timing but not do anything to the timing within each byte.

    I was of course referring to the I2C clock. If your signal rise and fall times really are as bad as described, you need to slow the clock down.  With a 133Khz clock you should be meeting the fast mode specifications.

  • In reply to David Schultz36:

    Hi, Abhishek, 

    I agree with David to slow down the I2C clock speed to relax the timing. This is the software workaround you can try. Do you have tried this and if it works well? 

    If you think David recommendation help to resolve your questions, please click on the This resolved my issue  button to close this thread.  

    Best Regards, 

    Lixin 

  • In reply to Lixin Chen1:

    Hi David, Lixin

    Firstly, Apologies for the delay in replying. I have been very busy at work. 

    The pausing in the middle of the I2C transaction to send data over a separate serial port somehow helped in solving the problem following which I have left it like that. But I am facing another issue with respect to the I2C code. We are in production mode right now and for certain MSP430s, I am unable to pause the code using the programmer after 2-3 hours. The code stops running and upon pausing I get the message ""Break at address "0xd00c4" with no debug information available, or outside of program code". For certain other ICs, the code runs fine for over 8 hours. For some, on the other hand, it fails within a minute.

    Could you please look at my code to see if there is something wrong that I am doing? Maybe there is an issue in the order of writing registers or something that is acceptable but not perfect because the code is giving inconsistent behaviour.

    Thanks and Regards1513.i2cCode.c

    Abhishek

  • In reply to Abhishek Veeraraghavan:

    You disable global interrupts but then enable the module interrupts. Much simpler to just not enable the module interrupts! (The interrupt flags will be set regardless of the state of the IE bits.) If some other device dislikes having its interrupt service delayed this could cause trouble.

    Most of i2cUcb0Cleanup() is useless. If you never enable the module interrupts, you don't need to disable them. Setting UCSWRST clears both the IE and IFG registers automatically.

    I usually go with an interrupt driven method so this polled stuff looks strange to me.

  • In reply to David Schultz36:

    Hi David,

    Thanks for going through the code. This was the existing code when I joined my workplace and because it was working, I let it be. I had been thinking of changing it as well. While it can be improved, there is no obvious error with it that should cause this behaviour, right?

    I might have diagnosed the cause of this. The MCLK frequency was 16MHz(through the internal DCO). On increasing or decreasing this frequency, the code is running fine in MCUs that were getting corrupted within seconds. As far as I know, the maximum frequency for MSP430F5524 is 25MHz. So, any idea why this could be happening? Could this simply be an issue with the ICs themselves due to improper handling, ESD events etc.?

    Here is the code where I am setting the MCLK frequency. Could you let me know if this is okay?

    UCSCTL3 |= SELREF_2;               // Set DCO FLL reference = REFO
    UCSCTL4 |= SELA_2;                   // Set ACLK = REFO
    UCSCTL0 = 0x0000;                    // Set lowest possible DCOx, MODx
    // Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize
    do
    {
    UCSCTL7 &= ~(XT2OFFG | XT1LFOFFG | DCOFFG);
    // Clear XT2,XT1,DCO fault flags
    SFRIFG1 &= ~OFIFG; // Clear fault flags
    }
    while (SFRIFG1&OFIFG); // Test oscillator fault flag

    __bis_SR_register(SCG0); // Disable the FLL control loop
    UCSCTL1 = DCORSEL_5; // Select DCO range 16MHz operation
    UCSCTL2 = FLLD_0 + 487; // Set DCO Multiplier for 16MHz // (487 + 1) * 32768 = 16MHz
    __bic_SR_register(SCG0); // Enable the FLL control loop

    // Worst-case settling time for the DCO when the DCO range bits have been
    // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
    // UG for optimization.
    // 32 x 32 x 16 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle

    __delay_cycles(500000);

    Thanks and Regards

    Abhishek

  • In reply to Abhishek Veeraraghavan:

    Hi, Abhishek, 

    I don't think it is an ESD issue that the code is running fine when increasing or decreasing this frequency in MCUs that were getting corrupted within seconds. This should be related to the frequency setting and the I2C communication speed setting. If the I2C code is removed and the code is running well, the issue can be addressed the I2C code. Then you can debug it step by step. 

    Regarding the MCLK 16MHz setting, I don't see anything incorrect. 

    Best Regards, 

    Lixin