Skip to content

Commit ceead4e

Browse files
sachinthegreenkartben
authored andcommitted
drivers: nrf_wifi: Add debug shell
Add a debug shell to the driver to provide advanced debug support such as reading/writing to RPU memory and registers etc. Signed-off-by: Sachin D Kulkarni <[email protected]>
1 parent fd538dc commit ceead4e

File tree

4 files changed

+388
-0
lines changed

4 files changed

+388
-0
lines changed

drivers/wifi/nrf_wifi/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ zephyr_library_sources_ifdef(CONFIG_NRF70_UTIL
6262
src/wifi_util.c
6363
)
6464

65+
zephyr_library_sources_ifdef(CONFIG_NRF70_DEBUG_SHELL
66+
src/shell.c
67+
src/debug_shell.c
68+
)
69+
6570
zephyr_compile_definitions_ifdef(CONFIG_NRF70_ON_QSPI
6671
# These are XIP related anomalies and aren't applicable for nRF7002 and cause
6772
# throughput issues.

drivers/wifi/nrf_wifi/Kconfig.nrfwifi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ config NRF70_UTIL
210210
depends on SHELL
211211
bool "Utility shell in nRF70 driver"
212212

213+
config NRF70_DEBUG_SHELL
214+
depends on SHELL
215+
bool "Debug shell in nRF70 driver"
216+
213217
config NRF70_QSPI_LOW_POWER
214218
bool "low power mode in QSPI"
215219
default y if NRF_WIFI_LOW_POWER
Lines changed: 364 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,364 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/* @file
8+
* @brief NRF Wi-Fi debug shell module
9+
*/
10+
#include <stdlib.h>
11+
#include <zephyr/shell/shell.h>
12+
#include "host_rpu_umac_if.h"
13+
#include "fmac_main.h"
14+
15+
extern struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep;
16+
struct nrf_wifi_ctx_zep *dbg_ctx = &rpu_drv_priv_zep.rpu_ctx_zep;
17+
18+
19+
static int nrf_wifi_dbg_read_mem(const struct shell *sh,
20+
size_t argc,
21+
const char *argv[])
22+
{
23+
enum nrf_wifi_status status;
24+
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx;
25+
char *ptr;
26+
unsigned long mem_type;
27+
unsigned long mem_offset;
28+
unsigned long num_words;
29+
unsigned int mem_val;
30+
unsigned int mem_start_addr;
31+
unsigned int mem_end_addr;
32+
unsigned int i;
33+
34+
fmac_dev_ctx = dbg_ctx->rpu_ctx;
35+
mem_type = strtoul(argv[1], &ptr, 10);
36+
mem_offset = strtoul(argv[2], &ptr, 10);
37+
num_words = strtoul(argv[3], &ptr, 10);
38+
39+
if (mem_type == 0) {
40+
mem_start_addr = RPU_ADDR_PKTRAM_START + (mem_offset * 4);
41+
mem_end_addr = RPU_ADDR_PKTRAM_END;
42+
} else if (mem_type == 1) {
43+
mem_start_addr = RPU_ADDR_GRAM_START + (mem_offset * 4);
44+
mem_end_addr = RPU_ADDR_GRAM_END;
45+
} else {
46+
shell_fprintf(sh,
47+
SHELL_ERROR,
48+
"Invalid memory type(%lu).\n",
49+
mem_type);
50+
return -ENOEXEC;
51+
}
52+
53+
if ((mem_start_addr % 4) != 0) {
54+
shell_fprintf(sh,
55+
SHELL_ERROR,
56+
"Invalid memory word offset(%lu). Needs to be a multiple of 4\n",
57+
mem_offset);
58+
return -ENOEXEC;
59+
}
60+
61+
if (mem_start_addr + (num_words * 4) - 1 > mem_end_addr) {
62+
shell_fprintf(sh,
63+
SHELL_ERROR,
64+
"Invalid number of words(%lu). Exceeds memory region\n",
65+
num_words);
66+
return -ENOEXEC;
67+
}
68+
69+
for (i = 0; i < (num_words * 4); i += 4) {
70+
status = hal_rpu_mem_read(fmac_dev_ctx->hal_dev_ctx,
71+
&mem_val,
72+
mem_start_addr + i,
73+
sizeof(mem_val));
74+
75+
if (status != NRF_WIFI_STATUS_SUCCESS) {
76+
shell_fprintf(sh,
77+
SHELL_ERROR,
78+
"Failed to read memory at 0x%x.\n",
79+
mem_start_addr + i);
80+
return -ENOEXEC;
81+
}
82+
83+
if (i % 16 == 0) {
84+
shell_fprintf(sh,
85+
SHELL_INFO,
86+
"\n0x%x: ", mem_start_addr + i);
87+
}
88+
89+
shell_fprintf(sh,
90+
SHELL_INFO,
91+
"0x%08x ",
92+
mem_val);
93+
}
94+
95+
shell_fprintf(sh,
96+
SHELL_INFO,
97+
"\n");
98+
return 0;
99+
}
100+
101+
102+
static int nrf_wifi_dbg_write_mem(const struct shell *sh,
103+
size_t argc,
104+
const char *argv[])
105+
{
106+
enum nrf_wifi_status status;
107+
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx;
108+
char *ptr;
109+
unsigned long mem_type;
110+
unsigned long mem_offset;
111+
unsigned int val;
112+
unsigned int mem_start_addr;
113+
unsigned int mem_end_addr;
114+
115+
fmac_dev_ctx = dbg_ctx->rpu_ctx;
116+
mem_type = strtoul(argv[1], &ptr, 10);
117+
mem_offset = strtoul(argv[2], &ptr, 10);
118+
val = strtoul(argv[3], &ptr, 10);
119+
120+
if (mem_type == 0) {
121+
mem_start_addr = RPU_ADDR_PKTRAM_START + (mem_offset * 4);
122+
mem_end_addr = RPU_ADDR_PKTRAM_END;
123+
} else if (mem_type == 1) {
124+
mem_start_addr = RPU_ADDR_GRAM_START + (mem_offset * 4);
125+
mem_end_addr = RPU_ADDR_GRAM_END;
126+
} else {
127+
shell_fprintf(sh,
128+
SHELL_ERROR,
129+
"Invalid memory type(%lu).\n",
130+
mem_type);
131+
return -ENOEXEC;
132+
}
133+
134+
if ((mem_start_addr % 4) != 0) {
135+
shell_fprintf(sh,
136+
SHELL_ERROR,
137+
"Invalid memory word offset(%lu). Needs to be a multiple of 4\n",
138+
mem_offset);
139+
return -ENOEXEC;
140+
}
141+
142+
if (mem_start_addr + 3 > mem_end_addr) {
143+
shell_fprintf(sh,
144+
SHELL_ERROR,
145+
"Invalid memory word offset. Exceeds memory region\n");
146+
return -ENOEXEC;
147+
}
148+
149+
status = hal_rpu_mem_write(fmac_dev_ctx->hal_dev_ctx,
150+
mem_start_addr,
151+
&val,
152+
sizeof(val));
153+
154+
if (status != NRF_WIFI_STATUS_SUCCESS) {
155+
shell_fprintf(sh,
156+
SHELL_ERROR,
157+
"Failed to write memory at 0x%x.\n",
158+
mem_start_addr);
159+
return -ENOEXEC;
160+
}
161+
162+
return 0;
163+
}
164+
165+
166+
static int nrf_wifi_dbg_read_reg(const struct shell *sh,
167+
size_t argc,
168+
const char *argv[])
169+
{
170+
enum nrf_wifi_status status;
171+
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx;
172+
char *ptr;
173+
unsigned long reg_type;
174+
unsigned long reg_offset;
175+
unsigned long num_regs;
176+
unsigned int reg_val;
177+
unsigned int reg_start_addr;
178+
unsigned int reg_end_addr;
179+
unsigned int i;
180+
181+
fmac_dev_ctx = dbg_ctx->rpu_ctx;
182+
reg_type = strtoul(argv[1], &ptr, 10);
183+
reg_offset = strtoul(argv[2], &ptr, 10);
184+
num_regs = strtoul(argv[3], &ptr, 10);
185+
186+
if (reg_type == 0) {
187+
reg_start_addr = RPU_ADDR_SBUS_START + (reg_offset * 4);
188+
reg_end_addr = RPU_ADDR_SBUS_END;
189+
} else if (reg_type == 1) {
190+
reg_start_addr = RPU_ADDR_PBUS_START + (reg_offset * 4);
191+
reg_end_addr = RPU_ADDR_PBUS_END;
192+
} else {
193+
shell_fprintf(sh,
194+
SHELL_ERROR,
195+
"Invalid register type(%lu).\n",
196+
reg_type);
197+
return -ENOEXEC;
198+
}
199+
200+
if ((reg_start_addr % 4) != 0) {
201+
shell_fprintf(sh,
202+
SHELL_ERROR,
203+
"Invalid register offset(%lu). Needs to be a multiple of 4\n",
204+
reg_offset);
205+
return -ENOEXEC;
206+
}
207+
208+
if (reg_start_addr + (num_regs * 4) - 1 > reg_end_addr) {
209+
shell_fprintf(sh,
210+
SHELL_ERROR,
211+
"Invalid number of registers(%lu). Exceeds bus region\n",
212+
num_regs);
213+
return -ENOEXEC;
214+
}
215+
216+
for (i = 0; i < num_regs * 4; i += 4) {
217+
status = hal_rpu_reg_read(fmac_dev_ctx->hal_dev_ctx,
218+
&reg_val,
219+
reg_start_addr + i);
220+
221+
if (status != NRF_WIFI_STATUS_SUCCESS) {
222+
shell_fprintf(sh,
223+
SHELL_ERROR,
224+
"Failed to read register at 0x%x.\n",
225+
reg_start_addr + i);
226+
return -ENOEXEC;
227+
}
228+
229+
shell_fprintf(sh,
230+
SHELL_INFO,
231+
"0x%x: 0x%08x\n",
232+
reg_start_addr + i,
233+
reg_val);
234+
}
235+
236+
shell_fprintf(sh,
237+
SHELL_INFO,
238+
"\n");
239+
return 0;
240+
}
241+
242+
243+
static int nrf_wifi_dbg_write_reg(const struct shell *sh,
244+
size_t argc,
245+
const char *argv[])
246+
{
247+
enum nrf_wifi_status status;
248+
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx;
249+
char *ptr;
250+
unsigned long reg_type;
251+
unsigned long reg_offset;
252+
unsigned int val;
253+
unsigned int reg_start_addr;
254+
unsigned int reg_end_addr;
255+
256+
fmac_dev_ctx = dbg_ctx->rpu_ctx;
257+
reg_type = strtoul(argv[1], &ptr, 10);
258+
reg_offset = strtoul(argv[2], &ptr, 10);
259+
val = strtoul(argv[3], &ptr, 10);
260+
261+
if (reg_type == 0) {
262+
reg_start_addr = RPU_ADDR_SBUS_START + (reg_offset * 4);
263+
reg_end_addr = RPU_ADDR_SBUS_END;
264+
} else if (reg_type == 1) {
265+
reg_start_addr = RPU_ADDR_PBUS_START + (reg_offset * 4);
266+
reg_end_addr = RPU_ADDR_PBUS_END;
267+
} else {
268+
shell_fprintf(sh,
269+
SHELL_ERROR,
270+
"Invalid register type(%lu).\n",
271+
reg_type);
272+
return -ENOEXEC;
273+
}
274+
275+
if ((reg_start_addr % 4) != 0) {
276+
shell_fprintf(sh,
277+
SHELL_ERROR,
278+
"Invalid register offset(%lu). Needs to be a multiple of 4\n",
279+
reg_offset);
280+
return -ENOEXEC;
281+
}
282+
283+
if (reg_start_addr + 3 > reg_end_addr) {
284+
shell_fprintf(sh,
285+
SHELL_ERROR,
286+
"Invalid register offset. Exceeds bus region\n");
287+
return -ENOEXEC;
288+
}
289+
290+
status = hal_rpu_reg_write(fmac_dev_ctx->hal_dev_ctx,
291+
reg_start_addr,
292+
val);
293+
294+
if (status != NRF_WIFI_STATUS_SUCCESS) {
295+
shell_fprintf(sh,
296+
SHELL_ERROR,
297+
"Failed to write register at 0x%x.\n",
298+
reg_start_addr);
299+
return -ENOEXEC;
300+
}
301+
302+
return 0;
303+
}
304+
305+
306+
307+
SHELL_STATIC_SUBCMD_SET_CREATE(
308+
nrf70_dbg,
309+
SHELL_CMD_ARG(read_mem,
310+
NULL,
311+
"<mem_type> <offset> <num_words>\n"
312+
"where:\n"
313+
"<mem_type> : One of the memory regions below\n"
314+
"0 - PKTRAM\n"
315+
"1 - GRAM\n"
316+
"<offset> : Word offset in the memory region\n"
317+
"<num_words> : Number of words to read\n",
318+
nrf_wifi_dbg_read_mem,
319+
4,
320+
0),
321+
SHELL_CMD_ARG(write_mem,
322+
NULL,
323+
"<mem_type> <offset> <val>\n"
324+
"where:\n"
325+
"<mem_type> : One of the memory regions below\n"
326+
"0 - PKTRAM\n"
327+
"1 - GRAM\n"
328+
"<offset> : Word offset in the memory region\n"
329+
"<val> : Value to be written\n",
330+
nrf_wifi_dbg_write_mem,
331+
4,
332+
0),
333+
SHELL_CMD_ARG(read_reg,
334+
NULL,
335+
"<reg_type> <offset> <num_regs>\n"
336+
"where:\n"
337+
"<reg_type> : One of the bus regions below\n"
338+
"0 - SYSBUS\n"
339+
"1 - PBUS\n"
340+
"<offset> : Register offset\n"
341+
"<num_words> : Number of registers to read\n",
342+
nrf_wifi_dbg_read_reg,
343+
4,
344+
0),
345+
SHELL_CMD_ARG(write_reg,
346+
NULL,
347+
"<reg_type> <offset> <val>\n"
348+
"where:\n"
349+
"<reg_type> : One of the bus regions below\n"
350+
"0 - SYSBUS\n"
351+
"1 - PBUS\n"
352+
"<offset> : Register offset\n"
353+
"<val> : Value to be written\n",
354+
nrf_wifi_dbg_write_reg,
355+
4,
356+
0),
357+
SHELL_SUBCMD_SET_END
358+
);
359+
360+
361+
SHELL_SUBCMD_ADD((nrf70), dbg, &nrf70_dbg,
362+
"nRF70 advanced debug commands\n",
363+
NULL,
364+
0, 0);

0 commit comments

Comments
 (0)