No I2C DMA on a general purpose 32bit MCU? - Page 1
Forum section: electronics / projects

author: RoadRunner
author_rank: Frequent Contributor
timestamp: March 13, 2019, 05:46:24 pm
content: Right now I am trying to interface few sensors chips to PIC32MX. I will be transferring 20K to 30K bytes every second from sensor to CPU.Problem is, I am operating I2C in interrupt mode and there are many other tasks also running in system , which may generate interrupt at any point. This causes I2C bus to hang(SDA or SCL pulled low till I power cycle sensor).I can not disable interrupt during I2C ISR because other interrupts have higher priority.I2C controller with these PIC32MX mcu appear to be not supporting dma, I looked around same class ARM chips, there I2C controller also do not support DMA. I think i2c having many states (i.e. start ,addr, ack/nack, restart , data,ack/nack ,stop) is the reason why getting DMA working is complicated and only reserve for little higher end I2C controller. I have used many CPU from nxp LPC series , there also I2C does have DMA and I2C does not work properly until unless you set interrupt priority to highestI have looked around , few expensive chips (other than PIC32) have really smart I2C controller, which can accept commands , like read byte , write byte , start stop ack/nack and every thing else done automatically, these I2C controller seems to be supporting DMA.It would be nice if few people share there experience with I2C transmitting/receiving large amount of data. while not being highest priority task and (maybe not lone task).

author: AndyC_772
author_rank: Super Contributor
timestamp: March 13, 2019, 06:14:20 pm
content: It's not at all obvious to me that an interrupt during an I2C transfer should cause the bus to hang. There's a maximum speed, but you can run it as slow as you like, and can pause at any time.The bus will hang (stuck low) if a receiving device misses a clock edge, and the master and slave end up out of sync.Is it possible that some other ISR is accessing registers that are involved with the I2C interface?Scope the I2C bus, and capture the last few transactions before the bus hangs. What does the last successful transfer look like? What happens when it hangs?I think you have a logical problem here, which isn't inherently anything to do with interrupt priority. Nothing in an I2C master ever needs to be done immediately.

author: dmills
author_rank: Super Contributor
timestamp: March 13, 2019, 06:32:19 pm
content: I2C is **Hated** around here because it is easy to get it to mostly sort of work, and a complete bastard to get it to work really reliably.I especially like the 'stuck bus because you hit restart in the debugger at just the wrong time' one, but there are many, many ways to break it.I think you probably can get the PIC32 to do DMA to the I2C peripheral, but I am not sure you would want to, I2C being as dog slow as it is and all and DMA not being particularly good about transactions that involve significant software state machines without much messing about with chained transfers.My bet is you have something else going on.Now if anyone knows why my PIC32 DMA based SPI driver can only work with one port at a time (Yes I am using different pairs of DMA cores for each bus) I would love some ideas.Regards, Dan.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 13, 2019, 08:12:51 pm
content: On STM32's, DMA transfers are supported with I2C.

author: JPortici
author_rank: Super Contributor
timestamp: March 13, 2019, 08:24:10 pm
content: I would try to find out what the REAL problem is.I've never had an I2C bus hanging because an interrupt happened inside another interrupt, on PIC32MX or any other MCU i encountered.Anyway I also hate I2C with passion as i need a state machine inside a state machine to do even the simplest things in a non-blocking fashion, and also because bus collision.It's usually easy to recover from the condition, but then your software has to be much more complicated to support resuming/retry operation

author: bson
author_rank: Unknown
timestamp: March 13, 2019, 09:10:31 pm
content: It's easy to imagine I2C doesn't have hard timing requirements, but it actually does. Sometimes you need to indicate a NAK or STOP during the last byte - not after, not before, but during. Sometimes before the previous is finished. Sometimes between bytes; depends on the controller. It can be very sensitive and if you get an interrupt at the wrong moment it's easy for the last byte in a read sequence for example not to be NAKed; it ends up ACKed and the device expects you to keep reading.It's special requirements like this that makes it impractical for I2C controllers to have FIFOs similar to UARTs, or to be DMA driven. You'd still need a lot of special handling of things like the last byte or two to make it work properly.

