cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F2 need to abort HAL_I2C_Mem_Read_IT

I have an issue where a HAL_I2C_Mem_Read_IT transaction just seems to hang.  It is plausible that this peripheral is temporarily unavailable and I already have working retry logic for the case where this call returns the "AF" error.  The hang may or may not be related, but I'd like to abort it and try again.  It isn't easy to get an I2C trace of this, but not impossible.  In any case, I'd like to add some code to address this issue if possible.

5 REPLIES 5
Pavel A.
Super User

You can set timeout for the I2C operation (using some TIM or systick interrupt) and call HAL_I2C_Master_Abort_IT.

Then you can probe the I2C SCL pin for "stuck" condition and try recovery as usual (make 9 SCL pulses, re-initialize the I2C).

 

I tried that, but HAL_I2C_Master_Abort_IT returns an error (HAL_Busy) in this case. In another post on this forum someone else also reported this. Apparently, Master_Abort works for some transactions but not the Mem transactions. Your other comment suggests that disabling and reenabling the I2C peripheral might work. 

Hello @eric239955_stm1_stmicro 

The function HAL_I2C_Master_Abort_IT cannot return HAL_BUSY.

HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress)
{
  /* Declaration of temporary variables to prevent undefined behavior of volatile usage */
  HAL_I2C_ModeTypeDef CurrentMode   = hi2c->Mode;

  /* Prevent unused argument(s) compilation warning */
  UNUSED(DevAddress);

  /* Abort Master transfer during Receive or Transmit process    */
  if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET) && ((CurrentMode == HAL_I2C_MODE_MASTER) || 
                                                             (CurrentMode == HAL_I2C_MODE_MEM)))
  {
    /* Process Locked */
    __HAL_LOCK(hi2c);

    hi2c->PreviousState = I2C_STATE_NONE;
    hi2c->State = HAL_I2C_STATE_ABORT;

    /* Disable Acknowledge */
    CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK);

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

    hi2c->XferCount = 0U;

    /* Disable EVT, BUF and ERR interrupt */
    __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR);

    /* Process Unlocked */
    __HAL_UNLOCK(hi2c);

    /* Call the corresponding callback to inform upper layer of End of Transfer */
    I2C_ITError(hi2c);

    return HAL_OK;
  }
  else
  {
    /* Wrong usage of abort function */
    /* This function should be used only in case of abort monitored by master device */
    /* Or periphal is not in busy state, mean there is no active sequence to be abort */
    return HAL_ERROR;
  }
}

 An alternatif to solve your issue is to call HAL_I2C_Master_Abort_IT in the Error callback function. 

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.
Saket_Om

Sorry, it returns HAL_ERROR.

Hello @eric239955_stm1_stmicro 

Could you please share the content of SR register when calling HAL_I2C_Master_Abort_IT().

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.
Saket_Om