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.

BQ35100: Read and Write DATA FLASH MEMORY BQ35100

Part Number: BQ35100
Other Parts Discussed in Thread: BQSTUDIO

Tool/software:

Good afternoon,
I'm an inexperienced programmer so I'm sorry if the question is somewhat inappropriate.

I am trying to change a value in the DATA FLASH MEMORY of my bq35100. To do this, I first verify that the device is in full access mode. Then I read the value of ccgain and it gives me a result of 17276.

After trying to change the value to these values: 0x1234 and 0x5678. After that I read the ccgain values ​​again but they still give 17276. What am I doing wrong? Am I missing something in between? I attach the code I use:

FUNCTIONS:

// Function to read a 16-bit register
uint16_t read16bitRegister(uint8_t reg_addr, unsigned char numBytesReceived) {
uint16_t data;
TWI_BQRead(reg_addr, numBytesReceived); // Read 2 bytes from the specified register
data = (twi_data_buffer[1] << 8) | twi_data_buffer[0]; // Combine the two bytes read in little-endian format
return data;
}

// Function to write a 16-bit register in little-endian format
void write16bitRegister(uint8_t reg_addr, uint16_t data) {
uint8_t low_byte = data & 0xFF;
uint8_t high_byte = (data >> 8) & 0xFF;
TWI_BQWrite(reg_addr, low_byte, high_byte); // Write the two bytes in little-endian format
_delay_ms(10); // Add a small delay to ensure the write completes
}

uint16_t readCCGain() {
uint16_t cc_gain;

// Step 1: Write the register address to ManufacturerAccessControl
write16bitRegister(MANUFACTURER_ACCESS_REG, 0x4000); // Address of CC Gain in DataFlash
_delay_ms(10); // Pause to process

// Step 2: Start reading from MACData (0x40)
TWI_BQRead(0x40, 2); // Read 2 bytes from MACData address (0x40)

// Step 3: Combine the two bytes read in little-endian format
cc_gain = (twi_data_buffer[1] << 8) | twi_data_buffer[0];

return cc_gain; // Return the CC Gain value
}

void writeCCGain(uint16_t new_value) {
uint8_t checksum;

// Step 1: Write the register address to ManufacturerAccessControl
write16bitRegister(MANUFACTURER_ACCESS_REG, 0x4000); // Address of CC Gain in DataFlash
_delay_ms(10); // Pause to process

// Step 2: Write the new value to MACData (0x40)
TWI_BQWrite(0x40, new_value & 0xFF, (new_value >> 8) & 0xFF); // Write the value in little-endian format

// Step 3: Calculate the checksum
checksum = 0x00 + 0x40 + (new_value & 0xFF) + ((new_value >> 8) & 0xFF); // Add the address and data values
checksum = ~checksum + 1; // 2's complement

// Step 4: Write the checksum and length
TWI_BQWrite(0x60, checksum, 0x02); // Write the checksum and length (2 bytes)
_delay_ms(10); // Pause to ensure the write completes
}

void displayCCGainOnConsole() {
uint16_t cc_gain;
char buffer[10]; // Buffer to store the value converted to string

// Read the CC Gain value
cc_gain = readCCGain(); // Call the function that reads CC Gain

// Convert the CC Gain value to a string (decimal)
itoa(cc_gain, buffer, 10); // Convert the value to a decimal string (base 10)

// Send the value to the console
send_AT_command("CC Gain value: ");
send_AT_command(buffer); // Send the converted value as a string
}

void verifyDeviceStatus() {
uint16_t control_status;
char buffer[10];

// Read the value from the Control Status register
control_status = read16bitRegister(CONTROL_STATUS_REG, 2); // Read 2 bytes from the Control Status register

// Extract SEC1 and SEC0 bits (bits 14 and 13)
uint8_t sec_bits = (control_status >> 13) & 0x03; // Get SEC1 and SEC0 bits

// Display the current mode on the console
if (sec_bits == 0x01) {
send_AT_command("Mode: Full Access");
} else if (sec_bits == 0x02) {
send_AT_command("Mode: Unsealed");
} else if (sec_bits == 0x03) {
send_AT_command("Mode: Sealed");
} else {
send_AT_command("Mode: Reserved or unknown");
}

// Display the Control Status value on the console (optional)
itoa(control_status, buffer, 16);
send_AT_command("Control Status value: ");
send_AT_command(buffer);
}

