cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_I2C_Master_Receive disable IRQ for long time

sifourquier
Associate

Hi use when i use middleware and Softwares packe witch X-CUBE-MEMS1 for read a accelerometer

But when i add this code my timer interrupt (at 10khz) miss interrupts

And i watche in HAL_I2C_Mem_Read 

 

__disable_irq();

          /* Read data from DR */
          *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR;

          /* Increment Buffer pointer */
          hi2c->pBuffPtr++;

          /* Update counter */
          hi2c->XferSize--;
          hi2c->XferCount--;

          /* Wait until BTF flag is set */
          count = I2C_TIMEOUT_FLAG * (SystemCoreClock / 25U / 1000U);
          do
          {
            count--;
            if (count == 0U)
            {
              hi2c->PreviousState       = I2C_STATE_NONE;
              hi2c->State               = HAL_I2C_STATE_READY;
              hi2c->Mode                = HAL_I2C_MODE_NONE;
              hi2c->ErrorCode           |= HAL_I2C_ERROR_TIMEOUT;

              /* Re-enable IRQs */
              __enable_irq();

              /* Process Unlocked */
              __HAL_UNLOCK(hi2c);

              return HAL_ERROR;
            }
          }
          while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET);

          /* Generate Stop */
          SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP);

          /* Read data from DR */
          *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR;

          /* Increment Buffer pointer */
          hi2c->pBuffPtr++;

          /* Update counter */
          hi2c->XferSize--;
          hi2c->XferCount--;

          /* Re-enable IRQs */
          __enable_irq();

 

He wait __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET

And during this time interrupt is disable.

4 REPLIES 4
TDK
Guru

It tells you right in the code why it's doing that:

https://github.com/STMicroelectronics/STM32CubeF1/blob/bdec2f6b0658b5725b41c96cb1f066c362acc4d0/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c#L1366

The I2C peripheral is extremely messy. You can use IT or DMA if you need interrupts to stay enabled.

HAL makes compromises. This was the compromise made to ensure bytes are sent quickly enough.

If you feel a post has answered your question, please click "Accept as Solution".
Foued_KH
ST Employee

Hello @sifourquier , 

Based on STM32Cube HAL functions, I2C data transfer can be performed in 3 modes: Blocking Mode, Interrupt Mode or DMA Mode : 

  • Blocking Mode:

The communication is performed in polling mode. The status of all data processing is returned by the same function after finishing transfer. example : HAL_I2C_Master_Receive()

  • Non-blocking modes

The communication is performed using Interrupts or DMA. These functions return the status of the transfer startup.
The end of the data processing will be indicated through the dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when using DMA mode.


For more details about I2C communication, I suggest you check this WIKI : Getting started with I2C - stm32mcu

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

sifourquier
Associate

Thanks you I have switch to interrupt mode

And HAL_I2C_Master_Transmit no disable interrupt i found strange to disable in read and not in write

Pavel A.
Evangelist III

Disabling interrupts in I2C_WaitOnFlagUntilTimeout seems to be only in STM32F1 'HAL' driver. For more modern MCUs there's no __disable_irq() there.