AnsweredAssumed Answered

KL25 I2C DMA

Question asked by Norbert Gal on Dec 6, 2015
Latest reply on Dec 12, 2015 by Jorge_Gonzalez

Hello!

 

I trying develope data transfer (acceleration data, gyroscope data, tempertaure data) FRDM-KL25 <<------->> MPU6050 with I2C and DMA, Without DMA reading is going fine but with DMA is it still without success.

 

This is the code for read data from MPU6050 throug I2C without DMA this is going fine:

void read_MPU6050()
{
    I2CReadMultiRegisters(MPU6050_ADDRESS, MPU6050_RA_ACCEL_XOUT_H, &MPU_6050_buffer[0], 14);
    convert_data();    
}
void I2CReadMultiRegisters(char SlaveID, char RegisterAddress, char * r, char n)
{
  char i;
  uint32_t t[3];
  IIC_StartTransmission(SlaveID,MWSR);
  i2c_Wait();
  i2c_write_byte(RegisterAddress);
  i2c_Wait();
  i2c_RepeatedStart();
  i2c_write_byte((SlaveID << 1) | 0x01);
  i2c_Wait();
  i2c_EnterRxMode();
  i2c_EnableAck();
  i = I2C1_D ; // Dummy read
  i2c_Wait();
  for(i=0;i<n-2;i++) 
  {
    *r = I2C1_D;
    r++;
    i2c_Wait();
  }
  i2c_DisableAck();
  *r = I2C1_D; 
  r++;
  i2c_Wait();
  i2c_Stop(); 
  *r = I2C1_D;
  Pause();
}

 

Reading with DMA is this:

void DMAread_MPU6050(){
    
    DMA_I2CReadMultiRegisters(MPU6050_ADDRESS,MPU6050_RA_ACCEL_XOUT_H,&MPU_6050_buffer[0],14);
    convert_data();    
}
void DMA_I2CReadMultiRegisters(char SlaveID, char RegisterAddress, char * r, char n)
{
  char i;
  IIC_StartTransmission(SlaveID,MWSR);
  i2c_Wait();
  i2c_write_byte(RegisterAddress);
  i2c_Wait();
  i2c_RepeatedStart();
  i2c_write_byte((SlaveID << 1) | 0x01);
  i2c_Wait();
  i2c_EnterRxMode();
  i2c_EnableAck();
  i = I2C1_D ; // Dummy read
  i2c_Wait();
  
  DMA_starttransfer(DMA_BASE_PTR,0, 14);
}
void DMA_starttransfer(DMA_MemMapPtr DMA_Channel, uint8_t index, uint32_t num_bytes)
{
    DMA_DSR_REG(DMA_Channel, index) = num_bytes;
    DMA_DAR_REG(DMA_Channel, index) = (uint32_t)(&MPU_6050_buffer[0]);
    DMA_DCR_REG(DMA_Channel, index) = DMA_DCR_ERQ_MASK|DMA_DCR_EINT_MASK;
    I2C1_C1 |= I2C_C1_DMAEN_MASK;
}

 

This is the initialization code for DMA and I2C:

void Init_I2C(void)
{
  SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTE_MASK | SIM_SCGC5_PORTB_MASK;
  SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK;
  PORTC_PCR10 = PORT_PCR_MUX(2);        //I2C SCL
  PORTC_PCR11 = PORT_PCR_MUX(2);        //I2C SDA

  I2C1_F  = 0x00;
  I2C1_C1 = I2C_C1_IICEN_MASK;
}

void DMA_RX_Init(DMA_MemMapPtr DMA_Channel, uint8_t dma_source, int index,
        uint32_t source_addr, uint32_t dest_addr, uint32_t num_bytes,uint32_t bytes_per_xfer)
{
    /* num_bytes is total bytes */
    /* setup depends on how many bytes per transfer */

    SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
    SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;

    uint32_t ssize_dsize_attr;

    /* setup ssize and dsize parameter for TCD ATTR register based on transfer size assigned above */
    /* 0:32bit; 1:8-bit, 2:16-bit  */
    switch (bytes_per_xfer) {
    case 8:
    default:
        ssize_dsize_attr = 1;
        break; /* 8-bit */
    case 16:
        ssize_dsize_attr = 2;
        break; /* 16-bit */
    case 32:
        ssize_dsize_attr = 0;
        break; /* 32-bit */
    }

    DMA_SAR_REG(DMA_Channel, index)= source_addr;                                          // Source address 
    DMA_DCR_REG(DMA_Channel, index)|= 0x0000;                                             // Source address increments 0 bytes (uint32)
    DMA_DAR_REG(DMA_Channel, index)|= dest_addr;                                           // Destination address 
    DMA_DCR_REG(DMA_Channel, index)|= ssize_dsize_attr << DMA_DCR_DINC_SHIFT;                 // Destination offset increments 
    DMA_DCR_REG(DMA_Channel, index)|= DMA_DCR_ERQ_MASK|DMA_DCR_EINT_MASK|DMA_DCR_D_REQ_MASK;//|DMA_DCR_CS_MASK;
    I2C1_C1 |= I2C_C1_DMAEN_MASK;//|I2C_C1_IICIE_MASK;
    DMA_DSR_BCR_REG(DMA_Channel, index)= num_bytes;                                            //Stop the transfer when all bytes is transfered
    DMA_DCR_REG(DMA_Channel, index)|= ((ssize_dsize_attr<<DMA_DCR_DSIZE_SHIFT)|(ssize_dsize_attr<<DMA_DCR_SSIZE_SHIFT)); // Source a destination size 0:32bit; 1:8-bit, 2:16-bit
    DMAMUX_CHCFG_REG(DMAMUX0_BASE_PTR,index)= (DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(dma_source)); // DMA source DMA Mux to tie source to DMA channel

}

 

And finally the main functon with DMA interrupt function:

int main(void)
{
    InitClock();
    InitSysTick();
    Init_I2C();
    DMA_RX_Init(DMA_BASE_PTR, I2C1_SOURCE, CHANNEL_0,
            (uint32_t) (&(I2C1_D )),(uint32_t)(&(MPU_6050_buffer[0])), 12,8 );    
    init_MPU6050();
    enable_irq(INT_DMA0 - 16);
        
    for(;;) {    
        read_MPU6050();
        //DMAread_MPU6050();

        counter++;
           Delay_mS(1000);
    }
        return 0;
}

void DMA_interrupt()
{
    i2c_DisableAck(); 
    i2c_Wait();
    i2c_Stop(); 
    interrupt++;
    DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;
    I2C1_C1 &= ~I2C_C1_DMAEN_MASK;
}

 

Iam working on this over the weekend but still not going. Can anyone help me and modify this code? I attach the whole of project. Thank You!

Outcomes