shell: Extend shell as a log backend
Initial logger backend support added to shell. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
989fef9c0e
commit
c71a5595dc
6 changed files with 378 additions and 4 deletions
|
@ -11,7 +11,7 @@
|
||||||
#include <shell/shell_types.h>
|
#include <shell/shell_types.h>
|
||||||
#include <shell/shell_history.h>
|
#include <shell/shell_history.h>
|
||||||
#include <shell/shell_fprintf.h>
|
#include <shell/shell_fprintf.h>
|
||||||
#include <logging/log_backend.h>
|
#include <shell/shell_log_backend.h>
|
||||||
#include <logging/log_instance.h>
|
#include <logging/log_instance.h>
|
||||||
#include <logging/log.h>
|
#include <logging/log.h>
|
||||||
#include <misc/util.h>
|
#include <misc/util.h>
|
||||||
|
@ -266,6 +266,19 @@ struct shell_transport {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @brief Shell statistics structure. */
|
||||||
|
struct shell_stats {
|
||||||
|
u32_t log_lost_cnt; /*!< Lost log counter.*/
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CONFIG_SHELL_STATS
|
||||||
|
#define SHELL_STATS_DEFINE(_name) static struct shell_stats _name##_stats
|
||||||
|
#define SHELL_STATS_PTR(_name) (&(_name##_stats))
|
||||||
|
#else
|
||||||
|
#define SHELL_STATS_DEFINE(_name)
|
||||||
|
#define SHELL_STATS_PTR(_name) NULL
|
||||||
|
#endif /* CONFIG_SHELL_STATS */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @internal @brief Flags for internal shell usage.
|
* @internal @brief Flags for internal shell usage.
|
||||||
*/
|
*/
|
||||||
|
@ -292,6 +305,7 @@ union shell_internal {
|
||||||
enum shell_signal {
|
enum shell_signal {
|
||||||
SHELL_SIGNAL_RXRDY,
|
SHELL_SIGNAL_RXRDY,
|
||||||
SHELL_SIGNAL_TXDONE,
|
SHELL_SIGNAL_TXDONE,
|
||||||
|
SHELL_SIGNAL_LOG_MSG,
|
||||||
SHELL_SIGNAL_KILL,
|
SHELL_SIGNAL_KILL,
|
||||||
SHELL_SIGNALS
|
SHELL_SIGNALS
|
||||||
};
|
};
|
||||||
|
@ -344,6 +358,10 @@ struct shell {
|
||||||
|
|
||||||
const struct shell_fprintf *fprintf_ctx;
|
const struct shell_fprintf *fprintf_ctx;
|
||||||
|
|
||||||
|
struct shell_stats *stats;
|
||||||
|
|
||||||
|
const struct shell_log_backend *log_backend;
|
||||||
|
|
||||||
LOG_INSTANCE_PTR_DECLARE(log);
|
LOG_INSTANCE_PTR_DECLARE(log);
|
||||||
|
|
||||||
/*!< New line character, only allowed values: \\n and \\r.*/
|
/*!< New line character, only allowed values: \\n and \\r.*/
|
||||||
|
@ -368,11 +386,14 @@ struct shell {
|
||||||
static const struct shell _name; \
|
static const struct shell _name; \
|
||||||
static struct shell_ctx UTIL_CAT(_name, _ctx); \
|
static struct shell_ctx UTIL_CAT(_name, _ctx); \
|
||||||
static u8_t _name##_out_buffer[CONFIG_SHELL_PRINTF_BUFF_SIZE]; \
|
static u8_t _name##_out_buffer[CONFIG_SHELL_PRINTF_BUFF_SIZE]; \
|
||||||
|
SHELL_LOG_BACKEND_DEFINE(_name, _name##_out_buffer, \
|
||||||
|
CONFIG_SHELL_PRINTF_BUFF_SIZE); \
|
||||||
SHELL_HISTORY_DEFINE(_name, 128, 8);/*todo*/ \
|
SHELL_HISTORY_DEFINE(_name, 128, 8);/*todo*/ \
|
||||||
SHELL_FPRINTF_DEFINE(_name## _fprintf, &_name, _name##_out_buffer, \
|
SHELL_FPRINTF_DEFINE(_name## _fprintf, &_name, _name##_out_buffer, \
|
||||||
CONFIG_SHELL_PRINTF_BUFF_SIZE, \
|
CONFIG_SHELL_PRINTF_BUFF_SIZE, \
|
||||||
true, shell_print_stream); \
|
true, shell_print_stream); \
|
||||||
LOG_INSTANCE_REGISTER(shell, _name, CONFIG_SHELL_LOG_LEVEL); \
|
LOG_INSTANCE_REGISTER(shell, _name, CONFIG_SHELL_LOG_LEVEL); \
|
||||||
|
SHELL_STATS_DEFINE(_name); \
|
||||||
static K_THREAD_STACK_DEFINE(_name##_stack, CONFIG_SHELL_STACK_SIZE);\
|
static K_THREAD_STACK_DEFINE(_name##_stack, CONFIG_SHELL_STACK_SIZE);\
|
||||||
static struct k_thread _name##_thread; \
|
static struct k_thread _name##_thread; \
|
||||||
static const struct shell _name = { \
|
static const struct shell _name = { \
|
||||||
|
@ -381,6 +402,8 @@ struct shell {
|
||||||
.ctx = &UTIL_CAT(_name, _ctx), \
|
.ctx = &UTIL_CAT(_name, _ctx), \
|
||||||
.history = SHELL_HISTORY_PTR(_name), \
|
.history = SHELL_HISTORY_PTR(_name), \
|
||||||
.fprintf_ctx = &_name##_fprintf, \
|
.fprintf_ctx = &_name##_fprintf, \
|
||||||
|
.stats = SHELL_STATS_PTR(_name), \
|
||||||
|
.log_backend = SHELL_LOG_BACKEND_PTR(_name), \
|
||||||
LOG_INSTANCE_PTR_INIT(log, shell, _name) \
|
LOG_INSTANCE_PTR_INIT(log, shell, _name) \
|
||||||
.newline_char = newline_ch, \
|
.newline_char = newline_ch, \
|
||||||
.thread = &_name##_thread, \
|
.thread = &_name##_thread, \
|
||||||
|
|
104
include/shell/shell_log_backend.h
Normal file
104
include/shell/shell_log_backend.h
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHELL_LOG_BACKEND_H__
|
||||||
|
#define SHELL_LOG_BACKEND_H__
|
||||||
|
|
||||||
|
#include <zephyr.h>
|
||||||
|
#include <logging/log_backend.h>
|
||||||
|
#include <logging/log_output.h>
|
||||||
|
#include <atomic.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern const struct log_backend_api log_backend_shell_api;
|
||||||
|
|
||||||
|
/** @brief Shell log backend states. */
|
||||||
|
enum shell_log_backend_state {
|
||||||
|
SHELL_LOG_BACKEND_UNINIT,
|
||||||
|
SHELL_LOG_BACKEND_ENABLED,
|
||||||
|
SHELL_LOG_BACKEND_DISABLED,
|
||||||
|
SHELL_LOG_BACKEND_PANIC,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief Shell log backend control block (RW data). */
|
||||||
|
struct shell_log_backend_control_block {
|
||||||
|
atomic_t cnt;
|
||||||
|
enum shell_log_backend_state state;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief Shell log backend instance structure (RO data). */
|
||||||
|
struct shell_log_backend {
|
||||||
|
const struct log_backend *backend;
|
||||||
|
struct k_fifo *fifo;
|
||||||
|
const struct log_output *log_output;
|
||||||
|
struct shell_log_backend_control_block *control_block;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief Prototype of function outputing processed data. */
|
||||||
|
int shell_log_backend_output_func(u8_t *data, size_t length, void *ctx);
|
||||||
|
|
||||||
|
/** @def SHELL_LOG_BACKEND_DEFINE
|
||||||
|
* @brief Macro for creating instance of shell log backend.
|
||||||
|
*
|
||||||
|
* @param _name Shell name.
|
||||||
|
* @param _buf Output buffer.
|
||||||
|
* @param _size Output buffer size.
|
||||||
|
*/
|
||||||
|
/** @def SHELL_LOG_BACKEND_PTR
|
||||||
|
* @brief Macro for retrieving pointer to the instance of shell log backend.
|
||||||
|
*
|
||||||
|
* @param _name Shell name.
|
||||||
|
*/
|
||||||
|
#if CONFIG_LOG
|
||||||
|
#define SHELL_LOG_BACKEND_DEFINE(_name, _buf, _size) \
|
||||||
|
LOG_BACKEND_DEFINE(_name##_backend, log_backend_shell_api); \
|
||||||
|
K_FIFO_DEFINE(_name##_fifo); \
|
||||||
|
LOG_OUTPUT_DEFINE(_name##_log_output, shell_log_backend_output_func, \
|
||||||
|
_buf, _size); \
|
||||||
|
static struct shell_log_backend_control_block _name##_control_block; \
|
||||||
|
static const struct shell_log_backend _name##_log_backend = { \
|
||||||
|
.backend = &_name##_backend, \
|
||||||
|
.fifo = &_name##_fifo, \
|
||||||
|
.log_output = &_name##_log_output, \
|
||||||
|
.control_block = &_name##_control_block \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SHELL_LOG_BACKEND_PTR(_name) (&_name##_log_backend)
|
||||||
|
#else /* CONFIG_LOG */
|
||||||
|
#define SHELL_LOG_BACKEND_DEFINE(_name, _buf, _size) /* empty */
|
||||||
|
#define SHELL_LOG_BACKEND_PTR(_name) NULL
|
||||||
|
#endif /* CONFIG_LOG */
|
||||||
|
|
||||||
|
/** @brief Enable shell log backend.
|
||||||
|
*
|
||||||
|
* @param backend Shell log backend instance.
|
||||||
|
* @param ctx Pointer to shell instance.
|
||||||
|
* @param init_log_level Initial log level set to all logging sources.
|
||||||
|
*/
|
||||||
|
void shell_log_backend_enable(const struct shell_log_backend *backend,
|
||||||
|
void *ctx, u32_t init_log_level);
|
||||||
|
|
||||||
|
/** @brief Disable shell log backend.
|
||||||
|
*
|
||||||
|
* @param backend Shell log backend instance.
|
||||||
|
*/
|
||||||
|
void shell_log_backend_disable(const struct shell_log_backend *backend);
|
||||||
|
|
||||||
|
/** @brief Trigger processing of one log entry.
|
||||||
|
*
|
||||||
|
* @param backend Shell log backend instance.
|
||||||
|
*
|
||||||
|
* @return True if message was processed, false if FIFO was empty
|
||||||
|
*/
|
||||||
|
bool shell_log_backend_process(const struct shell_log_backend *backend);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SHELL_LOG_BACKEND_H__ */
|
|
@ -19,12 +19,17 @@ zephyr_sources_ifdef(
|
||||||
shell_uart.c
|
shell_uart.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
zephyr_sources_ifdef(
|
||||||
|
CONFIG_SHELL_CMDS
|
||||||
|
shell_cmds.c
|
||||||
|
)
|
||||||
|
|
||||||
zephyr_sources_ifdef(
|
zephyr_sources_ifdef(
|
||||||
CONFIG_SHELL_HISTORY
|
CONFIG_SHELL_HISTORY
|
||||||
shell_history.c
|
shell_history.c
|
||||||
)
|
)
|
||||||
|
|
||||||
zephyr_sources_ifdef(
|
zephyr_sources_ifdef(
|
||||||
CONFIG_SHELL_CMDS
|
CONFIG_LOG
|
||||||
shell_cmds.c
|
shell_log_backend.c
|
||||||
)
|
)
|
||||||
|
|
|
@ -135,6 +135,17 @@ config SHELL_HISTORY_BUFFER
|
||||||
|
|
||||||
endif #SHELL_HISTORY
|
endif #SHELL_HISTORY
|
||||||
|
|
||||||
|
config SHELL_MAX_LOG_MSG_BUFFERED
|
||||||
|
int "Maximal number of log messages in FIFO"
|
||||||
|
default 8
|
||||||
|
help
|
||||||
|
When amount of buffered log messages exceeds this threshold oldest
|
||||||
|
messages are discarded.
|
||||||
|
|
||||||
|
config SHELL_STATS
|
||||||
|
bool "Enable shell statistics"
|
||||||
|
default y
|
||||||
|
|
||||||
config SHELL_CMDS
|
config SHELL_CMDS
|
||||||
bool "Enable built-in commands"
|
bool "Enable built-in commands"
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -1033,6 +1033,44 @@ static void shell_transport_evt_handler(enum shell_transport_evt evt_type,
|
||||||
k_poll_signal(signal, 0);
|
k_poll_signal(signal, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void shell_current_command_erase(const struct shell *shell)
|
||||||
|
{
|
||||||
|
shell_multiline_data_calc(&shell->ctx->vt100_ctx.cons,
|
||||||
|
shell->ctx->cmd_buff_pos,
|
||||||
|
shell->ctx->cmd_buff_len);
|
||||||
|
shell_op_cursor_horiz_move(shell, -shell->ctx->vt100_ctx.cons.cur_x);
|
||||||
|
shell_op_cursor_vert_move(shell, shell->ctx->vt100_ctx.cons.cur_y - 1);
|
||||||
|
|
||||||
|
clear_eos(shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shell_current_command_print(const struct shell *shell)
|
||||||
|
{
|
||||||
|
shell_fprintf(shell, SHELL_INFO, "%s", shell->name);
|
||||||
|
|
||||||
|
if (flag_echo_is_set(shell)) {
|
||||||
|
shell_fprintf(shell, SHELL_NORMAL, "%s", shell->ctx->cmd_buff);
|
||||||
|
shell_op_cursor_position_synchronize(shell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shell_log_process(const struct shell *shell)
|
||||||
|
{
|
||||||
|
bool processed;
|
||||||
|
int signaled;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
do {
|
||||||
|
shell_current_command_erase(shell);
|
||||||
|
processed = shell_log_backend_process(shell->log_backend);
|
||||||
|
shell_current_command_print(shell);
|
||||||
|
|
||||||
|
k_poll_signal_check(&shell->ctx->signals[SHELL_SIGNAL_RXRDY],
|
||||||
|
&signaled, &result);
|
||||||
|
|
||||||
|
} while (processed && !signaled);
|
||||||
|
}
|
||||||
|
|
||||||
static int shell_instance_init(const struct shell *shell, const void *p_config,
|
static int shell_instance_init(const struct shell *shell, const void *p_config,
|
||||||
bool use_colors)
|
bool use_colors)
|
||||||
{
|
{
|
||||||
|
@ -1057,6 +1095,10 @@ static int shell_instance_init(const struct shell *shell, const void *p_config,
|
||||||
shell->ctx->internal.flags.mode_delete = 1;
|
shell->ctx->internal.flags.mode_delete = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_SHELL_STATS)) {
|
||||||
|
shell->stats->log_lost_cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
shell->ctx->internal.flags.tx_rdy = 1;
|
shell->ctx->internal.flags.tx_rdy = 1;
|
||||||
shell->ctx->internal.flags.echo = CONFIG_SHELL_ECHO_STATUS;
|
shell->ctx->internal.flags.echo = CONFIG_SHELL_ECHO_STATUS;
|
||||||
shell->ctx->state = SHELL_STATE_INITIALIZED;
|
shell->ctx->state = SHELL_STATE_INITIALIZED;
|
||||||
|
@ -1106,13 +1148,23 @@ void shell_thread(void *shell_handle, void *dummy1, void *dummy2)
|
||||||
(void)shell_instance_uninit(shell);
|
(void)shell_instance_uninit(shell);
|
||||||
|
|
||||||
k_thread_abort(k_current_get());
|
k_thread_abort(k_current_get());
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
k_poll_signal_check(&shell->ctx->signals[SHELL_SIGNAL_LOG_MSG],
|
||||||
|
&signaled, &result);
|
||||||
|
|
||||||
|
if (!signaled) {
|
||||||
/* Other signals handled together.*/
|
/* Other signals handled together.*/
|
||||||
k_poll_signal_reset(
|
k_poll_signal_reset(
|
||||||
&shell->ctx->signals[SHELL_SIGNAL_RXRDY]);
|
&shell->ctx->signals[SHELL_SIGNAL_RXRDY]);
|
||||||
k_poll_signal_reset(
|
k_poll_signal_reset(
|
||||||
&shell->ctx->signals[SHELL_SIGNAL_TXDONE]);
|
&shell->ctx->signals[SHELL_SIGNAL_TXDONE]);
|
||||||
shell_process(shell);
|
shell_process(shell);
|
||||||
|
} else if (IS_ENABLED(CONFIG_LOG)) {
|
||||||
|
k_poll_signal_reset(
|
||||||
|
&shell->ctx->signals[SHELL_SIGNAL_LOG_MSG]);
|
||||||
|
/* process log msg */
|
||||||
|
shell_log_process(shell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1128,6 +1180,13 @@ int shell_init(const struct shell *shell, const void *transport_config,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (log_backend) {
|
||||||
|
if (IS_ENABLED(CONFIG_LOG)) {
|
||||||
|
shell_log_backend_enable(shell->log_backend,
|
||||||
|
(void *)shell, init_log_level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(void)k_thread_create(shell->thread,
|
(void)k_thread_create(shell->thread,
|
||||||
shell->stack, CONFIG_SHELL_STACK_SIZE,
|
shell->stack, CONFIG_SHELL_STACK_SIZE,
|
||||||
shell_thread, (void *)shell, NULL, NULL,
|
shell_thread, (void *)shell, NULL, NULL,
|
||||||
|
@ -1146,6 +1205,11 @@ static int shell_instance_uninit(const struct shell *shell)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_LOG)) {
|
||||||
|
/* todo purge log queue */
|
||||||
|
shell_log_backend_disable(shell->log_backend);
|
||||||
|
}
|
||||||
|
|
||||||
err = shell->iface->api->uninit(shell->iface);
|
err = shell->iface->api->uninit(shell->iface);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return err;
|
return err;
|
||||||
|
|
167
subsys/shell/shell_log_backend.c
Normal file
167
subsys/shell/shell_log_backend.c
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <shell/shell_log_backend.h>
|
||||||
|
#include <shell/shell.h>
|
||||||
|
#include "shell_ops.h"
|
||||||
|
#include <logging/log_ctrl.h>
|
||||||
|
|
||||||
|
int shell_log_backend_output_func(u8_t *data, size_t length, void *ctx)
|
||||||
|
{
|
||||||
|
shell_print_stream(ctx, data, length);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shell_log_backend_enable(const struct shell_log_backend *backend,
|
||||||
|
void *ctx, u32_t init_log_level)
|
||||||
|
{
|
||||||
|
log_backend_enable(backend->backend, ctx, init_log_level);
|
||||||
|
log_output_ctx_set(backend->log_output, ctx);
|
||||||
|
backend->control_block->cnt = 0;
|
||||||
|
backend->control_block->state = SHELL_LOG_BACKEND_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct log_msg *msg_from_fifo(const struct shell_log_backend *backend)
|
||||||
|
{
|
||||||
|
struct log_msg *msg = k_fifo_get(backend->fifo, K_NO_WAIT);
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
atomic_dec(&backend->control_block->cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fifo_flush(const struct shell_log_backend *backend)
|
||||||
|
{
|
||||||
|
struct log_msg *msg = msg_from_fifo(backend);
|
||||||
|
|
||||||
|
/* Flush log messages. */
|
||||||
|
while (msg) {
|
||||||
|
log_msg_put(msg);
|
||||||
|
msg = msg_from_fifo(backend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void msg_to_fifo(const struct shell *shell,
|
||||||
|
struct log_msg *msg)
|
||||||
|
{
|
||||||
|
atomic_val_t cnt;
|
||||||
|
|
||||||
|
k_fifo_put(shell->log_backend->fifo, msg);
|
||||||
|
|
||||||
|
cnt = atomic_inc(&shell->log_backend->control_block->cnt);
|
||||||
|
|
||||||
|
/* If there is too much queued free the oldest one. */
|
||||||
|
if (cnt >= CONFIG_SHELL_MAX_LOG_MSG_BUFFERED) {
|
||||||
|
log_msg_put(msg_from_fifo(shell->log_backend));
|
||||||
|
if (IS_ENABLED(CONFIG_SHELL_STATS)) {
|
||||||
|
shell->stats->log_lost_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shell_log_backend_disable(const struct shell_log_backend *backend)
|
||||||
|
{
|
||||||
|
fifo_flush(backend);
|
||||||
|
log_backend_disable(backend->backend);
|
||||||
|
backend->control_block->state = SHELL_LOG_BACKEND_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void msg_process(const struct log_output *log_output,
|
||||||
|
struct log_msg *msg)
|
||||||
|
{
|
||||||
|
u32_t flags = 0;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_SHELL)) {
|
||||||
|
flags |= LOG_OUTPUT_FLAG_COLORS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_SHELL)) {
|
||||||
|
flags |= LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_output_msg_process(log_output, msg, flags);
|
||||||
|
log_msg_put(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shell_log_backend_process(const struct shell_log_backend *backend)
|
||||||
|
{
|
||||||
|
const struct shell *shell =
|
||||||
|
(const struct shell *)backend->backend->cb->ctx;
|
||||||
|
struct log_msg *msg = msg_from_fifo(backend);
|
||||||
|
|
||||||
|
if (!msg) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_process(shell->log_backend->log_output, msg);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void put(const struct log_backend *const backend, struct log_msg *msg)
|
||||||
|
{
|
||||||
|
const struct shell *shell = (const struct shell *)backend->cb->ctx;
|
||||||
|
struct k_poll_signal *signal;
|
||||||
|
|
||||||
|
log_msg_get(msg);
|
||||||
|
|
||||||
|
switch (shell->log_backend->control_block->state) {
|
||||||
|
case SHELL_LOG_BACKEND_ENABLED:
|
||||||
|
msg_to_fifo(shell, msg);
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_MULTITHREADING)) {
|
||||||
|
signal = &shell->ctx->signals[SHELL_SIGNAL_LOG_MSG];
|
||||||
|
k_poll_signal(signal, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SHELL_LOG_BACKEND_PANIC:
|
||||||
|
msg_process(shell->log_backend->log_output, msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SHELL_LOG_BACKEND_DISABLED:
|
||||||
|
/* fall through */
|
||||||
|
/* no break */
|
||||||
|
default:
|
||||||
|
/* Discard message. */
|
||||||
|
log_msg_put(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void panic(const struct log_backend *const backend)
|
||||||
|
{
|
||||||
|
const struct shell *shell = (const struct shell *)backend->cb->ctx;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = shell->iface->api->enable(shell->iface, true);
|
||||||
|
|
||||||
|
if (err == 0) {
|
||||||
|
shell->log_backend->control_block->state =
|
||||||
|
SHELL_LOG_BACKEND_PANIC;
|
||||||
|
|
||||||
|
/* Move to the start of next line. */
|
||||||
|
shell_multiline_data_calc(&shell->ctx->vt100_ctx.cons,
|
||||||
|
shell->ctx->cmd_buff_pos,
|
||||||
|
shell->ctx->cmd_buff_len);
|
||||||
|
shell_op_cursor_vert_move(shell, -1);
|
||||||
|
shell_op_cursor_horiz_move(shell,
|
||||||
|
-shell->ctx->vt100_ctx.cons.cur_x);
|
||||||
|
|
||||||
|
while (shell_log_backend_process(shell->log_backend)) {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
shell_log_backend_disable(shell->log_backend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct log_backend_api log_backend_shell_api = {
|
||||||
|
.put = put,
|
||||||
|
.panic = panic
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue