Preventing automatic slave address ACK

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

Preventing automatic slave address ACK

Jump to solution
2,368 Views
alex323qp
Contributor III

Hi guys, I'm working with the KL25Z64 I2C peripheral and noticed that after setting the slave address the hardware automatically ACK the device address, if the slave is busy doing something else and doesn't ACK the following byte the line gets blocked (clock stretching?).

pastedImage_0.png

(zoom out - SCL line goes back to HIGH while SDA remains low)

pastedImage_1.png

Is there any way of stopping the hardware from ACK the slave address and control this from software? so that if the slave device is busy the master then receives a NACK?

Thanks and regards,

Alex.

1 Solution
1,456 Views
egoodii
Senior Contributor III

You might try toggling master/slave mode to 'reset' the peripheral state machines (maybe even instead of the SLFT/SHTF2 process?).

However, shouldn't you be just 'avoiding' bus-lock by simply 'properly handling' each byte received by the KL25?  As soon as you handle the data-byte, the hardware will free the bus.

But I think I am 'warming' to the gist of your request -- which is to find a 'clean' way for the KL25 to be 'too busy' to accept I2C traffic 'for a time', and you want it to 'fail to ACK' the device-address to signify that ('ala EEPROM I2C).  You might try just changing the slave address to the 'general call' address, OR simply 'disable' the I2C peripheral, for the time-frames where a transaction hasn't started and you don't wish to let a new one get started -- then presumably 'no-one' will ACK the address, leaving the master to receive a NAK.  I have a 'nagging worry' that you will find small 'windows' right at the end of an incoming-address where one or the other of these techniques might fail...  Whether or not you run into any issues may depend on what 'defines' the time-frames where the KL25 will be 'too busy'.  If 'right after a previous I2C transaction' can be the definition, then you will KNOW the bus is idle right at a time you can make the I2C-slave operational changeover to 'ignore' the KL25 assigned device address (until restored).

View solution in original post

0 Kudos
8 Replies
1,456 Views
alex323qp
Contributor III

Thanks guys, sorry for the ambiguity of the question, I'm using the kl25 in a multimaster environment. In the images above the MCU was acting as slave at that particular time.

I managed to get around my problem by using the I2Cx_SMB SLTF and SHTF2 registers to flag the state of the lines and reset the peripheral (I2Cx_C1 IICEN) to bring the lines back to HIGH (my priority atm is to prevent the bus from getting blocked):

pastedImage_0.png

It works up to a certain point, the problem now is that when the device tries to write to the line the I2Cx_S BUSY flag indicates the bus is still busy, I assume because the state machine never detected a STOP condition.

Is there any way of resetting the state machine?

Thanks again,

Alex.

0 Kudos
1,457 Views
egoodii
Senior Contributor III

You might try toggling master/slave mode to 'reset' the peripheral state machines (maybe even instead of the SLFT/SHTF2 process?).

However, shouldn't you be just 'avoiding' bus-lock by simply 'properly handling' each byte received by the KL25?  As soon as you handle the data-byte, the hardware will free the bus.

But I think I am 'warming' to the gist of your request -- which is to find a 'clean' way for the KL25 to be 'too busy' to accept I2C traffic 'for a time', and you want it to 'fail to ACK' the device-address to signify that ('ala EEPROM I2C).  You might try just changing the slave address to the 'general call' address, OR simply 'disable' the I2C peripheral, for the time-frames where a transaction hasn't started and you don't wish to let a new one get started -- then presumably 'no-one' will ACK the address, leaving the master to receive a NAK.  I have a 'nagging worry' that you will find small 'windows' right at the end of an incoming-address where one or the other of these techniques might fail...  Whether or not you run into any issues may depend on what 'defines' the time-frames where the KL25 will be 'too busy'.  If 'right after a previous I2C transaction' can be the definition, then you will KNOW the bus is idle right at a time you can make the I2C-slave operational changeover to 'ignore' the KL25 assigned device address (until restored).

0 Kudos
1,456 Views
alex323qp
Contributor III

Hi egoodii​,

"You might try just changing the slave address to the 'general call' address, OR simply 'disable' the I2C peripheral" - Genius!

I can't believe it never crossed my mind just to disable the I2C while the MCU was busy (one of those days I guess). Thanks heaps for the advice, it worked like a charm and the bus never gets locked :-).

Just for the record, I initially tried toggling between master/slave modes to reset the state machine but it didn't work.

Thanks again!

Alex.

0 Kudos
1,456 Views
egoodii
Senior Contributor III

I am elated to hear you have a usable process!

But disappointed about the 'master/slave toggle' failure-to-reset.  The 'wish' for a clean mechanism to 'reset' the I2C peripheral has come up before, but I didn't receive any feedback.  It would certainly be nice if NXP could come forth with a sequence of steps that would indeed guarantee a 'return to idle'...

0 Kudos
1,456 Views
alex323qp
Contributor III

Agree with you. I don't seem to be the only one trying to figure out how to reset the peripheral after it is locked. Doing a soft system reset does work but it is far from ideal.

Hopefully someone from NXP will throw some light on this?

A.

0 Kudos
1,456 Views
mjbcswitzerland
Specialist V

Hi

I am not sure that it is fully releated but I have found the following to realiably reset the I2C master when a bus busy is detected (in the particular case due to loss of arbitration):

ptrI2C->I2C_C1 &= ~(I2C_IEN); // disable I2S to clear busy

fnDelayLoop(100); // short delay before re-enabling the I2C controller (without delay it doesn't generate any further interrupts)

ptrI2C->I2C_C1 |= (I2C_IEN); // re-enable

If the slave is in a state in which it blocks the bus by holding the data line low the following unlocking sequence soves it:

1. Program the I2C lines as GPIO; SDA as input and SCL as output

2. clock SCL 'manually' until slave frees the data line

while (_READ_PORT_MASK(A, PORTA_BIT10) == 0) { // if the SDA line is low we clock the SCL line to free it

    _CONFIG_DRIVE_PORT_OUTPUT_VALUE_FAST_LOW(A, PORTA_BIT11, 0, (PORT_ODE | PORT_PS_UP_ENABLE)); // set output '0'

    fnDelayLoop(10);

    _CONFIG_PORT_INPUT_FAST_LOW(A, PORTA_BIT11, (PORT_ODE | PORT_PS_UP_ENABLE));

    fnDelayLoop(10);

}

3. Program pins as I2C again

Regards

Mark

0 Kudos
1,456 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Alexander Agudelo:

Earl Goodrich has good comments there.

If the KL25 is the I2C slave, then it will always generate an ACK when the configured slave address (I2Cx_A1) is matched. For any other transferred byte (not slave address) you can use the SMBus mode and set the bit FACK to 1 in the I2Cx_SMB register. In such mode the KL25 I2C slave can hold the SCL line for a moment after receiving 8 bytes, and the line is released when writing to I2Cx_C1[TXAK] either 0 or 1 (ACK/NACK).

Let us know if you have doubts.


Best regards!
Jorge Gonzalez

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
1,456 Views
egoodii
Senior Contributor III

It's not clear from your description whether the KL25 is the Master or the Slave in this transaction, but in I2C the master puts the device-address on the bus, and the slave supplies the contents for the ACK timeslot.  A slave may 'pace' ANY bit position by keeping the clock 'low' to stretch timing, but in GENERAL I think you will find that clock stretching happens after the ACK bit position.  This stretching will be the default action for each byte transferred to a 'microprocessor peripheral I2C' block (as slave), as EACH byte must be processed by firmware to release the hardware for the next transfer.  The ACK/NAK to return as a micro peripheral in slave mode is set BEFORE the upcoming byte is allowed  to transfer, excepting that 'device address' is directly recognized in hardware and ACKed if 'matched'.  Very few slaves 'pace' by sending NAKs at their device address -- only EEPROMs come to mind (as a write will take a LONG time, as in milliseconds, keeping the hardware busy).

0 Kudos