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.

BQ27220: OTP Program without bqstudio

Part Number: BQ27220
Other Parts Discussed in Thread: BQSTUDIO

Tool/software:

We want to update the OTP registers of FCC, DCap and Battery low% . We have followed the steps mentioned in 6.1 Data Memory Parameter Update Example in TRM of the BQ27220 Ic. the values its showing is 0x00 and even after changing the battery id accordingly their was no impact. Can you tell us the proper steps to follow. We are using the below script to write in it.

#!/bin/bash

echo "Reading 0x3a/3b Reg..."
sleep 1
value_3a=$(i2cget -y 0 0x55 0x3a b)
sleep 1
value_3b=$(i2cget -y 0 0x55 0x3b b)
echo "Value at register address 0x3a: $value_3a"
echo "Value at register address 0x3b: $value_3b"
operation_status=$(i2cget -y 0 0x55 0x3a)
SEC1=$(($operation_status >> 2 & 1))
SEC0=$(($operation_status >> 1 & 1))

#if already in Unseal
if [ $SEC1 -eq 1 ] && [ $SEC0 -eq 0 ]; then
 echo "Device already in UNSEAL IF BLOCK"
 echo "Reading 0x3a/3b Reg..."
 sleep 1
 value_3a=$(i2cget -y 0 0x55 0x3a b)
 sleep 1
 value_3b=$(i2cget -y 0 0x55 0x3b b)
 echo "Value at register address 0x3a: $value_3a"
 echo "Value at register address 0x3b: $value_3b"

elif [ $SEC1 -eq 0 ] && [ $SEC0 -eq 1 ]; then
 echo "Device already in FULL ACCESS ELSE IF BLOCK"
 sleep 1
 value_3a=$(i2cget -y 0 0x55 0x3a b)
 sleep 1
 value_3b=$(i2cget -y 0 0x55 0x3b b)
 echo "Value at FA 0x3a: $value_3a"
 echo "Value at FA 0x3b: $value_3b"

else
 echo "STEP 1"
 echo "Sending UNSEAL command...ELSE BLOCK"
 i2cset -y 0 0x55 0x00 0x14 b
 sleep 2
 i2cset -y 0 0x55 0x01 0x04 b
 sleep 2
 i2cset -y 0 0x55 0x00 0x72 b
 sleep 2
 i2cset -y 0 0x55 0x01 0x36 b
 sleep 2
 value_3a=$(i2cget -y 0 0x55 0x3a b)
 sleep 1
 value_3b=$(i2cget -y 0 0x55 0x3b b)
 echo "Value at US 0x3a: $value_3a"
 echo "Value at US 0x3b: $value_3b"
fi
echo "STEP 2"                                 	 
echo "Getting FULL ACCESS..."       	 
i2cset -y 0 0x55 0x00 0xFF b   	 
sleep 1                                    	 
i2cset -y 0 0x55 0x01 0xFF b               	 
sleep 1                                    	 
i2cset -y 0 0x55 0x00 0xFF b                	 
sleep 1                                     	 
i2cset -y 0 0x55 0x01 0xFF b                	 
sleep 1                                 	 
                                              	 
echo "Reading Operation Status"               	 
sleep 5                               	 
value_3a=$(i2cget -y 0 0x55 0x3a b)   	 
sleep 5                             	 
value_3b=$(i2cget -y 0 0x55 0x3b b)
echo "Value at register address 0x3a: $value_3a"
echo "Value at register address 0x3b: $value_3b"
                                            	 
                                            	 
#### Entering into Config Update #####      	 
                                              	 
echo "STEP 3"                                 	 
echo "Entering configuration update mode..."  	 
sleep 2                                       	 
i2cset -y 0 0x55 0x00 0x90 b               	 
sleep 2                                	 
i2cset -y 0 0x55 0x01 0x00 b           	 
                                       	 
echo "STEP 4"                              	 
#Polling OperationStatus register until bit 2 is set, with a try limit of 100 times
#try=0                                                                        	 
#max_try=100                                                                  	 
echo "Polling OperationStatus register for CFGUPDATE bit2..."                 	 
operation_status=$(i2cget -y 0 0x55 0x3b)                                     	 
while [ $((operation_status & 0x04)) -eq 0 ]; do                              	 
 echo "Waiting for config update...."                                         	 
 sleep 2 # Add a sleep to avoid high CPU usage in the loop                    	 
