SCL remains low after manual ACK in FACK='1' mode

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

SCL remains low after manual ACK in FACK='1' mode

3,476 Views
giovannivandela
Contributor I

I'm running I2C commands on secondary priority to a PIT module, that can delay I2C interrupt handling by about 50µs. I notice however, that, when a transfer completes followed by a stopbit and followed by a startbit before I can handle these interrupt flags, my code no longer responds to the transfercomplete. I deviated from the proposed flowchart by removing the return statements in the stopbit and startbit handling, to be able to process that TransferComplete that happened about 50µs ago.

Thus, I assume this TransferComplete flag is cleared when a start bit is received. I was not expecting this, nor do I find this behavior described in any manuals.

Kind of annoying, but I figured I would get around it disabling the FACK bit ('1') and 'manually' perform the ACK/NACKing when actually handling the TransferComplete (auto-ACK on addressing though, but setting FACK to '1' after an address match).

And here I run into the main problem. When the first byte of data is received, the ISR launches after the 8th clock, I write '0' to TXAK, I see the acknowledge on the oscilloscope (so far, so good), but after the ACK, SCL is kept low. I did read the data register (I find the value on on the oscilloscope in my buffer), I cleared the interrupt flag (no further interrupts follow anyway) and the bus hangs like this indefinitely.

I'm evaluating my ISR by means of driving some GPIOs hooked up to an oscilloscope, for my convenience. (In the screenshot, you can see these on C3 and C4.)

Message was edited by: Giovanni Vandelannoote Changed attachment to a clearer oscilloscope screenshot

Labels (1)
Tags (2)
0 Kudos
Reply
10 Replies

2,639 Views
rastislav_pavlanin
NXP Employee
NXP Employee

Hi Giovanni,

we have had some internal discussion regarding to the issue of locked SCL after FACK = 1 etc.

There is light difference between the I2C modules on KL17 with 128/256k flash and KL17 with 32/64k flash. And it looks like we have not proper flow chart in reference manual of KL17 with 128/256k flash (we have had proper one in past revisions, after newer revisions we accidentaly change it in wrong way). Please, if you use device with 128/256k flash then you will need to follow this flow chart for FACK = 1:

pastedImage_1.png

The difference is in write sequence of slave where delay + second read of IICD is required to be added. Please, let us know if this helped. Thanks for understanding.

regards

R.

0 Kudos
Reply

2,639 Views
giovannivandela
Contributor I

Hi Rastislav Pavlanin,

Thanks for the correction. However, as I stated previously, I never enter the ISR. So a modification to my ISR unfortunately doesn't change a thing. I think there is additional information that I'm lacking (or did not detect).

For example, the SMBus ISR flowchart does not show how to handle Start bit detection and Stop bit detection. I could assume this is because this 'low level' part of the SMBus ISR is depicted in the typical I2C ISR. The flowchart points this way when the FACK bit is '0'.

However, it is not indicated when one would change the value of the FACK bit. So if this is set once, e.g. at initialization (as is the case in my trial code), "FACK='1'?" is always true, in which case the SMBus flow chart does not refer to the typical I2C ISR flowchart anymore. Is it necessary to modify the FACK bit at any point?

0 Kudos
Reply

2,639 Views
chris_brown
NXP Employee
NXP Employee

Hi Giovanni,

What part are you using?

And is your part operating in master mode or slave mode?

And just a note about the TCF flag, the manuals do state that the TCF flag is only valid "during or immediately following a transfer to or from the I2C module".  So it is possible that because you have a PIT interrupt that is higher priority that can delay the handling of the I2C interrupt for so long, you are simply seeing that flag in an invalid state.  I would advise against this interrupt priority configuration (if possible) and would even advise against having an interrupt that takes so long (interrupts should be as short as possible). 

Regards,

Chris

0 Kudos
Reply

2,639 Views
giovannivandela
Contributor I

Hi Chris,

I am using a KL17 and the I2C interface operates as slave.

