I2C Master Mode DMA Kullanımı

Başlatan robikod, 02 Temmuz 2021, 15:26:27

robikod

Eeproma yazmak için normal moddan DMA moduna geçtim, normal modda gayet başarılı çalışırken, DMA modunda bir yerde takılıyor. Stm32f4 kullanıyorum ve kodlarım şu şekilde:

if(hi2c->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspInit 0 */

  /* USER CODE END I2C1_MspInit 0 */

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**I2C1 GPIO Configuration
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA
    */
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* Peripheral clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();
   /* I2C1 DMA Init */
    /* I2C1_RX Init */
    hdma_i2c1_rx.Instance = DMA1_Stream0;
    hdma_i2c1_rx.Init.Channel = DMA_CHANNEL_1;
    hdma_i2c1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_i2c1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_i2c1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_i2c1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_i2c1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_i2c1_rx.Init.Mode = DMA_NORMAL;
    hdma_i2c1_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_i2c1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_i2c1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hi2c,hdmarx,hdma_i2c1_rx);

    /* I2C1_TX Init */
    hdma_i2c1_tx.Instance = DMA1_Stream7;
    hdma_i2c1_tx.Init.Channel = DMA_CHANNEL_1;
    hdma_i2c1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_i2c1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_i2c1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_i2c1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_i2c1_tx.Init.Mode = DMA_NORMAL;
    hdma_i2c1_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_i2c1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_i2c1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hi2c,hdmatx,hdma_i2c1_tx);

    /* I2C1 interrupt Init */
    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
        HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
  /* USER CODE BEGIN I2C1_MspInit 1 */

  /* USER CODE END I2C1_MspInit 1 */
  
  }
}



Aşağıdaki kodda, HAL_I2C_Master_Transmit_DMA çağırdıktan sonra fonksiyonun içerisinden HAL_OK olarak çıkıyor ancak hemen I2C1_EV_IRQHandler içerisinde loopta kalıyor bu interruptan çıkamıyor. Bu neden olabilir ? Nasıl çözebilirim?

 
   while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY)
      {

      }
      errorCode = HAL_I2C_Master_Transmit_DMA(hi2c, (uint16_t)deviceAddress, (uint8_t*)dataArray, 2);
      if(errorCode != HAL_OK)
      {
      // print("%d",errorCode);
      }

robikod

Bu konuda yardımcı olabilecek yok mu ?

Cemre.

Merhaba,

Bu konu ST community forumunda da konuşulmuş. Hatta bug fix geçilmiş gözüküyor.

Tavsiye olarak CubeMX kütüphane paketlerini güncellemek ve proje ayarlarından en güncel kütüphaneyi kullanacak şekilde ayarlamak önerilebilir. Denemekte fayda var.

https://community.st.com/s/question/0D50X0000BTcGDf/bug-report-fix-hal-i2c-interrupt-handler-not-working

mr.engineer

ST'lerin bazı I2C modüllerinde problem olduğu söyleniyordu. Hala devam ediyor galiba sorun