cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F41x I2C/DMA Issue

kenny
Associate II
Posted on January 06, 2014 at 23:24

Hi Everyone,

I have written a DMA-based I2C driver that has been tested and is working reliably for normal healthy reads and writes. I get in to trouble if I try to write to a slave that does not ACK its address. In this case I want to log the error and continue on to the next transactions in my series.

In my test case I write a byte to a mux successfully then I try the following:

  • Attempt to write a single byte to a slave that does not exist.
  • The failing ACK of the slave address generates an I2C error interrupt.
  • Begin I2C ER IRQ
  • Clear the I2C error flags.
  • Disable DMA stream and clear its transfer flags.
  • Software reset the I2C peripheral and reconfigure it.
  • Configure DMA to write the single byte and enable the stream.
  • Request START by writing the appropriate bit in CR.
  • End I2C ER IRQ
  • I2C *event* handler clears the START condition and sets DMAEN.
  • The DMA write complete IRQ occurs.

This last action is the surprise to me. I2C DMA is only for the data portion. I haven't yet cleared the ADDR condition and the DMA is complete? That byte shouldn't be transferred until I2C makes a request to the DMA controller during the data phase.

As far as I can tell the initial conditions for single byte writes is the same. At least the DMA and I2C peripherals are configured identically.

Another bit of information is that DMA reads will work after the failing slave address NACK.

Anyone have a theory? 
1 REPLY 1
chen
Associate II
Posted on January 07, 2014 at 12:20

Hi

It appears to me that your code is doing exactly what you told it to do?!?

''In my test case I write a byte to a mux successfully then I try the following:

  • Attempt to write a single byte to a slave that does not exist.
  • The failing ACK of the slave address generates an I2C error interrupt.
  • Begin I2C ER IRQ
  • Clear the I2C error flags.
  • Disable DMA stream and clear its transfer flags.
  • Software reset the I2C peripheral and reconfigure it.
  • Configure DMA to write the single byte and enable the stream.

  • Request START by writing the appropriate bit in CR

    .
  • End I2C ER IRQ
  • I2C *event* handler clears the START condition and sets DMAEN.
  • The DMA write complete IRQ occurs.
This last action is the surprise to me''

Perhaps ''I want to log the error'' - you should just have an error flag.

Clear the error flag whenever you start an I2C message.

The I2C error interrupt should set the flag.

I fully admit I have no experience with DMA and I2C but from your desription - your code does what it says on the tin!