Skip to content

Commit 1663704

Browse files
committed
Add crash dump collection through CMUX.
1 parent ef55111 commit 1663704

File tree

10 files changed

+171
-2
lines changed

10 files changed

+171
-2
lines changed

app/boards/nrf9151dk_nrf9151_ns.overlay

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
&uart0 {
1515
status = "okay";
1616
hw-flow-control;
17+
current-speed = <1000000>;
1718

1819
dtr_uart0: dtr-uart {
1920
compatible = "nordic,dtr-uart";
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
# CMUX trace backend for modem coredump
8+
CONFIG_NRF_MODEM_LIB_TRACE=y
9+
CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_CMUX=y
10+
# Configure the modem trace level to coredump only
11+
CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_OVERRIDE=y
12+
CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_COREDUMP_ONLY=y

app/prj.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ CONFIG_SM_EXTERNAL_XTAL=n
136136
#CONFIG_LOG_MODE_IMMEDIATE=y
137137
#CONFIG_DEBUG_OPTIMIZATIONS=y
138138
#CONFIG_DTR_UART_LOG_LEVEL_DBG=y
139+
#CONFIG_THREAD_MONITOR=y
140+
#CONFIG_NRF_MODEM_LIB_LOG_LEVEL_DBG=y
139141

140142
# For using external GNSS antenna
141143
#CONFIG_MODEM_ANTENNA=y

app/scripts/sm_start_ppp.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ PPP_CMUX=$(ls /dev/gsmtty* | sort -V | head -n 2 | tail -n 1)
185185
log_dbg "AT CMUX: $AT_CMUX"
186186
log_dbg "PPP CMUX: $PPP_CMUX"
187187

188-
sleep 1
188+
sleep 5
189189
stty -F $AT_CMUX clocal
190190

191191
echo "Connect and wait for PPP link..."

app/src/sm_cmux.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,11 @@ static bool cmux_is_started(void)
302302
return (cmux.uart_pipe != NULL);
303303
}
304304

305+
bool sm_cmux_is_started(void)
306+
{
307+
return cmux_is_started();
308+
}
309+
305310
void sm_cmux_init(void)
306311
{
307312
const struct modem_cmux_config cmux_config = {
@@ -370,6 +375,18 @@ static struct cmux_dlci *cmux_get_dlci(enum cmux_channel channel)
370375
return &cmux.dlcis[!cmux.at_channel];
371376
}
372377
#endif
378+
#if defined(CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_CMUX)
379+
if (channel == CMUX_COREDUMP_CHANNEL) {
380+
#if defined(CONFIG_SM_GNSS_OUTPUT_NMEA_ON_CMUX_CHANNEL)
381+
/* The second to last DLCI. */
382+
return &cmux.dlcis[CHANNEL_COUNT - 2];
383+
#else
384+
/* The last DLCI. */
385+
return &cmux.dlcis[CHANNEL_COUNT - 1];
386+
#endif
387+
}
388+
#endif
389+
373390
#if defined(CONFIG_SM_GNSS_OUTPUT_NMEA_ON_CMUX_CHANNEL)
374391
if (channel == CMUX_GNSS_CHANNEL) {
375392
/* The last DLCI. */

app/src/sm_cmux.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@ enum cmux_channel {
2121
#if defined(CONFIG_SM_PPP)
2222
CMUX_PPP_CHANNEL,
2323
#endif
24+
#if defined(CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_CMUX)
25+
CMUX_COREDUMP_CHANNEL,
26+
#endif
2427
#if defined(CONFIG_SM_GNSS_OUTPUT_NMEA_ON_CMUX_CHANNEL)
2528
CMUX_GNSS_CHANNEL,
2629
#endif
2730
CMUX_EXT_CHANNEL_COUNT
2831
};
2932
struct modem_pipe *sm_cmux_reserve(enum cmux_channel);
3033
void sm_cmux_release(enum cmux_channel);
31-
34+
bool sm_cmux_is_started(void);
3235
#endif

drivers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
44

55
add_subdirectory_ifdef(CONFIG_DTR_UART dtr_uart)
6+
add_subdirectory_ifdef(CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_CMUX trace_backend_cmux)

drivers/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,20 @@
33
#
44
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
55

6+
if NRF_MODEM_LIB_TRACE
7+
8+
choice NRF_MODEM_LIB_TRACE_BACKEND
9+
10+
config NRF_MODEM_LIB_TRACE_BACKEND_CMUX
11+
bool "Stream modem coredump to CMUX"
12+
depends on SM_CMUX
13+
help
14+
Use CMUX trace backend for modem coredump.
15+
16+
endchoice # NRF_MODEM_LIB_TRACE_BACKEND
17+
18+
endif
19+
620
menu "Drivers"
721
rsource "dtr_uart/Kconfig"
822
endmenu
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
zephyr_library()
8+
zephyr_library_sources(cmux.c)

drivers/trace_backend_cmux/cmux.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/logging/log.h>
9+
#include <zephyr/modem/pipe.h>
10+
#include <modem/nrf_modem_lib_trace.h>
11+
#include <modem/trace_backend.h>
12+
13+
#include "sm_cmux.h"
14+
15+
LOG_MODULE_REGISTER(modem_trace_backend, CONFIG_MODEM_TRACE_BACKEND_LOG_LEVEL);
16+
17+
static K_SEM_DEFINE(tx_idle_sem, 0, 1);
18+
19+
static trace_backend_processed_cb trace_processed_callback;
20+
21+
static struct modem_pipe *pipe;
22+
23+
static void modem_pipe_event_handler(struct modem_pipe *pipe,
24+
enum modem_pipe_event event, void *user_data)
25+
{
26+
switch (event) {
27+
case MODEM_PIPE_EVENT_OPENED:
28+
LOG_DBG("Coredump DLCI opened.");
29+
break;
30+
31+
case MODEM_PIPE_EVENT_CLOSED:
32+
LOG_DBG("Coredump DLCI closed.");
33+
break;
34+
35+
case MODEM_PIPE_EVENT_TRANSMIT_IDLE:
36+
k_sem_give(&tx_idle_sem);
37+
break;
38+
39+
default:
40+
break;
41+
}
42+
}
43+
44+
int trace_backend_init(trace_backend_processed_cb trace_processed_cb)
45+
{
46+
if (trace_processed_cb == NULL) {
47+
return -EFAULT;
48+
}
49+
50+
trace_processed_callback = trace_processed_cb;
51+
52+
return 0;
53+
}
54+
55+
int trace_backend_deinit(void)
56+
{
57+
if (pipe != NULL) {
58+
modem_pipe_release(pipe);
59+
sm_cmux_release(CMUX_COREDUMP_CHANNEL, false);
60+
pipe = NULL;
61+
}
62+
return 0;
63+
}
64+
65+
int trace_backend_write(const void *data, size_t len)
66+
{
67+
size_t sent_len = 0;
68+
int ret = 0;
69+
70+
if (!sm_cmux_is_started()) {
71+
/* Drop the trace data */
72+
trace_processed_callback(len);
73+
return len;
74+
}
75+
76+
if (pipe == NULL) {
77+
pipe = sm_cmux_reserve(CMUX_COREDUMP_CHANNEL);
78+
modem_pipe_attach(pipe, modem_pipe_event_handler, NULL);
79+
}
80+
81+
const uint8_t *buf = (const uint8_t *)data;
82+
83+
while (sent_len < len) {
84+
k_sem_take(&tx_idle_sem, K_FOREVER);
85+
ret = modem_pipe_transmit(pipe, buf, len - sent_len);
86+
if (ret <= 0) {
87+
break;
88+
}
89+
90+
trace_processed_callback(ret);
91+
92+
sent_len += ret;
93+
buf += ret;
94+
}
95+
96+
if (ret == 0) {
97+
/* Retry by trace thread in modem lib */
98+
return -EAGAIN;
99+
} else if (ret < 0) {
100+
LOG_INF("Coredump: Sent %u out of %u bytes. (%d)", sent_len, len, ret);
101+
return ret;
102+
}
103+
104+
return sent_len;
105+
}
106+
107+
struct nrf_modem_lib_trace_backend trace_backend = {
108+
.init = trace_backend_init,
109+
.deinit = trace_backend_deinit,
110+
.write = trace_backend_write,
111+
};

0 commit comments

Comments
 (0)