Hi All
I have a nasty feeling that the I2C in the KL43 could have a problem.
I have used the same interrupt driven driver on just about all KL and K devices but this one behaves differently.
Initilly I had the problem that the BUSY bit was set in the stauts register after performing a read of a number of bytes from a slave. So I let the interupt routine run a few times (with a break point) and it all looked OK and if I work like this the problem isn't always seen and the operation then runs (continuously reading blocks of data from the slave [without any pauses on the bus] forever - whereby repeated starts are used for following read all the time).
But generally it was behaving wierdly and the most bizzare thing that is seen is the following. To make it clear I can run the same driver code on a KL46 and a KL43 (50kHz I2C clock) and see this difference:
KL46:
- the slave address has just been sent and the first byte of slave data is to be read
- in order to start the read of the byte of data a dummy read is made of the data register, which then kicks off the I2C master sending 9 clocks
- the the next interrupt arrives, the data byte is read, which then kicks off the read of the next byte, and so on until all but one are read
- before the final read the ACK bit is cleared so that there is no ACK sent to the slave
- finally the stop condition is sent.
KL43:
- the slave address has just been sent and the first byte of slave data is to be read
- in order to start the read of the byte of data a dummy read is made of the data register, which then kicks off the I2C master sending 9 clocks (but the master doesn't send 9 clocks but instead sends 'continuous' clocks)*
- the the next interrupt arrives, the data byte is read - here the master is still sending continuous clocks so the read is not controlling anything
- before the final read the ACK bit is cleared so that there is no ACK sent to the slave - because the master is sending clocks all the time the reading is not necessary synchronised (?)
- finally the stop condition is sent. When the bus blocks at busy I see that the master has sent an ACK to the last byte sent and there is no stop condition.
Comparing the user's manual for the KL43 and KL46 doesn't reveal any obvious major differences (KL43 has an additional status register) so I would expect the behaviour to be the same on both parts.
* The fact that the master sends continuous clocks is a major difference which suggest the root cause of the unreliability. This is very easy to reproduce since it just needs the debugger to break on the read of an available byte and the master will then be reading and ACKing each read for everever when the debugger is pausing the processor (the KL46 master will wait until the data register is read and then sends out the next 9 clocks as expected.
Is this an error in the I2C controller in this part or is there some new mode/behaviour that it defaults to?
Regards
Mark
P.S. There is a migration guide form the KL46 to the KL43 at http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4997.pdf?fasp=1&WT_TYPE=Application...
This explains that the new I2C can obtain faster speeds due to being double buffered.
It also states that there is no software impact when using the new I2C, which my tests with identical SW haven't been able to confirm..
Hi Everyone,
I apologize for being absent from the communities for so long. I got a response from our designers regarding this issue:
"The I2C module for this device has been optimized to support High Speed mode. In previous versions the module had to wait for the I2C_D register to be read in order to start the next transaction. This version includes a mechanism that "automatically reads" the I2C_D register allowing to start the next transaction immediately after the previous one has been received. This optimizes the communications speed in the module"
The solution is to follow the workflow diagram in the Reference Manual and set the I2C_C1_TXACK flag in the second to last byte to be read so the module stops sending clocks for reading.
Our recommendation is to do this using interrupts since a polling firmware migh not be fast enough to detect when the 2nd to las byte has been received and set the TXACK flag on time.
Saludos
Santiago Lopez -- Connectivity and IoT
Hola Santiago,
Estoy tratando de utilizar el sensor de aceleración en una FRDM-KL46Z vía I2C, utilizando el KSDK 1.2, pero constantemente me ha regresado el error ERR_SPEED (0x01) y he revisado constantemente la configuración del reloj de la CPU entre otras cosas y "no doy con la tecla" para que me funcione el módulo.
Alguna sugerencia? Te puedo enviar el archivo?
Hi Mark,
Thanks for your post, I was able to replicate this use case. It seems like the I2C master is kidnapping the SDA line keeping it low everytime the I2C_C1[TXAK] bit is cleared. This is causing the master to keep sending SCL clocks until I2C_C1[TXAK] is set. I will check this in deep with the team and will get back to you as soon as we have a solution.
Saludos
Santiago Lopez -- Connectivity and IoT
I have a similar problem with KL43Z.
I can read the built-in accelerometer using i2c soft (i2c_gpio), but if I try it with i2c hardware I have no succes.
Could be the same problem?
Regards,
Miguel
Hi Santiago
Thank you very much for the answer - I have abandoned the I2C on the KL43 for the moment (I have enough other things to do ;-) because I also implemented the modified interrupt flow diagram in the user's manual (with stop and start flag checking on entry) but this didn't help and actually caused more problems. I checked the latest KDS code and don't think that any demos are presently using interrupts (possibly spinning on the flags the code may be able to get past the difficulty) and after trying a few workaround "ideas" with no success I thought it best to wait for the experts who know what is going on inside and can probably work out the best workaround using simulation models or similar.
Hope you guys can work out why it is doing this and what can be done to get code operation again on it.
Regards
Mark
P.S. My feeling is that something has gone wrong with the new double buffered data register. I could imagine two reads being made immediately but then I woudl have expected it to stop once the data buffer is full again. Possibly here it is not recognising it correctly and so reading forever (?)