mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-09-02 15:26:54 +00:00
Kernel timeouts have always been a 32 bit integer despite the existence of generation macros, and existing code has been inconsistent about using them. Upcoming commits are going to make the timeout arguments opaque, so fix things up to be rigorously correct. Changes include: + Adding a K_TIMEOUT_EQ() macro for code that needs to compare timeout values for equality (e.g. with K_FOREVER or K_NO_WAIT). + Adding a k_msleep() synonym for k_sleep() which can continue to take integral arguments as k_sleep() moves away to timeout arguments. + Pervasively using the K_MSEC(), K_SECONDS(), et. al. macros to generate timeout arguments. + Removing the usage of K_NO_WAIT as the final argument to K_THREAD_DEFINE(). This is just a count of milliseconds and we need to use a zero. This patch include no logic changes and should not affect generated code at all. Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
311 lines
7.4 KiB
C
311 lines
7.4 KiB
C
/*
|
|
* 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)
|
|
{
|
|
int err = 0;
|
|
|
|
if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) {
|
|
const struct shell *shell;
|
|
|
|
shell = (const struct shell *)ctx;
|
|
|
|
/* Reenable transport in blocking mode */
|
|
err = shell->iface->api->enable(shell->iface, true);
|
|
}
|
|
|
|
if (err == 0) {
|
|
log_backend_enable(backend->backend, ctx, init_log_level);
|
|
log_output_ctx_set(backend->log_output, ctx);
|
|
backend->control_block->dropped_cnt = 0;
|
|
backend->control_block->state = SHELL_LOG_BACKEND_ENABLED;
|
|
}
|
|
}
|
|
|
|
static struct log_msg *msg_from_fifo(const struct shell_log_backend *backend)
|
|
{
|
|
struct shell_log_backend_msg msg;
|
|
int err;
|
|
|
|
err = k_msgq_get(backend->msgq, &msg, K_NO_WAIT);
|
|
|
|
return (err == 0) ? msg.msg : NULL;
|
|
}
|
|
|
|
static void fifo_flush(const struct shell_log_backend *backend)
|
|
{
|
|
struct log_msg *msg;
|
|
|
|
/* Flush log messages. */
|
|
while ((msg = msg_from_fifo(backend)) != NULL) {
|
|
log_msg_put(msg);
|
|
}
|
|
}
|
|
|
|
static void flush_expired_messages(const struct shell *shell)
|
|
{
|
|
int err;
|
|
struct shell_log_backend_msg msg;
|
|
struct k_msgq *msgq = shell->log_backend->msgq;
|
|
u32_t timeout = shell->log_backend->timeout;
|
|
u32_t now = k_uptime_get_32();
|
|
|
|
while (1) {
|
|
err = k_msgq_peek(msgq, &msg);
|
|
|
|
if (err == 0 && ((now - msg.timestamp) > timeout)) {
|
|
(void)k_msgq_get(msgq, &msg, K_NO_WAIT);
|
|
log_msg_put(msg.msg);
|
|
|
|
if (IS_ENABLED(CONFIG_SHELL_STATS)) {
|
|
atomic_inc(&shell->stats->log_lost_cnt);
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void msg_to_fifo(const struct shell *shell,
|
|
struct log_msg *msg)
|
|
{
|
|
int err;
|
|
struct shell_log_backend_msg t_msg = {
|
|
.msg = msg,
|
|
.timestamp = k_uptime_get_32()
|
|
};
|
|
|
|
err = k_msgq_put(shell->log_backend->msgq, &t_msg,
|
|
K_MSEC(shell->log_backend->timeout));
|
|
|
|
switch (err) {
|
|
case 0:
|
|
break;
|
|
case -EAGAIN:
|
|
case -ENOMSG:
|
|
{
|
|
flush_expired_messages(shell);
|
|
|
|
err = k_msgq_put(shell->log_backend->msgq, &msg, K_NO_WAIT);
|
|
if (err) {
|
|
/* Unexpected case as we just freed one element and
|
|
* there is no other context that puts into the msgq.
|
|
*/
|
|
__ASSERT_NO_MSG(0);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
/* Other errors are not expected. */
|
|
__ASSERT_NO_MSG(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
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, bool colors)
|
|
{
|
|
u32_t flags = LOG_OUTPUT_FLAG_LEVEL |
|
|
LOG_OUTPUT_FLAG_TIMESTAMP |
|
|
LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP;
|
|
|
|
if (colors) {
|
|
flags |= LOG_OUTPUT_FLAG_COLORS;
|
|
}
|
|
|
|
log_output_msg_process(log_output, msg, flags);
|
|
log_msg_put(msg);
|
|
}
|
|
|
|
bool shell_log_backend_process(const struct shell_log_backend *backend)
|
|
{
|
|
u32_t dropped;
|
|
const struct shell *shell =
|
|
(const struct shell *)backend->backend->cb->ctx;
|
|
bool colors = IS_ENABLED(CONFIG_SHELL_VT100_COLORS) &&
|
|
shell->ctx->internal.flags.use_colors;
|
|
struct log_msg *msg = msg_from_fifo(backend);
|
|
|
|
if (!msg) {
|
|
return false;
|
|
}
|
|
|
|
dropped = atomic_set(&backend->control_block->dropped_cnt, 0);
|
|
if (dropped) {
|
|
struct shell_vt100_colors col;
|
|
|
|
if (colors) {
|
|
shell_vt100_colors_store(shell, &col);
|
|
shell_vt100_color_set(shell, SHELL_VT100_COLOR_RED);
|
|
}
|
|
|
|
log_output_dropped_process(backend->log_output, dropped);
|
|
|
|
if (colors) {
|
|
shell_vt100_colors_restore(shell, &col);
|
|
}
|
|
}
|
|
|
|
msg_process(shell->log_backend->log_output, msg, colors);
|
|
|
|
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;
|
|
bool colors = IS_ENABLED(CONFIG_SHELL_VT100_COLORS) &&
|
|
shell->ctx->internal.flags.use_colors;
|
|
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_raise(signal, 0);
|
|
}
|
|
|
|
break;
|
|
case SHELL_LOG_BACKEND_PANIC:
|
|
shell_cmd_line_erase(shell);
|
|
msg_process(shell->log_backend->log_output, msg, colors);
|
|
|
|
break;
|
|
|
|
case SHELL_LOG_BACKEND_DISABLED:
|
|
/* fall through */
|
|
/* no break */
|
|
default:
|
|
/* Discard message. */
|
|
log_msg_put(msg);
|
|
}
|
|
}
|
|
|
|
static void put_sync_string(const struct log_backend *const backend,
|
|
struct log_msg_ids src_level, u32_t timestamp,
|
|
const char *fmt, va_list ap)
|
|
{
|
|
const struct shell *shell = (const struct shell *)backend->cb->ctx;
|
|
u32_t key;
|
|
u32_t flags = LOG_OUTPUT_FLAG_LEVEL |
|
|
LOG_OUTPUT_FLAG_TIMESTAMP |
|
|
LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP;
|
|
|
|
if (IS_ENABLED(CONFIG_SHELL_VT100_COLORS)) {
|
|
flags |= LOG_OUTPUT_FLAG_COLORS;
|
|
}
|
|
|
|
key = irq_lock();
|
|
if (!flag_cmd_ctx_get(shell)) {
|
|
shell_cmd_line_erase(shell);
|
|
}
|
|
log_output_string(shell->log_backend->log_output, src_level, timestamp,
|
|
fmt, ap, flags);
|
|
if (!flag_cmd_ctx_get(shell)) {
|
|
shell_print_prompt_and_cmd(shell);
|
|
}
|
|
irq_unlock(key);
|
|
}
|
|
|
|
static void put_sync_hexdump(const struct log_backend *const backend,
|
|
struct log_msg_ids src_level, u32_t timestamp,
|
|
const char *metadata, const u8_t *data, u32_t length)
|
|
{
|
|
const struct shell *shell = (const struct shell *)backend->cb->ctx;
|
|
u32_t key;
|
|
u32_t flags = LOG_OUTPUT_FLAG_LEVEL |
|
|
LOG_OUTPUT_FLAG_TIMESTAMP |
|
|
LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP;
|
|
|
|
if (IS_ENABLED(CONFIG_SHELL_VT100_COLORS)) {
|
|
flags |= LOG_OUTPUT_FLAG_COLORS;
|
|
}
|
|
|
|
key = irq_lock();
|
|
if (!flag_cmd_ctx_get(shell)) {
|
|
shell_cmd_line_erase(shell);
|
|
}
|
|
log_output_hexdump(shell->log_backend->log_output, src_level, timestamp,
|
|
metadata, data, length, flags);
|
|
if (!flag_cmd_ctx_get(shell)) {
|
|
shell_print_prompt_and_cmd(shell);
|
|
}
|
|
irq_unlock(key);
|
|
}
|
|
|
|
static void panic(const struct log_backend *const backend)
|
|
{
|
|
const struct shell *shell = (const struct shell *)backend->cb->ctx;
|
|
int err;
|
|
|
|
if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) {
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
static void dropped(const struct log_backend *const backend, u32_t cnt)
|
|
{
|
|
const struct shell *shell = (const struct shell *)backend->cb->ctx;
|
|
const struct shell_log_backend *log_backend = shell->log_backend;
|
|
|
|
atomic_add(&shell->stats->log_lost_cnt, cnt);
|
|
atomic_add(&log_backend->control_block->dropped_cnt, cnt);
|
|
}
|
|
|
|
const struct log_backend_api log_backend_shell_api = {
|
|
.put = IS_ENABLED(CONFIG_LOG_IMMEDIATE) ? NULL : put,
|
|
.put_sync_string = IS_ENABLED(CONFIG_LOG_IMMEDIATE) ?
|
|
put_sync_string : NULL,
|
|
.put_sync_hexdump = IS_ENABLED(CONFIG_LOG_IMMEDIATE) ?
|
|
put_sync_hexdump : NULL,
|
|
.dropped = dropped,
|
|
.panic = panic,
|
|
};
|