This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Register is not updated.....

Hi

I have an error that shows its ugly head now and then....
The µC I'm using is C8051F122.

When I debug I can locate the problem, but the bug does not show the same place in code all times.

What I see now is that when stepping over the following line:

SMB0CN = 0x44;

The register SMB0CN actually is set to 0xC4. This sets the BUSY bit in the register.

It can be resolved by removing the µC supply, but a RESET won't do. But after some time the problem shows again.....

Does anyone have an idea????

Best Regards....

  • What I see now is that when stepping over the following line:

    SMB0CN = 0x44;

    The register SMB0CN actually is set to 0xC4. This sets the BUSY bit in the register.

    you have no business whatsoever setting SMB0CN.7 I guess you are mixing IIC with SPI.

    Erik

  • Hi Erik

    Yeah I see that was a bad example since I´m not able to set this bit.

    Anyway the problem that a line of code is not taking any effect, have been seen on a simple variable too.

    Example:
    unsigned char xdata ucMyVar = 0;

    MyVar = 0xFF;

    In the watch window I see that the value of the variable still is 0 after stepping over the code....

    Any ideas?

    Regarding the I2C register SMB0CN. What will cause SMB0CN.7 to be set? Before i write 0x44 to the register, the register equals 0, and after writting it bit 7 is set.

    As mentioned earlier the problem only shows now and then, maybe 1-2 times each months. The solution is to power the µC down.

  • Compiler optimisation?

    "What will cause SMB0CN.7 to be set?"

    Surely, the Datasheet must tell you that?!

  • Do you have any interrupts? Is an interrupt scribbling over your memory? Is your stck big enough?

  • Is your stck big enough?

    I meant stack of course.

  • I have tried to use lower the optimisation with no luck. The problem is that I can not recreate the problem, so it is very hard to locate.

    I have I2C interrupt enabled, but it should not change the memory content. I have tried to set a break point in the interrupt function and it does enter the function.

    I guess the SMB0CN.7 bit is set to indicate if any device on the I2C line is trying to communicate, or?

  • Regarding the size of the stack, I'm not sure how to check if the size is large enough????

    Could you plz help?

  • Please note that it does makes no difference if I perform a reset by pulling the reset pin low, or if I press reset in the IDE. I see that the µC is reset but it starts with an error code indicating that I2C communication with onboard EEPROM fails. But if I turn off the supply shortly, and then let the µC startup the problem is gone.

    I'm trying to figure out what the difference is between resetting the µC and to power cycle it.

    The only thing that I can come up with is that the EEPROM is also powered down during the power cycle, but I can't see what difference that can make....

  • I'm trying to figure out what the difference is between resetting the µC and to power cycle it.

    The difference is that only one of these resets the I2C EEPROM, too. I2C can communication get stuck if you reset the master halfway through a transaction, and then just start a new one.

  • Hi Hans

    That was my theory too. But I'm not sure what how to prevent that communication is stopped halfway....

    Would it be enough to verify that the BUSY bit (SMB0CN.7) equals 0 (0=free, 1=busy)

  • unsigned char xdata ucMyVar = 0;
    
    ucMyVar = 0xFF;
    

    I'll assume that was just a typo...

    In the watch window I see that the value of the variable still is 0 after stepping over the code....

    Any ideas?

    That means nothing at all. In particular that does not constitute any kind of mistake. The compiler is allowed to move code around, as long as the end result is still the right one. You'll have to step on until at least the first instruction that reads this variable before you can conclude that the compiler isn't going to write to it in time.

  • But I'm not sure what how to prevent that communication is stopped halfway....

    You quite probably can't. Reset will reset everying. Immediately. Software gets no say in what is stopped or not, once the CPU resets.

    You'll have to reset I2C communication state in the slaves somehow...

  • Yeah ucMyVar was what I meant.

    What you are saying is that you can not trust the data in the watch window until the variable is used the next time?

    I know that the compiler can keep it anywhere in memory, but I surely would expect the watch window to reflect the value of the variable at all times (of course only global variables)....

  • "What you are saying is that you can not trust the data in the watch window"

    No, that's not it at all.

    The watch window will accurately display what's actually in the physical RAM.

    The problem is that the Compiler optimisation may mean that the physical RAM may not actually be updated at the precise point of the specific source line.

    You will have to look at the generated assembler to see precisely what's actually happening.

    "I know that the compiler can keep it anywhere in memory"

    That's not the point - see above.

    "I surely would expect the watch window to reflect the value of the variable at all times"

    No - you need to spend some time understanding how optimising compilers work!

  • The compiler can decide to remove variables that are not used. And it can decide to store a variable (all the time or sometimes) in a register. And the variables may not live through the full function call.

    Regarding I2C - you should check the state of the data line to see if any external device is driving the line. There are a number of articles you can Google for that describes how you can switch from I2C to GPIO and pin-toggle the clock line until you get the external device into a state where you can switch back to I2C and send a new start condition.

    Especially if I2C communication is used to equipment on a different PCB, you need to handle situations where a spurious pulse may lock up the transfer.