MKV58F1M0xxx24 i2c + edma

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

MKV58F1M0xxx24 i2c + edma

14,843 Views
sgmamike
Contributor I

Hi nxp. First time poster here. 

I have successfully used the fsl_i2c module to do blocking calls to I2C reads. 

That is all working. 

I would like to iterate on this to get EDMA working. 

I did not see any examples with EDMA + I2C. 

FWIW, EDMA + SPI is working nicely and I was hoping I2C would be just as easy. 

Here is the code I'm using.

I based it on the API docs in the Kinetis SDK 2.0 manual, and my functioning EDMA SPI example. 

The failure mode is that the I2C_MasterUserCallbackis not firing. 

// I2C init

i2c_master_config_t masterConfig;
I2C_MasterGetDefaultConfig(&masterConfig);
masterConfig.enableHighDrive = 0;
I2C_MasterInit(I2C0, &masterConfig, CLOCK_GetFreq(I2C0_CLK_SRC));

// EDMA init

uint32_t i2cChannel == 19U;
edma_config_t userConfig;

NVIC_SetPriority(DMA3_DMA19_IRQn, DMA0_INTERRUPT_PRIORITY);

DMAMUX_Init(DMAMUX);
DMAMUX_SetSource(DMAMUX, i2cChannel, kDmaRequestMux0I2C0);
DMAMUX_EnableChannel(DMAMUX, i2cChannel);

EDMA_GetDefaultConfig(&userConfig);
EDMA_Init(DMA0, &userConfig);

// Clear handles. Is an intermediary handle needed.
memset(&(i2cEdmaHandle), 0, sizeof(i2cEdmaHandle));
EDMA_CreateHandle(&(i2cEdmaHandle), DMA0, i2cChannel);

I2C_MasterCreateEDMAHandle(I2C0, &i2c_edma_m_handle, I2C_MasterUserCallback, NULL, &i2cEdmaHandle);

// transfer init

masterXfer.slaveAddress = 0x48;
masterXfer.direction = kI2C_Read;
masterXfer.subaddress = 0;
masterXfer.subaddressSize = 1;
masterXfer.data = masterRxData;
masterXfer.dataSize = 2;
masterXfer.flags = kI2C_TransferDefaultFlag;

// in my main loop, requesting data from I2C0

status = I2C_MasterTransferEDMA(I2C0, &i2c_edma_m_handle, &masterXfer);
if ((status != kStatus_Success) && (status != kStatus_DSPI_Busy))
{
   I2C_MasterTransferAbortEDMA(I2C0, &i2c_edma_m_handle);
   // do things to handle fault

}

// blocking wait for the callback to fire

// callback definition 

static void I2C_MasterUserCallback(I2C_Type *base, i2c_master_edma_handle_t *handle, status_t status, void *userData)
{
   if (status == kStatus_Success) {

     // do stuff with results
   }

}

0 Kudos
6 Replies

2,429 Views
chris_brown
NXP Employee
NXP Employee

Hi Mike,

So the callback is not being called, but do you see I2C traffic on the bus (physically see it on a scope or logic analyzer)?

~Chris 

0 Kudos

2,429 Views
sgmamike
Contributor I

Thanks Chris!

The transaction on the wire (with DMA) does not look good to say the least. 

Both clk and data are held low after, and it seems as if the data length is short by one byte. 

i2cDMAPNG.PNG

This is the non DMA capture

i2cNoDMAPNG.PNG

My guess is that I need to better define the transfer. 

I'll give that a shot. 

0 Kudos

2,429 Views
sgmamike
Contributor I

I decided to change the non-DMA approach to use the same transfer objects that I defined above. 

I wanted to verify that my masterXfer is defined properly. 

OLD CODE : 

I2C_MasterStart(I2C0, slave_addr, kI2C_Read);
while(!((status = I2C_MasterGetStatusFlags(I2C0)) & kI2C_IntPendingFlag));
result = I2C_MasterReadBlocking(I2C0, masterRxData, 2);
I2C_MasterStop(I2C0);

NEW CODE: 
result = I2C_MasterTransferBlocking(I2C0, &masterXfer);

The new code works without DMA, which should validate that my masterXfer is set up properly

masterXfer.slaveAddress = 0x48;
masterXfer.direction = kI2C_Read;
masterXfer.subaddress = 0;
masterXfer.subaddressSize = 0;
masterXfer.data = masterRxData;
masterXfer.dataSize = 2;
masterXfer.flags = kI2C_TransferDefaultFlag;

I get the same failure mode when using DMA. 

  • After the first of 2 data bytes from the slave, both clock and data are held low and the master does not seem to be clocking the slave or ending the transaction.
  • It is almost as if the EDMA API is ignoring my dataSize.
    • Even if I tweak subaddressSize to 1,
      • I can see they insert a write command for subaddress zero on the wire.
      • I see 2 more bytes as expected
    • When I change dataSize to 2 or 3 or 4,
      • I always get the waveform with just 2 bytes, then clock and data are held low.
      • I do not see anymore than the first byte from the slave. 
0 Kudos

2,429 Views
sgmamike
Contributor I

Changing DMA channel from 19 to 3 seems to have fixed my problem.

It looks like I was using the wrong mux group. 

oops. 

Thanks!

0 Kudos

2,429 Views
chris_brown
NXP Employee
NXP Employee

Hi Mike,

Ah!  Glad to hear it is resolved.  :smileyhappy:

Regards,

Chris 

0 Kudos

2,429 Views
sgmamike
Contributor I

BTW - the return value for I2C_MasterTransferEDMA is 0x00

0 Kudos