Skip to main content
Explorer II
December 16, 2023
Solved

I2C HAL_BUSY

  • December 16, 2023
  • 3 replies
  • 7968 views

Hello, I am receiving data on my STM32F411E board via the I2C interface with the Mpu9255 IMU sensor. I get HAL_BUSY status in case of any power outage or re-debug.

https://stackoverflow.com/questions/69912431/issue-in-the-i2c-communication-stm32-hal-library

When I apply the solution mentioned here, the problem is not solved directly. Additionally, I have to press the Reset button on the card. If I do this solution every time the card is turned on, the HAL_BUSY situation occurs less frequently, but I have tested it many times and sometimes it gets into this situation again.

Can I trigger the Reset button software for such situations? Unfortunately, the NVIC_SystemReset function did not work for me. I need your suggestions on this matter. Thanks.

    This topic has been closed for replies.
    Best answer by TDK

    The fix is to reassign SCL as an open-drain GPIO output and send 9 pulses, then re-initialize it as an I2C pin.

    > Can I trigger the Reset button software for such situations?

    You can always perform a software reset with HAL_NVIC_SystemReset(), but it won't solve the problem.

     

    If you're consistently getting into this state, there's likely a bug in your firmware (or hardware) that needs fixed.

    3 replies

    TDKAnswer
    Super User
    December 16, 2023

    The fix is to reassign SCL as an open-drain GPIO output and send 9 pulses, then re-initialize it as an I2C pin.

    > Can I trigger the Reset button software for such situations?

    You can always perform a software reset with HAL_NVIC_SystemReset(), but it won't solve the problem.

     

    If you're consistently getting into this state, there's likely a bug in your firmware (or hardware) that needs fixed.

    sheqomAuthor
    Explorer II
    December 16, 2023

    Thank you for your answer, I tried to do as you said, I am not very experienced in STM32 and embedded systems, I tried to make a function like this in my own way;

    void reset_I2C(){
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    ret = HAL_I2C_Mem_Read(&hi2c1, 0xD1, 0x75, 1, &ok, 1, 1000);
    if (ret != HAL_OK){
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Pull = GPIO_NOPULL;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);

    for (int i = 0; i < 21; i++) {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
    HAL_Delay(20);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
    HAL_Delay(20);
    }
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Pull = GPIO_PULLUP;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    MX_I2C1_Init();

    ret = HAL_I2C_Mem_Read(&hi2c1, 0xD1, 0x75, 1, &ok, 1, 1000);
    if (ret == HAL_OK){
    MPU9255_Init(&hi2c1);
    }
    else{
    reset_I2C();
    }
    }
    }


    It seems to be working fine. Are there any bugs you notice? I would be very happy if you could take a brief look at it.

    Super User
    December 16, 2023

    Looks good apart from what @Pavel A. says. You only need 9 pulses, but 21 won't hurt anything.

    > MX_I2C1_Init()

    The pins are re-initialized within here, so there's actually no need for you to do so yourself. May want to step through to verify.

    Might want to look at the state machine within hi2c1 to make sure it gets re-initialized correctly. Might need to call HAL_I2C_DeInit() beforehand if it isn't.

    Super User
    December 16, 2023

    When you configure the pin back to I2C mode, do not forget to set GPIO_InitStruct.Alternate, GPIO_InitStruct.Speed.

     

    Visitor II
    November 12, 2024

    I2C was designed to speed up data read access. After reading a data, if no NACK signal is detected, another data will be read as well, as the NACK signal was not sent out, causing the bus to lock up.