Possible bug in the MQX i2c Slave-mode driver code

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

Possible bug in the MQX i2c Slave-mode driver code

Jump to solution
3,290 Views
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 Kudos
Reply
1 Solution
2,390 Views
intevac_coder
Contributor III

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

 

I2C slave polled

View solution in original post

0 Kudos
Reply
7 Replies
2,390 Views
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 Kudos
Reply
2,391 Views
intevac_coder
Contributor III

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

 

I2C slave polled

0 Kudos
Reply
2,390 Views
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 Kudos
Reply
2,390 Views
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 Kudos
Reply
2,390 Views
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 Kudos
Reply
2,390 Views
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 Kudos
Reply
2,390 Views
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 Kudos
Reply