Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ner build fixups #180

Merged
merged 6 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions ftdi_flash.cfg
Original file line number Diff line number Diff line change
@@ -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
transport select jtag
104 changes: 85 additions & 19 deletions ner_environment/build_system/build_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -55,7 +58,53 @@ def clang(args):
# ==============================================================================

def debug(args):
pass

command = []
#if args.docker:
# print("Dockerized openocd unsupported for gdb")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we clean out unused code comments

# 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats this basename command for. I trust it works ig but i thought u could just directly do elf_files[0]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filepath is different inside of docker.

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
Expand All @@ -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"]

Expand All @@ -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)

Expand Down Expand Up @@ -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)

# ==============================================================================
Expand Down Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we find a way to get this streaming to work without that while loop? i thought we added that explicitly to get some form of sreamed output

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just don't use PIPE. Everything apparently works as long as the code doesn't need to access the output.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idk I tested before adding this and running flash showed nothing on output, but if u tested this then alright


returncode = process.wait()
if returncode != 0:
Expand All @@ -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
Copy link
Contributor

@dyldonahue dyldonahue Oct 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are better ways to detect WSL:

if platform.system() == "Linux" and "microsoft" in platform.uname().release.lower():

or

if 'WSL_DISTRO_NAME' in os.environ:
return 2 # WSL2

id rather us use one of these, seems cleaner than ur method

"""

if v.endswith("-Microsoft"):
return 1
elif v.endswith("microsoft-standard-WSL2"):
return 2

return 0


if __name__ == "__main__":
main()
Expand Down
40 changes: 23 additions & 17 deletions ner_environment/ner_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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...")
Expand Down Expand Up @@ -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":
Expand Down Expand Up @@ -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)")
Expand All @@ -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)
Expand All @@ -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()
Expand Down
7 changes: 7 additions & 0 deletions openocd.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
$_TARGETNAME configure -event gdb-detach {
reset run
shutdown
}

init
reset halt
Loading