shell: Refactor shell_history to use less RW memory
Shell history module reworked to use ring buffer for storing commands. Dedicated buffer is used to story all command lineary. History capacity is in bytes not in number of entries, e.g. many short commands can be stored or few long (depending on CONFIG_SHELL_HISTORY_BUFFER). Removed implicit command null termination from shell_history and added it to shell after fetching command line from the history. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
0e8517e1b6
commit
c2cb60f613
5 changed files with 198 additions and 61 deletions
|
@ -30,6 +30,10 @@ extern "C" {
|
|||
#define CONFIG_SHELL_PRINTF_BUFF_SIZE 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SHELL_HISTORY_BUFFER
|
||||
#define CONFIG_SHELL_HISTORY_BUFFER 0
|
||||
#endif
|
||||
|
||||
#define SHELL_CMD_ROOT_LVL (0u)
|
||||
|
||||
/**
|
||||
|
@ -643,7 +647,7 @@ extern void shell_print_stream(const void *user_ctx, const char *data,
|
|||
SHELL_LOG_BACKEND_DEFINE(_name, _name##_out_buffer, \
|
||||
CONFIG_SHELL_PRINTF_BUFF_SIZE, \
|
||||
_log_queue_size, _log_timeout); \
|
||||
SHELL_HISTORY_DEFINE(_name, CONFIG_SHELL_CMD_BUFF_SIZE, 7); \
|
||||
SHELL_HISTORY_DEFINE(_name##_history, CONFIG_SHELL_HISTORY_BUFFER); \
|
||||
SHELL_FPRINTF_DEFINE(_name##_fprintf, &_name, _name##_out_buffer, \
|
||||
CONFIG_SHELL_PRINTF_BUFF_SIZE, \
|
||||
true, shell_print_stream); \
|
||||
|
@ -655,7 +659,8 @@ extern void shell_print_stream(const void *user_ctx, const char *data,
|
|||
.default_prompt = _prompt, \
|
||||
.iface = _transport_iface, \
|
||||
.ctx = &UTIL_CAT(_name, _ctx), \
|
||||
.history = SHELL_HISTORY_PTR(_name), \
|
||||
.history = IS_ENABLED(CONFIG_SHELL_HISTORY) ? \
|
||||
&_name##_history : NULL, \
|
||||
.shell_flag = _shell_flag, \
|
||||
.fprintf_ctx = &_name##_fprintf, \
|
||||
.stats = SHELL_STATS_PTR(_name), \
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <zephyr.h>
|
||||
#include <misc/util.h>
|
||||
#include <misc/dlist.h>
|
||||
#include <ring_buffer.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -18,45 +19,88 @@ extern "C" {
|
|||
|
||||
|
||||
struct shell_history {
|
||||
struct k_mem_slab *mem_slab;
|
||||
struct ring_buf *ring_buf;
|
||||
sys_dlist_t list;
|
||||
sys_dnode_t *current;
|
||||
};
|
||||
|
||||
struct shell_history_item {
|
||||
sys_dnode_t dnode;
|
||||
u16_t len;
|
||||
char data[];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SHELL_HISTORY
|
||||
#define SHELL_HISTORY_DEFINE(_name, block_size, block_count) \
|
||||
\
|
||||
K_MEM_SLAB_DEFINE(_name##_history_memslab, \
|
||||
ROUND_UP(block_size + sizeof(struct shell_history_item), \
|
||||
sizeof(void *)), block_count, 4); \
|
||||
static struct shell_history _name##_history = { \
|
||||
.mem_slab = &_name##_history_memslab \
|
||||
/**
|
||||
* @brief Create shell history instance.
|
||||
*
|
||||
* @param _name History instance name.
|
||||
* @param _size Memory dedicated for shell history.
|
||||
*/
|
||||
#define SHELL_HISTORY_DEFINE(_name, _size) \
|
||||
static u8_t __noinit __aligned(sizeof(u32_t)) \
|
||||
_name##_ring_buf_data[_size]; \
|
||||
static struct ring_buf _name##_ring_buf = \
|
||||
{ \
|
||||
.size = _size, \
|
||||
.buf = { .buf8 = _name##_ring_buf_data } \
|
||||
}; \
|
||||
static struct shell_history _name = { \
|
||||
.ring_buf = &_name##_ring_buf \
|
||||
}
|
||||
#define SHELL_HISTORY_PTR(_name) (&_name##_history)
|
||||
#else /* CONFIG_SHELL_HISTORY */
|
||||
#define SHELL_HISTORY_DEFINE(_name, block_size, block_count) /*empty*/
|
||||
#define SHELL_HISTORY_PTR(_name) NULL
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize shell history module.
|
||||
*
|
||||
* @param history Shell history instance.
|
||||
*/
|
||||
void shell_history_init(struct shell_history *history);
|
||||
|
||||
/**
|
||||
* @brief Purge shell history.
|
||||
*
|
||||
* Function clears whole shell command history.
|
||||
*
|
||||
* @param history Shell history instance.
|
||||
*
|
||||
*/
|
||||
void shell_history_purge(struct shell_history *history);
|
||||
|
||||
/**
|
||||
* @brief Exit history browsing mode.
|
||||
*
|
||||
* @param history Shell history instance.
|
||||
*/
|
||||
void shell_history_mode_exit(struct shell_history *history);
|
||||
|
||||
/* returns true if remains in history mode.*/
|
||||
/**
|
||||
* @brief Get next entry in shell command history.
|
||||
*
|
||||
* Function returns next (in given direction) stored line.
|
||||
*
|
||||
* @param[in] history Shell history instance.
|
||||
* @param[in] up Direction.
|
||||
* @param[out] dst Buffer where line is copied.
|
||||
* @param[in,out] len Buffer size (intput), amount of copied
|
||||
* data (output).
|
||||
* @return True if remains in history mode.
|
||||
*/
|
||||
bool shell_history_get(struct shell_history *history, bool up,
|
||||
u8_t *dst, u16_t *len);
|
||||
|
||||
/**
|
||||
* @brief Put line into shell command history.
|
||||
*
|
||||
* If history is full, oldest entry (or entries) is removed.
|
||||
*
|
||||
* @param history Shell history instance.
|
||||
* @param line Data.
|
||||
* @param len Data length.
|
||||
*
|
||||
*/
|
||||
void shell_history_put(struct shell_history *history, u8_t *line, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Get state of shell history.
|
||||
*
|
||||
* @param history Shell history instance.
|
||||
*
|
||||
* @return True if in browsing mode.
|
||||
*/
|
||||
static inline bool shell_history_active(struct shell_history *history)
|
||||
{
|
||||
return (history->current) ? true : false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue