I've been working with MQX's I2C drivers. First, I think it's clever how the I2C driver was worked into standard fio driver, and this model works well. However, both using the driver an examining the operation and code I am somewhat concerned.
Understand that I2C is one of the most delicate and fragile busses out there. If you aren't convinced of this I can point to entire design notes (practically a thesis) talking about the correct pull-ups to use on the bus. If you actually work though all the formulas, tolerances, capacitance, slew rates, etc, you find that there is no proper value of of pull-up that will actually meet all the criteria. Couple this with the 5 and 3V busses, trace lengths, conflicting documentation, variations between manufactures devices, etc. It's amazing or works at all. But is does generally work, and it is a compelling bus to use nonetheless.
So the thing is that the driver needs to be really robust, and expect things to go wrong on the bus... more so for I2C than any other basic serial communication bus. In using the MQX driver I have noticed a few things:
The interrupt driven I2C driver still relies on components from the polled I2C driver, specifically in the area of IOCTL. In the polled IOCTL code there are numerous busy polls waiting on a hardware register state change. However, I don't know that in every case the resister is guaranteed, by design or configuration, to change.
To hit one of these simply try to write to a device that is not there and flush the stream. It will get stuck here forever in i2c_pol_ki2c.c:
while ( I2C_S_BUSY_MASK == ((tmp=i2c_ptr->S) & (I2C_S_BUSY_MASK | I2C_S_TCF_MASK)))
In the driver simply search for every instance of 'while' that is coupled with the polling of a hardware register for a state change (there are seven of them in i2c_pol_ki2c.c). In every case is the register guaranteed to hit the terminal condition? My experience thus far says the answer is no.
Thank you for your feedback. It is always helpfully to receive customer’s feedback in order to improve our products. I will inform this feedback to our development team.
Have a nice day!
Update to this post: The area it was actually getting stuck in the example above was the line above it, here:
while (io_info_ptr->TX_IN != io_info_ptr->TX_OUT)
Where TX_IN was not equal to TX_OUT. Perhaps the condition was that no device was acknowledging on the bus?
I 100% agree with you about the dangerousness of these while() located in the code. I also don't see the benefit to use the interrupt driven driver if polling is done at the end for flushing or other ioctls.
When I worked on an MCF52259 I had to modify the driver to fix that; see : MCF52259 "interrupt" I2C driver enhancements . This was very easy to implement such a fully interrupt driven processing without any while() remaining, and to add support for a timeout. so I don"t understand why this has not been done in the standard MQX release.
Maybe you could adapt these changes to the Kinetis...
Yes, that's the second serious issue! The expectation is that the interrupt driven I/O driver contains no (significant) polling, and if it does it should be noted in the driver documentation. These ioctl calls should be converted to event driven in every place the hardware supports it (NOTE: feature request!).
But primarily I am most concerned about the non-terminating conditions at the driver level. This makes the driver unsuitable for deployment on any system. It's just a problem waiting to manifest.