Skip to content

Commit 38028d8

Browse files
SeppoTakalotrantanen
authored andcommitted
app: Improve pipe handling of CMUX tracing and allow configurable drop
Improve handling of pipe open-close events of CMUX tracing module. Allow TX timeout to be defined by Kconfig. Remove unnecessary loop from trace backend as nRF library already loops on -EAGAIN. Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no> Signed-off-by: Markus Lassila <markus.lassila@nordicsemi.no> (cherry picked from commit fb20dbe)
1 parent 3e615c9 commit 38028d8

4 files changed

Lines changed: 66 additions & 33 deletions

File tree

app/src/sm_cmux.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#endif
1111
#include "sm_util.h"
1212
#include "sm_uart_handler.h"
13+
#include "sm_trace_backend_cmux.h"
1314
#include <zephyr/logging/log.h>
1415
#include <zephyr/modem/cmux.h>
1516
#include <zephyr/modem/pipe.h>
@@ -339,6 +340,9 @@ static void stop_work_fn(struct k_work *work)
339340

340341
/* Will stop the UART when calling the close_pipe() function. */
341342
if (sm_cmux_is_started()) {
343+
#if defined(CONFIG_SM_MODEM_TRACE_BACKEND_CMUX)
344+
sm_trace_backend_detach();
345+
#endif
342346
modem_cmux_release(&cmux.instance);
343347

344348
close_pipe(&cmux.uart_pipe);
@@ -437,6 +441,10 @@ static int cmux_start(void)
437441
return ret;
438442
}
439443

444+
#if defined(CONFIG_SM_MODEM_TRACE_BACKEND_CMUX)
445+
sm_trace_backend_attach(sm_cmux_reserve(CMUX_MODEM_TRACE_CHANNEL));
446+
#endif
447+
440448
ret = modem_pipe_open(cmux.uart_pipe, K_SECONDS(CONFIG_SM_MODEM_PIPE_TIMEOUT));
441449
if (!ret) {
442450
cmux.uart_pipe_open = true;

app/src/sm_trace_backend_cmux.c

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99
#include <zephyr/modem/pipe.h>
1010
#include <modem/nrf_modem_lib_trace.h>
1111
#include <modem/trace_backend.h>
12-
#include "sm_cmux.h"
12+
#include "sm_util.h"
1313

1414
LOG_MODULE_REGISTER(modem_trace_backend, CONFIG_MODEM_TRACE_BACKEND_LOG_LEVEL);
1515

1616
static K_SEM_DEFINE(tx_idle_sem, 0, 1);
1717

1818
static trace_backend_processed_cb trace_processed_callback;
19+
static struct modem_pipe *trace_pipe;
1920

2021
static void modem_pipe_event_handler(struct modem_pipe *pipe,
2122
enum modem_pipe_event event, void *user_data)
@@ -25,7 +26,14 @@ static void modem_pipe_event_handler(struct modem_pipe *pipe,
2526
case MODEM_PIPE_EVENT_TRANSMIT_IDLE:
2627
k_sem_give(&tx_idle_sem);
2728
break;
28-
29+
case MODEM_PIPE_EVENT_CLOSED:
30+
LOG_INF("Trace pipe closed");
31+
trace_pipe = NULL;
32+
break;
33+
case MODEM_PIPE_EVENT_OPENED:
34+
LOG_INF("Trace pipe opened");
35+
trace_pipe = pipe;
36+
break;
2937
default:
3038
break;
3139
}
@@ -38,58 +46,66 @@ int trace_backend_init(trace_backend_processed_cb trace_processed_cb)
3846
}
3947

4048
trace_processed_callback = trace_processed_cb;
49+
trace_pipe = NULL;
4150

4251
return 0;
4352
}
4453

4554
int trace_backend_deinit(void)
4655
{
47-
sm_cmux_release(CMUX_MODEM_TRACE_CHANNEL);
48-
56+
if (trace_pipe) {
57+
modem_pipe_release(trace_pipe);
58+
trace_pipe = NULL;
59+
}
4960
return 0;
5061
}
5162

