ATTACHMENTS:
#!/bin/env python
#==========================================================================
# (c) 2015 TI
#--------------------------------------------------------------------------
# Redistribution and use of this file in source and binary forms, with
# or without modification, are permitted.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#==========================================================================
#==========================================================================
# IMPORTS
#==========================================================================
import sys
import time
from hi_functions import *
from intelhex import IntelHex
import struct
from hw_interface import *
#==========================================================================
# CONSTANTS
#==========================================================================
PAGE_SIZE = 64
handle = hw_interface(config.DEVICE_I2C_ADDR, config.HW_INTERFACE)
# header values
Ace_ID_Value_0x00 = 0xACE00001
Ace_ID_Value_Add = 0x267E4C8C
# Global Variables
failure = 1
error_flag = 0
# Local Variables
tDelay = 5
#==========================================================================
# Functions
#==========================================================================
# Function to bit-reverse a byte array in place
# '{:08b}'.format(x)converts a byte to a bit string, 8 bits, leading 0s
# slice operator bitstr[start:end:step] reverses the bit string when step -1
# int(bitstr,2) converts bit string (base 2) back to an integer
# write back to the same array
def bit_rev(data):
index = 0
for x in data:
data[index] = int('{:08b}'.format(x)[::-1], 2)
index +=1
return data
# Need to zero-fill 32-bit arrays when writing to flash, which is initialized to 0xFFFFFFFF
def four_byte_array(n):
retval = byteArray(n)
for i in range(4-len(retval)):
retval.append(0)
return retval
# Main Region0/1 Update function
def region_update(region_num):
global failure
failure = 1
global error_flag
error_flag = 0
global rp0
rp0 = 0
global rp1
rp1 = 0
# Read region 0/1 pointer
rp = FLrr(handle, region_num)
rp0 = FLrr(handle, 0)
rp1 = FLrr(handle, 1)
#print 'Region %d pointer currently set to address 0x%x' %(region_num, rp)
if rp == Ace_ID_Value_Add:
print 'Image in Flash memory is a "Low-Region.bin" file with offset 0x00, ' \
'but needs to be a "Flash.bin" file with 2 regions'
error_flag = 1
elif (rp == 0x2000) or (rp == 0x20000):
print 'Region %d pointer currently set to address 0x%x' %(region_num, rp)
# we use a second instance of file in raw mode to write into flash
try:
f=open(filename, 'rb')
except:
print "Unable to open file '" + filename + "'"
assert 1
# unroll first loop iteration
# Read from the file
filedata = f.read(PAGE_SIZE)
# Write the data to the bus
data1 = array('B', filedata)
length = len(data1)
if (length < 4):
print """Input file is not a valid low-region file"""
print """A low region files is an application binary (max 64k) with a prepended 4k boot header."""
sys.exit()
if (((data1[3] << 24) | (data1[2] << 16) | (data1[1] << 8) | data1[0]) != Ace_ID_Value_0x00) :
print """Input file is not a valid low-region file"""
print """A low region files is an application binary (max 64k) with a prepended 4k boot header."""
sys.exit()
# erase region 0 or 1
# Max image size is 64K plus a 4K header = 17 sectors
FLem(handle, rp, 17)
print 'Programming Region %d image at offset 0x%x' %(region_num, rp)
FLad(handle, rp)
#Truncate the array to the exact data size
if (length < PAGE_SIZE):
del data1[length:]
FLwd(handle, data1)
count = 0
while 1:
# Read from the file
filedata = f.read(PAGE_SIZE)
length = len(filedata)
if (length == 0):
break
# Write the data to the bus
data1 = array('B', filedata)
#Truncate the array to the exact data size
if (length < PAGE_SIZE):
del data1[length:]
FLwd(handle, data1)
count += 1
if count == 64:
print '4K block written'
count = 0
f.close()
print 'Region %d write complete' %region_num
# verify boot sequence using FLrr and FLvy
rp = FLrr(handle, region_num)
failure = FLvy(handle, rp)
if failure != 0:
print 'Verification of region %d FAILED' %region_num
error_flag = 2
else:
print 'Verification of region %d SUCCEEDED' %region_num
error_flag = 0
# # write in the region pointers
# rpblock0 = array('B')
# rpblock1 = array('B')
#
# for i in range(64):
# rpblock0.append(0xFF)
# rpblock1.append(0xFF)
#
# if rp0 == 0x2000:
# rpblock0[0] = 0x00
# rpblock0[1] = 0x00
# rpblock0[2] = 0x02
# rpblock0[3] = 0x00
#
# rpblock1[0] = 0x00
# rpblock1[1] = 0x20
# rpblock1[2] = 0x00
# rpblock1[3] = 0x00
# else:
# rpblock0[0] = 0x00
# rpblock0[1] = 0x20
# rpblock0[2] = 0x00
# rpblock0[3] = 0x00
#
# rpblock1[0] = 0x00
# rpblock1[1] = 0x00
# rpblock1[2] = 0x02
# rpblock1[3] = 0x00
#
# # Erase region 0 data record
# FLem(handle, 0x0, 1)
# # ___ region 0 ___
# FLad(handle, 0x0)
# FLwd(handle, rpblock0)
#
# rpblock0[0] = 0xFF
# rpblock0[1] = 0xFF
# rpblock0[2] = 0xFF
# rpblock0[3] = 0xFF
#
# rpblock0[60] = 0x00
# rpblock0[61] = 0x00
# rpblock0[62] = 0x00
# rpblock0[63] = 0x00
# # ___ region 0 ___
# FLad(handle, 0x1000 - 0x40)
# FLwd(handle, rpblock0)
#
# # Erase region 1 data record
# FLem(handle, 0x1000, 1)
# # ___ region 1 ___
# FLad(handle, 0x1000)
# FLwd(handle, rpblock1)
#
# rpblock1[0] = 0xFF
# rpblock1[1] = 0xFF
# rpblock1[2] = 0xFF
# rpblock1[3] = 0xFF
#
# rpblock1[60] = 0x00
# rpblock1[61] = 0x00
# rpblock1[62] = 0x00
# rpblock1[63] = 0x00
#
# # ___ region 1 ___
# FLad(handle, 0x2000 - 0x40)
# FLwd(handle, rpblock1)
else:
print 'FW Pointer in Flash image set to unknown value (not 0x2000 or 0x20000). ' \
'If you are using a TBT system, please contact Intel for Alpine Ridge FW update method.' \
'If this is a non-TBT system, please download a "flash-image.bin" file from the TPS6598X Config-Tool' \
'and try again'
error_flag = 1
return error_flag
def flip_reg_ptrs():
global rp0
rp0 = 0
global rp1
rp1 = 0
# Read region 0/1 pointer
rp0 = FLrr(handle, 0)
rp1 = FLrr(handle, 1)
# write in the region pointers
rpblock0 = array('B')
rpblock1 = array('B')
for i in range(64):
rpblock0.append(0xFF)
rpblock1.append(0xFF)
if rp0 == 0x2000:
rpblock0[0] = 0x00
rpblock0[1] = 0x00
rpblock0[2] = 0x02
rpblock0[3] = 0x00
rpblock1[0] = 0x00
rpblock1[1] = 0x20
rpblock1[2] = 0x00
rpblock1[3] = 0x00
else:
rpblock0[0] = 0x00
rpblock0[1] = 0x20
rpblock0[2] = 0x00
rpblock0[3] = 0x00
rpblock1[0] = 0x00
rpblock1[1] = 0x00
rpblock1[2] = 0x02
rpblock1[3] = 0x00
# Erase region 0 data record
FLem(handle, 0x0, 1)
# ___ region 0 ___
FLad(handle, 0x0)
FLwd(handle, rpblock0)
rpblock0[0] = 0xFF
rpblock0[1] = 0xFF
rpblock0[2] = 0xFF
rpblock0[3] = 0xFF
rpblock0[60] = 0x00
rpblock0[61] = 0x00
rpblock0[62] = 0x00
rpblock0[63] = 0x00
# ___ region 0 ___
FLad(handle, 0x1000 - 0x40)
FLwd(handle, rpblock0)
# Erase region 1 data record
FLem(handle, 0x1000, 1)
# ___ region 1 ___
FLad(handle, 0x1000)
FLwd(handle, rpblock1)
rpblock1[0] = 0xFF
rpblock1[1] = 0xFF
rpblock1[2] = 0xFF
rpblock1[3] = 0xFF
rpblock1[60] = 0x00
rpblock1[61] = 0x00
rpblock1[62] = 0x00
rpblock1[63] = 0x00
# ___ region 1 ___
FLad(handle, 0x2000 - 0x40)
FLwd(handle, rpblock1)
#==========================================================================
# MAIN PROGRAM
#==========================================================================
if __name__ == "__main__":
if (len(sys.argv) < 2):
print "usage: flash_update <tps65982xxx_low_region.bin> [I2C address]"
sys.exit()
filename = sys.argv[1]
if len(sys.argv) > 2:
if sys.argv[2][:2] == '0x':
config.DEVICE_I2C_ADDR = int(sys.argv[2],16)
else:
config.DEVICE_I2C_ADDR = int(sys.argv[2])
# Open the device
try :
handle.hw_open(config.HW_INTERFACE, config.PORT, config.SPI_PORT, config.BITRATE, config.SPIBITRATE, config.DEVICE_I2C_ADDR)
except Exception as e :
print e.message
sys.exit()
while 1: #Break if any errors occur
VERSION_REG.read(handle)
print 'OLD FW Version in running in APP Mode before FW Update'
VERSION_REG.show()
BOOT_FLAGS.read(handle)
if BOOT_FLAGS.fieldByName('BootOk').value == 0:
error_flag = 1
break
elif BOOT_FLAGS.fieldByName('Region1').value == 0:
print 'Region 0 running --> Update Region 1 first, then Region 0'
region_update(1)
if error_flag == 0:
flip_reg_ptrs()
#Reset before continuing
GAID(handle)
time.sleep(tDelay)
if error_flag == 0:
print 'Region 1 was updated successfully and Region Pointers are flipped'
#Check to see if BOOT is OK before updating 2nd Region
BOOT_FLAGS.read(handle)
if BOOT_FLAGS.fieldByName('BootOk').value == 0:
error_flag = 4
break
else:
BOOT_FLAGS.show()
VERSION_REG.read(handle)
print 'New FW Version in running in APP Mode after Region 1 Update'
VERSION_REG.show()
region_update(1)
if error_flag == 0:
flip_reg_ptrs()
print 'Reset after both Regions Updated'
GAID(handle)
time.sleep(tDelay)
if error_flag == 0:
print 'Region 1, then Region 0 was updated successfully and Pointers reverted to original values'
else:
error_flag = 5
break
else:
error_flag = 2
break
elif ((BOOT_FLAGS.fieldByName('Region0').value == 1) and (BOOT_FLAGS.fieldByName('Region1').value == 1)) and \
((BOOT_FLAGS.fieldByName('Region0Invalid').value == 1) or (BOOT_FLAGS.fieldByName('Region0FlashErr').value == 1) or (BOOT_FLAGS.fieldByName('Region0CRCFail').value == 1)):
print 'Region 1 running --> Update Region 0 first, then Region 1'
region_update(0)
#Reset before continuing
GAID(handle)
time.sleep(tDelay)
if error_flag == 0:
print 'Region 0 was updated successfully'
#Check to see if BOOT is OK before updating 2nd Region
BOOT_FLAGS.read(handle)
if BOOT_FLAGS.fieldByName('BootOk').value == 0:
error_flag = 4
break
else:
BOOT_FLAGS.show()
VERSION_REG.read(handle)
print 'New FW Version in running in APP Mode after Region 0 Update'
VERSION_REG.show()
region_update(1)
print 'Reset after both Regions Updated'
GAID(handle)
time.sleep(tDelay)
if error_flag == 0:
print 'Region 0, then Region 1 was updated successfully'
else:
error_flag = 5
break
else:
error_flag = 2
break
else:
error_flag = 3
break
BOOT_FLAGS.read(handle)
if BOOT_FLAGS.fieldByName('BootOk').value == 0:
error_flag = 6
else:
VERSION_REG.read(handle)
print 'New FW Version in running in APP Mode after FW Update'
VERSION_REG.show()
break
if error_flag == 0:
print 'SUCCESS!!! FW Update of Region 0 & 1 was completed without errors'
elif error_flag == 1:
print '\nERROR 1: TPS65982 stuck in BOOT Mode before Update attempted'
print '\nBOOT_FLAGS register printed below.'
print '(Refer to bits [13..3] for details) \n'
BOOT_FLAGS.read(handle)
BOOT_FLAGS.show()
elif error_flag == 2:
print '\nERROR 2: 1st Region update attempted but not successful or not verified. ' \
'Either incorrect ".bin" file existed in Flash or new "Low-region.bin" file may be corrupted'
elif error_flag == 3:
print '\nERROR 3: Undefined BOOT_FLAGS conditions encountered. No update was attempted'
elif error_flag ==4:
print '\nERROR 4: TPS65982 stuck in BOOT Mode after 1st Region Update attempted'
elif error_flag ==5:
print '\nERROR 5: 2nd Region Update failed, but 1st Region update was successful and Verified'
else:
print 'ERROR: TPS65982 stuck in Boot Mode after 2nd Region update'
# Close the device
try:
handle.hw_close()
except Exception as e:
print e.message
sys.exit()
sys.exit()
C:\Py_I2C_Full_FWUpdate>flash_update_fullFW_I2C_Enhanced.py config82_v1.7.6_low_region.bin
TPS65982 Debug Tool Version 1.1
I2C Bitrate set to 400 kHz
I2C Bus lock timeout set to 150 ms
SPI Bitrate set to 8000 kHz
OLD FW Version in running in APP Mode before FW Update
VERSION 0001.03.00
Region 1 running --> Update Region 0 first, then Region 1
Success
Success
Success
Region 0 pointer currently set to address 0x2000
Programming Region 0 image at offset 0x2000
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
Region 0 write complete
Success
Verification of region 0 SUCCEEDED
Region 0 was updated successfully
Boot Flags (0x2d)
[0:0] BootOk True
[1:1] ExtPhvSwitch False
[2:2] DeadBatteryFlag False
[3:3] SpiFlashPresent True
[4:4] Region0 True
[5:5] Region1 False
[6:6] Region0Invalid False
[7:7] Region1Invalid False
[8:8] Region0FlashErr False
[9:9] Region1FlashErr False
[11:11] UartCRCFail False
[12:12] Region0CRCFail False
[13:13] Region1CRCFail False
[14:14] CustomerOTPInvalid False
[16:15] OneCallI2COtpBits 0x1
[22:22] Debug Ctl 1 state at boot low
[23:23] Debug Ctl 2 state at boot low
[26:24] DevNumber 0
[27:27] UartBoot False
[28:28] UartOverflowErr False
[29:29] IntPhvSwitch False
[30:30] UartRetryErr False
[31:31] UartTimeoutErr False
[33:32] OTPValid 2
[34:34] SWD Disable False
[36:36] Vout3v3Ctl True
[37:37] WaitForVin3V3 False
[41:40] OneCallI2cOtpBits 1
[54:50] Vout3v3Threshold 6
New FW Version in running in APP Mode after Region 0 Update
VERSION 0001.07.06
Success
Success
Success
Region 1 pointer currently set to address 0x20000
Programming Region 1 image at offset 0x20000
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
Region 1 write complete
Success
Verification of region 1 SUCCEEDED
Reset after both Regions Updated
Region 0, then Region 1 was updated successfully
New FW Version in running in APP Mode after FW Update
VERSION 0001.07.06
SUCCESS!!! FW Update of Region 0 & 1 was completed without errors
C:\Py_I2C_Full_FWUpdate>
C:\Py_I2C_Full_FWUpdate>flash_update_fullFW_I2C_Enhanced.py config82_v1.7.6_low_region.bin
TPS65982 Debug Tool Version 1.1
I2C Bitrate set to 400 kHz
I2C Bus lock timeout set to 150 ms
SPI Bitrate set to 8000 kHz
OLD FW Version in running in APP Mode before FW Update
VERSION 0001.03.00
Region 0 running --> Update Region 1 first, then Region 0
Success
Success
Success
Region 1 pointer currently set to address 0x20000
Programming Region 1 image at offset 0x20000
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
Region 1 write complete
Success
Verification of region 1 SUCCEEDED
Success
Success
Region 1 was updated successfully and Region Pointers are flipped
Boot Flags (0x2d)
[0:0] BootOk True
[1:1] ExtPhvSwitch False
[2:2] DeadBatteryFlag False
[3:3] SpiFlashPresent True
[4:4] Region0 True
[5:5] Region1 False
[6:6] Region0Invalid False
[7:7] Region1Invalid False
[8:8] Region0FlashErr False
[9:9] Region1FlashErr False
[11:11] UartCRCFail False
[12:12] Region0CRCFail False
[13:13] Region1CRCFail False
[14:14] CustomerOTPInvalid False
[16:15] OneCallI2COtpBits 0x1
[22:22] Debug Ctl 1 state at boot low
[23:23] Debug Ctl 2 state at boot low
[26:24] DevNumber 0
[27:27] UartBoot False
[28:28] UartOverflowErr False
[29:29] IntPhvSwitch False
[30:30] UartRetryErr False
[31:31] UartTimeoutErr False
[33:32] OTPValid 2
[34:34] SWD Disable False
[36:36] Vout3v3Ctl True
[37:37] WaitForVin3V3 False
[41:40] OneCallI2cOtpBits 1
[54:50] Vout3v3Threshold 6
New FW Version in running in APP Mode after Region 1 Update
VERSION 0001.07.06
Success
Success
Success
Region 1 pointer currently set to address 0x2000
Programming Region 1 image at offset 0x2000
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
4K block written
Region 1 write complete
Success
Verification of region 1 SUCCEEDED
Success
Success
Reset after both Regions Updated
Region 1, then Region 0 was updated successfully and Pointers reverted to original values
New FW Version in running in APP Mode after FW Update
VERSION 0001.07.06
SUCCESS!!! FW Update of Region 0 & 1 was completed without errors
C:\Py_I2C_Full_FWUpdate>
__________________________________________________________________________________________________________________________
If you have been developing a product with the TPS65982 and attempted to update the FW in the SPI Flash memory using I2C, then you may have downloaded the TPS65982-HIUTILITY Host Interface Utility Tool.
The Host Interface Utility Tool allows you to access the Host Interface of the TPS65982: Read from Registers, Write to Registers, Send 4CC ASCII Commands, and even Update the FW of the TPS65982 over I2C using a friendly GUI.
After learning about the operation of the part using the GUI, you may want to start writing your own code to control the TPS65982. Although jumping straight to writing C-code for an Embedded Processor sounds like fun, it can be difficult to translate a GUI to code.
An easy intermediate step to take would be to open the TPS6598X Utilities Command Line prompt, edit the Python scripts, and test to see if your system reacts in the expected way.
The Host Interface Utility GUI currently allows you to update Region 0 and Region 1 of the FW separately:
But the final implementation of code may require that Both Regions 0 & 1 are updated at the same time! Using the "flash_update_region_0.py" and "flash_update_region_1.py" scripts as a reference, a new Python script was written to combine these 2 scripts into 1 function, then call that function twice and update both regions of the FW at the same time. Here is what it looks like when the original "flash_update_region_0.py" script is run from the CMD Line:
For example, let's say I released a product with FW version 1.3.0 and I want to update my product in the field to the latest FW version. At the time of writing this example Python script, FW version 1.7.6 was the latest. Updating Region 0 and Region 1 separately works, but how should they be combined into a single program that I can then port to code for an Embedded Processor?
The new script, "flash_update_fullFW_I2C_Enhanced.py", updates both Region 0 and Region 1 sequentially and Resets the TPS65982 to load the new FW version. The script was edited in the PyCharm IDE Free version, and here is what it looks like when it is running:
The full "flash_update_fullFW_I2C_Enhanced.py" script is attached to this post, along with .txt files of the Printout showing that the program is a Success after updating Region 1 first, then Region 0 or updating Region 0 first, then Region 1. If errors are encountered, the program aborts and the errors are explained in plain text.
To run this script without making changes, simply drag and drop it into the same folder as the existing Python Host Interface utilities scripts, and open the CMD Line to run it:
