Skip to content

Commit 2802d56

Browse files
jonathannilsen57300
authored andcommitted
[nrf fromtree] boards: nordic: update custom JLink reset scheme for ADACv2
Version 2 of the ADAC interface implemented by secure domain firmware changes the ADAC RESET command used in the custom reset handling in the JLink support scripts. The command has been split into two commands, RESET and START, and has different semantics from the previous RESET command. The new RESET command resets both the application and radio domains without starting the CPUs again, and the START command must then be used to start the CPUs. Update the JLink support scripts for nrf54h20dk/nrf54h20/cpuapp, nrf54h20dk/nrf54h20/cpurad, nrf9280pdk/nrf9280/cpuapp and nrf9280pdk/nrf9280/cpurad so that they read out the ADAC interface version from the device and use the newer commands if ADAC version 2 is detected. If the version is lower than 2, the legacy implementation is used. Also improve the CTRL-AP MAILBOX transaction implementation to avoid the need for arbitrary sleeps or unnecessary polling of the MAILBOX. This should improve stability when using the script. Signed-off-by: Jonathan Nilsen <[email protected]> (cherry picked from commit d403d73)
1 parent e46d2e6 commit 2802d56

File tree

4 files changed

+960
-82
lines changed

4 files changed

+960
-82
lines changed

boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript

Lines changed: 239 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,248 @@
1+
// Constants specific to the application core
2+
__constant U32 _CPUCONF_ADDR = 0x52011000;
3+
__constant U32 _PROCESSOR_ID = 2;
4+
__constant U32 _DOMAIN_ID = 2;
5+
__constant U32 _NUM_OTHER_PROCESSORS = 1;
6+
const U32 _OTHER_PROCESSOR_IDS[1] = {3};
7+
18
// Debug Halting Control and Status Register
2-
__constant U32 _DHCSR_ADDR = 0xE000EDF0;
3-
__constant U32 _DHCSR_DBGKEY = (0xA05F << 16);
4-
__constant U32 _DHCSR_C_DEBUGEN = (1 << 0);
5-
__constant U32 _DHCSR_C_HALT = (1 << 1);
9+
__constant U32 _DHCSR_ADDR = 0xE000EDF0;
10+
__constant U32 _DHCSR_DBGKEY = (0xA05F << 16);
11+
__constant U32 _DHCSR_C_DEBUGEN = (1 << 0);
12+
__constant U32 _DHCSR_C_HALT = (1 << 1);
613

714
// Debug Exception and Monitor Control Register
8-
__constant U32 _DEMCR_ADDR = 0xE000EDFC;
9-
__constant U32 _DEMCR_VC_CORERESET = (1 << 0);
10-
__constant U32 _DEMCR_TRCENA = (1 << 24);
15+
__constant U32 _DEMCR_ADDR = 0xE000EDFC;
16+
__constant U32 _DEMCR_VC_CORERESET = (1 << 0);
17+
__constant U32 _DEMCR_TRCENA = (1 << 24);
1118