I read the note about the TCF flag, but it lacks clarity. "during or immediately following" unfortunately does not give one much to go by. It just mentions the TCF bit is cleared when reading/writing the data register, but doesn't mention what else clears this bit. The fact that this flag is invalid when the ISR is finally fired does show this to be true of course, but the mechanism behind it is not clear. Regardless, I can't do much about that which is why I want to delay the following Stop bit and Start bit.

I am aware that the PIT ISR is quite lengthy, but the calculations have a strict time requirement, so I have yet to work out a work-around for this. Until I do, I'm stuck with it.

Which brings me to my actual issue, which is the FACK functionality. In my original post, I mentioned that there is no more respone after the 'manual' ACK. I also mentioned that in the idle state, I reset the FACK bit to '0', as to auto-acknowledge an addressmatch (because in the SMBUS spec, a slave always has to acknowledge addressing, I am however not implementing SMBUS, even though the FACK functionality seems to be meant for SMBUS).

This seemed a bit too complicated however, and upon examining the proposed flow chart for an SMBUS implementation (just to know how to use the FACK functionality), I see that an addressmatch is not auto-acknowledged, but just 'manually' acknowledged.

So I modified (simplified) my implementation to always leave the FACK bit at '1'. When I do this, I never receive any IRQ. Not even once. So even Start and Stop don't generate an IRQ.

Some details:

- the I2C is running on priority 0 (maximum), so the PIT cannot disturb it

- I'm using Kinetis Design Studio, provided by NXP

- When not setting the FACK bit to '1', I do get interrupts

The initialization of the module looks like this:

void init_IWF_I2C(void) {

     i2c_slave_config_t I2C_slaveConfig;

     I2C0->SMB |= 0x80; // Disable automatic ACK transmission to extend ACK or NACK

     I2C_slaveConfig.addressingMode = kI2C_Address7bit;

     I2C_slaveConfig.enableGeneralCall = false;

     I2C_slaveConfig.enableWakeUp = false;

     I2C_slaveConfig.enableHighDrive = false;

     I2C_slaveConfig.enableBaudRateCtl = false;

     I2C_slaveConfig.enableSlave = true;

     I2C_slaveConfig.slaveAddress = 0x42;

     I2C_SlaveInit(I2C0, &I2C_slaveConfig);

     /*  Enable I2C0 slave NVIC interrupt. */

     NVIC_SetPriority(I2C0_IRQn, 0);

     EnableIRQ(I2C0_IRQn);

     I2C_EnableInterrupts(I2C0, kI2C_GlobalInterruptEnable | kI2C_StartStopDetectInterruptEnable);

}

The ISR starts like this:

void I2C0_IRQHandler(void) {

     DEBUG_PIN_TOGGLE;          // toggles oscilloscope C3

     //... rest of ISR

}

I found no hint as to why interrupts would be absent hen enabling ('1') the FACK bit.

Edit: I forgot to mention that, on the oscilloscope, all I see now is Start -> address -> NACK -> Stop, and the DEBUG_IN remaining static all the time.

0 Kudos
Reply

2,639 Views
chris_brown
NXP Employee
NXP Employee

Hi Giovanni,

I see.  These types of I2C problems can be problematic and difficult to debug / fix.  So I may not have any good concrete answers right now, unfortunately.  

What I would like to currently offer is maybe the use of DMA would keep things on track and be an acceptable workaround to this issue?  Could you try this?

To help, I have written a document on how to implement a DMA based receive function.  It is based on master mode and the Kinetis W series but should apply to this as well. It is also based on KSDK version 1.3, but you should be able to apply the concepts to another software set if needed.  Anyways, here it is, and please let me know if it helps.  

https://community.nxp.com/docs/DOC-330946 

Regards,

Chris 

0 Kudos
Reply

2,639 Views
rastislav_pavlanin
NXP Employee
NXP Employee

Hi Giovanni,

I would recommend you to look at this thread from Mark Butcher

https://community.nxp.com/message/576467#comment-576467

who did a great job with evaluating the I2C module with double buffering feature (included in KL17 as well) for both master and slave mode.

regards

R.

0 Kudos
Reply

2,639 Views
giovannivandela
Contributor I

Hi Rastislav Pavlanin,

All I found in that huge thread was:

" Title:

