2016-07-13 02:05 PM
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.//mainint 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 initvoid 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 #stm32l0xx2016-07-15 07:29 AM
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-