Tool/software:
I'm using the BQ76942 and am trying to use OTP programming but cannot enter FULL ACCESS mode.
I've been using the chip on these boards for months now with no issues. The hardware is working and well understood.
Page 125 in the TRM describes the process for Data Memory Access and I believe I am executing this correctly. I've verified this with my LA as a check. I'm including this code so you can have a look.
What state does the IC have to be in to enter full access (other than first going through UNSEALED.) Do I enter CFG_UPDATE before or after going through the process to enter FULL ACCESS? Should I do the register reset before or after?
Any help you can give is appreciated! I'm including the relevant code. Perhaps there is some easy mistake in that.
Function calls for FULLACCESS:
CommandSubcommands(BQ769x2_RESET); // Resets the BQ769x2 registers writeDataMemoryAccess(0x9257, 0x0414, 2); delayUS(60000); writeDataMemoryAccess(0x9259, 0x3672, 2); delayUS(60000); writeDataMemoryAccess(0x925B, 0xFFFF, 2); delayUS(60000); writeDataMemoryAccess(0x925D, 0xFFFF, 2); delayUS(60000); uint8_t battery_status_data = checkBQAccessMode(); if(battery_status_data != 4) { // while(1) // { // LEDControl("R", 100, 4); // } } delayUS(60000); // Enter CONFIGUPDATE mode (Subcommand 0x0090) - It is required to be in CONFIG_UPDATE mode to program the device RAM settings // See TRM for full description of CONFIG_UPDATE mode CommandSubcommands(SET_CFGUPDATE); delayUS(60000); //Use OTP_WR_CHECK() to determine if the chip is ready for OTP programming. OTP WR CHECK will return uint8_t otp_write_status = OTPWriteCheck(); delayUS(60000); if(otp_write_status == 0X80){ //Write to the desired OTP Register and send the OTP Write command test = 1; }
The writeDataMemoryAccess() function:
void writeDataMemoryAccess(uint16_t memory_address, uint16_t value, uint8_t size){ uint8_t address[2] = {0}; address[0] = memory_address & 0xFF; // Lower byte of address address[1] = (memory_address >> 8) & 0xFF; // Upper byte of address uint8_t data[32] = {0}; uint8_t i; // Prepare data in little endian format for(i = 0; i < size; i++){ data[i] = (value >> (i * 8)) & 0xFF; } // Prepare the buffer for checksum calculation uint8_t checksum_buffer[2 + size]; // 0x3E, 0x3F, and data buffer checksum_buffer[0] = address[0]; // 0x3E checksum_buffer[1] = address[1]; // 0x3F for(i = 0; i < size; i++){ checksum_buffer[2 + i] = data[i]; // Data bytes starting at 0x40 } // Calculate checksum using existing Checksum function uint8_t checksum = Checksum(checksum_buffer, 2 + size); // Length calculation: data length + 4 (for 0x3E, 0x3F, 0x60, 0x61) uint8_t length = size + 4; // Write lower byte of address to 0x3E I2C_WriteReg(0x3E, &address[0], 1); // Write upper byte of address to 0x3F I2C_WriteReg(0x3F, &address[1], 1); // Write data to 0x40 I2C_WriteReg(0x40, data, size); // Write checksum to 0x60 I2C_WriteReg(0x60, &checksum, 1); // Write length to 0x61 I2C_WriteReg(0x61, &length, 1); }
The I2C_WriteReg() function is just a pass through to STM32 HAL_I2C_Mem_Write() function.