1219
// CPU wait enable register
13-
__constant U32 _CPUCONF_CPUWAIT_ADDR = 0x5201150C;
20+
__constant U32 _CPUCONF_CPUWAIT_OFFSET = 0x50C;
21+
22+
// CTRL-AP
23+
__constant U32 _CTRLAP_ID = 4;
24+
__constant U32 _CTRLAP_READY_BANK = 0;
25+
__constant U32 _CTRLAP_READY_OFFSET = 1;
26+
__constant U32 _CTRLAP_READY = 0;
27+
__constant U32 _CTRLAP_MAILBOX_BANK = 1;
28+
__constant U32 _CTRLAP_MAILBOX_TXDATA_OFFSET = 0;
29+
__constant U32 _CTRLAP_MAILBOX_TXSTATUS_OFFSET = 1;
30+
__constant U32 _CTRLAP_MAILBOX_RXDATA_OFFSET = 2;
31+
__constant U32 _CTRLAP_MAILBOX_RXSTATUS_OFFSET = 3;
32+
__constant U32 _CTRLAP_MAILBOX_NO_DATA_PENDING = 0;
33+
__constant U32 _CTRLAP_MAILBOX_DATA_PENDING = 1;
34+
__constant int _CTRLAP_TIMEOUT_MS = 500;
35+
36+
// ADAC transaction buffers
37+
static U32 _adacTx[20];
38+
static U32 _adacRx[20];
39+
40+
// Failed to send to the CTRL-AP MAILBOX
41+
__constant int _ERR_TX = -1;
42+
// Failed to receive from the CTRL-AP MAILBOX
43+
__constant int _ERR_RX = -2;
44+
// ADAC command returned an error
45+
__constant int _ERR_REPLY = -3;
46+
47+
// Wait for an AP register read to return the expected value.
48+
int _WaitForDataStatus(U32 regOffset, int expectedStatus)
49+
{
50+
int status;
51+
int ret;
52+
int start;
53+
int elapsed;
54+
55+
status = 0;
56+
start = JLINK_GetTime();
57+
elapsed = 0;
58+
59+
do {
60+
ret = JLINK_CORESIGHT_ReadDAP(regOffset, 1, &status);
61+
elapsed = JLINK_GetTime() - start;
62+
} while ((ret < 0 || status != expectedStatus) && (elapsed < _CTRLAP_TIMEOUT_MS));
63+
64+
if (ret < 0) {
65+
return ret;
66+
}
67+
68+
return status;
69+
}
70+
71+
// Continuously read from the CTRL-AP MAILBOX until there is no more pending data.
72+
void _DrainMailbox(void)
73+
{
74+
int ret;
75+
int status;
76+
int data;
77+
78+
ret = JLINK_CORESIGHT_ReadDAP(_CTRLAP_MAILBOX_RXSTATUS_OFFSET, 1, &status);
79+
while (ret >= 0 && status == _CTRLAP_MAILBOX_DATA_PENDING) {
80+
JLINK_CORESIGHT_ReadDAP(_CTRLAP_MAILBOX_RXDATA_OFFSET, 1, &data);
81+
ret = JLINK_CORESIGHT_ReadDAP(_CTRLAP_MAILBOX_RXSTATUS_OFFSET, 1, &status);
82+
}
83+
}
84+
85+
// Perform an ADAC transaction by:
86+
// * writing the given sequence of words to MAILBOX.TXDATATA, waiting for MAILBOX.TXSTATUS
87+
// readiness before each write.
88+
// * reading a sequence of words from MAILBOX.RXDATA, waiting for MAILBOX.RXSTATUS readiness before
89+
// each read.
90+
//
91+
// The message to send is read from _adacTx and the reply is written to _adacRx.
92+
// Optionally checks if a single data word is returned and returns an error if it is non-zero.
93+
//
94+
// Assumes that the correct AP and AP bank for CTRL-AP MAILBOX has been selected in the DP.
95+
int _DoAdacTransaction(int checkReplyStatus)
96+
{
97+
int numWords;
98+
int ret;
99+
int data;
100+
int i;
101+
102+
i = 0;
103+
numWords = 2 + (_adacTx[1] >> 2); // Length based on the length field of the message
104+
105+
while (i < numWords) {
106+
ret = _WaitForDataStatus(_CTRLAP_MAILBOX_TXSTATUS_OFFSET,
107+
_CTRLAP_MAILBOX_NO_DATA_PENDING);
108+
if (ret != _CTRLAP_MAILBOX_NO_DATA_PENDING) {
109+
JLINK_SYS_Report1("Timed out waiting for CTRL-AP TX readiness - result: ",
110+
ret);
111+
return _ERR_TX;
112+
}
113+
114+
ret = JLINK_CORESIGHT_WriteDAP(_CTRLAP_MAILBOX_TXDATA_OFFSET, 1, _adacTx[i]);
115+
if (ret < 0) {
116+
JLINK_SYS_Report1("Failed to write CTRL-AP TX data - result: ", ret);
117+
return _ERR_TX;
118+
}
119+
120+
i += 1;
121+
}
122+
123+
i = 0;
124+
numWords = 2; // Minimum message length
125+
126+
while (i < numWords) {
127+
ret = _WaitForDataStatus(_CTRLAP_MAILBOX_RXSTATUS_OFFSET,
128+
_CTRLAP_MAILBOX_DATA_PENDING);
129+
if (ret != _CTRLAP_MAILBOX_DATA_PENDING) {
130+
JLINK_SYS_Report1("Timed out waiting for CTRL-AP RX data - result: ", ret);
131+
return _ERR_RX;
132+
}
133+
134+
ret = JLINK_CORESIGHT_ReadDAP(_CTRLAP_MAILBOX_RXDATA_OFFSET, 1, &data);
135+
if (ret < 0) {
136+
JLINK_SYS_Report1("Failed to read CTRL-AP RX data - result: ", ret);
137+
return _ERR_RX;
138+
}
139+
140+
if (i == 1) {
141+
// Update total length based on the message length field
142+
numWords = 2 + (data >> 2);
143+
}
144+
145+
_adacRx[i] = data;
146+
i += 1;
147+
}
148+
149+
if (checkReplyStatus && _adacRx[1] == 4 && _adacRx[2] != 0) {
150+
JLINK_SYS_Report1("ADAC command failed with status: ", _adacRx[2]);
151+
return _ERR_REPLY;
152+
}
153+
154+
return 0;
155+
}
156+
157+
int ResetTarget(void)
158+
{
159+
int err;
160+
U32 adacMajorVersion;
161+
U32 i;
162+
163+
// Select CTRL-AP bank 0, used for the READY register
164+
JLINK_CORESIGHT_WriteDAP(JLINK_CORESIGHT_DP_REG_SELECT, 0,
165+
(_CTRLAP_ID << 24) | (_CTRLAP_READY_BANK << 4));
166+
167+
// Wait for the READY register to indicate that the AP can be used.
168+
err = _WaitForDataStatus(_CTRLAP_READY_OFFSET, _CTRLAP_READY);
169+
if (err < 0) {
170+
JLINK_SYS_Report1("Timed out waiting for CTRL-AP readiness - result: ", err);
171+
return -1;
172+
}
173+
174+
// Select CTRL-AP bank 1, used for the MAILBOX registers for ADAC communication
175+
JLINK_CORESIGHT_WriteDAP(JLINK_CORESIGHT_DP_REG_SELECT, 0,
176+
(_CTRLAP_ID << 24) | (_CTRLAP_MAILBOX_BANK << 4));
177+
178+
// Extract any pre-existing data from the mailbox in case there was previously
179+
// an aborted transaction.
180+
_DrainMailbox();
181+
182+
// Read the ADAC version
183+
_adacTx[0] = 0xA3000000; // Command VERSION
184+
_adacTx[1] = 0x00000004; // Data length 4 bytes
185+
_adacTx[2] = 0x00000000; // Type 0 (ADAC version)
186+
err = _DoAdacTransaction(0);
187+
if (err < 0) {
188+
return -1;
189+
}
190+
191+
adacMajorVersion = (_adacRx[2] >> 24) & 0xff;
192+
JLINK_SYS_Report1("ADAC major version: ", adacMajorVersion);
193+
194+
if (adacMajorVersion >= 2) {
195+
// There is a very small chance that this command fails if the domain reset itself
196+
// at the exact same time the command was issued. Therefore we retry a few times.
197+
i = 0;
198+
while (i < 3) {
199+
// Reset non-essential domains
200+
_adacTx[0] = 0xA30A0000; // Command RESET
201+
_adacTx[1] = 0x00000004; // Data length 4 bytes
202+
_adacTx[2] = 0x00000000; // (reserved)
203+
err = _DoAdacTransaction(1);
204+
if (err >= 0) {
205+
break;
206+
} else if (err != _ERR_REPLY) {
207+
return -1;
208+
}
209+
210+
i = i + 1;
211+
}
212+
213+
// Start the core in halted mode
214+
_adacTx[0] = 0xA3090000; // Command START
215+
_adacTx[1] = 0x00000004; // Data length 4 bytes
216+
_adacTx[2] = 0x01000000 | (_PROCESSOR_ID << 16); // Own processor, Flags HALT
217+
err = _DoAdacTransaction(1);
218+
if (err < 0) {
219+
return -1;
220+
}
14221

15-
int ResetTarget(void) {
16-
// ADAC reset
17-
JLINK_CORESIGHT_WriteDP(2, 0x04000010);
18-
JLINK_CORESIGHT_WriteAP(0, 0xA3030000);
19-
JLINK_CORESIGHT_WriteAP(0, 0x00000004);
20-
JLINK_CORESIGHT_WriteAP(0, 0x01020000);
222+
// Start other cores normally (will fail silently if no firmware is present)
223+
i = 0;
224+
while (i < _NUM_OTHER_PROCESSORS) {
225+
_adacTx[0] = 0xA3090000; // Command START
226+
_adacTx[1] = 0x00000004; // Data length 4 bytes
227+
_adacTx[2] = 0x00000000 |
228+
(_OTHER_PROCESSOR_IDS[i] << 16); // Other processor, No flags
229+
err = _DoAdacTransaction(0);
230+
if (err < 0 && err != _ERR_REPLY) {
231+
return -1;
232+
}
21233

22-
JLINK_SYS_Sleep(100);
23-
JLINK_CORESIGHT_ReadAP(2);
24-
JLINK_CORESIGHT_ReadAP(2);
25-
JLINK_CORESIGHT_ReadAP(2);
26-
JLINK_CORESIGHT_ReadAP(2);
234+
i = i + 1;
235+
}
236+
} else {
237+
// Reset single domain via legacy implementation
238+
_adacTx[0] = 0xA3030000; // Command RESET
239+
_adacTx[1] = 0x00000004; // Data length 4 bytes
240+
_adacTx[2] = 0x01000000 | (_DOMAIN_ID << 16); // Own domain, Mode HALT
241+
err = _DoAdacTransaction(1);
242+
if (err < 0) {
243+
return -1;
244+
}
245+
}
27246

28247
// Halt the CPU
29248
JLINK_MEM_WriteU32(_DHCSR_ADDR, (_DHCSR_DBGKEY | _DHCSR_C_HALT | _DHCSR_C_DEBUGEN));
@@ -32,7 +251,7 @@ int ResetTarget(void) {
32251
JLINK_MEM_WriteU32(_DEMCR_ADDR, (_DEMCR_VC_CORERESET | _DEMCR_TRCENA));
33252

34253
// Disable CPU wait
35-
JLINK_MEM_WriteU32(_CPUCONF_CPUWAIT_ADDR, 0);
254+
JLINK_MEM_WriteU32(_CPUCONF_ADDR + _CPUCONF_CPUWAIT_OFFSET, 0);
36255

37256
// Clear vector catch stuff
38257
JLINK_MEM_WriteU32(_DEMCR_ADDR, _DEMCR_TRCENA);

0 commit comments

Comments
 (0)