This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

BQ40Z80: Unable to write ManufacturerBlockAccess() data over SMBus using C code

Part Number: BQ40Z80
Other Parts Discussed in Thread: BQSTUDIO, EV2400

Hi support team,

As per the technical reference manual of BQ40Z80, I am trying to Read Chemical ID() (0x0006) via ManufacturerBlockAccess() method. Unfortunately, the write command has failed and it generates a timeout error.  please go through below list of issue detail:

Hardware Information: 

BMS IC: BQ40Z80

MCU : ESP32

Method: A

Step-1: Initialized ESP32 I2C driver

Step-2: Aligned frame format for SMBus

Step-3: Writing data over smbus: {0x44, 0x02, 0x06, 0x00}, It gives timeout error even I had tried with various timeout.

Step-4: Read data over smbus: {0x44} due to failure of write it has returned {0x54, 0x00, 0xa1, 0x01, 0x00, 0x00}.

Method: B

Step-1: Using EV2400 module with BQ40Z80 and access using bqstudio

Step-2: I am able to write block requests and getting proper responses as well.

 I am curious to know that where did I make mistake in my C code. One more thing I am able to read some of registers with proper values. Here, I am posting c code for your reference:

esp_err_t smbus_write_block(const smbus_info_t * smbus_info, uint8_t command, uint8_t * data, uint8_t len)
{
// Protocol: [S | ADDR | Wr | As | COMMAND | As | LEN | As | DATA-1 | As | DATA-2 | As ... | DATA-LEN | As | P]
esp_err_t err = ESP_FAIL;
if (_is_init(smbus_info) && data)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, smbus_info->address << 1 | WRITE_BIT, ACK_CHECK);
i2c_master_write_byte(cmd, command, ACK_CHECK);
i2c_master_write_byte(cmd, len, ACK_CHECK);
for (size_t i = 0; i < len; ++i)
{
i2c_master_write_byte(cmd, data[i], ACK_CHECK);
}
i2c_master_stop(cmd);
err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout));
i2c_cmd_link_delete(cmd);
}
return err;
}

esp_err_t smbus_read_block(const smbus_info_t * smbus_info, uint8_t command, uint8_t * data, uint8_t * len)
{
// Protocol: [S | ADDR | Wr | As | COMMAND | As | Sr | ADDR | Rd | As | LENs | A | DATA-1 | A | DATA-2 | A ... | DATA-LEN | N | P]
esp_err_t err = ESP_FAIL;

if (_is_init(smbus_info) && data && len)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, smbus_info->address << 1 | WRITE_BIT, ACK_CHECK);
i2c_master_write_byte(cmd, command, ACK_CHECK);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, smbus_info->address << 1 | READ_BIT, ACK_CHECK);
uint8_t slave_len = 0;
i2c_master_read_byte(cmd, &slave_len, ACK_VALUE);
err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout));
i2c_cmd_link_delete(cmd);

if (err != ESP_OK)
{
*len = 0;
return err;
}

if (slave_len > *len)
{
ESP_LOGW(TAG, "slave data length %d exceeds data len %d bytes", slave_len, *len);
slave_len = *len;
}

cmd = i2c_cmd_link_create();
for (size_t i = 0; i < slave_len - 1; ++i)
{
i2c_master_read_byte(cmd, &data[i], ACK_VALUE);
}
i2c_master_read_byte(cmd, &data[slave_len - 1], NACK_VALUE);
i2c_master_stop(cmd);
err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout));
i2c_cmd_link_delete(cmd);

if (err == ESP_OK)
{
*len = slave_len;
}
else
{
*len = 0;
}
}
return err;
}

Calling above APIS:
int8_t buff[2] = {0x06, 0x00};

uint8_t data[32U] = {0U};

uint8_t length;

if (ESP_OK != smbus_write_block(&smbusInfo, 0x44, buff, 2))
{
ESP_LOGE(TAG, "Failed to smbus_write_word SMBUS");
}

length = 6;

if (ESP_OK != smbus_read_block(&smbusInfo, 0x44, data, &length))
{
ESP_LOGE(TAG, "Failed to smbus_read_block SMBUS");
}
else
{
print_data (data, length);
}

The output of the above code snippet:
E (20351) smbus: I2C timeout
E (20351) smbus: Failed to smbus_write_word SMBUS
I (20371) smbus: RX DATA:
I (20371) smbus: 0x54
I (20371) smbus: 0x00
I (20371) smbus: 0xa1
I (20371) smbus: 0x01
I (20371) smbus: 0x00
I (20371) smbus: 0x00

SMBUS Code ref: github.com/.../esp32-smbus