AnsweredAssumed Answered

I2C interface through DMA

Question asked by hosS on Sep 28, 2013
Hi,
I have a long configuration to be done through I2C interface, so I thought I have to do it using DMA. I am trying to read device ID as a start. 
The problem is that the I2C sequence doesn't reach the end (I2C_GenerateSTOP), but I can see that the value I need to get (the ID) in the DR register with the System Viewer in Keil. I think that I am missing something. Here is my DMA configuration and I2C reading sequence.
static void I2C2_DMA_Config(uint8_t* buffer)
{
  DMA_InitTypeDef DMA_InitStructure;
   
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
     
  /* Initialize the DMA_Channel member */
  DMA_InitStructure.DMA_Channel = DMA_Channel_1;
   
  /* Initialize the DMA_PeripheralBaseAddr member */
  DMA_InitStructure.DMA_PeripheralBaseAddr = I2C2->DR; //((uint32_t)0x40005410)
   
  /* Initialize the DMA_Memory0BaseAddr member */
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer;
   
  /* Initialize the DMA_PeripheralInc member */
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   
  /* Initialize the DMA_MemoryInc member */
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   
  /* Initialize the DMA_PeripheralDataSize member */
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
   
  /* Initialize the DMA_MemoryDataSize member */
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
   
  /* Initialize the DMA_Mode member */
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
   
  /* Initialize the DMA_Priority member */
  DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
   
  /* Initialize the DMA_FIFOMode member */
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
   
  /* Initialize the DMA_FIFOThreshold member */
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
   
  /* Initialize the DMA_MemoryBurst member */
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
   
  /* Initialize the DMA_PeripheralBurst member */
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
   
  /* If using DMA for Reception */
//  if (Direction == IOE_DMA_RX)
//  {   
    /* Initialize the DMA_DIR member */
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
     
    /* Initialize the DMA_BufferSize member */
    DMA_InitStructure.DMA_BufferSize = 2;
     
    DMA_DeInit(DMA1_Stream0);
     
    DMA_Init(DMA1_Stream0, &DMA_InitStructure);
//  }
//  /* If using DMA for Transmission */
//  else if (Direction == IOE_DMA_TX)
//  {
//    /* Initialize the DMA_DIR member */
//    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
//   
//    /* Initialize the DMA_BufferSize member */
//    DMA_InitStructure.DMA_BufferSize = 1;
//   
//    DMA_DeInit(IOE_DMA_TX_STREAM);
//   
//    DMA_Init(IOE_DMA_TX_STREAM, &DMA_InitStructure);
//  }
}
 
 
uint8_t DCMI_SingleRandomRead1(uint8_t Device, uint16_t Addr)
{
  uint8_t LSB_Addr, MSB_Addr;
  uint32_t timeout = DCMI_TIMEOUT_MAX;
  uint8_t Data = 0;
//  uint8_t IOE_BufferRX[2] = {0x00, 0x00};
 
  LSB_Addr=(uint8_t)(Addr);
  MSB_Addr=(uint8_t)(Addr>>8);
   
  /* Configure DMA Peripheral */
  I2C2_DMA_Config((uint8_t*)Data);
   
  /* Enable DMA NACK automatic generation */
  I2C_DMALastTransferCmd(I2C2, ENABLE);
 
  /* Generate the Start Condition */
  I2C_GenerateSTART(I2C2, ENABLE);
 
  /* Test on I2C2 EV5 and clear it */
  timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
  {
    /* If the timeout delay is exeeded, exit with error code */
    if ((timeout--) == 0) return 0xFF;
  }
   
  /* Send DCMI selcted device slave Address for write */
  I2C_Send7bitAddress(I2C2, Device, I2C_Direction_Transmitter);
  
  /* Test on I2C2 EV6 and clear it */
  timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    /* If the timeout delay is exeeded, exit with error code */
    if ((timeout--) == 0) return 0xFF;
  }
 
  /* Send I2C2 location address MSB */
  I2C_SendData(I2C2, (uint8_t)(MSB_Addr));
 
  /* Test on I2C2 EV8 and clear it */
  timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    /* If the timeout delay is exeeded, exit with error code */
    if ((timeout--) == 0) return 0xFF;
  }
 
    /* Send I2C2 location address LSB */
  I2C_SendData(I2C2, (uint8_t)(LSB_Addr));
 
  /* Test on I2C2 EV8 and clear it */
  timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    /* If the timeout delay is exeeded, exit with error code */
    if ((timeout--) == 0) return 0xFF;
  }
   
   
  /* Clear AF flag if arised */
  I2C2->SR1 |= (uint16_t)0x0400;
 
  /* Generate the Start Condition */
  I2C_GenerateSTART(I2C2, ENABLE);
   
  /* Test on I2C2 EV6 and clear it */
  timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
  {
    /* If the timeout delay is exeeded, exit with error code */
    if ((timeout--) == 0) return 0xFF;
  }
   
  /* Send DCMI selcted device slave Address for write */
  I2C_Send7bitAddress(I2C2, 0x79, I2C_Direction_Receiver);
    
  /* Test on I2C2 EV6 and clear it */
  timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
  {
    /* If the timeout delay is exeeded, exit with error code */
    if ((timeout--) == 0) return 0xFF;
  }
 
 
  /* Enable I2C DMA request */
  I2C_DMACmd(I2C2,ENABLE);
   
  /* Enable DMA RX Channel */
  DMA_Cmd(DMA1_Stream0, ENABLE);
   
  /* Wait until DMA Transfer Complete */
  timeout = DCMI_TIMEOUT_MAX; /* Initialize timeout value */
  while (!DMA_GetFlagStatus(DMA1_Stream0, DMA_FLAG_TCIF0))
  {
    if ((timeout--) == 0) return 0xFF;
  }       
   
  /* Send STOP Condition */
  I2C_GenerateSTOP(I2C2, ENABLE);
   
  /* Disable DMA RX Channel */
  DMA_Cmd(DMA1_Stream0, DISABLE);
   
  /* Disable I2C DMA request */ 
  I2C_DMACmd(I2C2,DISABLE);
   
  /* Clear DMA RX Transfer Complete Flag */
  DMA_ClearFlag(DMA1_Stream0,DMA_FLAG_TCIF0);
   
  /* return a pointer to the IOE_Buffer */
   
  return Data;

Outcomes