ra8-firmware
0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
gen_jlink_w4.py
Go to the documentation of this file.
1
#!/usr/bin/env python3
2
# SPDX-License-Identifier: MIT
3
# Copyright (c) 2026 Brighton Sikarskie
4
"""Emit a J-Link script that programs MRAM with w4 and starts without a reset.
5
6
Why w4 instead of loadfile/loadbin:
7
loadfile/loadbin both trigger SYSRESETREQ before programming. After that
8
reset the RA8D2 runs on its ~4 MHz internal oscillator; J-Link uploads
9
its RAMCode to SRAM and calls Prepare/Program/Finalize. After ~13
10
consecutive operations the MRAM controller accumulates error state that
11
only a physical PORST (power-on reset) can clear, causing every subsequent
12
flash attempt to fail.
13
14
Why not "r" to restart after w4 writes:
15
J-Link Commander's "r" command on RA8D2 with TrustZone invokes a
16
device-specific reset sequence that again runs RAMCode Prepare(), causing
17
the same accumulation. Instead, the generated script injects the firmware
18
entry point directly into the CPU core registers via DCRSR/DCRDR while
19
the CPU is halted, then issues "g" (go). No SYSRESETREQ is issued at any
20
point, so the MRAM controller state never accumulates.
21
22
DCRSR/DCRDR register injection (ARMv8-M reference manual, C1.6):
23
DCRDR (0xE000EDF8): data register -- write the value here first
24
DCRSR (0xE000EDF4): selector register -- set bit 16 (write) + reg index
25
Register indices used:
26
15 (0x0F) = PC
27
17 (0x11) = MSP
28
16 (0x10) = xPSR (set T bit, Thread mode: 0x01000000)
29
20 (0x14) = CFBP (CONTROL | FAULTMASK | BASEPRI | PRIMASK, all zero)
30
31
Usage:
32
python3 scripts/gen/gen_jlink_w4.py <binary> <base_addr_hex> \
33
[--device <device_name>]
34
python3 scripts/gen/gen_jlink_w4.py firmware.bin 0x02000000 > flash.jlink
35
36
The binary must be a flat raw image whose first byte maps to base_addr.
37
Use arm-none-eabi-objcopy -O binary to produce one from an ELF.
38
39
Note: pass -SelectEmuBySN <SN> to JLinkExe on the command line, NOT via
40
the generated script. Placing SelectEmuBySN inside the commander script
41
causes J-Link to fail subsequent halt commands on RA8D2 with SSD enabled.
42
"""
43
44
import
struct
45
import
sys
46
from
pathlib
import
Path
47
48
# Minimum positional argument count: <binary> <base_addr_hex>
49
MIN_ARGS = 3
50
51
52
def
main
() -> None:
53
"""Emit the J-Link commander script for one binary at one base address.
54
55
Writes the script to stdout; the caller pipes it to JLinkExe. Exits 1 on
56
a usage error and returns None otherwise -- there is no partial-success
57
state, since the script is either fully emitted or not at all.
58
"""
59
if
len(sys.argv) < MIN_ARGS:
60
print(
61
f
"Usage: {sys.argv[0]} <binary> <base_addr_hex> [--device DEV]"
,
62
file=sys.stderr,
63
)
64
sys.exit(1)
65
66
bin_file: str = sys.argv[1]
67
base: int = int(sys.argv[2], 16)
68
device: str =
"R7KA8D2KF_CPU0"
69
70
i: int = 3
71
while
i < len(sys.argv):
72
if
sys.argv[i] ==
"--device"
and
i + 1 < len(sys.argv):
73
device = sys.argv[i + 1]
74
i += 2
75
else
:
76
print(f
"Unknown arg: {sys.argv[i]}"
, file=sys.stderr)
77
sys.exit(1)
78
79
with
Path(bin_file).open(
"rb"
)
as
f:
80
data: bytes = f.read()
81
82
while
len(data) % 4:
83
data += b
"\xff"
84
85
initial_sp: int = struct.unpack_from(
"<I"
, data, 0)[0]
86
reset_handler: int = struct.unpack_from(
"<I"
, data, 4)[0] & 0xFFFFFFFE
87
88
print(f
"device {device}"
)
89
print(
"si SWD"
)
90
print(
"speed 1000"
)
91
print(
"connect"
)
92
print(
"halt"
)
93
for
idx
in
range(0, len(data), 4):
94
word: int = struct.unpack_from(
"<I"
, data, idx)[0]
95
print(f
"w4 0x{base + idx:08X} 0x{word:08X}"
)
96
97
print(f
"w4 0xE000EDF8 0x{initial_sp:08X}"
)
98
print(
"w4 0xE000EDF4 0x00010011"
)
99
print(
"w4 0xE000EDF8 0x01000000"
)
100
print(
"w4 0xE000EDF4 0x00010010"
)
101
print(
"w4 0xE000EDF8 0x00000000"
)
102
print(
"w4 0xE000EDF4 0x00010014"
)
103
print(f
"w4 0xE000EDF8 0x{reset_handler:08X}"
)
104
print(
"w4 0xE000EDF4 0x0001000F"
)
105
print(
"g"
)
106
print(
"q"
)
107
108
109
if
__name__ ==
"__main__"
:
110
main
()
main
void main(void)
The application entry point Reset_Handler hands control to.
Definition
main.c:298
scripts
gen
gen_jlink_w4.py
Generated by
1.16.1