cancel
Showing results for 
Search instead for 
Did you mean: 

CubeMx HAL F3 version 1.4 I2C slave limitations

loik
Associate
Posted on March 08, 2016 at 14:30

Hello,

For my application I am writing an i2c slave that uses polling mode.

I noticed that the slave_receive function implementation is not practical.

HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout)

You must pass the Size parameter, however there is no way to receive less than Size bytes.

If the master sends less than expected number of bytes and then a stop flag. The Hal will just return an HAL_ERROR status.

So i'm proposing a modification that uses existing mechanisms by using the XFerCount variable.

Here is the modified code.

HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout)

{

  if(hi2c->State == HAL_I2C_STATE_READY)

  {  

    if((pData == NULL ) || (Size == 0))

    {

      return  HAL_ERROR;                                    

    }

    

    /* Process Locked */

    __HAL_LOCK(hi2c);

    hi2c->XferCount = 0;

    hi2c->State = HAL_I2C_STATE_SLAVE_BUSY_RX;

    hi2c->ErrorCode   = HAL_I2C_ERROR_NONE;

    

    /* Enable Address Acknowledge */

    hi2c->Instance->CR2 &= ~I2C_CR2_NACK;

    /* Wait until ADDR flag is set */

    if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout) != HAL_OK)      

    {

      /* Disable Address Acknowledge */

      hi2c->Instance->CR2 |= I2C_CR2_NACK;

      return HAL_TIMEOUT;

    }

    /* Clear ADDR flag */

    __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);

    

    /* Wait until DIR flag is reset Receiver mode */

    if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, SET, Timeout) != HAL_OK)      

    {

      /* Disable Address Acknowledge */

      hi2c->Instance->CR2 |= I2C_CR2_NACK;

      return HAL_TIMEOUT;

    }

    while(Size > 0)

    {

      /* Wait until RXNE flag is set */

      if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout) != HAL_OK)      

      {

        /* Disable Address Acknowledge */

        hi2c->Instance->CR2 |= I2C_CR2_NACK;

        

        /* Store Last receive data if any */

        if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET)

        {

          /* Read data from RXDR */

          (*pData++) = hi2c->Instance->RXDR;

         

hi2c->XferCount++;

        }

        

        if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT)

        {

          return HAL_TIMEOUT;

        // A stop condition occured, consider it's a timeout

        }else if (hi2c->ErrorCode == HAL_I2C_ERROR_NONE) {

          return HAL_TIMEOUT;

        } else {

          return HAL_ERROR;

        }

      }

      

      /* Read data from RXDR */

      (*pData++) = hi2c->Instance->RXDR;

      hi2c->XferCount++;

      Size--;

    }

    

    /* Wait until STOP flag is set */

    if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF) != HAL_OK)

    {

      /* Disable Address Acknowledge */

      hi2c->Instance->CR2 |= I2C_CR2_NACK;

      if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)

      {

        return HAL_ERROR;

      }

      else

      {

        return HAL_TIMEOUT;

      }

    }

    /* Clear STOP flag */

    __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_STOPF);

    

    /* Wait until BUSY flag is reset */

    if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout) != HAL_OK)      

    {

      /* Disable Address Acknowledge */

      hi2c->Instance->CR2 |= I2C_CR2_NACK;

      return HAL_TIMEOUT;

    }

    

    /* Disable Address Acknowledge */

    hi2c->Instance->CR2 |= I2C_CR2_NACK;

    

    hi2c->State = HAL_I2C_STATE_READY;

    /* Process Unlocked */

    __HAL_UNLOCK(hi2c);

    

    return HAL_OK;

  }

  else

  {

    return HAL_BUSY;

  }

}

And then when using this function you can know how many bytes were received by checking the hi2c.XFferCount value if a HAL_TIMEOUT status is returned

#stm32f3-i2c-slave-polling-hal
1 REPLY 1
Walid FTITI_O
Senior II
Posted on March 08, 2016 at 18:45

Hi le_devehat.loik, 

Thank you for your feedback and contribution. I will report this to the right team.

-Hannibal-