For the reference: the same problem is described there, but the author's solution doesn't work for me - I2C busy flag strange behaviour
I used STM32CubeMX to generate project template with I2C peripherals initialization. Unfortunately it works somehow strange: after HAL_I2C_MspInit(I2C1)
is being invoked, bus is considered permanently busy.
If I try to apply
__HAL_RCC_I2C1_FORCE_RESET();
HAL_Delay(1000);
__HAL_RCC_I2C1_RELEASE_RESET();
That resolves problem with BUSY
flag, but causes problem - SB
bit not being set after START
is generated. According to debugger, I2C registers are cleared completely after the reset - I suspect this is the problem with that method.
I also confimed short voltage drop at SDA line during startup, that is probably the cause of the issue. I took a closer look at SDA/SCL pins initialization code generated by CubeMX:
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
/**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.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
I changed it to put clock enable before HAL_GPIO_Init()
invocation and now my I2C communications works (at least I didn't noticed anything weird yet).
Finally, my question is - is there any better solution for this? CubeMX places clock enable code after the GPIO init method invocation. I can stay with two invocations of __HAL_RCC_I2C1_CLK_ENABLE()
, but that's quite ugly in my opinion, so I am looking for any better solution, either software or hardware.
Device is STM32F100RB on STM32VLDiscovery board (with STLink v1), in case that matters.