Possible bug in the MQX i2c Slave-mode driver code

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

Possible bug in the MQX i2c Slave-mode driver code

跳至解决方案
3,309 次查看
gomer
Contributor I

I have been trying to get a slave-mode i2c driver working in MQX, running on an MCF52259.  During the process, I encountered what I think is a bug.

 

I am using MQX v3.6.0, but I've verified this bug still exists in the latest v3.6.2 code.  The offending code is on line 600-ish of the 'i2c_int_mcf52xx.c' module:

 

 /* Receive requested */
if (((I2C_STATE_RECEIVE == io_info_ptr->STATE) || (I2C_STATE_ADDRESSED_AS_SLAVE_RX == io_info_ptr->STATE)) && (0 != io_info_ptr->RX_REQUEST))
{
    // find! WAM -- bug: assign RX_IN + 1, NOT post increment, or else we always fall into
    //                   the "tmp == io_info_ptr->RX_OUT" conditional and disable INTs.
    tmp = io_info_ptr->RX_IN + 1;
    //tmp = io_info_ptr->RX_IN++;
    if (tmp >= io_info_ptr->INIT.RX_BUFFER_SIZE) tmp = 0;
    if (tmp == io_info_ptr->RX_OUT)
    {
        i2c_ptr->I2CR &= (~ MCF52XX_I2C_I2CR_IIEN);
    }
    else


          .....

          .....


You can see the (original) line of code I commented out above, and replaced with the line in red.  That modification actually came directly from the same algorithm in the master-mode code block higher up in the file.

 

I'm not sure if this forum is the most appropriate place to post bugs or not, but at least it may help the next person trying to use this driver in slave-mode.

 

Once I made that change, the driver began to accept characters from the master as expected.

 

Thanks,

Gomer

 

0 项奖励
回复
1 解答
2,409 次查看
intevac_coder
Contributor III

I did fix the polling slave I2C  bug.  You can see the fix and examples here:

 

I2C slave polled

在原帖中查看解决方案

0 项奖励
回复
7 回复数
2,409 次查看
intevac_coder
Contributor III

I've found a bug in the i2c_pol_ki2c.c file as well.  The problem is similar - the counter i is decremented after receiving the address.  This causes the function to look for one more byte to receive than it should.

0 项奖励
回复
2,410 次查看
intevac_coder
Contributor III

I did fix the polling slave I2C  bug.  You can see the fix and examples here:

 

I2C slave polled

0 项奖励
回复
2,409 次查看
gomer
Contributor I

Found another bug in the ic2 slave-mode code.  In the same module, line 622-ish:

 

else
{
    i2c_ptr->I2SR &= (~ MCF52XX_I2C_I2SR_IIF);
    io_info_ptr->RX_REQUEST--;
    // find! WAM -- bug: slave-mode driver does not NAK read requests... this does not

    //                   belong here.  Maybe CnP from Master-mode block above?
    //if (1 == io_info_ptr->RX_REQUEST)
    //{
    //   i2c_ptr->I2CR |= MCF52XX_I2C_I2CR_TXAK;
    //}

    io_info_ptr->ONTHEWAY = TRUE;
    io_info_ptr->RX_BUFFER[io_info_ptr->RX_IN] = i2c_ptr->I2DR;   // receive data
    io_info_ptr->RX_IN = tmp;
    io_info_ptr->STATISTICS.RX_PACKETS++;
}

0 项奖励
回复
2,409 次查看
intevac_coder
Contributor III

I am getting a strange interaction with the I2C slave under MQX 3.7 with the Kinetis processor as well.  When I want to receive 2 bytes as a slave, the master has to transmit 3.  If I need 4 bytes, the master must send 5.  The last byte is junk and is always discarded.  If the extra byte isn't transmitted by the master to the slave, the byte reception loses synchronization.  Is there a simliar bug in the K40 code as the bug described above that would cause this?

0 项奖励
回复
2,409 次查看
PetrM
Senior Contributor I

Hello,

 

the first one is a bug, thank you for reporting that here. The fix will be available in the next MQX release.

 

The second one - the original code is correct. Regardless of operating mode (master/slave), the I2C receiver must generate proper ACK/NACK to signal the transmitter whether to continue or to stop transfer. The condition here checks and issues NACK for the last byte to be received by slave (must be set one byte before).

 

Regards,

PetrM

 

0 项奖励
回复
2,409 次查看
gomer
Contributor I

Hmmm... I'm not an i2c expert, but I do work with experts.  And in all my experience and knowledge (and the EE on the team confirms this), if the slave device NAKs a byte transmitted by the Master, the Master treats that as an error and stops transmitting.

 

That's indeed exactly what was happening too, until I removed that portion of code.

 

I think we might be confusing a Master *read* operation from a Slave with a Master *transmit* operation to a Slave.  The latter is the case in that 2nd bug report.  That code snippet comes from the portion of code which is recieving data from the Master.  So for it to NAK (or 'not acknowledge') any byte along the way would imply an error back to the master.

 

For what it's worth, I've attached a file with the entire body of the Slave portion of this driver code, as I've augmented it to get it working.  Until I made all the changes outlined as you see in that file (marked with 'find! WAM'), this driver simply would not work for us. There are a few more potential bugs or enhancements in there, in addition to what I've listed already.

 

Again... I'm no expert, I just know what worked, and I was using a Tektronix MSO 1404 scope to capture and decode the addr/data on the bus the whole time to verify transitions and timing.

 

Thanks!

Gomer

0 项奖励
回复
2,409 次查看
Potatoswatter
Contributor I

Quoting section 15.5.1.3 of the Freescale MC9S08MP16 manual,

If the slave receiver does not acknowledge the master in the 9th bit time, the SDA line must be left high by the slave. The master interprets the failed acknowledge as an unsuccessful data transfer.


If the master receiver does not acknowledge the slave transmitter after a data byte transmission, the slave interprets this as an end of data transfer and releases the SDA line.

So, for interoperability with other Freescale products, slave mode should always acknowledge receipt.

0 项奖励
回复