I'm working on a Battery Management System (BMS) project and utilizing the BQ76952 AFE chip. I've successfully configured the chip and can reliably read voltage and current registers under normal conditions. However, I'm encountering an issue where the I2C communication between the AT32F415 controller and the BQ76952 intermittently halts. During this problem, the SDA line goes high, and the SCL line remains low. I've used a logic analyzer to monitor the I2C communication.
Regrettably, I'm unable to share the specific software code due to my company's proprietary policies, but I'll provide as much detail as I can. I've identified that this I2C issue occurs when the AFE reports a Cell Under Voltage (CUV) alarm and attempts to control the discharge FETs. The AFE repeatedly cycles between turning off and turning on the DSG FETs as it responds to the alarm, and I'm concurrently attempting to read voltage and current data via I2C from the microcontroller.
I've attempted to address this issue by reducing the I2C timeout value and clearing error flags, but these measures have not resolved the problem. How can I ensure that the I2C communication remains stable and reliable, particularly when CUV alarms are triggered and the AFE controls the FETs in quick succession?
Below are I2C config define
#define I2C_TIMEOUT 0xFFF
#define I2Cx_SPEED 400000
#define I2Cx_ADDRESS 0x87
#define I2Cx_PORT I2C1
#define I2Cx_CLK CRM_I2C1_PERIPH_CLOCK
#define I2Cx_SCL_PIN GPIO_PINS_6
#define I2Cx_SCL_GPIO_PORT GPIOF
#define I2Cx_SCL_GPIO_CLK CRM_GPIOF_PERIPH_CLOCK
#define I2Cx_SDA_PIN GPIO_PINS_7
#define I2Cx_SDA_GPIO_PORT GPIOF
#define I2Cx_SDA_GPIO_CLK CRM_GPIOF_PERIPH_CLOCK
#define I2Cx_EVT_IRQn I2C1_EVT_IRQn
#define I2Cx_ERR_IRQn I2C1_ERR_IRQn
void i2c_config(i2c_handle_type* hi2c)
{
/* reset i2c peripheral */
i2c_reset(hi2c->i2cx);
/* i2c peripheral initialization */
i2c_lowlevel_init(hi2c);
/* i2c peripheral enable */
i2c_enable(hi2c->i2cx, TRUE);
}
void i2c_lowlevel_init(i2c_handle_type* hi2c)
{
gpio_init_type gpio_initstructure;
// uint32_t sample_i2cx=hi2c->i2cx;
if(hi2c->i2cx == I2Cx_PORT)
// if(sample_i2cx == I2Cx_PORT)
{
/* i2c periph clock enable */
crm_periph_clock_enable(I2Cx_CLK, TRUE);
crm_periph_clock_enable(I2Cx_SCL_GPIO_CLK, TRUE);
crm_periph_clock_enable(I2Cx_SDA_GPIO_CLK, TRUE);
crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
gpio_pin_remap_config(I2C1_GMUX_0010,TRUE);
/* gpio configuration */
gpio_initstructure.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
gpio_initstructure.gpio_pull = GPIO_PULL_UP;
gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MAXIMUM;
/* configure i2c pins: scl */
gpio_initstructure.gpio_pins = I2Cx_SCL_PIN;
gpio_init(I2Cx_SCL_GPIO_PORT, &gpio_initstructure);
/* configure i2c pins: sda */
gpio_initstructure.gpio_pins = I2Cx_SDA_PIN;
gpio_init(I2Cx_SDA_GPIO_PORT, &gpio_initstructure);
/* configure and enable i2c interrupt */
nvic_irq_enable(I2Cx_EVT_IRQn, 0, 0);
nvic_irq_enable(I2Cx_ERR_IRQn, 0, 0);
i2c_init(hi2c->i2cx, I2C_FSMODE_DUTY_2_1, I2Cx_SPEED);
//i2c_clock_stretch_enable(hi2c->i2cx,FALSE);
//i2c_general_call_enable(hi2c->i2cx,FALSE);
//i2c_own_address1_set(hi2c->i2cx, I2C_ADDRESS_MODE_7BIT, I2Cx_ADDRESS);
}
}
I am using FreeRTOS kernel and read and write register are done in one of critical task. I will share where code is continously call over by Critical Task. I can say that my controller is not stuck in any loop, because of CAN communication and happening, Led blink in happening, State machine is transitioning accept the I2C bus are not responding as it is. Every I2C communication are returning some I2C error, most of the time its in bus error. So i am little stuck as i tried multiple approached and not able to fixed it due not understanding the Root cause of it. Please help me here.
{
if(flag == I2C_BUSYF_FLAG)
{
timeout = 0xFFF;
while(i2c_flag_get(hi2c->i2cx, flag) != RESET)
{
time_check = timeout;
/* check timeout */
if((timeout--) == 0)
{
hi2c->error_code = I2C_ERR_TIMEOUT;
//i2c_flag_clear(hi2c->i2cx, I2C_BUSYF_FLAG);
return I2C_ERR_TIMEOUT;
}
}
}
It is getting called this i2C wait flag again and again for every i2c read and write.