Skip to content

Commit

Permalink
FPGA SoC programming uart (#90)
Browse files Browse the repository at this point in the history
Co-authored-by: Benoit Denkinger <[email protected]>
  • Loading branch information
benoitdenkinger and Benoit Denkinger authored Oct 8, 2024
1 parent d4950f8 commit d1736e6
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 17 deletions.
113 changes: 98 additions & 15 deletions cmake/fpga/uart_programmer/uart_programmer.py
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
3 changes: 1 addition & 2 deletions cmake/tmrg/tmrg/tmrg.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit d1736e6

Please sign in to comment.