I2C: Slave does not hold bus between byte transfers and may result in lost data

Errata Description:

When the I2C module is used as a slave device, the bus is not held by the slave between byte transfers. If the I2C slave I2C_D register and the data buffer are full, incoming data from an I2C master will overwrite data in the data buffer.

Errata Workaround:

When configured as a slave, the delay in processing incoming bytes should be minimized. Delay can be minimized by the use of DMA or increased interrupt priority."

A quote from an errata, which I haven't found yet on the NXP website.

However, I found nothing related to the FACK bit or the crippling of the I2C module (or at least it's interrupts). Can you point out which part of that thread you were recommending specifically?

I've tried not initializing any module that could generate an interrupt, other than the I2C0 module, but  the results are the same. No interrupts are generated, but if I put the line where I set FACK to '1' in comment, everything works as it should...

Can you refer me to an SMBUS implementation that makes use of this functionality, for example?

0 Kudos
Reply

2,639 Views
rastislav_pavlanin
NXP Employee
NXP Employee

Giovanni,

the errata mentioned above are valid also for KL17, we have just not release them yet.

I wanted to point out especially the .pdf file attached at the beginning of the thread where Mark showed his experience how to work in slave mode with I2C module with double buffered feature with differ with some other I2C modules available on our Kinetis devices. The fact is that it does not comunicate the FACK or better to say SMBUS features available on that devices.

  To be honest, I am not familiar with SMBUS implementation. All I know is that in past we were developing a library to support SMBUS, but most probably the library does not support I2C modules with double buffered feature. You can look at:

NXP Power Management Bus (PMBus) Library|NXP

By the way, did you fully followed the diagram for SMBus routines? (Typical I2C SMBus interrupt routine)

regards

R.

0 Kudos
Reply

2,639 Views
giovannivandela
Contributor I

Hi Rastislav Pavlanin,

Indeed, the pdf posted on that thread only shows interrupts after acknowledging (9th clock pulse), while the interrupt with FACK set to '1' comes after the 8th clock pulse, before acknowledging.

I am not very familiar with SMBUS implementation either, as it is not my goal to implement SMBUS. I only want to use the 'manual' acknowledging. As for following the SMBus IRQ diagram, I did make the modifications to line up with the SMBus interrupt routine as far as the slave portion is concerned. However, as the controller never enters the ISR, I guess it doesn't matter whether I followed it or not so far.

I had a look already at the code supplied with the NXP PMBus Library you suggest, but found no code related to the setting of the FACK it. In fact, nothing related to the initialization of the hardware I2C module. Also, this code was developed for/on the 56F8xxx series of controllers. I'm not sure how this would map on the KL17.

Do you have any errata related to the KL17 that you can release here?

0 Kudos
Reply

2,639 Views
rastislav_pavlanin
NXP Employee
NXP Employee

Giovanni,

yes, there will be one errata more regarding to I2C module for this device. But I think nor from them are related to your issue. In next errata release we will add these errata related to I2C module:

1.Title:

I2C: Address match wake-up from low-power mode cannot receive data

Errata Description:

When the device is in a low-power mode that supports address match wake-up, receiving a matching address will wake up the MCU,  however, the I2C will not respond correctly. I2C traffic after the wake-up address will not generate TCF interrupt events.

Errata Workaround:

Either one of the following sequences will enable the address match wake-up to operate correctly:

  • §Send only the matching slave address followed by a repeated start and then resend the matching slave address including any subsequent data
  • §Send only the matching slave address followed by a stop condition and then resend the matching slave address including any subsequent data

2. Title:

I2C: Slave does not hold bus between byte transfers and may result in lost data

Errata Description:

When the I2C module is used as a slave device, the bus is not held by the slave between byte transfers. If the I2C slave I2C_D register and the data buffer are full, incoming data from an I2C master will overwrite data in the data buffer.

Errata Workaround:

When configured as a slave, the delay in processing incoming bytes should be minimized.  Delay can be minimized by the use of DMA or increased interrupt priority

We have couple of thread related to I2C module here. Did you read that one? :

Helpful I2C Observations

regards

R.

0 Kudos
Reply