主题中讨论的其他器件:UNIFLASH
以下假设从 ECU 不支持通过 XCP 刷写。
对于 C2000器件、UniFlash 期望十六进制文件的 romwidth=16。 简而言之、如果您尝试使用 UniFlash 将常规 Intel Hex 文件下载到 C2000器件、则无法按预期进行编程。 更多信息:
我将使用矢量 canape 进行数据采集和校准。 校准会话之后、可以保存包含校准常量(ASAP2中的特征表示)的存储器的图像文件(Intel hex)、想法是将文件刷写到器件中、以冻结该特定器件中的校准更改、而无需重新编译软件。
接下来的挑战是如何将 canape true Intel hex 文件转换为 UniFlash C2000 hex 文件(romwidth=16)、以便 canape (或任何其他 MCD 工具)可用于汽车工作流程。 我的解决方案是使用 Python 脚本解析 canape hex 文件、从而将八位位组放置在正确的地址的正确位置、从而允许 UniFlash 对 C2000器件进行编程。 请在下方找到 Python 脚本。
它需要在该线程 https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1225978/tms320f28379d-implementation-of-xcp-on-can-for-c2000中概述的定制寻址方案 、其中 ASAP2地址空间是设备地址空间的2 x。 授权这是一个非常具体的用例、但可以修改脚本、以便可以生成真正的 Intel hex 文件的其他第三方工具配合 C2000/UniFlash 使用。
注1:输入一半由 Python IntelHex (https://pypi.org/project/intelhex/)完成。 一种快速的解决方案是使用其'HEX2BIN'脚本、只要您愿意手动输入起始地址、bin 文件就可以直接与 UniFlash 一起使用。 不过、我需要一个自包含可编程文件、而且格式与 hex2000实用程序从 CCS 输出的格式完全相同。 后者意味着我可以通过文件将编译器输出"校准"与 CA 输出校准进行比较。
注2:Python IntelHex 具有 IntelHex16位类、但我无法将其输出为 C2000 hex 文件。
# Python program to create a word addressable HEX file suitable for TI UniFlash # to program a C2000 device from a byte addressable Intel HEX file generated by CANape. # # It expects that the CANape (XCP / ASAP2) addresses are 2 x C2000 device addresses. # # Usage : python.exe CANapeHex2UniFlashHex.py canape_input.hex uniflash_output.hex # # Tested with Python 3.10. import sys # Class for the input Intel hex file. Credit: pypi.org/.../ from intelhex import IntelHex class UniFlashDict: '''Creates a dictionary of values with additional metadata suitable for UniFlash hex file construction from an IntelHex object''' def __init__(this, intelhex_obj): # New empty dictionary. this.dict = dict() # Get the ASAP2 Address range of Intel HEX file but # halve to give the Device Address. this.min_addr = int(intelhex_obj.minaddr()/2) this.max_addr = int(intelhex_obj.maxaddr()/2) # Prepare values used for record construction. this.ext_linear_addr = this.min_addr >> 16 & 0xFFFF this.seg_base_addr = this.min_addr & 0xFFFF # Iterate through the ASAP2 byte addressed dictionary and create a word addressed dictionary. idx_uf = this.min_addr idx_ih = intelhex_obj.minaddr() while idx_ih < intelhex_obj.maxaddr(): this.dict[idx_uf] = intelhex_obj[idx_ih] | (intelhex_obj[idx_ih + 1] << 8) # Increment ASAP2 address by two bytes. idx_ih += 2 # Increment C2000 address by one word. idx_uf += 1 def minaddr(this): '''The absolute start address.''' return this.min_addr def maxaddr(this): '''The absolute end address.''' return this.max_addr def extended_linear_address(this): '''Returns the two data bytes (big endian) which specify the upper 16 bits of the 32 bit absolute address for all subsequent type 00 records; these upper address bits apply until the next 04 record.''' return this.ext_linear_addr def segment_base_address(this): '''The 16-bit starting address for the data.''' return this.seg_base_addr def update_checksum( current_csum, new_data, num_of_bytes ): '''Updates the running total of the input checksum with new data.''' idx = num_of_bytes ret_csum = current_csum temp_new_data = new_data while(idx > 0): ret_csum += temp_new_data & 0xFF temp_new_data = temp_new_data >> 8 idx -= 1 return ret_csum def finalize_checksum( current_csum ): '''Returns the LSB of the two's complement of the input.''' ret_csum = current_csum ret_csum = ~ret_csum # Invert ret_csum = ret_csum + 1 # Add 1 ret_csum = ret_csum & 0xFF # Keep LSB only. return ret_csum def main(): DATA_REC_TYPE = 0x00 DATA_REC_TYPE_STR = f'{DATA_REC_TYPE:0{2}X}' DATA_REC_BYTE_COUNT = 0x20 # Fixed at 32 bytes. DATA_REC_BYTE_COUNT_STR = f'{DATA_REC_BYTE_COUNT:0{2}X}' EXT_LIN_ADDR_REC_TYPE = 0x02000004 EXT_LIN_ADDR_REC_TYPE_STR = f'{EXT_LIN_ADDR_REC_TYPE:0{8}X}' EOF_REC_STR = ':00000001FF' try: # Get an instance of the Intel HEX file input. ih_in = IntelHex(sys.argv[1]) # Open/create a file for the output. uf_out_file = open(sys.argv[2], "w") # Get an instance of the UniFlash dictionary. uf_dict = UniFlashDict(ih_in) # Prepare and write the Extended Linear Address record. e.g. ":020000040009F1" record_str = ':' + EXT_LIN_ADDR_REC_TYPE_STR + f'{uf_dict.extended_linear_address():0{4}X}' record_csum = update_checksum(0,EXT_LIN_ADDR_REC_TYPE,4) record_csum = update_checksum(record_csum,uf_dict.extended_linear_address(),4) record_csum = finalize_checksum(record_csum) # Append checksum byte. record_str += f'{record_csum:0{2}X}' uf_out_file.write(record_str+"\n") # Get the address for the first record. record_start_address = uf_dict.segment_base_address() # Initialise loop variables. idx = uf_dict.minaddr() word_counter = 0 # Loop through all dictionary values and create multiple data records in the output file. while idx < (uf_dict.minaddr() + len(uf_dict.dict)): if word_counter == 0: # At the start of the record, concatenate the byte count, address and record type. e.g. ":20C13000" record_str = ':' + DATA_REC_BYTE_COUNT_STR + f'{record_start_address:0{4}X}' + DATA_REC_TYPE_STR record_csum = DATA_REC_BYTE_COUNT + ((record_start_address & 0xFF00) >> 8) + (record_start_address & 0x00FF) + DATA_REC_TYPE # Process a word. # Concatenate dictionary values (words) record_str += f'{uf_dict.dict[idx]:0{4}X}' # Keep a running total of each word (2 bytes) for the checksum. record_csum = update_checksum(record_csum, uf_dict.dict[idx], 2) # Keep a count of how many words have been processed for each record. word_counter += 1 # After sixteen words: Finalize checksum, write to the file and prepare for a new record. if word_counter == 16: # Finalize checksum. record_csum = finalize_checksum( record_csum ) # Append checksum byte. record_str += f'{record_csum:0{2}X}' # Record is now complete so output to file with a new line. uf_out_file.write(record_str+"\n") # Calculate next start address. i.e. Add 16 (words). record_start_address += 16 # Force prepartion of a new record. word_counter = 0 # Move to the next word in the dictionary. idx += 1 # Write the End Of File record. It doesn't change so can use a literal. record_str = EOF_REC_STR uf_out_file.write(record_str+"\n") uf_out_file.close() except Exception as e: print("\nError! " + repr(e)) if (len(sys.argv) != 3): print("Usage:") print("python.exe IntelHex2UniFlashHex.py intel.hex uniflash.hex") else: main()