Merge pull request #68 from oleo65/python-flash-script
Introduces Python helper script for flashing with OpenOCD (pyocd)
This commit is contained in:
commit
54c6c09ff0
5 changed files with 107 additions and 0 deletions
1
flashing/pyocd/.gitignore
vendored
Normal file
1
flashing/pyocd/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
__pycache__/
|
||||||
27
flashing/pyocd/README.md
Normal file
27
flashing/pyocd/README.md
Normal file
|
|
@ -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 slightly 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
|
||||||
|
```
|
||||||
42
flashing/pyocd/flash_firmware.py
Normal file
42
flashing/pyocd/flash_firmware.py
Normal file
|
|
@ -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_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("--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()
|
||||||
|
|
||||||
|
with ConnectHelper.session_with_chosen_probe() as session:
|
||||||
|
|
||||||
|
board = session.board
|
||||||
|
target: Target = board.target
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
if not args.skip_firmware:
|
||||||
|
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_address_reader = MacAddressReader(target)
|
||||||
|
mac_address = mac_address_reader.get_static_mac_address()
|
||||||
|
print(f'Static manufacturer MAC address (DEVICEADDR): {mac_address}')
|
||||||
36
flashing/pyocd/mac_address_reader.py
Normal file
36
flashing/pyocd/mac_address_reader.py
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
from pyocd.core.target import Target
|
||||||
|
|
||||||
|
|
||||||
|
class MacAddressReader():
|
||||||
|
|
||||||
|
MEMORY_ADDRESS = 0x100000A4
|
||||||
|
|
||||||
|
def __init__(self, target: Target) -> None:
|
||||||
|
self.target = target
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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] | 0xc000 # Bitwise OR
|
||||||
|
|
||||||
|
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()
|
||||||
1
flashing/pyocd/requirements.txt
Normal file
1
flashing/pyocd/requirements.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
pyocd>=0.34.1
|
||||||
Loading…
Add table
Reference in a new issue