From f4df95e6a0e866ccb6e41429dc6bbfd5efcca9b3 Mon Sep 17 00:00:00 2001 From: Ole Odendahl Date: Sun, 23 Oct 2022 11:38:12 +0200 Subject: [PATCH 01/10] Added mac converter class for easy reading of mac address from microcontroller. --- flashing/.gitignore | 1 + flashing/mac_converter.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 flashing/.gitignore create mode 100644 flashing/mac_converter.py diff --git a/flashing/.gitignore b/flashing/.gitignore new file mode 100644 index 0000000..ba0430d --- /dev/null +++ b/flashing/.gitignore @@ -0,0 +1 @@ +__pycache__/ \ No newline at end of file diff --git a/flashing/mac_converter.py b/flashing/mac_converter.py new file mode 100644 index 0000000..800c7e7 --- /dev/null +++ b/flashing/mac_converter.py @@ -0,0 +1,31 @@ +from pyocd.core.target import Target + + +class MacConverter(): + + MEMORY_ADDRESS = 268435620 # 0x100000A4 + + def __init__(self, target: Target) -> None: + self.target = target + + def get_mac_address(self) -> str: + memory_blocks = self._get_blocks() + + return self._convert_blocks(memory_blocks) + + def _get_blocks(self): + memory_blocks = self.target.read_memory_block32(self.MEMORY_ADDRESS, 2) + + return memory_blocks + + def _convert_blocks(self, memory_blocks: list[int]) -> str: + first_block = f'{memory_blocks[0]:x}'.rjust(8, '0') + + modified_second_block = memory_blocks[1] | 49152 # Bitwise OR with 0xc000 + + second_block = f'{modified_second_block:x}' + + mac_string = (second_block[4:] + first_block) + prettified_mac = ':'.join(mac_string[i:i+2] for i in range(0, len(mac_string), 2)) + + return prettified_mac.upper() From 1174bcab67c94450f8da67ec80c1f9ef091534b3 Mon Sep 17 00:00:00 2001 From: Ole Odendahl Date: Sun, 23 Oct 2022 11:48:24 +0200 Subject: [PATCH 02/10] Added script for facilitating flashing procedures with pyocd. --- flashing/flash_firmware.py | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 flashing/flash_firmware.py diff --git a/flashing/flash_firmware.py b/flashing/flash_firmware.py new file mode 100644 index 0000000..ec79262 --- /dev/null +++ b/flashing/flash_firmware.py @@ -0,0 +1,42 @@ +import argparse + +from pathlib import Path + +from pyocd.core.helpers import ConnectHelper +from pyocd.core.target import Target +from pyocd.flash.file_programmer import FileProgrammer + +from mac_converter import MacConverter + +parser = argparse.ArgumentParser() +parser.add_argument("-a", "--all", action="store_true", help="Flash softdevice and firmware.") +parser.add_argument("--only-mac", action="store_true", help="Read only the mac address from controller.") +parser.add_argument("-s", "--softdevice", action="store", help="File path to softdevice file.", default="../sdk/s140nrf52720/s140_nrf52_7.2.0_softdevice.hex", type=Path) +parser.add_argument("-f", "--firmware", action="store", help="File path to firmware file.", default="../code/b-parasite/_build/nrf52840_xxaa.hex", type=Path) + +args = parser.parse_args() + +with ConnectHelper.session_with_chosen_probe() as session: + + board = session.board + target: Target = board.target + + if not args.only_mac: + if args.all: + softdevice_path: Path = args.softdevice + print(f"Flashing softdevice {softdevice_path.name}...") + FileProgrammer(session).program(str(softdevice_path)) + + target.reset_and_halt() + target.resume() + + firmware_path: Path = args.firmware + print(f"Flashing firmware {firmware_path.name}...") + FileProgrammer(session).program(str(firmware_path)) + + target.reset_and_halt() + target.resume() + + mac_converter = MacConverter(target) + mac_address = mac_converter.get_mac_address() + print(f'Device MAC Address: {mac_address}') From 39f839b794f555e08aa00391860c55e748f6c8b0 Mon Sep 17 00:00:00 2001 From: Ole Odendahl Date: Sun, 23 Oct 2022 17:32:57 +0200 Subject: [PATCH 03/10] Changed use of memory addresses in mac address reader to hex representation. --- flashing/flash_firmware.py | 4 ++-- flashing/{mac_converter.py => mac_address_reader.py} | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) rename flashing/{mac_converter.py => mac_address_reader.py} (83%) diff --git a/flashing/flash_firmware.py b/flashing/flash_firmware.py index ec79262..4d0790b 100644 --- a/flashing/flash_firmware.py +++ b/flashing/flash_firmware.py @@ -6,7 +6,7 @@ from pyocd.core.helpers import ConnectHelper from pyocd.core.target import Target from pyocd.flash.file_programmer import FileProgrammer -from mac_converter import MacConverter +from mac_address_reader import MacAddressReader parser = argparse.ArgumentParser() parser.add_argument("-a", "--all", action="store_true", help="Flash softdevice and firmware.") @@ -37,6 +37,6 @@ with ConnectHelper.session_with_chosen_probe() as session: target.reset_and_halt() target.resume() - mac_converter = MacConverter(target) + mac_converter = MacAddressReader(target) mac_address = mac_converter.get_mac_address() print(f'Device MAC Address: {mac_address}') diff --git a/flashing/mac_converter.py b/flashing/mac_address_reader.py similarity index 83% rename from flashing/mac_converter.py rename to flashing/mac_address_reader.py index 800c7e7..a52c55a 100644 --- a/flashing/mac_converter.py +++ b/flashing/mac_address_reader.py @@ -1,9 +1,9 @@ from pyocd.core.target import Target -class MacConverter(): +class MacAddressReader(): - MEMORY_ADDRESS = 268435620 # 0x100000A4 + MEMORY_ADDRESS = 0x100000A4 def __init__(self, target: Target) -> None: self.target = target @@ -21,7 +21,7 @@ class MacConverter(): def _convert_blocks(self, memory_blocks: list[int]) -> str: first_block = f'{memory_blocks[0]:x}'.rjust(8, '0') - modified_second_block = memory_blocks[1] | 49152 # Bitwise OR with 0xc000 + modified_second_block = memory_blocks[1] | 0xc000 # Bitwise OR second_block = f'{modified_second_block:x}' From 82027616463ece91882958a120137f492d0316ef Mon Sep 17 00:00:00 2001 From: Ole Odendahl Date: Sun, 23 Oct 2022 17:35:15 +0200 Subject: [PATCH 04/10] Added requirements file for python environment setup. --- flashing/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 flashing/requirements.txt diff --git a/flashing/requirements.txt b/flashing/requirements.txt new file mode 100644 index 0000000..6e6bf07 --- /dev/null +++ b/flashing/requirements.txt @@ -0,0 +1 @@ +pyocd>=0.34.1 \ No newline at end of file From a25ec5ca5838ad045622bc01535ca201f2c7b5b3 Mon Sep 17 00:00:00 2001 From: Ole Odendahl Date: Sun, 23 Oct 2022 18:00:11 +0200 Subject: [PATCH 05/10] Simplified the cli of flashing scripts. --- flashing/flash_firmware.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/flashing/flash_firmware.py b/flashing/flash_firmware.py index 4d0790b..be1e138 100644 --- a/flashing/flash_firmware.py +++ b/flashing/flash_firmware.py @@ -9,10 +9,10 @@ from pyocd.flash.file_programmer import FileProgrammer from mac_address_reader import MacAddressReader parser = argparse.ArgumentParser() -parser.add_argument("-a", "--all", action="store_true", help="Flash softdevice and firmware.") -parser.add_argument("--only-mac", action="store_true", help="Read only the mac address from controller.") -parser.add_argument("-s", "--softdevice", action="store", help="File path to softdevice file.", default="../sdk/s140nrf52720/s140_nrf52_7.2.0_softdevice.hex", type=Path) -parser.add_argument("-f", "--firmware", action="store", help="File path to firmware file.", default="../code/b-parasite/_build/nrf52840_xxaa.hex", type=Path) +parser.add_argument("-s", "--softdevice", action="store", help="Optional file path to softdevice file.", default="../sdk/s140nrf52720/s140_nrf52_7.2.0_softdevice.hex", type=Path) +parser.add_argument("-f", "--firmware", action="store", help="Optional file path to firmware file.", default="../code/b-parasite/_build/nrf52840_xxaa.hex", type=Path) +parser.add_argument("--skip-softdevice", action="store_true", help="Skip flashing of the softdevice.") +parser.add_argument("--skip-firmware", action="store_true", help="Skip flashing of firmware.") args = parser.parse_args() @@ -21,15 +21,15 @@ with ConnectHelper.session_with_chosen_probe() as session: board = session.board target: Target = board.target - if not args.only_mac: - if args.all: - softdevice_path: Path = args.softdevice - print(f"Flashing softdevice {softdevice_path.name}...") - FileProgrammer(session).program(str(softdevice_path)) + if not args.skip_softdevice: + softdevice_path: Path = args.softdevice + print(f"Flashing softdevice {softdevice_path.name}...") + FileProgrammer(session).program(str(softdevice_path)) - target.reset_and_halt() - target.resume() + target.reset_and_halt() + target.resume() + if not args.skip_firmware: firmware_path: Path = args.firmware print(f"Flashing firmware {firmware_path.name}...") FileProgrammer(session).program(str(firmware_path)) From 53e52f32677ffbc764473ef2557acd119c9d3914 Mon Sep 17 00:00:00 2001 From: Ole Odendahl Date: Sun, 23 Oct 2022 18:09:43 +0200 Subject: [PATCH 06/10] Moving the flashing files to different subfolder for better discoverability. --- flashing/{ => pyocd}/.gitignore | 0 flashing/{ => pyocd}/flash_firmware.py | 4 ++-- flashing/{ => pyocd}/mac_address_reader.py | 0 flashing/{ => pyocd}/requirements.txt | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename flashing/{ => pyocd}/.gitignore (100%) rename flashing/{ => pyocd}/flash_firmware.py (86%) rename flashing/{ => pyocd}/mac_address_reader.py (100%) rename flashing/{ => pyocd}/requirements.txt (100%) diff --git a/flashing/.gitignore b/flashing/pyocd/.gitignore similarity index 100% rename from flashing/.gitignore rename to flashing/pyocd/.gitignore diff --git a/flashing/flash_firmware.py b/flashing/pyocd/flash_firmware.py similarity index 86% rename from flashing/flash_firmware.py rename to flashing/pyocd/flash_firmware.py index be1e138..78b968a 100644 --- a/flashing/flash_firmware.py +++ b/flashing/pyocd/flash_firmware.py @@ -9,8 +9,8 @@ from pyocd.flash.file_programmer import FileProgrammer from mac_address_reader import MacAddressReader parser = argparse.ArgumentParser() -parser.add_argument("-s", "--softdevice", action="store", help="Optional file path to softdevice file.", default="../sdk/s140nrf52720/s140_nrf52_7.2.0_softdevice.hex", type=Path) -parser.add_argument("-f", "--firmware", action="store", help="Optional file path to firmware file.", default="../code/b-parasite/_build/nrf52840_xxaa.hex", type=Path) +parser.add_argument("-s", "--softdevice", action="store", help="Optional file path to softdevice file.", default="../../sdk/s140nrf52720/s140_nrf52_7.2.0_softdevice.hex", type=Path) +parser.add_argument("-f", "--firmware", action="store", help="Optional file path to firmware file.", default="../../code/b-parasite/_build/nrf52840_xxaa.hex", type=Path) parser.add_argument("--skip-softdevice", action="store_true", help="Skip flashing of the softdevice.") parser.add_argument("--skip-firmware", action="store_true", help="Skip flashing of firmware.") diff --git a/flashing/mac_address_reader.py b/flashing/pyocd/mac_address_reader.py similarity index 100% rename from flashing/mac_address_reader.py rename to flashing/pyocd/mac_address_reader.py diff --git a/flashing/requirements.txt b/flashing/pyocd/requirements.txt similarity index 100% rename from flashing/requirements.txt rename to flashing/pyocd/requirements.txt From 100f4046faf26895bbff41284b09bc30769ff0c5 Mon Sep 17 00:00:00 2001 From: Ole Odendahl Date: Sun, 23 Oct 2022 18:10:08 +0200 Subject: [PATCH 07/10] Added basic readme for flashing based on issue #67. --- flashing/pyocd/README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 flashing/pyocd/README.md diff --git a/flashing/pyocd/README.md b/flashing/pyocd/README.md new file mode 100644 index 0000000..296d50f --- /dev/null +++ b/flashing/pyocd/README.md @@ -0,0 +1,27 @@ +# Flashing with pyocd + +This is a different approach to flash the firmware on the b-parasites. It is completely optional. + +## Basic instructions + +(Based on the discussion in issue #67) + +The instructions will probably differ alot depending on your debugging probe and hardware setup. + +The setup is fairly straightforward and documented in the `pyocd` [docs](https://pyocd.io/). + +I used an inexpensive debugging probe from Aliexpress called `nanoDAP` from `Muse Labs` which is less than 10 € and readily available. The J-LINKs are hard to get and quite expensive. In my understanding basically all `CMSIS-DAP`-compatible probes which are recognized by `pyocd` should work. + +After connecting the debugging probe via usb and connecting the b-parasite as described in the wiki, flashing was easy and fast. + +For a complete flashing of softdevice and firmware use the provided python script. Assuming you put the `*.hex` files in default locations it boils down to one simple command: + +``` +python ./flash_firmware.py +``` + +For help and documentation of the available command line flags use + +``` +python ./flash_firmware.py -h +``` \ No newline at end of file From e45bb43b84e7142c731ca5f7704f8b8660d1d522 Mon Sep 17 00:00:00 2001 From: Ole Odendahl Date: Sun, 23 Oct 2022 18:51:56 +0200 Subject: [PATCH 08/10] Clarified mac address code so that it will be clearer what it contains (static device mac). --- flashing/pyocd/flash_firmware.py | 4 ++-- flashing/pyocd/mac_address_reader.py | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/flashing/pyocd/flash_firmware.py b/flashing/pyocd/flash_firmware.py index 78b968a..8a2a918 100644 --- a/flashing/pyocd/flash_firmware.py +++ b/flashing/pyocd/flash_firmware.py @@ -38,5 +38,5 @@ with ConnectHelper.session_with_chosen_probe() as session: target.resume() mac_converter = MacAddressReader(target) - mac_address = mac_converter.get_mac_address() - print(f'Device MAC Address: {mac_address}') + mac_address = mac_converter.get_static_mac_address() + print(f'Static manufacturer MAC address: {mac_address}') diff --git a/flashing/pyocd/mac_address_reader.py b/flashing/pyocd/mac_address_reader.py index a52c55a..5e370cd 100644 --- a/flashing/pyocd/mac_address_reader.py +++ b/flashing/pyocd/mac_address_reader.py @@ -8,7 +8,12 @@ class MacAddressReader(): def __init__(self, target: Target) -> None: self.target = target - def get_mac_address(self) -> str: + def get_static_mac_address(self) -> str: + ''' + Reads the static mac address assigned by the manufacturer. + + This chip property is readonly and may be different from the mac address in the application code. + ''' memory_blocks = self._get_blocks() return self._convert_blocks(memory_blocks) From d8dfcc69a95cb17b5da2fe4379d81f3d96f61c49 Mon Sep 17 00:00:00 2001 From: Ole Odendahl Date: Sun, 23 Oct 2022 18:55:46 +0200 Subject: [PATCH 09/10] Final cosmetic changes in flashing code to improve output and variable naming. --- flashing/pyocd/flash_firmware.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flashing/pyocd/flash_firmware.py b/flashing/pyocd/flash_firmware.py index 8a2a918..2233660 100644 --- a/flashing/pyocd/flash_firmware.py +++ b/flashing/pyocd/flash_firmware.py @@ -37,6 +37,6 @@ with ConnectHelper.session_with_chosen_probe() as session: target.reset_and_halt() target.resume() - mac_converter = MacAddressReader(target) - mac_address = mac_converter.get_static_mac_address() - print(f'Static manufacturer MAC address: {mac_address}') + mac_address_reader = MacAddressReader(target) + mac_address = mac_address_reader.get_static_mac_address() + print(f'Static manufacturer MAC address (DEVICEADDR): {mac_address}') From 149e15480d595f40ff0d96b5c1d739931409b87e Mon Sep 17 00:00:00 2001 From: Ole Odendahl Date: Sun, 23 Oct 2022 19:00:57 +0200 Subject: [PATCH 10/10] Fixed typo in readme and changed meaning of the sentence to better reflect the actual situation. --- flashing/pyocd/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flashing/pyocd/README.md b/flashing/pyocd/README.md index 296d50f..a8e99b2 100644 --- a/flashing/pyocd/README.md +++ b/flashing/pyocd/README.md @@ -6,7 +6,7 @@ This is a different approach to flash the firmware on the b-parasites. It is com (Based on the discussion in issue #67) -The instructions will probably differ alot depending on your debugging probe and hardware setup. +The instructions will probably differ slightly depending on your debugging probe and hardware setup. The setup is fairly straightforward and documented in the `pyocd` [docs](https://pyocd.io/).