Skip to main content
Visitor II
May 21, 2023
Question

I'm getting HAL_I2C_STATE_BUSY_RX

  • May 21, 2023
  • 2 replies
  • 4957 views

Hello,

I have developed a code in FreeRTOS mode that contains two main tasks. The first one check if I have received an RX buffer on the I2C bus, and the second one manage the data that has been received.

However, after receiving the first buffer, I am getting HAL_I2C_STATE_BUSY_RX, and I cannot transmit a response to the master device but I'm able to receive another RX buffer . Can anyone please help me?

I'm using I2C in DMA normal mode.


_legacyfs_online_stmicro_images_0693W00000bkVdiQAE.png32-> HAL_I2C_STATE_READY
_legacyfs_online_stmicro_images_0693W00000bkVdJQAU.png34-> HAL_I2C_STATE_BUSY_RX
_legacyfs_online_stmicro_images_0693W00000bkVd4QAE.png

    This topic has been closed for replies.

    2 replies

    Super User
    May 22, 2023

    Does your receive code re-call the HAL_I2C_Receive_DMA() after it gets the first buffer?

    Are you relying on the hi2c structure flags to tell the 2nd task when data is ready? You should be using a semaphore or other RTOS construct to communicate between tasks. The HAL code is NOT thread safe by itself.

    Show more of your code, and please paste into the forums using the "</>" button below, not as screen capture images.

    Mabou.1Author
    Visitor II
    May 22, 2023

    Yes, that's correct. When my code recall HAL_I2C_Receive_DMA() once this function returns HAL_OK indicating that the reception is successful,

    I proceed to send a notification to the second task to inform it about the detection of an RX buffer. Subsequently, I transmit this buffer to the second task by a queue.

    < if(HAL_I2C_GetState(&hi2c1) == HAL_I2C_STATE_READY)

     {

     ret = HAL_I2C_Slave_Receive_DMA(&hi2c1, (uint8_t*)&RX_I2C_Buffer, sizeof(RX_I2C_Buffer));

     if(ret == HAL_OK)

     {

     QueueStatus = osMessageQueuePut(I2CBufferQueueHandle, &RX_I2C_Buffer, sizeof(RX_I2C_Buffer), 500);

     xTaskNotify( xTaskMannageCmdHandle, RX_I2C_SUCCESSFULLY_DETECTED, eSetBits);

     }

     }

    >

    Super User
    May 22, 2023

    You can't have RX_DMA active and try to transmit. I2C can only do one at a time. Since you are the slave, there should not be any more incoming data until you have sent your response. So don't restart the receive until after you have sent your response.

    And a curiosity: why do you use BOTH a queue and task notify? just posting to the queue should be sufficient.

    ST Employee
    May 22, 2023

    Hello @Mabou.1​ ,

    I couldn't understand your issue but maybe you can check the end of the transfer :

     do
     {
     if(HAL_I2C_Master_Transmit_DMA(&I2cHandle, (uint16_t)I2C_ADDRESS, (uint8_t*)TxBuffer, TXBUFFERSIZE)!= HAL_OK)
     {
     Error_Handler();
     }
     /* Wait for the end of the transfer */ 
     /* Check the current state of the peripheral; if it’s busy you need to wait for the end of current
     transfer before starting a new one.*/ 
     while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
     {
     } 
     }

    Foued

    Mabou.1Author
    Visitor II
    May 22, 2023

    Hello,

    < while (1)

     {

     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

     ret1 = HAL_I2C_GetState(&hi2c1);

     if(HAL_I2C_GetState(&hi2c1) == HAL_I2C_STATE_READY){

     ret = HAL_I2C_Slave_Receive_DMA(&hi2c1, rxbuffer, sizeof(rxbuffer));

     if(ret == HAL_OK){

     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

     }

     }

     }

     /* USER CODE END 3 */

    }

    void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)

    {

    BufferReceived++;

    }

    >

    In the first iteration of my while loop, the code detects an I2C RX bus, but it's not true because I'm not sending anything from the master. After that, if I set a breakpoint on the line ret1 = HAL_I2C_GetState(&hi2c1); , I get ret1 = HAL_I2C_BUSY_RX, but despite that, I am able to receive from other I2C buses, but I'm not able to transmit. This problem occur when I use DMA or IT mode

    Mabou.1Author
    Visitor II
    May 22, 2023

    Hello,

    < while (1)

     {

     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

     ret1 = HAL_I2C_GetState(&hi2c1);

     if(HAL_I2C_GetState(&hi2c1) == HAL_I2C_STATE_READY){

     ret = HAL_I2C_Slave_Receive_DMA(&hi2c1, rxbuffer, sizeof(rxbuffer));

     if(ret == HAL_OK){

     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

     }

     }

     }

     /* USER CODE END 3 */

    }

    void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)

    {

    BufferReceived++;

    }

    >

    In the first iteration of my while loop, the code detects an I2C RX bus, but it's not true because I'm not sending anything from the master. After that, if I set a breakpoint on the line ret1 = HAL_I2C_GetState(&hi2c1); , I get ret1 = HAL_I2C_BUSY_RX, but despite that, I am able to receive from other I2C buses, but I'm not able to transmit. This problem occur when I use DMA or IT mode.

    And if I add the lines of code below I enter in a blocking loop.

    <

    while(HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)

    {

    }

    >