63+
void sm_trace_backend_attach(struct modem_pipe *pipe)
64+
{
65+
modem_pipe_attach(pipe, modem_pipe_event_handler, NULL);
66+
}
67+
68+
void sm_trace_backend_detach(void)
69+
{
70+
if (trace_pipe) {
71+
modem_pipe_release(trace_pipe);
72+
trace_pipe = NULL;
73+
}
74+
}
75+
5276
int trace_backend_write(const void *data, size_t len)
5377
{
54-
struct modem_pipe *pipe = sm_cmux_reserve(CMUX_MODEM_TRACE_CHANNEL);
55-
const uint8_t *buf = (const uint8_t *)data;
56-
size_t sent_len = 0;
5778
int ret = 0;
5879

59-
if (!sm_cmux_dlci_is_open(CMUX_MODEM_TRACE_CHANNEL)) {
60-
LOG_DBG("Dropped %u bytes.", len);
80+
if (!trace_pipe || !sm_pipe_is_open(trace_pipe)) {
81+
LOG_DBG_RATELIMIT("Pipe closed, dropped %u bytes.", len);
6182
trace_processed_callback(len);
6283
return len;
6384
}
6485

65-
modem_pipe_attach(pipe, modem_pipe_event_handler, NULL);
66-
67-
while (sent_len < len) {
68-
ret = modem_pipe_transmit(pipe, buf, len - sent_len);
69-
if (ret < 0) {
70-
LOG_WRN("TX error (%d). Dropped %u bytes.", ret, len - sent_len);
71-
trace_processed_callback(len);
72-
return ret;
73-
} else if (ret == 0) {
74-
if (k_sem_take(&tx_idle_sem, K_SECONDS(1)) != 0) {
75-
LOG_WRN("TX timeout.");
76-
break;
77-
}
78-
} else {
79-
sent_len += ret;
80-
buf += ret;
81-
}
82-
}
86+
/* No need to retry here.
87+
* The nrf_modem_lib_trace.c:trace_fragment_write() handles
88+
* retrying if the backend returns -EAGAIN.
89+
*
90+
* In congested situations, the modem trace fifos will overflow and drop data.
91+
*/
8392

84-
if (sent_len) {
85-
trace_processed_callback(sent_len);
93+
if (k_sem_take(&tx_idle_sem, K_MSEC(100)) != 0) {
94+
LOG_WRN_RATELIMIT("TX timeout.");
95+
return -EAGAIN;
8696
}
8797

88-
if (sent_len < len) {
89-
LOG_DBG("Sent %u out of %u bytes.", sent_len, len);
98+
ret = modem_pipe_transmit(trace_pipe, data, len);
99+
if (ret < 0) {
100+
LOG_WRN("TX error (%d). Dropped %u bytes.", ret, len);
101+
trace_processed_callback(len);
102+
return ret;
103+
} else if (ret == 0) {
104+
return -EAGAIN;
90105
}
106+
trace_processed_callback(ret);
91107

92-
return sent_len;
108+
return ret;
93109
}
94110

95111
struct nrf_modem_lib_trace_backend trace_backend = {

app/src/sm_trace_backend_cmux.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/*
2+
* Copyright (c) 2026 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
void sm_trace_backend_attach(struct modem_pipe *pipe);
8+
9+
void sm_trace_backend_detach(void);

app/src/sm_uart_handler.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,10 @@ static void uart_callback(const struct device *dev, struct uart_event *evt, void
342342
!atomic_test_bit(&uart_state, SM_UART_STATE_TX_ENABLED_BIT))) {
343343
/* TX buffer is empty or we aborted due to TX being disabled. */
344344
k_sem_give(&tx_done_sem);
345-
uart_callback_notify_pipe_transmit_idle();
346345
} else {
347346
tx_start();
348347
}
348+
uart_callback_notify_pipe_transmit_idle();
349349
break;
350350
case UART_RX_RDY:
351351
rx_buf_ref(evt->data.rx.buf);

0 commit comments

Comments
 (0)