cancel
Showing results for 
Search instead for 
Did you mean: 

HAL Interrupt Driven I2C OVR Error

devin
Associate
Posted on July 13, 2016 at 23:05

I am attempting to implement an interrupt driven I2C slave on the STM32L051. The problem is that I keep receiving the HAL_I2C_ERROR_OVR error in the HAL_I2C_ErrorCallback. The below code is just an example and is configured to receive a 3 byte message and respond with a single byte status. Running this code triggers the OVR error once the master transmits and then appears to continuously trigger the I2C1_IRQHandler, tying up other operations. The slave cannot use stretching so I have disabled it as shown in the below code. I am fairly new to HAL and have mostly been using the STM32Fxx series with the std peripheral libraries. I have reviewed the published examples, even copied some into my more complex code-base, only to get the same OVR error. Do any of you guys have any suggestions/advice/etc. that could push me towards a workable solution?

Thanks.

//main

int main(void)

{

  /* USER CODE BEGIN 1 */

int responseSize = 1;

int bytesToReceive = 3;

bool error = false;

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();

  /* Configure the system clock */

  SystemClock_Config();

  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  MX_I2C1_Init();

  /* Initialize interrupts */

  MX_NVIC_Init();

  i2c_response[0] = 0x01;

  responseSize = 1;

  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

//**** Slave Rx/Tx Interrupt based ****//

if(slaveRxCallbackTriggered)

{

slaveRxCallbackTriggered = false;

if(responseSize > 0)

{

if(!IOModule_TransmitToMaster(i2c_response,responseSize))

{

error = true;

}

}

IOModule_ReceiveFromMaster(bytesToReceive);

}

else

IOModule_ReceiveFromMaster(bytesToReceive);

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

}

/*------------------------------------------------------------------------------

I2C Receive data from master

 *------------------------------------------------------------------------------*/

bool IOModule_ReceiveFromMaster(int numberOfBytes)

{

bool result = false;

if(HAL_I2C_GetState(&hi2c1) == HAL_I2C_STATE_READY)

{

HAL_StatusTypeDef status = HAL_I2C_Slave_Receive_IT(&hi2c1, (uint8_t *)i2c_rx_array, numberOfBytes);

if(status == HAL_OK)

{

result = true;

}

}

return result;

}

/*------------------------------------------------------------------------------

I2C Transmit data to master

 *------------------------------------------------------------------------------*/

bool IOModule_TransmitToMaster(uint8_t txBuffer[], int bufferSize)

{

bool result = false;

while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)

  {

  } 

HAL_StatusTypeDef status = HAL_I2C_Slave_Transmit(&hi2c1, (uint8_t*)txBuffer, bufferSize, 10000);

HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,GPIO_PIN_RESET);

if(status == HAL_OK)

{

result = true;

}

return result;

}

/*------------------------------------------------------------------------------

I2C Slave Rx Complete Callback

 *------------------------------------------------------------------------------*/

void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2CxHandle)

{

slaveRxCallbackTriggered = true;

}

/*------------------------------------------------------------------------------

I2C Error Callback

 *------------------------------------------------------------------------------*/

void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)

{

lastErrorCode = HAL_I2C_GetError(&hi2c1);

}

//I2C1 init

void MX_I2C1_Init(void)

{

  hi2c1.Instance = I2C1;

  hi2c1.Init.Timing = 0x000006C5;

  hi2c1.Init.OwnAddress1 = 0x24;

  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;

  hi2c1.Init.OwnAddress2 = 0;

  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;

  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;

  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE;

  HAL_I2C_Init(&hi2c1);

    /**Configure Analogue filter 

    */

  HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE);

}

void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)

{

  GPIO_InitTypeDef GPIO_InitStruct;

  if(hi2c->Instance==I2C1)

  {  

    /**I2C1 GPIO Configuration    

    PB6     ------> I2C1_SCL

    PB7     ------> I2C1_SDA 

    */

    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* Peripheral clock enable */

    __HAL_RCC_I2C1_CLK_ENABLE();

  }

}

#hal-i2c #ovr #stm32l0xx
1 REPLY 1
Walid FTITI_O
Senior II
Posted on July 15, 2016 at 16:29

Hi parker.devin,

Before starting a new communication transfer, you need to 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. Try to add before HAL_I2C_Slave_Receive_IT() the following :

while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
{
}

-Hannibal-