done                                                                          	 
echo "CFGUPDATE mode confirmed."                        	 
sleep 3                                                 	 
                                                        	 
echo "Reading Operation Status"                      	 
sleep 5                                                                       	 
value_3a=$(i2cget -y 0 0x55 0x3a b)                                           	 
sleep 5                                              	 
value_3b=$(i2cget -y 0 0x55 0x3b b)                     	 
echo "Value at register address 0x3a: $value_3a"        	 
echo "Value at register address 0x3b: $value_3b"
                                           	 
operation_status=$(i2cget -y 0 0x55 0x3a)
SEC1=$(($operation_status >> 2 & 1))                                          	 
SEC0=$(($operation_status >> 1 & 1))       	 
                                           	 
if [ $SEC1 -ne 0 ] && [ $SEC0 -ne 1 ];then              	 
    	echo "Getting FULL ACCESS..."      	 
    	i2cset -y 0 0x55 0x00 0xFF b        	 
    	sleep 5                             	 
    	i2cset -y 0 0x55 0x01 0xFF b                 	 
    	sleep 5                         	 
    	i2cset -y 0 0x55 0x00 0xFF b          	 
    	sleep 2                               	 
    	i2cset -y 0 0x55 0x01 0xFF b                                          	 
    	sleep 2                                                               	 
else                                                                          	 
    	echo "Else"                                                           	 
                                                                              	 
fi                                                      	 
###### Design Capacity ########                         	 
                                                        	 
echo "STEP 5"                                        	 
echo "FCC OTP Update"
                               	 
i2cset -y 0 0x55 0x3e 0xe9 b                         	 
sleep 1                                              	 
i2cset -y 0 0x55 0x3f 0x40 b                  	 
sleep 1                                    	 
i2cset -y 0 0x55 0x40 0x17 b                                                  	 
sleep 1                                                                       	 
i2cset -y 0 0x55 0x41 0x70 b                                                  	 
sleep 1                                                                       	 
echo "Design capacity COMMAND END."                                           	 
                                                                              	 
                                                                              	 
echo "STEP 6"                                                                 	 
result=$(( (0xff - (0x40 + 0xe9 + 0x17 + 0x70)) & 0xff ))                     	 
# Print the result                                                            	 
printf "0x%x\n" $result                                                       	 
echo "The output of checksum is : $result"                                    	 
                                                                              	 
echo "STEP 7"                                           	 
i2cset -y 0 0x55 0x60 $result                           	 
sleep 2                                                 	 
i2cset -y 0 0x55 0x61 0x06                           	 
sleep 2
echo "STEP 8"                                                                 	 
i2cset -y 0 0x55 0x00 0x91                                                    	 
sleep 2                                                                       	 
i2cset -y 0 0x55 0x01 0x00                                                    	 
sleep 2                                                                       	 
echo "Exit config Update"                               	 
                                                        	 
i2cset -y 0 0x55 0x00 0x14 b                            	 
sleep 1                                              	 
i2cset -y 0 0x55 0x01 0x04 b                                                  	 
sleep 1                                                                       	 
i2cset -y 0 0x55 0x00 0x72 b                         	 
sleep 1                                                 	 
i2cset -y 0 0x55 0x01 0x36 b                            	 
sleep 1                                    	 
echo "UNSEAL process completed."


