• AVR Freaks

Hot!i2c ACKSTAT bit doesn`t seem correct

Author
hindenbu
New Member
  • Total Posts : 15
  • Reward points : 0
  • Joined: 2008/09/30 11:43:11
  • Location: 0
  • Status: offline
2010/02/10 14:31:39 (permalink)
0

i2c ACKSTAT bit doesn`t seem correct

I'm in the initial phases of setting up I2C master support on my PIC24FJ256GB110.  In my 3.3V hardware design, SCL2 and SDA2 are being pulled up with 2.2K resistors.

On initialization, I'm setting the following configuration bits:


        _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
        _CONFIG2( 0xF7FF & IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_HS & FNOSC_PRIPLL & PLLDIV_DIV2 & IOL1WAY_ON)
        _CONFIG3( WPCFG_WPCFGDIS & WPDIS_WPDIS)        //Disable erase/write protect of all memory regions.


I have no slave device connected to the SCL2 and SDA2 pins yet.  For testing purposes, I have the following code, which I intend to verify "hangs" at the point where ACKSTAT is checked:


void I2CInit(void)
{       
OpenI2C2((I2C_ON | I2C_IDLE_CON | I2C_CLK_HLD | I2C_IPMI_DIS | I2C_7BIT_ADD |
         I2C_SLW_EN | I2C_SM_DIS | I2C_GCALL_DIS | I2C_STR_DIS |
         I2C_NACK | I2C_ACK_DIS | I2C_RCV_DIS |
         I2C_STOP_DIS | I2C_RESTART_DIS |I2C_START_DIS),
         35); // turn on I2C2, run with a BRG value of 35, which should yield a baud of
             // about 400KHz
             
IdleI2C2();       
StartI2C2();
   
while(I2C2CONbits.SEN);
   
MasterWriteI2C2(0x59);
 while (I2C2STATbits.TBF);
 
while (I2C2STATbits.ACKSTAT);  // I am deliberately trying to get the application to hang here

// unrelated code continues here
   // ...
   // ...
}



...Yet, when I execute this code, I invariably fail the ACKSTAT check, and fall through to the "unrelated code."  I can't even begin to explain why this would happen; my expectation would be that, if no device is attached, my pullups should cause SDA to be driven high when not controlled by the PIC master (e.g., when expecting bar-ACK), and therefore my code should hang, waiting for a bar-ACK that never comes.

My analyzer shows a start condition and a nice 400Khz waveform for SCL's nine clock cycles.  And, after the sending of the R/W bit, SDA remains high (expected behavior when no slave device is connected).  I can't for the life of me figure out, then, why my system doesn't hang on the ACKSTAT check.

Can anyone see anything wrong or insufficient with my theory, my initializations, or my algorithm?  Can anyone save my hair before it's all pulled out?
post edited by hindenbu - 2010/02/11 08:57:40
#1

