diff --git a/cmake/fpga/uart_programmer/uart_programmer.py b/cmake/fpga/uart_programmer/uart_programmer.py index 578af09..637c64a 100644 --- a/cmake/fpga/uart_programmer/uart_programmer.py +++ b/cmake/fpga/uart_programmer/uart_programmer.py @@ -1,12 +1,26 @@ +import sys import serial import argparse import serial.tools.list_ports +def progress_bar(progress, total, info_str, bar_length=40): + percent = float(progress) / total + arrow = '=' * int(round(percent * bar_length)) + spaces = ' ' * (bar_length - len(arrow)) + + sys.stdout.write(f"\r[{'=' * len(arrow)}{spaces}] {int(percent * 100)}% {info_str}") + sys.stdout.flush() + + # Add a new line when the progress reaches 100% + if progress == total: + sys.stdout.write('\n') + def program( - text_hex : str, + text_hex : str, data_hex : str, - baudrate : int, - dev : str, + baudrate : int, + dev : str, + debug : bool = False ): ser = serial.Serial(dev, baudrate, timeout=100) @@ -48,19 +62,86 @@ def program( num_text_bytes = len(text_bytes).to_bytes(4, byteorder='little') num_data_bytes = (len(data_bytes)).to_bytes(4, byteorder='little') - - print("-----------------------------------------------------") + dev_baud_str = f"----- Programming {dev} at baudrate {baudrate} ---" + str_len = len(dev_baud_str) + print(f"{'-' * str_len}") print(f"----- Programming {dev} at baudrate {baudrate} ---") + print(f"{'-' * str_len}") ser.write(num_text_bytes) - ser.write(text_bytes) + + sync_f = False + text_tx_error = 0 + for idx, byte in enumerate(text_bytes): + wbyte = byte.to_bytes(1, 'big') + ser.write(wbyte) + if debug: + if not sync_f: + # Wait for the first similar byte + while not sync_f: + rbyte = ser.read(1) + if rbyte == wbyte: + sync_f = True + else: + rbyte = ser.read(1) + if rbyte != wbyte: + text_tx_error += 1 + print(f"ERROR: sent and received bytes mismatch!") + print(f"ERROR: write/read bytes: {wbyte.hex()} / {rbyte.hex()}") + else: + print(f"INFO: TEXT TX {idx}/{len(text_bytes)} correct ({int(idx/len(text_bytes)*100)}%)") + else: + progress_bar(idx+1, len(text_bytes), 'text segment') ser.write(num_data_bytes) - ser.write(data_bytes) - print(f"------------ Finished programming ------------------") - print(f"----- Bytes written: Text {len(text_bytes)}, Data: {len(data_bytes)} --------") - print("-----------------------------------------------------") + sync_f = False + data_tx_error = 0 + for idx, byte in enumerate(data_bytes): + wbyte = byte.to_bytes(1, 'big') + ser.write(wbyte) + if debug: + if not sync_f: + # Wait for the first similar byte + while not sync_f: + rbyte = ser.read(1) + if rbyte == wbyte: + sync_f = True + else: + rbyte = ser.read(1) + if rbyte != wbyte: + data_tx_error += 1 + print(f"ERROR: sent and received bytes mismatch!") + print(f"ERROR: write/read bytes: {wbyte.hex()} / {rbyte.hex()}") + else: + print(f"INFO: DATA TX {idx}/{len(data_bytes)} correct ({int(idx/len(data_bytes)*100)}%)") + else: + progress_bar(idx+1, len(data_bytes), 'data segment') + + # Find the maximum width based on the length of text_bytes and data_bytes + text_width = len(str(len(text_bytes))) + data_width = len(str(len(data_bytes))) + + # Calculate the width of the longest line including text labels and values + # The part before the values: "--------- Bytes written : Text " + prefix_length = len("--------- Bytes written : Text ") + # Calculate the full width of the lines + line_width = prefix_length + max(text_width, data_width) + len(", Data: ") + max(text_width, data_width) + header_str = " Finished programming " + header_pad_width = int((line_width - len(header_str)) / 2) + + # Print the header with the calculated line width + print(f"{'-' * header_pad_width}{header_str}{'-' * header_pad_width}") + + # Print the aligned output + print(f"--------- Bytes written : Text {len(text_bytes):<{text_width}}, Data: {len(data_bytes):<{data_width}}") + # Print errors only if they are actually counted + if debug: + print(f"--------- Bytes read errors: Text {text_tx_error:<{text_width}}, Data: {data_tx_error:<{data_width}}") + + # Print the final footer line with the same calculated width + print(f"{'-' * line_width}") + def getport(dev): ports = serial.tools.list_ports.comports() @@ -100,17 +181,19 @@ def main(): parser.add_argument('--data-hex', type=str, required=True, help='Hext file of DATA section') parser.add_argument('--baudrate', type=int, default=115200, help='Baudrate of the UART bootloader') parser.add_argument('--dev', type=str, required=True, help='Path to the UART device e.g. /dev/ttyUSB0') + parser.add_argument('--debug', action='store_true', help='Debug enabled (read back data on the UART and check the values are matching)') args = parser.parse_args() dev = getport(args.dev) program( - text_hex=args.text_hex, - data_hex=args.data_hex, - baudrate=args.baudrate, - dev=dev, - ) + text_hex=args.text_hex, + data_hex=args.data_hex, + baudrate=args.baudrate, + dev=dev, + debug=args.debug + ) if __name__ == "__main__": main() diff --git a/cmake/tmrg/tmrg/tmrg.cmake b/cmake/tmrg/tmrg/tmrg.cmake index cd23e0f..3ca6315 100644 --- a/cmake/tmrg/tmrg/tmrg.cmake +++ b/cmake/tmrg/tmrg/tmrg.cmake @@ -115,7 +115,6 @@ function(tmrg IP_LIB) get_filename_component(V_SOURCE_EXT ${vfile} EXT) list(APPEND TRMG_GEN "${OUTDIR}/${V_SOURCE_WO_EXT}TMR${V_SOURCE_EXT}") endforeach() - set_source_files_properties(${TRMG_GEN} PROPERTIES GENERATED TRUE) set(TMRG_COMMAND ${Python3_VIRTUAL_ENV}/bin/tmrg --stats --tmr-dir=${OUTDIR} ${ARG_CONFIG_FILE} ${IP_TMRG_SRC} @@ -211,7 +210,7 @@ function(tmrg IP_LIB) # Get the existing linked libraries safe_get_target_property(LINKED_IP ${IP_LIB} INTERFACE_LINK_LIBRARIES "") - # Trigger the dependencies tmrg targets f they exist + # Trigger the dependencies tmrg targets if they exist foreach(linked_lib ${LINKED_IP}) alias_dereference(linked_lib ${linked_lib}) # Check if a tmrg target exists