Go Down

Topic: I2C DMA (Read 254 times) previous topic - next topic

biccius

Mar 21, 2019, 06:52 pm Last Edit: Mar 21, 2019, 06:54 pm by biccius
Hi everyone

I'm trying to reduce the cycle time of an application running on SAM3X8E. Currently everything is very tight: total time cycle <1ms

The only real bottleneck remains an I2C reading that I'm currently doing with Wire.h at 400Khz successfully.

Are there libraries or examples of use of I2C with DMA?

I searched around (for example here: http://forum.arduino.cc/index.php?topic=152643.0) but found nothing working.

Thank you

ard_newbie


I guess it's a continuous reading of an I2C slave ?


biccius

I guess it's a continuous reading of an I2C slave ?
Yes. I have to read the status of 4 MCP23017 connected via I2C to the same bus.
I use them as input port expander and at every cycle i read the status of 8 pin of a MCP23017 with these instructions:


  Wire.beginTransmission(_address);
  Wire.write (reg);
  Wire.endTransmission ();
  Wire.requestFrom (_address, 1);
  return Wire.read();

ard_newbie

#3
Mar 22, 2019, 08:02 pm Last Edit: Mar 23, 2019, 05:50 am by ard_newbie
There are 2 PDC DMA for the TWI peripheral (TWI0 (SDA1/SCL1), TWI1(SDA/SCL)), and one AHB DMA for TWI0(SDA1/SCL1).

To read alternatively 4 I2C slaves with one arduino DUE board, it should be interesting to read 2 of them with the first I2C bus (TWI0(SDA1/SCL1)), and the last 2 with the other IC2 bus. This configuration requires adding 2K2 pull-ups for SDA1/SCL1 and nothing more for SDA/SCL because pull-ups are already there. Of course I guess your slaves beakout boards don't have pull-ups.

There is no library for that, you'll have to write your own code with TWI registers. Although this should not be too difficult, you should try first this configuration (2 I2C bus for 4 slaves) without a PDC DMA. In theory, this should be twice as fast. However, with the wire library, it's not possible to use both TWI (TWI0 and TW1) at the same time, you'll have to write your own code using TWI registers.

If the read speed is twice as fast as the one you can reach with your actual code, is it ok for your project ?


biccius

#4
Mar 29, 2019, 02:13 pm Last Edit: Mar 29, 2019, 02:13 pm by biccius
I've found this library:
https://github.com/collin80/due_wire/

"An alternative I2C library for Due with DMA support"

I can't understand if it really uses DMA or not.

Library seems to work. The only problem i get is that sometimes the bus "hang" and the routine keep waiting in a infinite state without trying to restore the control of the bus.


Code: [Select]


uint8_t TwoWire::requestFrom(uint8_t address, uint16_t quantity, uint8_t sendStop)
{
if (quantity > BUFFER_LENGTH) quantity = BUFFER_LENGTH;

// perform blocking read into buffer
int readed = 0;
TWI_StartRead(twi, address, 0, 0);
do {
// Stop condition must be set during the reception of last byte
if (readed + 1 == quantity) TWI_SendSTOPCondition( twi);

TWI_WaitByteReceived(twi, RECV_TIMEOUT);

rxBuffer[readed++] = TWI_ReadByte(twi);
} while (readed < quantity);
TWI_WaitTransferComplete(twi, RECV_TIMEOUT);

// set rx buffer iterator vars
rxBufferIndex = 0;
rxBufferLength = readed;

return readed;
}


Go Up