18 Replies Related Threads

    Mike017
    Super Member
    • Total Posts : 2698
    • Reward points : 0
    • Joined: 2007/08/25 08:11:31
    • Location: Lincoln, RI, USA
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 11:22:04 (permalink)
    0
    Hi,
     
    Possibly, it's interpreting the high SDA line as a received NACK (1) and then the fall through. 'Not sure [8|]
     
    Good Luck,
    Mike
    #2
    hindenbu
    New Member
    • Total Posts : 15
    • Reward points : 0
    • Joined: 2008/09/30 11:43:11
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 11:37:00 (permalink)
    0
    Well, a NACK (1) is what I expect when I have no device attached.  Yet, the line where I'm looking for it:


    while (I2C2STATbits.ACKSTAT);


    ...fails, implying that ACKSTAT is 0.

    It's as if the I2C2STAT register isn't being properly updated or something.  Yet, I clearly see the proper SCL and SDA sequence on my analyzer when it runs...
    post edited by hindenbu - 2010/02/11 11:59:39

    Attached Image(s)

    #3
    hindenbu
    New Member
    • Total Posts : 15
    • Reward points : 0
    • Joined: 2008/09/30 11:43:11
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 11:39:47 (permalink)
    0
    If I receive a NACK (1), shouldn't the ACKSTAT bit be set to 1 on the ninth SCL cycle?  Or am I missing something?
    #4
    Mike017
    Super Member
    • Total Posts : 2698
    • Reward points : 0
    • Joined: 2007/08/25 08:11:31
    • Location: Lincoln, RI, USA
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 12:28:22 (permalink)
    0
    Hi,

    Well, a NACK (1) is what I expect when I have no device attached.  Yet, the line where I'm looking for it:



    while (I2C2STATbits.ACKSTAT);



    ...fails, implying that ACKSTAT is 0.
    If the ACKSTAT bit is set (NACK received) it will fall through the while(1).
    If a wait is needed at that test line then while(!I2C2STATbits.ACKSTST) should work. You can check that bit in a watch window using a breakpoint just after the while assuming it falls through.

    Good Luck,
    Mike
    post edited by Mike017 - 2010/02/11 12:29:37
    #5
    hindenbu
    New Member
    • Total Posts : 15
    • Reward points : 0
    • Joined: 2008/09/30 11:43:11
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 12:40:16 (permalink)
    0
    ORIGINAL: Mike017
    If the ACKSTAT bit is set (NACK received) it will fall through the while(1).  [...]


    Um...a while(1) should infinitely loop, and should not fall through.  So, if ACKSTAT is set to 1 (NACK received), my while statement will always evaluate true, and I should enter an infinite loop.  This is the expected behavior, but is not what I'm seeing.

    Isn't ACKSTAT loaded with the value of the SDA2 line (1) at the time of the ninth SCL2 cycle?  And, as a result, shouldn't my while statement, as written, continuously loop?  It doesn't.  What am I misunderstanding?
    #6
    Mike017
    Super Member
    • Total Posts : 2698
    • Reward points : 0
    • Joined: 2007/08/25 08:11:31
    • Location: Lincoln, RI, USA
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 13:00:13 (permalink)
    0
    OK - I (miss)understood that fall through was not into some while function code.
     
    Isn't ACKSTAT loaded with the value of the SDA2 line (1) at the time of the ninth SCL2 cycle? 
    It seems so with this...
    24.2.2.3SLAVE ACKNOWLEDGE
    The receiving device is obliged to generate an Acknowledge signal, ìACKî, after the reception of
    each byte. The master device must generate an extra SCLx clock which is associated with this
    Acknowledge bit.
    I'm just checking to see if something else is required.
     
    Mike
    #7
    hindenbu
    New Member
    • Total Posts : 15
    • Reward points : 0
    • Joined: 2008/09/30 11:43:11
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 13:08:49 (permalink)
    0
    ORIGINAL: Mike017

    OK - I (miss)understood that fall through was not into some while function code. [...]


    Ah, I see.  :)  No...under "normal" (slave = attached and working) operation, it should fall through after a 0 is received via the ACKSTAT bit from the slave.  But I am deliberately testing with no slave attached, and it is sensing a 0 ACKSTAT value somehow anyway, despite the analyzer signaling I provided in the attachment a few posts back, where it clearly indicates that SDA2 is high on the ninth SCL2 cycle.

    It's as if something is preventing the I2C2STAT register from being updated when it should be or something, but I can't tell why.
    #8
    Mike017
    Super Member
    • Total Posts : 2698
    • Reward points : 0
    • Joined: 2007/08/25 08:11:31
    • Location: Lincoln, RI, USA
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 13:30:51 (permalink)
    0
    24.2.1.5ACKNOWLEDGE (A) OR NOT ACKNOWLEDGE (N)
    All data byte transmissions must be Acknowledged (ACK) or Not Acknowledged (NACK) by the
    receiver. The receiver will pull the SDAx line low for an ACK or release the SDAx line for a NACK.
    The Acknowledge is a one-bit period using one SCLx clock.


    The only issue I see is the above as well as Fig 24-3 (of the FRM) which describe both ACK/NACK as being one bit duration. Possibly clocking out a stop condition in code will help.
    #9
    hindenbu
    New Member
    • Total Posts : 15
    • Reward points : 0
    • Joined: 2008/09/30 11:43:11
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 13:46:38 (permalink)
    0
    Yes, because it is only of one-bit duration, it is critical that SDA2 be appropriate during the ninth SCL2 cycle, which it is, according to my analyzer log (q.v.)  It is during that clock period that ACKSTAT should be set, and my understanding is that it's set to whatever the SDA2 line has on it at that time.  My demonically possessed code indicates otherwise somehow.

    A stop condition shouldn't really be necessary for ACKSTAT to be set properly, since certain I2C transactions (e.g., sequential reads) can take place with multiple transmissions (and ACKS) before a stop, I believe.  I appreciate the help you've tried to provide so far.
    #10
    Teejwi
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2010/02/01 21:25:38
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 13:51:09 (permalink)
    4 (1)
    My thoughts...

    Your code as presented here doesn't allow enough time between waiting for TBF to clear and waiting for the ackstat to be set.  TBF will clear on the falling edge of the 8th SCL and ACKSTAT will be written on the falling edge of the 9th SCL.

    Your processor can execute anywhere from 16 to 160 instructions in that 1 SCL time.   (ie 16MIPS cpu and 400khz I2c = 40 instructions per SCL).  Thus, it has gone past that check before the bit gets written.
    post edited by Teejwi - 2010/02/11 13:53:23
    #11
    hindenbu
    New Member
    • Total Posts : 15
    • Reward points : 0
    • Joined: 2008/09/30 11:43:11
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 13:56:16 (permalink)
    0
    ORIGINAL: Teejwi

    My thoughts...

    Your code as presented here doesn't allow enough time between waiting for TBF to clear and waiting for the ackstat to be set.  TBF will clear on the 8th SCL and ACKSTAT will be set on the 9th SCL.

    Your processor can execute anywhere from 16 to 160 instructions in that 1 SCL time.   (ie 16MIPS cpu and 400khz I2c = 40 instructions per SCL)


    I wondered about this.  I think I can get around that problem if I change the line:


          while (I2C2STATbits.TBF);


    to:


          while (I2C2STATbits.TRSTAT);


    ...right?  I will try this, and report back.  I've seen reference designs which do it both ways, but I must admit I think I've seen more of the latter...

    #12
    Teejwi
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2010/02/01 21:25:38
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 14:05:55 (permalink)
    0
    ORIGINAL: hindenbu

    ORIGINAL: Teejwi

    My thoughts...

    Your code as presented here doesn't allow enough time between waiting for TBF to clear and waiting for the ackstat to be set.  TBF will clear on the 8th SCL and ACKSTAT will be set on the 9th SCL.

    Your processor can execute anywhere from 16 to 160 instructions in that 1 SCL time.   (ie 16MIPS cpu and 400khz I2c = 40 instructions per SCL)


    I wondered about this.  I think I can get around that problem if I change the line:


        while (I2C2STATbits.TBF);


    to:


        while (I2C2STATbits.TRSTAT);


    ...right?  I will try this, and report back.  I've seen reference designs which do it both ways, but I must admit I think I've seen more of the latter...


    According to the doc that should work.  TRSTAT shouldn't come down until after ACKSTAT is set.  ("Hardware clear at end of slave Acknowledge").

    I do my I2C with an interrupt driven state machine, so I can't say for certain.

    And now that I've reread your original post I should clarify that you'll get 35 instructions (BRG) between falling SCLs.  Heh.  Missed the BRG on the first read.
    post edited by Teejwi - 2010/02/11 14:07:08
    #13
    hindenbu
    New Member
    • Total Posts : 15
    • Reward points : 0
    • Joined: 2008/09/30 11:43:11
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 14:13:32 (permalink)
    0
    Bingo, Teejwi!  Using TRSTAT instead, I now hang on the ACKSTAT check as I would like (given the nature of my test).

    The reason I didn't pursue this earlier is because of one thing: if you look at my analyzer results in the attachment in one of the posts near the top of this thread, my SDA line is high during both the eighth and ninth SCL clocks (because I happened to be requesting a READ in my example, so the eighth SDA bit was set high).  I had speculated that it may just try to fill ACKSTAT "too early," and because of my specific example, that it should still "accidentally work," so to speak, since SDA was high during that time too.

    I'm unclear why checking the ACKSTAT bit prematurely, results in it being evaluated as zero.  Shouldn't it fail-safe to a one?!?  If you have any thoughts on that, I'd be interested in them.  In the meantime, thanks for the help, Teejwi and Mike017.  Now I can move on to troubleshooting my slave device which doesn't work at all.  [:'(]
    #14
    Mike017
    Super Member
    • Total Posts : 2698
    • Reward points : 0
    • Joined: 2007/08/25 08:11:31
    • Location: Lincoln, RI, USA
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 14:29:02 (permalink)
    0
    #15
    Teejwi
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2010/02/01 21:25:38
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/11 17:47:23 (permalink)
    0
    Sweet.  Glad you got it sorted!




     


    #16
    Teejwi
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2010/02/01 21:25:38
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/17 15:38:43 (permalink)
    0
    my SDA line is high during both the eighth and ninth SCL clocks (because I happened to be requesting a READ in my example, so the eighth SDA bit was set high).  I had speculated that it may just try to fill ACKSTAT "too early," and because of my specific example, that it should still "accidentally work," so to speak, since SDA was high during that time too.


    Just to clarify something for you here (Hey, I'm new to I2C myself, so just passing on what I've learned, figured out and postulated...)

    SDA and SCL float high ("1") unless something is pulling them down - that's the point of the pull-up resistors.

    After the 8th SCL fall, therefore, SDA will be high regardless if it's a read or write...unless whichever device was being talked to grabs it and pulls it low signifying ACK.

    Think about it this way...if you transmit an address out on an I2C bus with no slaves, nothing will respond (by pulling the clock low)...so you'll read a NACK on that 9th SCL fall.

    The bus DOES default/failsafe to '1'...but only if you wait until a valid time (9th SCL) to check it.

    If mcp made the default (NACK) = 0 and ACK =1, then the bit would be reflecting the opposite of the logic state of the bus...which would get confusing when looking at bits vs scope traces. 
    #17
    hindenbu
    New Member
    • Total Posts : 15
    • Reward points : 0
    • Joined: 2008/09/30 11:43:11
    • Location: 0
    • Status: offline
    RE: i2c ACKSTAT bit doesn`t seem correct 2010/02/17 16:18:09 (permalink)
    0
    ORIGINAL: Teejwi

    [...]
    Think about it this way...if you transmit an address out on an I2C bus with no slaves, nothing will respond (by pulling the clock low)...so you'll read a NACK on that 9th SCL fall.

    The bus DOES default/failsafe to '1'...but only if you wait until a valid time (9th SCL) to check it.

    If mcp made the default (NACK) = 0 and ACK =1, then the bit would be reflecting the opposite of the logic state of the bus...which would get confusing when looking at bits vs scope traces. 


    Yes, this is exactly right.  I don't think I worded properly what my confusion was about.  It's specifically about the power-on-reset state of the ACKSTAT bit in its register.  Intuitively, it seems like the ACKSTAT bit should be set high at the initial power-on state, thus indicating (safely) a NACK in the event the bit were read out-of-sequence, for the very reasons you describe.  If I don't do my initial setup dancing properly, and then hustle off to go check ACKSTAT...it won't be updated; after power-on reset, it'll still say "0," and it'll look to the clumsy like a false ACK if it's evaluated.

    I see that the entire register defaults to 0x00 at POR.  It may be that it has to default that way (the entire register low), so it's kinda "tough luck" for the ACKSTAT default state.  Oh well.  We'll just have to not-be clumsy, and just babysit it ourselves--as a robust design should anyway.  :)
    #18
    ric
    Super Member
    • Total Posts : 25244
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: RE: i2c ACKSTAT bit doesn`t seem correct 2020/01/03 14:43:09 (permalink)
    5 (2)
    This is an ancient post, but I see some people are still referring to it.
    The OP's code failed because of incorrect handling of the ACKSTAT bit.
    It is never correct to wait on that bit being set/clear. It is in an indeterminate state while a transaction is being performed. It is not updated to the received value until the TRSTAT bit goes low, so if you read it before then, you could get anything.
    Once TRSTAT goes low, ACKSTAT has been updated, so you only need to read it once.
     
    As I said at the start, it is NEVER correct to wait on ACKSTAT. Wait until it has been updated, and read it ONCE.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #19
    Jump to:
    © 2020 APG vNext Commercial Version 4.5