void unlockDevice() {
verifyDeviceStatus(); // Verify the current state before attempting to unlock

uint16_t control_status = read16bitRegister(CONTROL_STATUS_REG, 2); // Read the current state
uint8_t sec_bits = (control_status >> 13) & 0x03; // Get SEC1 and SEC0 bits

// If the device is in Sealed mode (11), send the Unseal command
if (sec_bits == 0x03) {
send_AT_command("Attempting to unlock the device...");

// Step 1: Send the Unseal command (typically 0x8000)
write16bitRegister(MANUFACTURER_ACCESS_REG, 0x8000); // Send Unseal command
_delay_ms(1000); // Pause to process

// Step 2: Send the Full Access command if necessary (0xFFFF)
write16bitRegister(MANUFACTURER_ACCESS_REG, 0xFFFF); // Send Full Access command
_delay_ms(1000); // Pause to process

send_AT_command("Unlock command sent. Verifying status...");

// Verify the status after attempting to unlock
verifyDeviceStatus(); // Display the new state on the console
} else {
send_AT_command("The device is already unlocked.");
}
}

void writeToDataFlash(uint16_t address, uint16_t value1, uint16_t value2) {
uint8_t checksum;
uint8_t macData[4];
uint8_t sum = 0;

// Write the address to ManufacturerAccessControl (0x3E, 0x3F) in little-endian
write16bitRegister(MANUFACTURER_ACCESS_REG, address); // Write address 0x4000 to ManufacturerAccessControl
_delay_ms(500); // Pause to process

// Write the data to MACData (0x40–0x43) in big-endian
macData[0] = (value1 >> 8) & 0xFF; // High byte of value1
macData[1] = value1 & 0xFF; // Low byte of value1
macData[2] = (value2 >> 8) & 0xFF; // High byte of value2
macData[3] = value2 & 0xFF; // Low byte of value2

// Write the 4 bytes of data to MACData
TWI_BQWrite(0x40, macData[0], macData[1]); // Write the first two bytes (0x40-0x41)
TWI_BQWrite(0x42, macData[2], macData[3]); // Write the second two bytes (0x42-0x43)
_delay_ms(500); // Pause to process

// Calculate the checksum: complement of the sum of ManufacturerAccessControl and MACData
sum += (address & 0xFF); // Low byte of the address
sum += (address >> 8) & 0xFF; // High byte of the address
sum += macData[0]; // Sum of the data
sum += macData[1];
sum += macData[2];
sum += macData[3];
checksum = ~sum + 1; // 2's complement

// Write the checksum to MACDataSum (0x60)
TWI_BQWrite(0x60, checksum, 0x00); // Write the checksum
_delay_ms(500); // Pause to process

// Write the data length to MACDataLen (0x61)
TWI_BQWrite(0x61, 0x08, 0x00); // Total length: 4 + length of MACData
_delay_ms(500); // Pause to process
}

void changeCCGainValue() {
uint16_t new_value1 = 0x1234; // First value to write (0x1234 in hexadecimal)
uint16_t new_value2 = 0x5678; // Second value to write (0x5678 in hexadecimal)

unlockDevice(); // Ensure the device is unlocked

_delay_ms(1000);

// Call the function to write to DataFlash at address 0x4000
writeToDataFlash(0x4000, new_value1, new_value2);

// Send a message to the console to confirm
send_AT_command("New values written to CC Gain: 0x1234 and 0x5678");
}

MAIN:

_delay_ms(3000); 

send_AT_command("Reading CC Gain value...");

displayCCGainOnConsole();

_delay_ms(1000); 

send_AT_command("Changing CC Gain values...");

changeCCGainValue();

_delay_ms(3000); 

