AnsweredAssumed Answered

STM32f072rb nucleo DMA for I2C and USART

Question asked by Minor.Nils on Oct 15, 2016
Latest reply on Oct 31, 2016 by Nesrine M
Hi there,

i am struggling a bit by using my STM32f072rb nucleo to run it as an I2C1 Master sending and receiving via DMA. At the same time I am using USART1 to print over serial com port. For that i am using I2C1 and DMA channels 2 and 3, for USART1 I am using channels 4 and 5. USART is working :), and I2C works in non DMA mode, so i can see the Slave is acking the master when I search for it, but i really need to get I2C running over DMA. So when i reset the board it works for one time, what could be the problem for that? What have i done wrong with the DMA config?


 
void PSOM_i2c_init (void) {
     
    I2cHandle.Instance                          = I2C1;                         //Schnittstelle I2C1
    I2cHandle.Init.Timing                   = 0x00A51314;                           //Timingwert für I2C
    I2cHandle.Init.OwnAddress1          = 0xA1;                                         //Eigene Adresse
    I2cHandle.Init.AddressingMode   = I2C_ADDRESSINGMODE_7BIT;  //7Bit Adressierungsmodus
    I2cHandle.Init.DualAddressMode  = I2C_DUALADDRESS_DISABLED; //Keine Dualadressnutzung
    I2cHandle.Init.OwnAddress2          = 0xA1;
    I2cHandle.Init.OwnAddress2Masks = 0;
    I2cHandle.Init.GeneralCallMode  = I2C_GENERALCALL_DISABLED; //Kein Gerneralcall
    I2cHandle.Init.NoStretchMode        = I2C_NOSTRETCH_ENABLED;        //Aktiviere Nostretch
     
    HAL_I2CEx_ConfigAnalogFilter(&I2cHandle, I2C_ANALOGFILTER_ENABLE);
 
     
    if (HAL_I2C_Init(&I2cHandle) != HAL_OK) {   //Rufe Init Funktion auf --> diese Ruft unter anderem die HAL_I2C_MspInit();
        //If not HAL_OK then activate LED2
        Error_Handler();
    }
}

void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) { 
     
  GPIO_InitTypeDef  GPIO_InitStruct;
    static DMA_HandleTypeDef hdma_i2c_tx;
  static DMA_HandleTypeDef hdma_i2c_rx;
  RCC_PeriphCLKInitTypeDef RCC_PeripCLKInitStruct;         //set clock
  
  /*##-1- Configure the I2C clock source. The clock is derived from the SYSCLK #*/
  RCC_PeripCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
  RCC_PeripCLKInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
  HAL_RCCEx_GetPeriphCLKConfig(&RCC_PeripCLKInitStruct);
  
  //Enable the GPIO-clock
  __HAL_RCC_GPIOB_CLK_ENABLE();//__GPIOB_CLK_ENABLE();
  //Enable the I2C-Clock
  __HAL_RCC_I2C1_CLK_ENABLE();//__I2C1_CLK_ENABLE();
 __HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMAx clock
     
  //Configure GPIOB Pin_8 as SCL for I2C
  GPIO_InitStruct.Pin       = GPIO_PIN_8;
  GPIO_InitStruct.Mode      = GPIO_MODE_AF_OD;
  GPIO_InitStruct.Pull      = GPIO_PULLUP;
  GPIO_InitStruct.Speed     = GPIO_SPEED_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);       //init GPIOB PIN8 (SCL-Pin)
  
  //Configure GPIOB Pin_9 as SDA for USART
  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);         //init GPIOB PIN9 (SDA-Pin)
  
    /*##-4- Configure the DMA Channels #########################################*/
  /* Configure the DMA handler for Transmission process */
  hdma_i2c_tx.Instance                 = DMA1_Channel2;
  hdma_i2c_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
  hdma_i2c_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
  hdma_i2c_tx.Init.MemInc              = DMA_MINC_ENABLE;
  hdma_i2c_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_i2c_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
  hdma_i2c_tx.Init.Mode                = DMA_NORMAL;
  hdma_i2c_tx.Init.Priority            = DMA_PRIORITY_LOW;
  HAL_DMA_Init(&hdma_i2c_tx);  
  
  __HAL_LINKDMA(hi2c, hdmatx, hdma_i2c_tx);  /* Associate the initialized DMA handle to the the I2C handle */
     
  /* Configure the DMA handler for Transmission process */
  hdma_i2c_rx.Instance                 = DMA1_Channel3;
  hdma_i2c_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
  hdma_i2c_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
  hdma_i2c_rx.Init.MemInc              = DMA_MINC_ENABLE;
  hdma_i2c_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_i2c_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
  hdma_i2c_rx.Init.Mode                = DMA_NORMAL;
  hdma_i2c_rx.Init.Priority            = DMA_PRIORITY_HIGH;
  HAL_DMA_Init(&hdma_i2c_rx);
     
  __HAL_LINKDMA(hi2c, hdmarx, hdma_i2c_rx);     /* Associate the initialized DMA handle to the the I2C handle */
 
    /*##-5- Configure the NVIC for DMA #########################################*/
  /* NVIC configuration for DMA transfer complete interrupt (I2Cx_TX) */
  HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 1);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
  
   /* NVIC configuration for DMA transfer complete interrupt (I2Cx_RX) */
  HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);  
  HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
  
  /*##-6- Configure the NVIC for I2C ########################################*/  
  HAL_NVIC_SetPriority(I2C1_IRQn, 0, 1);
  HAL_NVIC_EnableIRQ(I2C1_IRQn);
}


void I2C1_Handler(void) {
    //Call Hal_I2C_EventHandler
    HAL_I2C_EV_IRQHandler(&I2cHandle);  //Eventhandler - Dieser kümmert sich automatisch um das erzeugen von Startconditions, ACKs, NACKs, Stopbits und Stopcondition
    HAL_I2C_ER_IRQHandler(&I2cHandle);  //Errorhandler
}
 
void DMA1_Channel2_3_IRQHandler(void)
{
    HAL_DMA_IRQHandler(I2cHandle.hdmatx); 
  HAL_DMA_IRQHandler(I2cHandle.hdmarx);
}

 
void HAL_UART_MspInit (UART_HandleTypeDef* huart) {
  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==USART1)
  {
    __USART1_CLK_ENABLE();          /* Peripheral clock enable */
   
    /* USART1 GPIO Configuration   
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX  */
         
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    /* Peripheral DMA channels 4 & 5 init*/
   
    hdma_usart1_rx.Instance = DMA1_Channel4;   
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_DISABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_usart1_rx);
 
    __HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx);
 
    hdma_usart1_tx.Instance = DMA1_Channel5;
    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_tx.Init.MemInc = DMA_MINC_DISABLE;
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_usart1_tx.Init.Mode = DMA_CIRCULAR;
    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_usart1_tx);
 
    __HAL_LINKDMA(huart,hdmatx, hdma_usart1_tx);
 
  /* System interrupt init*/
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  }
     
     
}

Attachments

Outcomes