cancel
Showing results for 
Search instead for 
Did you mean: 

I2C endless loop in HAL_I2C_GetState

Roger Heil
Associate II
Posted on January 18, 2017 at 16:20

Hi,

im using a STM32L476RG and want to interace an extrenal RTC via I2C.

cube = 4.19.0

lib L4 = 1.6.0

hi2c1.Instance = I2C1;

hi2c1.Init.Timing = 0x10909CEC;

hi2c1.Init.OwnAddress1 = 0;

hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;

hi2c1.Init.OwnAddress2 = 0;

hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;

hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;

hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

/**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();

/* Peripheral DMA init*/

hdma_i2c1_rx.Instance = DMA1_Channel7;

hdma_i2c1_rx.Init.Request = DMA_REQUEST_3;

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;

if (HAL_DMA_Init(&hdma_i2c1_rx) != HAL_OK)

{

Error_Handler();

}

__HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c1_rx);

hdma_i2c1_tx.Instance = DMA1_Channel6;

hdma_i2c1_tx.Init.Request = DMA_REQUEST_3;

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;

if (HAL_DMA_Init(&hdma_i2c1_tx) != HAL_OK)

{

Error_Handler();

}

__HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c1_tx);

Sourcecode:

while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY){ }

if(HAL_I2C_Master_Transmit_DMA(&hi2c1, RTC_ADDRESS, (uint8_t*)txBuffer, TX_BUFFERSIZE)!= HAL_OK)

{

Error_Handler();

}

while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY){ }

So I'm waiting until the bus is free. But after the first transmit, the HAL_I2C_GetState never get ready!

0690X000006064mQAA.png0690X000006064sQAA.png

The logic analyser detects a ACK for the  RTC.

Could someone help me? I read a lot of forum sides, but do not found a concret solution for this problem.

regards

Roger

#l4
9 REPLIES 9
Posted on January 19, 2017 at 00:01

What's the content of hi2c1 and the I2C registers?

JW

Posted on January 19, 2017 at 09:32

Hi,

I made a snapshot of the variable, when the system runnes inside the HAL_I2C_GetState.

regards Roger

0690X0000060651QAA.png
Posted on January 19, 2017 at 23:23

And the interrupt handlers are set how?

JW

Posted on January 20, 2017 at 00:05

Hi,

I hope this is the right source code you are looking for!?

regards Roger

stm32l4xx_it.c

void DMA1_Channel6_IRQHandler(void)

{

/* USER CODE BEGIN DMA1_Channel6_IRQn 0 */

/* USER CODE END DMA1_Channel6_IRQn 0 */

HAL_DMA_IRQHandler(&hdma_i2c1_tx);

/* USER CODE BEGIN DMA1_Channel6_IRQn 1 */

/* USER CODE END DMA1_Channel6_IRQn 1 */

}

/**

* @brief This function handles DMA1 channel7 global interrupt.

*/

void DMA1_Channel7_IRQHandler(void)

{

/* USER CODE BEGIN DMA1_Channel7_IRQn 0 */

/* USER CODE END DMA1_Channel7_IRQn 0 */

HAL_DMA_IRQHandler(&hdma_i2c1_rx);

/* USER CODE BEGIN DMA1_Channel7_IRQn 1 */

/* USER CODE END DMA1_Channel7_IRQn 1 */

}

dma.c

/* DMA1_Channel6_IRQn interrupt configuration */

 

HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 5, 0);

 

HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);

 

/* DMA1_Channel7_IRQn interrupt configuration */

 

HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 5, 0);

 

HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
Chensie
Associate II
Posted on January 20, 2017 at 02:36

Hello,

When you use DMA with I2C to Transmit or Receive data,  you should 

Enable I2Cx_ER_IRQn and I2Cx_EV_IRQn interrupts.

because they all called I2C_DMAXferCplt (hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt)

and it  enable interrupt call to handle I2C state.

 

  __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR);

 

 

Posted on January 20, 2017 at 08:36

Hi,

when I insert into i2c.c the lines

   

HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);

HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);

the system runnes into this Assember line

WWDG_IRQHandler:

080137b0: b.n 0x80137b0 <WWDG_IRQHandler>
Posted on January 21, 2017 at 15:02

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)

{

GPIO_InitTypeDef GPIO_InitStruct;

if(i2cHandle->Instance==I2C1)

{

/* USER CODE BEGIN I2C1_MspInit 0 */

/* USER CODE END I2C1_MspInit 0 */

....

__HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c1_rx);

......

__HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c1_tx);

/* Peripheral 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 */

}

}
Posted on January 23, 2017 at 08:57

Hi,

this is the I2C_MSPInit that I'm actually running.

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)

{

   GPIO_InitTypeDef GPIO_InitStruct;

   if(i2cHandle->Instance==I2C1)

   {

      /* USER CODE BEGIN I2C1_MspInit 0 */

      /* USER CODE END I2C1_MspInit 0 */

   /**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();

   /* Peripheral DMA init*/

   hdma_i2c1_rx.Instance = DMA1_Channel7;

   hdma_i2c1_rx.Init.Request = DMA_REQUEST_3;

   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;

   if (HAL_DMA_Init(&hdma_i2c1_rx) != HAL_OK)

   {

      Error_Handler();

   }

   __HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c1_rx);

   hdma_i2c1_tx.Instance = DMA1_Channel6;

   hdma_i2c1_tx.Init.Request = DMA_REQUEST_3;

   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;

   if (HAL_DMA_Init(&hdma_i2c1_tx) != HAL_OK)

   {

      Error_Handler();

   }

   __HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c1_tx);

   /* USER CODE BEGIN I2C1_MspInit 1 */

   // NVIC for I2Cx

   HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);

   HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);

   HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);

   HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);

   /* USER CODE END I2C1_MspInit 1 */

   }

}

Alexandre T
Associate II
Posted on October 17, 2017 at 09:39

Hello

Heil.R

,

I'm having the same issue.

Did you find the solution ?