I2C CMSIS abort slave transfer

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

I2C CMSIS abort slave transfer

1,965 Views
ville_ojaniemi
Contributor I

Hi,

I'm having an issue when trying to use the kinetis SDK(2.6) CMSIS I2C in multimaster mode.

The problem is that I can't cancel slave receive to start sending data in master mode.

So what I try to do is that my device is in slave mode waiting for incoming data and occasionally it changes to master mode to transmit data to other device, and then goes back to slave mode listening.

I can enter slave mode just fine with

Driver_I2C3.SlaveReceive(rx_buffer,rx_buffer_size);

But when I want to send data, I need to stop the slave receive first. I found that the CMISIS interface has an option to stop transfer, so I tried that:

Driver_I2C3.Control(ARM_I2C_ABORT_TRANSFER,0);

BUT, in the source code for the abort transfer there is the following code:

case ARM_I2C_ABORT_TRANSFER:
            if (!i2c->resource->base->A1)
            {
                /* Disable master interrupt and send STOP signal */
                I2C_MasterTransferAbort(i2c->resource->base, &(i2c->handle->master_handle));


                i2c->handle->master_handle.transferSize      = 0;
                i2c->handle->master_handle.transfer.data     = NULL;
                i2c->handle->master_handle.transfer.dataSize = 0;
            }
            /* If slave receive */
            else if (!(i2c->resource->base->S & kI2C_TransferDirectionFlag))
            {
                i2c->resource->base->C1 |= I2C_C1_TXAK_MASK;


                while (i2c->handle->slave_handle.isBusy)
                {
                }
                /* Disable slave interrupt */


                I2C_SlaveTransferAbort(i2c->resource->base, &(i2c->handle->slave_handle));


                i2c->handle->slave_handle.transfer.data     = NULL;
                i2c->handle->slave_handle.transfer.dataSize = 0;
            }
            return ARM_DRIVER_OK;

The code gets stuck in the while loop:

while (i2c->handle->slave_handle.isBusy)
{
}

If you have suggestions on how to move forward, or a different way of achieving multimaster, or examples or anything I'd greatly appriciete them!

Labels (1)
0 Kudos
4 Replies

1,698 Views
tomahola
Contributor II

I'm having this same issue with the same processor.  In my case the K66 processor is only Master with one slave on the bus.  After I2C is initialized it will be in a busy state so I need to do ARM_I2C_ABORT_TRANSFER.  This seems always to succeed.  However, sometimes (about 10% probability) the MasterReceive() will fail and leave the I2C in a busy state.  I can recover from this by giving the ARM_I2C_ABORT_TRANSFER but sometimes that will get stuck into the infinite loop.

I find it very strange that ARM_I2C_ABORT_TRANSFER can get stuck in an infinite loop.  I would expect it would give immediately the stop condition on the bus and set the I2C hardware in an idle state.

0 Kudos

1,775 Views
ville_ojaniemi
Contributor I

Oh sorry, I thought I mentioned, but it seems I didn't. I'm using MK66FN2M0VMD18

0 Kudos

1,775 Views
Alexis_A
NXP TechSupport
NXP TechSupport

Hello asd,

 

Looking in to the driver I found that the device is put in busy and doesn't left this state until a transmission is received so you will need to notify the slave that the actual master will leave the arbitration of the bus. Also you will need to take in count the following note in the reference manual:

 pastedImage_1.png

 

So if you change to master in one of this cycles you will lose the arbitration again and change to slave, so I think that a notification system will be required in other to change the arbitration between masters.

 

Let me know if this helps you.

 

Best Regards,

Alexis Andalon

0 Kudos

1,775 Views
Alexis_A
NXP TechSupport
NXP TechSupport

Hi,

Could you let me know which kinetis device are you using?

Best Regards,

Alexis Andalon

0 Kudos