I am using two STM32F303K8 Nucleos and hooked up the SDA/SCL (GPIO B PIN 6 & 7) pins to 3.3V across roughly 4.7K resistors to 3V3.
When I check the voltage on the pins, both are 3V3 so it's not locking up and it's sitting idle yet the I2C (or HAL at least) keeps telling me it's busy.
I took most of the code out of the CubeMX example using HAL 1.10.
This is the main loop for it
while(true)
{
#ifdef MASTER_BOARD
do
{
if(HAL_I2C_Master_Transmit_IT(&I2CHandle, (uint16_t)0x30F, (uint8_t*)aTxBuffer, 7) != HAL_OK)
{
Error_Handler();
}
while(HAL_I2C_GetState(&I2CHandle) != HAL_I2C_STATE_READY)
{
}
}while(HAL_I2C_GetError(&I2CHandle) == HAL_I2C_ERROR_AF);
HAL_Delay(1000);
#else
do
{
if(HAL_I2C_Slave_Receive_IT(&I2CHandle, (uint8_t*)aRxBuffer, 7) != HAL_OK)
{
Error_Handler();
}
while(HAL_I2C_GetState(&I2CHandle) != HAL_I2C_STATE_READY)
{
}
}while(HAL_I2C_GetError(&I2CHandle) == HAL_I2C_ERROR_AF);
#endif
}
This is the initialization (HAL_I2C_Init() calls the HAL_I2C_MspInit() function internally)
bool InitI2C()
{
I2CHandle.Instance = I2C1;
I2CHandle.Init.Timing = 0x00400B27;
I2CHandle.Init.OwnAddress1 = 0x30F;
I2CHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_10BIT;
I2CHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2CHandle.Init.OwnAddress2 = 0xFF;
I2CHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2CHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if(HAL_I2C_Init(&I2CHandle) != HAL_OK)
return false;
HAL_I2CEx_ConfigAnalogFilter(&I2CHandle, I2C_ANALOGFILTER_ENABLE);
return true;
}
The MspInit function along with the I2C interrupts
extern "C"
{
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct;
/*##-1- Configure the I2C clock source. The clock is derived from the SYSCLK #*/
RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
RCC_PeriphCLKInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);
/*##-2- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
__HAL_RCC_GPIOB_CLK_ENABLE();
/* Enable I2Cx clock */
__HAL_RCC_I2C1_CLK_ENABLE();
/*##-3- Configure peripheral GPIO ##########################################*/
/* I2C TX GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* I2C RX GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*##-4- Configure the NVIC for I2C ########################################*/
/* NVIC for I2Cx */
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 1, 1);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 1, 2);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
}
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
}
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
}
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
}
}
Yes the Msp function triggers because I tested it with an LED toggle. The issue is that the interrupts never fire off (which would toggle an LED upon complete transmission) and both the master and slave hang on this
while(HAL_I2C_GetState(&I2CHandle) != HAL_I2C_STATE_READY)
It doesn't matter which boots up first, or if at the same time. It just hangs saying it's busy.
Everywhere I am reading people are always having issues setting this up and nobody has any valid solution.
Edit 1:
So I got it to a state where the SDA pin is high and SCL is low. I am not sure what this means, did it get stuck trying to figure out the ACK? All that happens after the master transmits this is that it gets stuck in the busy loop and so does the receiver. But it only happens when the master boots up after the slave. If the slave boots up first both lines will remain high.
Edit 2:
Figured it out, read below.