Example for i2c_t3 DMA

Status
Not open for further replies.

Kareem

Member
Hi
I'm trying to run an MPU9250's accelerometer at 4KHz and save it's values in a buffer while sampling other sensors on a lower frequency and then print the accelerometer buffer values along with other sensors vaslues at 50Hz (print to serial and/or SD card).
I'm looking for good examples to run i2c_t3 in dma mode and save values in a buffer, but I couldn't find any. It would be great if someone can suggest how to do it or share a good example.

Than you!
 
Just commented on the duplicate post. When I saw this I first wondered if 4,000 IMU updates were possible and if the transfer time would allow getting the info over i2c.

Then I saw DMA - and that is not something I've seen done.

The MPU9250 has an interrupt signal to say when data is ready. That would be required for any fast access - and it might trigger DMA? But perhaps get that working first to see what can work.
 
I managed to run the accelerometer at 4Khz in the main loop (CPU time) using the “data ready” interrupt. There is a thread that explains how to make MPU9250 operate at this high frequency here

https://github.com/kriswiner/MPU9250/issues/106

My goal is to run the IMU data acquisition in the background using dma and use cpu time to run other tasks

Sorry for the duplication. I thought my post went to the wrong form
I would appreciate any help
Thank you
 
I did a quick search and don't see that i2c was done with DMA like it has been with SPI - for other devices. The nature of two data lines and each out brings a return is different that the setup and return of i2c.

There are MPU9250 devices that run on SPI - that would be faster transfer and perhaps better map to DMA usage.

Of course onehorse only presents i2c if using his hardware - so hardware is a consideration.
 
dont forget to use mutex if you have other devices attached, unless you want your sketch and dma to clash on the i2c bus... but you have enough i2c busses to dedicate one for DMA only so a mutex is not needed if thats the case
 
Indeed - when I add 'i2c_t3' to my search - Hit #1 points right to github/Manitou ... GitHub - nox771/i2c_t3: Enhanced I2C library for Teensy 3!

Assuming this is the only i2c device from a single access point Mutex isn't relevant, that is good info Manitou - had not ever had reason to look that far into ReadMe.

Indeed this example exists and shows sample usage: ...\hardware\teensy\avr\libraries\i2c_t3\examples\advanced_master\advanced_master.ino

Even sending out the request for callback() based on a data ready interrupt might be helpful? This might help on another thread just switched from Wire.h ... I'll give it a try.
 
dont forget to use mutex if you have other devices attached, unless you want your sketch and dma to clash on the i2c bus... but you have enough i2c busses to dedicate one for DMA only so a mutex is not needed if thats the case

Yes, I'm dedicating Wire1 for DMA.
 
i2c_t3 does have a DMA mode (I2C_OP_MODE_DMA) and non-blocking Wire.sendTransmission(), so you can do other things before checking done() or callback.

Read the documentation at https://github.com/nox771/i2c_t3

I've been reviewing this library all yesterday, but I couldn't get much out of the examples it has. It is mainly the advanced_master.ino example that uses dma, and it just shows how you can set the I2C_OP_MODE_DMA and does basic data transfer. I need more details on how to set the I2C to save specific sensor values (accelerometer values only) in memory to be retrieved later using an interrupt.
 
I was going to give it a look. It generates a callback when done - you can do what is desired then with the data. I don't see it in the example.

>> void (*user_onReqFromDone)(void); // Master Rx Callback Function

In the header :: 929: inline void onReqFromDone(void (*function)(void)) { i2c->user_onReqFromDone = function; }

If you setup DMA write and leave is that where you finish up?
 
I was going to give it a look. It generates a callback when done - you can do what is desired then with the data. I don't see it in the example.

>> void (*user_onReqFromDone)(void); // Master Rx Callback Function

In the header :: 929: inline void onReqFromDone(void (*function)(void)) { i2c->user_onReqFromDone = function; }

If you setup DMA write and leave is that where you finish up?

the DMAChannel library has it's own version of that function that get called every time DMA finishes a transfer called attachInterrupt
Code:
// An interrupt routine can be run when the DMA channel completes
	// the entire transfer, and also optionally when half of the
	// transfer is completed.
	void attachInterrupt(void (*isr)(void)) {
		_VectorsRam[channel + IRQ_DMA_CH0 + 16] = isr;
		NVIC_ENABLE_IRQ(IRQ_DMA_CH0 + channel);
	}

I tried using the following code

Code:
        Wire1.setOpMode(I2C_OP_MODE_DMA);
        if(Wire1.i2c->opMode == I2C_OP_MODE_DMA){
            Serial.printf("OK (Channel %d)\n",Wire1.i2c->DMA->channel);
            //Wire1.i2c->DMA->triggerContinuously();

           // Wire1.i2c->DMA->triggerAtHardwareEvent(readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01);
            Wire1.i2c->DMA->attachInterrupt(i2c0_isr_22);
            Wire1.i2c->DMA->sourceBuffer(accelCount,3);
            Wire1.i2c->DMA->destination((volatile uint8_t&)buff);
            Wire1.i2c->DMA->transferSize(6);
            Wire1.i2c->DMA->transferCount(1);
            Wire1.i2c->DMA->disableOnCompletion();
            Wire1.i2c->DMA->enable();

        }
        else
            Serial.print("Failed, using ISR\n");
}
.....
void loop()
{  

  Serial.println(cn);
   delay(100);
}
void i2c0_isr_22(void) {
  cn=cn+1;

}

The DMA channel get defined as channel 0 successfully, but the interrupt never gets triggered as the values of cn remain unuqdated regardless of the trigger type.
 
I tried to us the non-blocking commends in my code but adding them doesn't seem to change much. Can you explain to me how would you use them to continuously parse data from a sensor in the background
 
Status
Not open for further replies.
Back
Top