Thank you. All the best

  • Hello Christian,

    Can you try to change the value of a different register, just to see if the process can work on a separate register. I would recommend trying to change the value in any of the Manufacturer Info Block registers.

    Regards,

    Adrian

  • Hello Adrian,

    I have tried writing to the manufacturer block, specifically at address 0x4040, but the same thing keeps happening, the registry value is not updated. Here is the code used:

    void readManufacturerBlock(uint16_t address) {
    char buffer[10];

    // Step 1: Write the address to ManufacturerAccessControl (0x3E)
    escribirRegistro16bits(MANUFACTURER_ACCESS_REG, address); // Set the address to read from
    _delay_ms(500); // Pause to process

    // Step 2: Read 4 bytes from MACData (0x40–0x43)
    lecturaTWI_BQ(0x40, 4); // Read 4 bytes from MACData (0x40–0x43)

    // Step 3: Combine the bytes into two 16-bit values (big-endian format)
    uint16_t value1 = (twi_data_buffer[1] << 8) | twi_data_buffer[0]; // First 2 bytes (little-endian to big-endian)
    uint16_t value2 = (twi_data_buffer[3] << 8) | twi_data_buffer[2]; // Last 2 bytes (little-endian to big-endian)

    // Step 4: Print the values to the console
    enviar_comando_AT("Manufacturer Block Values: ");

    // Convert and print the first value
    itoa(value1, buffer, 16); // Convert to hexadecimal
    enviar_comando_AT("0x");
    enviar_comando_AT(buffer);
    enviar_comando_AT(" ");

    // Convert and print the second value
    itoa(value2, buffer, 16); // Convert to hexadecimal
    enviar_comando_AT("0x");
    enviar_comando_AT(buffer);
    enviar_comando_AT("\r\n"); // Newline for formatting
    }

    void changeManufacturerInfoBlock() {
    uint16_t new_value1 = 0xAAAA; // First value to write (0xAAAA in hexadecimal)
    uint16_t new_value2 = 0xBBBB; // Second value to write (0xBBBB in hexadecimal)

    desbloquearDispositivo(); // Ensure the device is unlocked

    _delay_ms(1000);

    // Step 1: Read and print the current values from the Manufacturer Information Block
    enviar_comando_AT("Reading Manufacturer Block before writing...");
    readManufacturerBlock(0x4040); // Read and print the current values

    _delay_ms(1000);

    // Step 2: Write the new values to the Manufacturer Information Block at address 0x4040
    enviar_comando_AT("Writing new values to Manufacturer Block...");
    writeManufacturerBlock(0x4040, new_value1, new_value2); // Using your functions

    _delay_ms(1000);

    // Step 3: Read and print the new values from the Manufacturer Information Block
    enviar_comando_AT("Reading Manufacturer Block after writing...");
    readManufacturerBlock(0x4040); // Read and print the new values
    }


    void writeManufacturerBlock(uint16_t address, uint16_t value1, uint16_t value2) {
    uint8_t checksum;
    uint8_t macData[4];
    uint8_t sum = 0;

    // Step 1: Write the address to ManufacturerAccessControl (0x3E) in little-endian format
    escribirRegistro16bits(MANUFACTURER_ACCESS_REG, address); // Write the address to ManufacturerAccessControl
    _delay_ms(500); // Pause to process

    // Step 2: Write the data to MACData (0x40–0x43) in big-endian format
    macData[0] = (value1 >> 8) & 0xFF; // High byte of value1
    macData[1] = value1 & 0xFF; // Low byte of value1
    macData[2] = (value2 >> 8) & 0xFF; // High byte of value2
    macData[3] = value2 & 0xFF; // Low byte of value2

    // Write the first two bytes to MACData (0x40–0x41)
    escrituraTWI_BQ(0x40, macData[0], macData[1]);

    // Write the next two bytes to MACData (0x42–0x43)
    escrituraTWI_BQ(0x42, macData[2], macData[3]);
    _delay_ms(500); // Pause to process

    // Step 3: Calculate the checksum (complement of the sum of ManufacturerAccessControl and MACData)
    sum += (address & 0xFF); // Low byte of the address
    sum += (address >> 8) & 0xFF; // High byte of the address
    sum += macData[0]; // Add the data
    sum += macData[1];
    sum += macData[2];
    sum += macData[3];
    checksum = ~sum + 1; // 2's complement

    // Step 4: Write the checksum to MACDataSum (0x60)
    escrituraTWI_BQ(0x60, checksum, 0x00); // Write the checksum
    _delay_ms(500); // Pause to process

    // Step 5: Write the length of the data to MACDataLen (0x61)
    escrituraTWI_BQ(0x61, 0x08, 0x00); // Total length: 4 bytes of data + 4 (8 in total)
    _delay_ms(500); // Pause to process
    }

    MAIN:

    // Try reading and writing new values to the Manufacturer Information Block
    enviar_comando_AT("Writing and reading values to/from Manufacturer Information Block...");
    changeManufacturerInfoBlock();

    CONSOLE LOGS:

    Reading Manufacturer Block before writing...
    Manufacturer Block Values:
    0x
    0

    0x
    0


    Writing new values to Manufacturer Block...
    Reading Manufacturer Block after writing...
    Manufacturer Block Values:
    0x
    0

    0x
    0

    Thank you.

    Regards.

  • Hello Christian,

    Are you able to use BQStudio? This can help in debugging your code. Can you share digital logic captures of the communication lines when you are writing and reading from the device?

    Regards,

    Adrian