diff --git a/ftdi_flash.cfg b/ftdi_flash.cfg index 1a43006..a80dc2b 100644 --- a/ftdi_flash.cfg +++ b/ftdi_flash.cfg @@ -1,16 +1,16 @@ adapter driver ftdi -ftdi vid_pid 0x0403 0x6010 +ftdi_vid_pid 0x0403 0x6010 # Initial state: Assuming 0x0008 doesn't interfere with your setup # and 0x000b sets the required initial states for your other signals. -ftdi layout_init 0x0008 0x000b +ftdi_layout_init 0x0008 0x000b -ftdi layout_signal LED_Tx -data 0x00F0 -oe 0x00F0 -ftdi layout_signal LED_Rx -data 0x00F0 -oe 0x00F0 +ftdi_layout_signal LED_Tx -data 0x00F0 -oe 0x00F0 +ftdi_layout_signal LED_Rx -data 0x00F0 -oe 0x00F0 # Configure GPIOL0 (ADBUS4) as nSRST, assuming active low reset # Setting `-data` for active low, `-oe` to enable output. # If tri-state isn't supported, this configures the pin as push-pull. -ftdi layout_signal nSRST -data 0x0010 -oe 0x0010 +ftdi_layout_signal nSRST -data 0x0010 -oe 0x0010 -transport select jtag \ No newline at end of file +transport select jtag diff --git a/ner_environment/build_system/build_system.py b/ner_environment/build_system/build_system.py index 99d6705..82483a0 100644 --- a/ner_environment/build_system/build_system.py +++ b/ner_environment/build_system/build_system.py @@ -14,9 +14,12 @@ # To see a list of available commands and additional configuration options, run `ner --help` # ============================================================================== import argparse +import platform import subprocess import sys import os +import glob +import time # custom modules for functinality that is too large to be included in this script directly from .miniterm import main as miniterm @@ -31,7 +34,7 @@ def build(args): command = ["docker", "compose", "run", "--rm", "ner-gcc-arm", "make", "clean"] else: command = ["docker", "compose", "run", "--rm", "ner-gcc-arm", "make", f"-j{os.cpu_count()}"] - run_command(command) + run_command(command, stream_output=True) # ============================================================================== # Clang command @@ -55,7 +58,53 @@ def clang(args): # ============================================================================== def debug(args): - pass + + command = [] + #if args.docker: + # print("Dockerized openocd unsupported for gdb") + # sys.exit(1) + + command = command + ["openocd"] + + current_directory = os.getcwd() + if args.ftdi: + ftdi_path = os.path.join(current_directory, "Drivers", "Embedded-Base", "ftdi_flash.cfg") + command = command + ["-f", ftdi_path] + else: + command = command + ["-f", "interface/cmsis-dap.cfg"] + + build_directory = os.path.join("build", "*.elf") + elf_files = glob.glob(build_directory) + if not elf_files: + print("Error: No ELF file found in ./build/") + sys.exit(1) + + elf_file = os.path.basename(os.path.normpath(elf_files[0])) # Take the first ELF file found + print(f"Found ELF file: {elf_file}") + + halt_command = command + ["-f", "flash.cfg", "-f", os.path.join(current_directory, "Drivers", "Embedded-Base", "openocd.cfg"), +"-c", "init", "-c", "reset halt"] + ocd = subprocess.Popen(halt_command) + time.sleep(1) + + # for some reason the host docker internal thing is broken on linux despite compose being set correctly, hence this hack + gdb_uri = "host.docker.internal" + if platform.system() == "Linux" and is_wsl() == 0: + gdb_uri = "localhost" + + send_command = ["docker", "compose", "run", "--rm", "ner-gcc-arm", "arm-none-eabi-gdb", f"/home/app/build/{elf_file}", "-ex", f"target extended-remote {gdb_uri}:3333"] + + subprocess.run(send_command) + + # make terminal clearer + time.sleep(4) + print("\nKilling openocd...") + ocd.terminate() + time.sleep(1) + + + + # ============================================================================== # Flash command @@ -64,6 +113,10 @@ def debug(args): def flash(args): command = [] + if args.docker and args.ftdi: + print("Cannot flash ftdi from docker") + sys.exit(1) + if args.docker: command = ["docker", "compose", "run", "--rm", "ner-gcc-arm"] @@ -75,8 +128,18 @@ def flash(args): command = command + ["-f", ftdi_path] else: command = command + ["-f", "interface/cmsis-dap.cfg"] - - command = command + ["-f", "flash.cfg"] + + + build_directory = os.path.join("build", "*.elf") + elf_files = glob.glob(build_directory) + if not elf_files: + print("Error: No ELF file found in ./build/") + sys.exit(1) + + elf_file = elf_files[0] # Take the first ELF file found + print(f"Found ELF file: {elf_file}") + + command = command + ["-f", "flash.cfg", "-c", f"program {elf_file} verify reset exit"] run_command(command, stream_output=True) @@ -206,6 +269,11 @@ def main(): # ============================================================================== parser_debug = subparsers.add_parser('debug', help="Start a debug session") + parser_debug.add_argument( + '--ftdi', + action="store_true", + help="Set this flag if the device uses an FTDI chip", + ) parser_debug.set_defaults(func=debug) # ============================================================================== @@ -257,21 +325,7 @@ def run_command(command, stream_output=False, exit_on_fail=True): if stream_output: - process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) - - # Stream the output in real-time - while True: - output = process.stdout.readline() - if output == '' and process.poll() is not None: - break - if output: - print(output.strip()) - - # Capture any remaining output - stderr_output = process.stderr.read() - if stderr_output: - print(stderr_output, file=sys.stderr) - + process = subprocess.Popen(command, text=True) returncode = process.wait() if returncode != 0: @@ -294,6 +348,18 @@ def disconnect_usbip(): command = ["sudo", "usbip", "detach", "-p", "0"] run_command(command, exit_on_fail=False) +def is_wsl(v: str = platform.uname().release) -> int: + """ + detects if Python is running in WSL + """ + + if v.endswith("-Microsoft"): + return 1 + elif v.endswith("microsoft-standard-WSL2"): + return 2 + + return 0 + if __name__ == "__main__": main() diff --git a/ner_environment/ner_setup.py b/ner_environment/ner_setup.py index fb38de0..2a7045d 100644 --- a/ner_environment/ner_setup.py +++ b/ner_environment/ner_setup.py @@ -9,6 +9,18 @@ except ImportError: distro = None +def is_wsl(v: str = platform.uname().release) -> int: + """ + detects if Python is running in WSL + """ + + if v.endswith("-Microsoft"): + return 1 + elif v.endswith("microsoft-standard-WSL2"): + return 2 + + return 0 + def run_command(command, check=True, shell=False): try: result = subprocess.run(command, check=check, shell=shell, text=True, capture_output=True) @@ -19,22 +31,20 @@ def run_command(command, check=True, shell=False): print(f"Command failed: {e.cmd}\nReturn code: {e.returncode}\nOutput: {e.output}\nError: {e.stderr}", file=sys.stderr) sys.exit(1) -def check_docker_and_rust(): - print("This script requires Docker and Rust to be installed.") - answer = input("Do you have Docker and Rust installed? (yes/no): ").strip().lower() +def check_docker(): + print("This script requires Docker to be installed.") + answer = input("Do you have Docker installed? (yes/no): ").strip().lower() if 'y' not in answer: sys.exit(1) os_type = platform.system() if os_type == 'Windows': - print("Windows OS detected. If on windows, you must be using bash (included with git), instead of cmd or powershell") - answer = input("Are you using bash? (yes/no): ").strip().lower() - if 'y' not in answer: - sys.exit(1) + print("Windows OS detected. If on windows, you must be using WSL. Revist the docs and reinstall. Sorry") + sys.exit(1) def docker_pull(image_url): os_type = platform.system() - if os_type=='Windows' or os_type == 'Darwin': + if is_wsl() or os_type == 'Darwin': print("Please open the Docker Desktop application before proceeding") answer =input("Is the Docker Desktop app running? (yes/no)") print("Pulling Docker image...") @@ -70,11 +80,7 @@ def install_precommit(venv_python): def install_openocd(): os_type = platform.system() try: - if os_type == "Windows": - print("Please install OpenOCD manually on Windows. You can download it from https://gnutoolchains.com/arm-eabi/openocd/") - print("You will need to unzip the downloaded file and run the exe file.") - return - elif os_type == "Darwin": + if os_type == "Darwin": run_command(["brew", "install", "openocd"]) elif os_type == "Linux": @@ -113,8 +119,8 @@ def main(): print("Everyone's system is different, and if you already have something installed, or know exactly") print("what you are doing, feel free to manually go about this as needed.") - # Step 0: Check for Docker and Rust - check_docker_and_rust() + # Step 0: Check for Docker + check_docker() # Step 1: pull image answer = input("Would you like to pull the docker image? (yes/no)") @@ -137,7 +143,7 @@ def main(): answer = input("Would you like to install all python packages in the venv? (yes/no)") if 'y' in answer: # Use the venv's Python - venv_python = os.path.join(venv_path, 'Scripts', 'python') if os_type == "Windows" else os.path.join(venv_path, 'bin', 'python') + venv_python = os.path.join(venv_path, 'bin', 'python') # Step 4: run setup.py (installs requirements and entry points) run_setup(venv_python) @@ -151,7 +157,7 @@ def main(): install_openocd() # Step 6: Install usbip if on Linux - if os_type == "Linux": + if os_type == "Linux" and is_wsl() == 0: answer = input("Would you like to install usbip? (yes/no)") if 'y' in answer: install_usbip() diff --git a/openocd.cfg b/openocd.cfg new file mode 100644 index 0000000..12a8374 --- /dev/null +++ b/openocd.cfg @@ -0,0 +1,7 @@ +$_TARGETNAME configure -event gdb-detach { + reset run + shutdown +} + +init +reset halt