author: RoadRunner
author_rank: Frequent Contributor
timestamp: March 13, 2019, 10:00:00 pm
content: All of the suggestion are quite useful, thanks everybody for there time, as pointed out by Honorable member , There must have been a fault condition occurred on bus, and if i found out what is it and how to prevent it from happening and clear it , every thing should be up and running once again. But i do not know why i am not getting right feeling about it , because USB interrupts will at minimum occur at every 1ms.Just to add more information to the post here the screenshot, Ch1 and Ch2 are I2C , and CH3 pointing to USB interrupt(Having Higher priority than I2C),Edit: Actually you can trigger DMA on I2C Interrupt, i am looking into this how useful this is, to minimize overheads .Reagrds

author: AndyC_772
author_rank: Super Contributor
timestamp: March 13, 2019, 10:51:08 pm
content: Looks like the last thing to happen on your I2C bus is a repeated start condition (SDA high to low while SCL is high), followed by SCL being driven low. These are the first two events which happen immediately prior to the slave address being transmitted, and they're normal. It's completely OK, as far as the slaves are concerned, to stop the bus indefinitely in this state.The CPU is driving the bus low at this point, so all it needs to do once it's finished processing the other interrupt, is carry on.Maybe there's a driver problem here. What exactly happens when the repeated start condition is completed? Does the driver expect to be told what byte to transmit after the repeated start has begun, but before it completes? That would certainly introduce a timing constraint which is entirely unnecessary, and would cause the system to fail if an interrupt is triggered just after the repeated start condition is initiated.

author: RoadRunner
author_rank: Frequent Contributor
timestamp: March 13, 2019, 11:51:11 pm
content: Actually problem is, While USB ISR is executing , I2C interrupt seems to getting completely ignored, they do not set an interrupt flag to get later processed.

author: AndyC_772
author_rank: Super Contributor
timestamp: March 14, 2019, 08:49:43 am
content: Could the USB ISR be clearing multiple interrupt flags rather than just its own?I find it hard to believe that an interrupt would simply not be generated, just because the CPU is executing an ISR at the time. I can, however, believe that a USB stack might contain a bug which results in other interrupt flags being cleared.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: March 14, 2019, 09:48:31 am
content: With a hardware i2C peripheral it shouldn't be possible for problems to be caused by poor latency.To get to the bottom of this, it is helpful to put markers on all other ISRs to set a pin while active ( or output fast UART data) so you can tell exactly what is happenning when on the scope.ideally have a pin per ISR stay high for the duration of the ISR to see when interrupts overlap.

author: Ice-Tea
author_rank: Super Contributor
timestamp: March 14, 2019, 09:56:06 am
content: Just a thought.. 20-30kB of data on a 400kH I²C bus seems a bit like a stretch?

author: Siwastaja
author_rank: Super Contributor
timestamp: March 14, 2019, 10:02:57 am
content: Quote from: SiliconWizard on March 13, 2019, 08:12:51 pmOn many (especially older) STM32's, it's not very useful, even though there is a "supported" tick in a box. You still need an interrupt-driven state machine to control it, and turn on the DMA transfer at a correct time, and can only DMA part of the transfer.Some newer controllers can do a full DMA cycle with just a single, initial configuration (per transfer), but it is not always obvious whether the controller is capable of this or not. "Supports DMA" claim doesn't suffice, I'm afraid.But as others have pointed out, the lack of DMA isn't the actual problem OP is having.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: March 14, 2019, 11:30:18 am
content: Quote from: AndyC_772 on March 14, 2019, 08:49:43 amMake sure you are using the hardware atomic bit ops, i.e. IFSxCLR=1<<_IFSx_xxx_MASK , NOT IFSxbits.xxx=0Also make sure you are clearing the IF bit at the start of the ISR, in case it gets set again by hardware before the ISR has ended due to other ints. if you clear at the end, you may clear an int that should have been serviced.

