Clearing I2C bus hung condition with MQX drivers

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Clearing I2C bus hung condition with MQX drivers

2,800 次查看
pmt
Contributor V

I don't see anywhere in the MQX I2C driver or documentation about handling a bus hung condition. 

Sometimes after power up, my first operation:

// Set bit rate to 400K
param = 400000;
ret = ioctl(fd, IO_IOCTL_I2C_SET_BAUD, &param);

returns I2C_ERROR_DEVICE_BUSY

But I am the only bus master, so I suspect the bus needs to be clocked until it is released by whatever slave device is keeping it.  Is there a proper methodology to do this within the context of the MQX driver (i.e. not banging on the low level I2C registers)?

Thanks,

PMT

7 回复数

2,053 次查看
DavidS
NXP Employee
NXP Employee

Hi PMT,

Have you enabled the clock to the I2C module?

More importantly is the module enabled in the user_config.h header?

#define BSPCFG_ENABLE_I2C0       1

Which Kinetis device are you using? What hardware?  What tools/IDE?  What version of MQX?

Regards,

David

0 项奖励
回复

2,053 次查看
pmt
Contributor V

Yes, II2C is enabled, and the system works most of the time.  Just on occasion with a warm boot it gets this error.  

K60, derivative of the K60xxxF120 BSP, MQX 4.1, Keil 5.4.    

I did not verify the bus hung condition with a scope but I will do this next.  But I did peruse the MQX I2C drivers, and I could not find any handling for a bus-hung condition, that is when a slave peripheral is not fully clocked out and is holding the data line.  So, I follow the same sequence of operations as the MQX I2C application code example:

fd = fopen("ii2c0:", NULL);
// Set bit rate to 400K
param = 400000;
ret = ioctl(fd, IO_IOCTL_I2C_SET_BAUD, &param);
if (ret == I2C_ERROR_DEVICE_BUSY)

{

// I get here

}

Looking at the SET_BAUD I/O handler in the driver it simply test for a busy bus then gives up:

i2c_ptr->S & I2C_S_BUSY_MASK

So my I2C bus is BUSY, but the K60 is (or would be) the only master on the bus, at least if I could get that far in the example initialization.

So the proper way to clear a bus hung is to keep clocking the CL line until the slave device releases the data line, but there is no ioctl() call to do this.  Do I have to bang on the I2C registers directly?

Thanks,

PMT

0 项奖励
回复

2,053 次查看
DavidS
NXP Employee
NXP Employee

Hi Chris,

I've poked around and only see a I2C_HAL_SendStart() call and not a clear bus error call.

If that call does nothing for you, then I would suggest bit bang 9 CL transactions to clear the device.

If you have access to the I2C device reset line, can you toggle it?

Regards,

David

0 项奖励
回复

2,053 次查看
pmt
Contributor V

David,

Unfortunately I have no direct access to the devices reset lines, only I2C bus.  I'll try I2C_HAL_SendStart().  BTW, this application note explains it well: 

http://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf​​

This problem existed ever since the creation of the I2C bus.  I'm sure I can clear this condition with direct register access to the I2C device or HAL layer, but I am trying to play nice and stay within the framework of the MQX io driver.

I think this is just an oversight in the MQX io driver.  What should happen is an addition of an _ioctl() call to clear this condition (solution 1 of the application note).  I'll take a stab at it, but consider this a feature request!

Thanks,

PMT

0 项奖励
回复

2,053 次查看
DavidS
NXP Employee
NXP Employee

Hi PMT,

Thanks for the link.  I had a similar one:

http://www.nxp.com/documents/user_manual/UM10204.pdf  

3.1.16 Bus clear In the unlikely event where the clock (SCL) is stuck LOW, the preferential procedure is to reset the bus using the HW reset signal if your I2C devices have HW reset inputs. If the I 2C devices do not have HW reset inputs, cycle power to the devices to activate the mandatory internal Power-On Reset (POR) circuit. If the data line (SDA) is stuck LOW, the master should send nine clock pulses. The device that held the bus LOW should release it sometime within those nine clocks. If not, then use the HW reset or cycle power to clear the bus.

I submit as a feature request.

Regards,

David

2,053 次查看
pmt
Contributor V

BTW, this is related to this thread:

How can you detect hang / recover on Kinetis i2c?

2,053 次查看
pmt
Contributor V

David,

To the author's points above regarding preferred methods, I guess they are preferred in his mind, but not in the real world!  Expressing a reset line to one or more devices on the serial bus (for the devices that have it) begins to defeat the purpose of having a "2-wire" serial bus.  A master reset is OK, but these are usually after cold or warm boot only.  Cycling power to an embedded system is also never a welcome option, which is why we run MQX and not Windows!

I wonder if the SHTF2 in the I2Cx_SMB control register is set under this condition.  The driver can detect this and with user intervention clock out the condition assuming it is the only master on the bus.

Anyway, this is a classic issue with I2C and some sort of handling of this within the MQX driver would be very welcome!

Thanks,

PMT