AnsweredAssumed Answered

I2C DMA driver problem

Question asked by Cristiano Rodrigues on Apr 9, 2019
Latest reply on Apr 24, 2019 by Cristiano Rodrigues

Hello!

 

I made a FreeRTOS I2C DMA implementation (based on the SDK i2c DMA driver example) and it is running fine. But...

...But I found a problem that I think is worth being reviewed.

 

While sending data (in my case:  start + 1 slave address byte+ 1subaddress byte  + 1 data byte), "I2C_RunDMATransfer" function is called more than one time and almost simultaneously  "I2C_RunTransferStateMachineDMA" is also called by the IRQ ("I2C_MasterTransferDMAHandleIRQ"). It happens that both functions can change the "remainingBytesDMA" variable. So, when "I2C_RunDMATransfer" is called, the "remainingBytesDMA" is 1 and before "I2C_RunDMATransfer" ends the "remainingBytesDMA" variable is changed to 0, then in the end of "I2C_RunDMATransfer" that operation "handle->remainingBytesDMA -= transfer_size;" is made and the "remainingBytesDMA" goes from 0 to a very big number and later "DMA_PrepareTransfer" asserts in "(xfer_count <= DMA_MAX_TRANSFER_COUNT) && (0 == transferBytes % byteWidth)"

 

As a workaround I made the following change in "I2C_RunDMATransfer":

changed this
DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
DMA_StartTransfer(handle->dmaHandle);
handle->remainingBytesDMA -= transfer_size;
handle->buf += transfer_size;   


to that
DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
DMA_StartTransfer(handle->dmaHandle);
if(handle->remainingBytesDMA >= transfer_size)
{
        handle->remainingBytesDMA -= transfer_size;
}
else
{
        handle->remainingBytesDMA = 0;
}
handle->buf += transfer_size;

 

In the attached file I have the FreeRTOS inplementation, if you need it.

 

Outcomes