diff --git a/doc/services/shell/index.rst b/doc/services/shell/index.rst index 7638b5a55e48..523892a2fd31 100644 --- a/doc/services/shell/index.rst +++ b/doc/services/shell/index.rst @@ -623,6 +623,33 @@ This feature is activated by: :kconfig:option:`CONFIG_SHELL_LOG_BACKEND` set to RTT (:kconfig:option:`CONFIG_LOG_BACKEND_RTT`), which are available earlier during system initialization. +RTT Backend Channel Selection +***************************** + +Instead of using the shell as a logger backend, RTT shell backend and RTT log +backend can also be used simulatenously, but over different channels. By +separating them, the log can be captured or monitored without shell output or +the shell may be scripted without log interference. Enabling both the Shell RTT +backend and the Log RTT backend does not work by default, because both default +to channel ``0``. There are two options: + +1. The Shell buffer can use an alternate channel, for example using +:kconfig:option:`SHELL_BACKEND_RTT_BUFFER` set to ``1``. +This allows monitoring the log using `JLinkRTTViewer +`_ +while a script interfaces over channel 1. + +2. The Log buffer can use an alternate channel, for example using +:kconfig:option:`LOG_BACKEND_RTT_BUFFER` set to ``1``. +This allows interactive use of the shell through JLinkRTTViewer, while the log +is written to file. + +.. warning:: + Regardless of the channel selection, the RTT log backend must be explicitly + enabled using :kconfig:option:`LOG_BACKEND_RTT` set to ``y``, because it + defaults to ``n`` when the Shell RTT backend is also enabled using + :kconfig:option:`SHELL_BACKEND_RTT` being set to ``y``. + Usage ***** diff --git a/subsys/shell/backends/Kconfig.backends b/subsys/shell/backends/Kconfig.backends index cfa5070f8e0f..af5291545ef5 100644 --- a/subsys/shell/backends/Kconfig.backends +++ b/subsys/shell/backends/Kconfig.backends @@ -139,6 +139,14 @@ config SHELL_PROMPT_RTT Displayed prompt name for RTT backend. If prompt is set, the shell will send two newlines during initialization. +config SHELL_BACKEND_RTT_BUFFER + int "Buffer number used for shell input and output." + range 0 SEGGER_RTT_MAX_NUM_UP_BUFFERS + default 0 + help + Select index of up-buffer used for shell output, by default it uses + terminal up-buffer and its settings. + config SHELL_RTT_RX_POLL_PERIOD int "RX polling period (in milliseconds)" default 10 diff --git a/subsys/shell/backends/shell_rtt.c b/subsys/shell/backends/shell_rtt.c index d0e9e16bb925..6490975893a5 100644 --- a/subsys/shell/backends/shell_rtt.c +++ b/subsys/shell/backends/shell_rtt.c @@ -9,9 +9,13 @@ #include #include -BUILD_ASSERT(!(IS_ENABLED(CONFIG_LOG_BACKEND_RTT) && - COND_CODE_0(CONFIG_LOG_BACKEND_RTT_BUFFER, (1), (0))), +#if IS_ENABLED(CONFIG_LOG_BACKEND_RTT) +BUILD_ASSERT(!(CONFIG_SHELL_BACKEND_RTT_BUFFER == CONFIG_LOG_BACKEND_RTT_BUFFER), "Conflicting log RTT backend enabled on the same channel"); +#endif + +static uint8_t shell_rtt_up_buf[CONFIG_SEGGER_RTT_BUFFER_SIZE_UP]; +static uint8_t shell_rtt_down_buf[CONFIG_SEGGER_RTT_BUFFER_SIZE_DOWN]; SHELL_RTT_DEFINE(shell_transport_rtt); SHELL_DEFINE(shell_rtt, CONFIG_SHELL_PROMPT_RTT, &shell_transport_rtt, @@ -27,7 +31,7 @@ static void timer_handler(struct k_timer *timer) { const struct shell_rtt *sh_rtt = k_timer_user_data_get(timer); - if (SEGGER_RTT_HasData(0)) { + if (SEGGER_RTT_HasData(CONFIG_SHELL_BACKEND_RTT_BUFFER)) { sh_rtt->handler(SHELL_TRANSPORT_EVT_RX_RDY, sh_rtt->context); } } @@ -45,7 +49,17 @@ static int init(const struct shell_transport *transport, k_timer_init(&sh_rtt->timer, timer_handler, NULL); k_timer_user_data_set(&sh_rtt->timer, (void *)sh_rtt); k_timer_start(&sh_rtt->timer, K_MSEC(CONFIG_SHELL_RTT_RX_POLL_PERIOD), - K_MSEC(CONFIG_SHELL_RTT_RX_POLL_PERIOD)); + K_MSEC(CONFIG_SHELL_RTT_RX_POLL_PERIOD)); + + if (CONFIG_SHELL_BACKEND_RTT_BUFFER > 0) { + SEGGER_RTT_ConfigUpBuffer(CONFIG_SHELL_BACKEND_RTT_BUFFER, "Shell", + shell_rtt_up_buf, sizeof(shell_rtt_up_buf), + SEGGER_RTT_MODE_NO_BLOCK_SKIP); + + SEGGER_RTT_ConfigDownBuffer(CONFIG_SHELL_BACKEND_RTT_BUFFER, "Shell", + shell_rtt_down_buf, sizeof(shell_rtt_down_buf), + SEGGER_RTT_MODE_NO_BLOCK_SKIP); + } return 0; } @@ -78,12 +92,12 @@ static int write(const struct shell_transport *transport, const uint8_t *data8 = (const uint8_t *)data; if (rtt_blocking) { - *cnt = SEGGER_RTT_WriteNoLock(0, data8, length); - while (SEGGER_RTT_HasDataUp(0)) { + *cnt = SEGGER_RTT_WriteNoLock(CONFIG_SHELL_BACKEND_RTT_BUFFER, data8, length); + while (SEGGER_RTT_HasDataUp(CONFIG_SHELL_BACKEND_RTT_BUFFER)) { /* empty */ } } else { - *cnt = SEGGER_RTT_Write(0, data8, length); + *cnt = SEGGER_RTT_Write(CONFIG_SHELL_BACKEND_RTT_BUFFER, data8, length); } sh_rtt->handler(SHELL_TRANSPORT_EVT_TX_RDY, sh_rtt->context); @@ -94,7 +108,7 @@ static int write(const struct shell_transport *transport, static int read(const struct shell_transport *transport, void *data, size_t length, size_t *cnt) { - *cnt = SEGGER_RTT_Read(0, data, length); + *cnt = SEGGER_RTT_Read(CONFIG_SHELL_BACKEND_RTT_BUFFER, data, length); return 0; }