Skip to content

Commit 1f1ff8d

Browse files
nordic-krchnashif
authored andcommitted
samples: shell_module: Add shell_uart_release command
shell_uart_release command shows how shell can be uninitialized and release transport resources (uart) and reinitialized at runtime. Signed-off-by: Krzysztof Chruscinski <[email protected]>
1 parent 265e9db commit 1f1ff8d

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

samples/subsys/shell/shell_module/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ project(shell_module)
66

77
target_sources(app PRIVATE src/main.c src/test_module.c)
88
target_sources_ifdef(CONFIG_SHELL_DYNAMIC_CMDS app PRIVATE src/dynamic_cmd.c src/qsort.c)
9+
target_sources_ifdef(CONFIG_SHELL_BACKEND_SERIAL app PRIVATE src/uart_reinit.c)
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright (c) 2021 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#include <shell/shell.h>
7+
#include <shell/shell_uart.h>
8+
#include <drivers/uart.h>
9+
#include <device.h>
10+
11+
void shell_init_from_work(struct k_work *work)
12+
{
13+
const struct device *dev =
14+
device_get_binding(CONFIG_UART_SHELL_ON_DEV_NAME);
15+
bool log_backend = CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL > 0;
16+
uint32_t level =
17+
(CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL > LOG_LEVEL_DBG) ?
18+
CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL;
19+
20+
shell_init(shell_backend_uart_get_ptr(), dev, true, log_backend, level);
21+
}
22+
23+
static void shell_reinit_trigger(void)
24+
{
25+
static struct k_work shell_init_work;
26+
27+
k_work_init(&shell_init_work, shell_init_from_work);
28+
int err = k_work_submit(&shell_init_work);
29+
30+
(void)err;
31+
__ASSERT_NO_MSG(err >= 0);
32+
}
33+
34+
static void direct_uart_callback(const struct device *dev, void *user_data)
35+
{
36+
static uint8_t buf[1];
37+
static bool tx_busy;
38+
39+
uart_irq_update(dev);
40+
41+
42+
if (uart_irq_rx_ready(dev)) {
43+
while (uart_fifo_read(dev, buf, sizeof(buf))) {
44+
if (!tx_busy) {
45+
uart_irq_tx_enable(dev);
46+
}
47+
}
48+
}
49+
50+
if (uart_irq_tx_ready(dev)) {
51+
if (!tx_busy) {
52+
(void)uart_fifo_fill(dev, buf, sizeof(buf));
53+
tx_busy = true;
54+
} else {
55+
tx_busy = false;
56+
uart_irq_tx_disable(dev);
57+
if (buf[0] == 'x') {
58+
uart_irq_rx_disable(dev);
59+
shell_reinit_trigger();
60+
}
61+
}
62+
}
63+
}
64+
65+
static void uart_poll_timer_stopped(struct k_timer *timer)
66+
{
67+
shell_reinit_trigger();
68+
}
69+
70+
static void uart_poll_timeout(struct k_timer *timer)
71+
{
72+
char c;
73+
const struct device *dev = k_timer_user_data_get(timer);
74+
75+
while (uart_poll_in(dev, &c) == 0) {
76+
if (c != 'x') {
77+
uart_poll_out(dev, c);
78+
} else {
79+
k_timer_stop(timer);
80+
}
81+
}
82+
}
83+
84+
K_TIMER_DEFINE(uart_poll_timer, uart_poll_timeout, uart_poll_timer_stopped);
85+
86+
static void shell_uninit_cb(const struct shell *shell, int res)
87+
{
88+
__ASSERT_NO_MSG(res >= 0);
89+
const struct device *dev =
90+
device_get_binding(CONFIG_UART_SHELL_ON_DEV_NAME);
91+
92+
if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN)) {
93+
/* connect uart to my handler */
94+
uart_irq_callback_user_data_set(dev, direct_uart_callback, NULL);
95+
uart_irq_tx_disable(dev);
96+
uart_irq_rx_enable(dev);
97+
} else {
98+
k_timer_user_data_set(&uart_poll_timer, (void *)dev);
99+
k_timer_start(&uart_poll_timer, K_MSEC(10), K_MSEC(10));
100+
}
101+
}
102+
103+
static int cmd_uart_release(const struct shell *shell, size_t argc, char **argv)
104+
{
105+
ARG_UNUSED(argc);
106+
ARG_UNUSED(argv);
107+
108+
if (shell != shell_backend_uart_get_ptr()) {
109+
shell_error(shell, "Command dedicated for shell over uart");
110+
return -EINVAL;
111+
}
112+
113+
shell_print(shell, "Uninitializing shell, use 'x' to reinitialize");
114+
shell_uninit(shell, shell_uninit_cb);
115+
116+
return 0;
117+
}
118+
119+
SHELL_CMD_REGISTER(shell_uart_release, NULL,
120+
"Uninitialize shell instance and release uart, start loopback "
121+
"on uart. Shell instance is renitialized when 'x' is pressed",
122+
cmd_uart_release);

0 commit comments

Comments
 (0)