author: RoadRunner
author_rank: Frequent Contributor
timestamp: March 14, 2019, 03:29:18 pm
content: Quote from: Siwastaja on March 14, 2019, 10:02:57 amSimilar problem is with PIC32 as well , you can certainly trigger DMA on I2C interrupt , but I2C interrupt is genrated on24.4.2.1 MASTER INTERRUPTS Master mode operations that generate a master interrupt are:Start Condition – 1 BRG time after falling edge of SDAxRepeated Start Sequence – 1 BRG time after falling edge of SDAxStop Condition – 1 BRG time after the rising edge of SDAxData transfer byte received – 8th falling edge of SCLx (after receiving eight bits of data from slave)During send ACK sequence – 9th falling edge of SCLx (after sending ACK or NACK to slave)Data transfer byte transmitted – 9th falling edge of SCLx (regardless of receiving ACK from slave)During a slave-detected Stop – When slave sets the P bit (I2CxSTAT<4>)if any of these Condition occur, DMA will be triggered which make no sens. you can not mask individual trigger source, which make DMA not very useful for I2C,Quote from: mikeselectricstuff on March 14, 2019, 11:30:18 amThank you for suggestion i will look into this now , and report back the results.One more question stucked in my head , what is the point of using I2C in interrupt mode? while device attached on i2c is normally do not have really urgent handling requirements and I2C gives out multiple interrupts even for one byte transfer. if we let I2C running is polling, we will save time wasted in context switching and jumping to and from ISR.Is there a advantage of I2C in interrupt mode vs Polling?

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: March 14, 2019, 04:04:42 pm
content: Quote from: RoadRunner on March 14, 2019, 03:29:18 pmI2C is fairly slow, so you may not want to wait around for transactions.

author: RoadRunner
author_rank: Frequent Contributor
timestamp: March 14, 2019, 04:11:04 pm
content: Quote from: mikeselectricstuff on March 14, 2019, 04:04:42 pmWith Polling i am actually thinking about preidically (in idle loop, or even better wtih limited maximum polling rate ) checking for status and acting on it, program flow will just return if nothing need to done, flow will not wait there to finish i2c things.will intrrupt still holds any adantage over such polling driver?

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: March 14, 2019, 05:03:04 pm
content: Quote from: RoadRunner on March 14, 2019, 04:11:04 pmNot much, as long as the i2C hardware makes no assumptions about service time. Don't know if this is the case for the PIC32MX peripheral.What is annoying is most MCU I2C peripherals implement all the bells and whistles of I2C that hardly anyone uses, like clock-stretching and multimaster. it wouldn't take much extra logic to implement something that's much easier to use for the vast majority of use cases which are to just read or write a bunch of bytes from a device.

author: Ice-Tea
author_rank: Super Contributor
timestamp: March 14, 2019, 05:39:24 pm
content: I actually had device clock-stretch a few weeks ago. So it *does* happen

author: RoadRunner
author_rank: Frequent Contributor
timestamp: March 14, 2019, 11:57:45 pm
content: Quote from: mikeselectricstuff on March 14, 2019, 11:30:18 amI was already using IFSxCLR to clear USB interrupts.Just now Problem is solved. Now i cleared USB interrupt flag after serving USB ISR Task. previously USB flag was cleared before serving the ISR task, and I2C interrupt appears while USB interrupt flag was already cleared but ISR was still executing.What could be causing this, i will read up. if someone already know answer please share your view.

author: mikerj
author_rank: Super Contributor
timestamp: March 15, 2019, 01:17:18 pm
content: Quote from: dmills on March 13, 2019, 06:32:19 pmSame here, we would always choose an SPI peripheral over I2C unless there is no other choice and we've all suffered from I2C related headaches.Worst was a optical dispersion compensating DSP device with built in I2C master that bootloaded it's code from a serial EEPROM. A reset or loss of clock at the wrong time (outside of our control) would leave the bus locked up since the DSP master had no stuck bus detection/release. Ended up wiring SDA/SCL to a couple of spare pins on our own micro so we could bit bash enough clock cycles to release the bus.