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

dist/tools/openocd: fix parsing of flash bank base #19620

Merged
merged 1 commit into from
May 23, 2023
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
69 changes: 6 additions & 63 deletions dist/tools/openocd/openocd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -195,42 +195,7 @@ _is_binfile() {
[[ -z "${firmware_type}" ]] && _has_bin_extension "${firmware}"; }
}

# Split bank info on different lines without the '{}'
_split_banks() {
# Input:
# ...
# {name nrf51 base 0 size 0 bus_width 1 chip_width 1} {name nrf51 base 268439552 size 0 bus_width 1 chip_width 1}
# ...
# or for newer openocd versions (v0.12.0 or higher)
# ...
# {name nrf51.flash driver nrf51 base 0 size 0 bus_width 1 chip_width 1 target nrf51.cpu} {name nrf51.uicr ...}
# ...
#
# Output:
# ...
# name nrf51 base 0 size 0 bus_width 1 chip_width 1
# name nrf51 base 268439552 size 0 bus_width 1 chip_width 1
# ...
# or for newer openocd versions (v0.12.0 or higher)
# ...
# name nrf51.flash driver nrf51 base 0 size 0 bus_width 1 chip_width 1 target nrf51.cpu
# name nrf51.uicr driver nrf51 base 268439552 size 0 bus_width 1 chip_width 1 target nrf51.cpu
# ...
#
# The following command needs specific osx handling (non gnu):
# * Same commands for a pattern should be on different lines
# * Cannot use '\n' in the replacement string
local sed_escaped_newline=\\$'\n'

sed -n '
/^{.*}$/ {
s/\} /\}'"${sed_escaped_newline}"'/g
s/[{}]//g
p
}'
}

_flash_list_raw() {
_flash_list() {
# Openocd output for 'flash list' is either
# ....
# {name nrf51 base 0 size 0 bus_width 1 chip_width 1} {name nrf51 base 268439552 size 0 bus_width 1 chip_width 1}
Expand Down Expand Up @@ -272,32 +237,10 @@ _flash_list_raw() {
-c 'shutdown'" 2>&1
}

# Outputs bank info on different lines without the '{}'
_flash_list() {
# ....
# name nrf51 base 0 size 0 bus_width 1 chip_width 1
# name nrf51 base 268439552 size 0 bus_width 1 chip_width 1
# ....
# or for newer openocd versions (v0.12.0 or higher)
# ....
# name nrf51.flash driver nrf51 base 0 size 0 bus_width 1 chip_width 1 target nrf51.cpu
# name nrf51.uicr driver nrf51 base 268439552 size 0 bus_width 1 chip_width 1 target nrf51.cpu
# ....
_flash_list_raw | _split_banks
}

# Print flash address for 'bank_num' num defaults to 1
# _flash_address [bank_num:1]
# Print flash address for 'bank_num' num defaults to 0
# _flash_address [bank_num:0]
_flash_address() {
# extract the line from '_flash_list' output for bank with number 'bank_num'
bank=$(_flash_list | awk "NR==${1:-1}")
# determine the column of base address, a line can have following formats
# name nrf51 base 268439552 size 0 bus_width 1 chip_width 1
# or for newer openocd versions (v0.12.0 or higher)
# name nrf51.flash driver nrf51 base 0 size 0 bus_width 1 chip_width 1 target nrf51.cpu
base_addr_idx=$(echo ${bank} | awk '{ for (i=1; i <= NF; i++) if ($i == "base") print i + 1 }')
# extract the base address in hexadecimal format
printf 0x"%08x" $(echo ${bank} | cut -d " " -f${base_addr_idx})
_flash_list | "${RIOTTOOLS}/openocd/openocd_flashinfo.py" --idx "${1:-0}"
}

do_flashr() {
Expand All @@ -317,7 +260,7 @@ do_flashr() {
# This allows flashing normal binary files without env configuration
if _is_binfile "${IMAGE_FILE}" "${IMAGE_TYPE}"; then
# hardwritten to use the first bank
FLASH_ADDR=$(_flash_address 1)
FLASH_ADDR=$(_flash_address 0)
echo "Binfile detected, adding ROM base address: ${FLASH_ADDR}"
IMAGE_TYPE=bin
IMAGE_OFFSET=$(printf "0x%08x\n" "$((${IMAGE_OFFSET} + ${FLASH_ADDR}))")
Expand Down Expand Up @@ -366,7 +309,7 @@ do_flash() {
# This allows flashing normal binary files without env configuration
if _is_binfile "${IMAGE_FILE}" "${IMAGE_TYPE}"; then
# hardwritten to use the first bank
FLASH_ADDR=$(_flash_address 1)
FLASH_ADDR=$(_flash_address 0)
echo "Binfile detected, adding ROM base address: ${FLASH_ADDR}"
IMAGE_TYPE=bin
IMAGE_OFFSET=$(printf "0x%08x\n" "$((${IMAGE_OFFSET} + ${FLASH_ADDR}))")
Expand Down
69 changes: 69 additions & 0 deletions dist/tools/openocd/openocd_flashinfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env python3
"""
Utility to parse the output of OpenOCD's "flash list" command
"""
import argparse
import sys

NUMERIC_FIELDS = {"base", "size", "bus_width", "chip_width"}


def parse_flash_info(lines):
"""
Read output of OpenOCD's "flash list" command given in lines into a list
of dictionaries

:param lines: Output of "flash list" lines

:return: [{"name": "nrf52.flash", "base": 0, ...},
{"name": "nrf52.uicr", ...}, ...]
"""
tokens = []
for line in lines:
for word in line.split():
if word.startswith('{') and len(word) > 1:
tokens += ["{", word[1:]]
elif word.endswith('}') and len(word) > 1:
tokens += [word[:-1], "}"]
else:
tokens.append(word)

idx = 0
result = []
while idx < len(tokens):
entry = {}
while idx < len(tokens) and tokens[idx] != "{":
idx += 1
idx += 1
while idx < len(tokens) and tokens[idx] != "}":
if idx + 1 >= len(tokens) or tokens[idx + 1] == "}":
break
key = tokens[idx]
value = tokens[idx + 1]
if key in NUMERIC_FIELDS:
value = int(value, 0)
entry[key] = value
idx += 2
if idx < len(tokens) and tokens[idx] == "}":
result.append(entry)

return result


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Parse OpenOCD's \"flash list\" output")
parser.add_argument("--field", default="base", type=str,
help="Field to extract (default \"base\")")
parser.add_argument("--idx", default=0, type=int,
help="Index of the bank to extract info from " +
"(default 0)")
args = parser.parse_args()
info = parse_flash_info(sys.stdin)
if args.idx < 0 or args.idx >= len(info):
sys.exit("flash bank index out of range")
value = info[args.idx][args.field]
if args.field in NUMERIC_FIELDS:
print(f"0x{value:08x}")
else:
print(value)