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: