mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-09-06 09:41:56 +00:00
If burst of log messages was passed to the shell log backend, it was likely that messages were lost because shell had no means to control arrivals of log messages. Added log message enqueueing timeout to the shell instance to allow blocking logger thread if short-term arrival rate exceeded shell capabilities. Added kconfig option for setting log message queue size and timeout in RTT and UART instances. Added section in shell documentation which explains interaction between the logger and shell instance acting as a logger backend. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
110 lines
2.5 KiB
C
110 lines
2.5 KiB
C
/*
|
|
* Copyright (c) 2018 Makaio GmbH
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <shell/shell_rtt.h>
|
|
#include <init.h>
|
|
#include <SEGGER_RTT.h>
|
|
#include <logging/log.h>
|
|
|
|
SHELL_RTT_DEFINE(shell_transport_rtt);
|
|
SHELL_DEFINE(shell_rtt, "rtt:~$ ", &shell_transport_rtt,
|
|
CONFIG_SHELL_BACKEND_RTT_LOG_MESSAGE_QUEUE_SIZE,
|
|
CONFIG_SHELL_BACKEND_RTT_LOG_MESSAGE_QUEUE_TIMEOUT,
|
|
SHELL_FLAG_OLF_CRLF);
|
|
|
|
LOG_MODULE_REGISTER(shell_rtt, CONFIG_SHELL_RTT_LOG_LEVEL);
|
|
|
|
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)) {
|
|
sh_rtt->handler(SHELL_TRANSPORT_EVT_RX_RDY, sh_rtt->context);
|
|
}
|
|
}
|
|
|
|
static int init(const struct shell_transport *transport,
|
|
const void *config,
|
|
shell_transport_handler_t evt_handler,
|
|
void *context)
|
|
{
|
|
struct shell_rtt *sh_rtt = (struct shell_rtt *)transport->ctx;
|
|
|
|
sh_rtt->handler = evt_handler;
|
|
sh_rtt->context = context;
|
|
|
|
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, CONFIG_SHELL_RTT_RX_POLL_PERIOD,
|
|
CONFIG_SHELL_RTT_RX_POLL_PERIOD);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int uninit(const struct shell_transport *transport)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int enable(const struct shell_transport *transport, bool blocking)
|
|
{
|
|
struct shell_rtt *sh_rtt = (struct shell_rtt *)transport->ctx;
|
|
|
|
if (blocking) {
|
|
k_timer_stop(&sh_rtt->timer);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int write(const struct shell_transport *transport,
|
|
const void *data, size_t length, size_t *cnt)
|
|
{
|
|
struct shell_rtt *sh_rtt = (struct shell_rtt *)transport->ctx;
|
|
const u8_t *data8 = (const u8_t *)data;
|
|
|
|
*cnt = SEGGER_RTT_Write(0, data8, length);
|
|
|
|
sh_rtt->handler(SHELL_TRANSPORT_EVT_TX_RDY, sh_rtt->context);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int read(const struct shell_transport *transport,
|
|
void *data, size_t length, size_t *cnt)
|
|
{
|
|
*cnt = SEGGER_RTT_Read(0, data, length);
|
|
|
|
return 0;
|
|
}
|
|
|
|
const struct shell_transport_api shell_rtt_transport_api = {
|
|
.init = init,
|
|
.uninit = uninit,
|
|
.enable = enable,
|
|
.write = write,
|
|
.read = read
|
|
};
|
|
|
|
static int enable_shell_rtt(struct device *arg)
|
|
{
|
|
ARG_UNUSED(arg);
|
|
bool log_backend = CONFIG_SHELL_RTT_INIT_LOG_LEVEL > 0;
|
|
u32_t level = (CONFIG_SHELL_RTT_INIT_LOG_LEVEL > LOG_LEVEL_DBG) ?
|
|
CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_RTT_INIT_LOG_LEVEL;
|
|
|
|
shell_init(&shell_rtt, NULL, true, log_backend, level);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Function is used for testing purposes */
|
|
const struct shell *shell_backend_rtt_get_ptr(void)
|
|
{
|
|
return &shell_rtt;
|
|
}
|
|
SYS_INIT(enable_shell_rtt, POST_KERNEL, 0);
|