KL17 I²C slave receiver with DMA - last byte read twice

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

KL17 I²C slave receiver with DMA - last byte read twice

1,171 Views
sergegadeyne
Contributor I

Hello,

I'm working on a Kinetis KL17 microcontroller with KDS 3.2.0 and Kinetis SDK 2.0.

I would like to offload reception of I²C data to DMA for improved performance.

The initialization code looks as follows:

DMAMUX_Init(DMAMUX0);
DMAMUX_SetSource(DMAMUX0, 0, (uint8_t)kDmaRequestMux0I2C0);
DMAMUX_EnableChannel(DMAMUX0, 0);

DMA_Init(DMA0);
DMA_CreateHandle(dma_handle, DMA0, 0);
DMA_SetCallback(dma_handle, dma_cb, ctx);

I2C_SlaveGetDefaultConfig(&slave_config);
slave_config.slaveAddress = BOARD_I2C_SLAVE_ADDR;
I2C_SlaveInit(I2C0, &slave_config);

DMA_CreateHandle(dma_handle, DMA0, 0);
DMA_SetCallback(dma_handle, dma_cb, ctx);

I2C_SlaveTransferCreateHandle(I2C0, i2c_handle, i2c_slave_cb, ctx);
I2C_SlaveTransferNonBlocking(I2C0, i2c_handle, kI2C_SlaveAllEvents);

The DMA is configured in the registered I²C callback function (called by I2C_SlaveTransferHandleIRQ() from interrupt context - when the received address matches the slave address).

The length of the received data is unknown beforehand, so a large enough buffer is allocated (32 bytes in this example).

The DMA transfer is aborted when the stop condition is detected.

static void i2c_slave_cb(I2C_Type *base, i2c_slave_transfer_t *xfer, void *data)
{
   ...
   switch (xfer->event) {
   ...
   case kI2C_SlaveAddressMatchEvent:
      DMA_PrepareTransfer(&transfer_config,
                          &I2C0->D, sizeof(I2C0->D),
                           ctx->buf, sizeof(*ctx->buf),
                           ctx->len, kDMA_PeripheralToMemory);
      DMA_SubmitTransfer(&ctx->dma_handle, &transfer_config,
                          kDMA_EnableInterrupt);
      DMA_StartTransfer(&ctx->dma_handle);
      I2C_EnableDMA(I2C0, true);
      break;
   ...
   case kI2C_SlaveCompletionEvent:
      I2C_EnableDMA(I2C0, false);
      DMA_AbortTransfer(&ctx->dma_handle);
      break;
   ...
}

As is visible in the first attachment, the length of the received data is 5 bytes in this example.

When the data is printed on LPUART0 in the application the last byte seems to be duplicated (second attachment).

Investigation of the DMA BCR register shows that the initial value of 0x20 (32 bytes) is decremented to 0x1a (26 bytes).

This seems to indicate that the DMA got 6 requests to transfer a byte to the destination memory.

It's unclear to me how this behaviour is triggered. Did I misconfigure the DMA/I²C modules? Something else?

Kind regards,

Serge

Labels (1)
0 Kudos
2 Replies

1,006 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Serge,

I am sorry for the delay, have you solved your issue?

BR

Xiangjun Rong

0 Kudos

1,006 Views
sergegadeyne
Contributor I

Hello Xiangjun,

I have not yet resolved the issue at hand.

Kind regards,

Serge

0 Kudos