Hardware : STM32L452RET6
Software : STM32CubeFW_L4 v1.17
My problem : After using I2C with standard polling functions, i would like to use IT Functions to optimize my firmware. I try to work with HAL_I2C_Master_Transmit_IT & HAL_I2C_Master_Receive_IT but my firmware stay blocked in the I2C1_EV_IRQHandler :
void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c)
{
/* Get current IT Flags and IT sources value */
uint32_t itflags = READ_REG(hi2c->Instance->ISR);
uint32_t itsources = READ_REG(hi2c->Instance->CR1);
/* I2C events treatment -------------------------------------*/
if (hi2c->XferISR != NULL)
{
hi2c->XferISR(hi2c, itflags, itsources);
}
}
The IT flags seems not to be cleared and the hi2c->XferISR register seems to be NULL : enter image description here
Edit 1 : Some additional informations : The following functions are never called.
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
I tried to clear I2C_FLAG_TXE & I2C_FLAG_TXIS but it's seems not possible.
Edit 2 : To answer some questions in comment :
The init code is well passed :
Status I2C_Init(I2C_HandleTypeDef *hi2c)
{
// Peripheral Clock Enable
__HAL_RCC_I2C1_CLK_ENABLE();
hi2c->Instance = I2C1;
hi2c->Init.Timing = 0x10909CEC;
hi2c->Init.OwnAddress1 = 0;
hi2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c->Init.OwnAddress2 = 0;
hi2c->Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
// Interrupts Activation
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
if (HAL_I2C_Init(hi2c) != HAL_OK)
{
return STATUS_ERROR;
}
return STATUS_OK;
}
There is no bus activity on scope.
-
1\$\begingroup\$ How have you initialized the I2C? Did you write init code yourself or did you let CubeIDE/CubeMX generate initial code for you? \$\endgroup\$Justme– Justme2021年09月06日 14:54:57 +00:00Commented Sep 6, 2021 at 14:54
-
\$\begingroup\$ Is the slave responding correct? \$\endgroup\$jay– jay2021年09月06日 16:05:58 +00:00Commented Sep 6, 2021 at 16:05
-
\$\begingroup\$ @jay That would be unknown, since the ISR is null, so the code would not even go that far to know if any slave is on the bus. \$\endgroup\$Justme– Justme2021年09月06日 17:54:52 +00:00Commented Sep 6, 2021 at 17:54
-
\$\begingroup\$ TXE sounds like TX empty. Meantime TXIS is used for slave mode. Read the reference manual. \$\endgroup\$jay– jay2021年09月06日 23:23:46 +00:00Commented Sep 6, 2021 at 23:23
-
\$\begingroup\$ p1127, I2C_TXDR register is not empty. p1141, Slave transmitter A transmit interrupt status (TXIS) is generated when the I2C_TXDR register becomes empty. An interrupt is generated if the TXIE bit is set in the I2C_CR1 register. The TXIS bit is cleared when the I2C_TXDR register is written with the next data byte to be transmitted. \$\endgroup\$jay– jay2021年09月06日 23:24:06 +00:00Commented Sep 6, 2021 at 23:24
1 Answer 1
Ok i found the source of my problem :
I have three steps to drive the I2C :
- My main function drive a peripheral one : VL53L0X_Init(...);
- My peripheral function drive a register one : I2C_WriteRegister(...);
- My register function use HAL_I2C_Master_Transmit_IT(...);
On the first one : I give a pointer on I2C Structure when it is received i saved this pointer with : *I2C = hi2c;
I2C is the global variable contained in the peripheral file : I2C_HandleTypeDef I2C.
My error here is to affect the pointer to the variable. The solution is to declare a pointer and to copy the I2C structure pointer to it during the init :
I2C_HandleTypeDef *I2C;
I2C_HandleTypeDef *hi2c;
I2C = hi2c;