We have also tried changing the battery id according to 8.3.2 Using ot.fs file but to no avail.

  • Updating OTP is a more complex process than explained in the TRM for data memory updates (which apply to data in RAM, not OTP - at least for writes).

    You'll have to re-create the commands from the .ot.fs file that is generated by bqStudio when you export the Golden Image. bqStudio will create the commands for programming OTP based on the configuration that was programmed into RAM using bqStudio Data Memory view.

    This .ot.fs file has comments that denote the time when your system needs to apply the OTP programming voltage so you have to add control logic to your code that follows these comments in the .ot.fs file.

  • Hi Dominik,

    Can you provide an .ot.fs file for updating the OTP memory. We don't have the required hardware for the bqStudio to generate the Golden image. Is their any way to get the .ot.fs file from the bqStudio in demo mode or without the hardware.

  • bqStudio can't generate this .ot.fs file without the bq27220 EVM because it needs to read the image data from the gauge. There is no way to generate this in demo mode without the hardware.

  • Hi Dominik,

    Can you provide a .ot.fs file for updating OTP registers.

    I get that their is a need of a programming voltage of 7.4v during the process but can you specify at which step it needs to be given and to which path and pin in the schematic.

  • The .ot.fs file that bqStudio generates contains instructions when to apply the programming voltage. An example is attached. This file isn't trivial to generate (you can't easily do this without bqStudio and the EVM). bqStudio with the EVM is required.https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/196/0220_5F00_0_5F00_03_2D00_bq27220.ot.fs

  • Hi Dominik,

    I have 3 Doubts,

    1. The maximum Voltage rating of BAT pin is given as 6V in the Datasheet 

    How will it be able to handle 7.4V OTP programing voltage which is necessary for the process.

    2. Here is the Schematic of BQ27220 ic on our custom board.

      

    how can we provide the 7.4 voltage to the IC in this schematic if it can handle it.

    3. In the .ot.fs file that you shared, how is the device address getting changed from AA to 16 after going into ROM mode.

  • 1: The OTP voltage must not be applied to BAT. It is applied to GPOUT. The datasheet limit doesn't apply for this particular programming mode.

    2: You have to add a test point or a jumper/header to temporarily connect GPOUT to the OTP programming voltage (and disconnect it from your system).

    3: This command instructs the gauge to stop running the gauging firmware and change over to another FW in ROM which is used to program OTP: W: AA 00 00 0F. The gauge stops responding on 0xAA and uses 0x16 as the device address after this command.

  • Hi Dominik,

    Thank you for clearing our doubts, I was able to change the otp profile 1 to the default values mentioned inside the .ot.fs file that you shared.

    Now i want to modify it to set the fcc = 0x1770, Dcap= 0x1b58 and battery low % = 0x00.

    Can you tell us how can we modify the code in .ot.fs file to be able to do it. Or if possible can you share an .ot.fs file with these changes.

    Also, how many times can we change each OTP profiles. Also how can we change other profiles instead of only otp profile 1.

  • The documentation for the commands that program OTP is not public. I cannot share this on E2E.

    The official development flow for this gauge is based on bqStudio and the gauge EVM. The idea is that you test gauge configuration using bqStudio, the EVM, your battery and your system (e.g. patch the EVM between your system and the battery) and once this is working well, bqStudio exports your settings in an .ot.fs file for production.

  • You cannot change default OTP profile once it's programmed. You can use the SET_PROFILE_X commands an unlimited amount of times (these commands copy the OTP contents for the selected profile into RAM so there is no restriction on number of times).

  • Hi Dominik,
    We've changed the OTP to our custom values. Could you please let me know how many times we can program the profile area? We were able to change it a second time, but it didn't update to the value we wanted. Also, could you guide us on how to program profiles 2 or 3 in the OTP?

  • Hello,

    You can change the values bit-wise from a 0 to 1. So for example, you can program a value of 0x02, And then you can re-program the same parameter to 0x03 or 0x0A but not 0x00 or 0x08. Therefore the number of re-writes depends on the values that your program. This can be 0 or a rather high number.

    Check out 8.3.2 in the TRM https://www.ti.com/lit/ug/sluubd4a/sluubd4a.pdf:

    Programming the OTP Profile 1: 1. Fill out the CEDV Profile 1 section in RAM with required values. 2. Write CEDV Profile Select → Battery ID to 4. Programming the OTP Profile 2: 1. Fill out the CEDV Profile 1 section in RAM with required values. 2. Write CEDV Profile Select → Battery ID to 8. Programming the OTP Profile 3: 1. Fill out the CEDV Profile 1 section in RAM with required values. 2. Write CEDV Profile Select → Battery ID to 16.