cancel
Showing results for 
Search instead for 
Did you mean: 

Missing DMA interrupt after I2C transmit

saccrue
Associate II
Posted on November 15, 2012 at 02:02

I am working on an i2c driver that utilizes DMA for the master transmits.

Everything seems to be set fine because I get hundreds of successful transactions but every once in a while, I issue a transaction but never get the DMA interrupt. I have both interrupts set for success and error and I get the success interrupt after just about every transaction.

Every once in a while, I miss the interrupt. I put some counters in the event handler to make sure that I get the expected interrupts and I do, but I never get an error interrupt and I miss that one success.

It seems to be only on the larger transfers, 268 bytes. The smaller ones all succeed and most of the 268 bytes ones succeed but I would say that once every 30 seconds of flooding the bus with transactions, the DMA doesn't interrupt.

The priority of the DMA is set to 2.

Can anyone shed some light on what may be going on?
10 REPLIES 10
Posted on November 15, 2012 at 12:35

Sounds a bit like a flash device.

So are you not seeing a DMA TC interrupt? How are you recovering from that? Is there any indication from the DMA controller that the address/count end up where they should? Or is there and error/bus condition reported by the DMA, or I2C ACK failure or something?

If a flash device, is there any commonality in the addresses at which this failure is noted.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
saccrue
Associate II
Posted on November 15, 2012 at 16:20

I am not accessing a flash, i'm writing to another controller, which just drops the data when it receives it.

Correct, no TC interrupt.

The thing that bothers  me is that I don't see a TE interrupt either. Checking the DMA register, it shows a remaining byte count, which is not the same value from test case to test case.

I turned off all other tx requests except for the 268 byte ones and the hardware has been running fine since. So, it appears that multiple writes are causing the issue.

If I have a buffer with data in it and the DMA is ongoing, and someone writes to that buffer again, would that cause the DMA to stop and not generate an error interrupt?

Thanks for your time.

Posted on November 16, 2012 at 07:45

> I turned off all other tx requests except for the 268 byte ones

> and the hardware has been running fine since.

> If I have a buffer with data in it and the DMA is ongoing, and someone writes to that

> buffer again, would that cause the DMA to stop and not generate an error interrupt?

Writing to memory being read from DMA shoudln't cause any error (unless some heavy silicon bug, but I doubt that). OTOH, writing to DMA registers while a transfer is in progress, could quite well cause various ''funny'' effects.

How exactly are you performing ''tx requests''? Any code to show?

JW
saccrue
Associate II
Posted on November 16, 2012 at 14:59

I didn't think the writing to the memory buffer would cause an issue, however, copying the data to a temp buffer and setting the DMA to pull from that buffer seemed to solve the issue at first, but, I saw it hang again this morning.

I can't post code, unfortunately, but, a tx request consists of the following:

  • Obtaining a semaphore

  • Setting the Start condition

  • Setting up the DMA in the

    I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED

    IRQ and disabling the i2c I2C_IT_EVT interrupts.

  • DMA IRQ enables i2c I2C_IT_EVT interrupts so we can get the event interrupts again.

  • Release the semaphore after setting the stop bit in the

    I2C_EVENT_MASTER_BYTE_TRANSMITTED

    IRQ

This will run for hours and hours (10+) sending buffer after buffer. When I do get the failure, what I see is the DMA IRQ never fires because it stops with bytes left. Here are the registers:

DMA_CCR6

    EN = 1

    TCIE = 1

    HTIE = 0

    TEIE = 0

    DIR = 0

    CIRC = 0

    PINC = 0

    MINC = 0

    PSIZE = 0

    PL = 2

    MEM2MEM = 0

DMA_CNDTR6

    NDT = 0x010C

DMA_CPAR6

    0x40005410

DMA_CMAR6

    0x2000155C

What happens from here is I sit in a loop trying to get the semaphore which fails.

Any help figuring out what may stop the DMA with no error interrupt would be appreciated. I did have the error interrupt enabled (I don't in this register dump), but it never fired.

Thanks for your time.

From: waclawek.jan

Posted: Friday, November 16, 2012 7:45 AM

Subject: Missing DMA interrupt after I2C transmit

> I turned off all other tx requests except for the 268 byte ones

> and the hardware has been running fine since.

> If I have a buffer with data in it and the DMA is ongoing, and someone writes to that

> buffer again, would that cause the DMA to stop and not generate an error interrupt?

Writing to memory being read from DMA shoudln't cause any error (unless some heavy silicon bug, but I doubt that). OTOH, writing to DMA registers while a transfer is in progress, could quite well cause various ''funny'' effects.

How exactly are you performing ''tx requests''? Any code to show?

JW
jpeacock2399
Associate II
Posted on November 16, 2012 at 16:00

Are you sure your target device is accepting data?  From the decription it sounds like you are not getting an ACK after sending a data byte.  The I2C logic will stall and your DMA will never complete.  The problem may well be in your peripheral and not the STM32 I2C.

To debug this you may have to run without DMA.  That way you can check the BTF flag after every transmit.

  Jack Peacock
saccrue
Associate II
Posted on November 16, 2012 at 16:26

I have a high level of confidence in the target peripheral because it has been in service for a long time and is designed as a test interface which does nothing but drop the data when it receives it, but, I will check just to make sure.

Thanks.

saccrue
Associate II
Posted on November 16, 2012 at 19:34

If the data byte is nack'd by the target peripheral, and the DMA stalls, what should happen? Shouldn't the i2c hardware retry? Or, do we catch that ack failure and cancel the DMA and idle the i2c?

Edit: I did notice an occasional I2C_IT_AF interrupt. It appears that the DMA completed on both cases. The handler for the AF on the address does a restart and the handler for the AF on data generates a stop condition. Both recover fine, no bytes remaining in the DMA and the transactions continue normally.

Posted on November 19, 2012 at 09:58

> I can't post code, unfortunately, but, a tx request consists of the following:

The first thing to do wh

en searching for

roots of some problem is to

cut down the code to absolute m

inimum exhibiting the problem, or to write a minimal test program. You surely cou

ld then post that.

I

don't say it's always possible, but usually is and helps you to understand the nature of problem, too. Often

, while constructing

/testing minimal code

,

the ca

use of problem is found

by the original aut

hor of question.

> Here are the registers:

What device?

>

    TEIE = 0

Why?

>    DIR = 0

Why?

>

 MINC = 0

Why?

JW
saccrue
Associate II
Posted on November 19, 2012 at 15:44

Hi Jan,

Thanks for the reply. You are correct about stripping down the code. I'm not the original author so a good portion of my time has been spent understanding the top to bottom flow that the I2C and DMA are a small part of. But, you raise some very interesting questions. The original author never implemented a DMA error handler so I have since put on in, but, I don't hit the breakpoint when my transfer fails.

What is interesting is why the DIR and MINC bits seem to be set wrong. On the TX, I would expect the DIR bit to indicate a memory to peripheral direction and the MINC bit should be set and the PINC bit should be clear. Seems to me that if the MINC is cleared, then it would make sense that the DMA would stop mid transfer and we would not see an error. I checked the code and it does set these to the correct values when the DMA is setup, and, the setup code is semaphore protected.

I think this is a very good place to stare at for a while.

Thanks Jan!