drivers: bbram: Introduce BBRAM shell
Add 'bbram' command which is very convenient tool for examining and modyfying BBRAM content. Examples: Write one byte: $ bbram write backup_regs 0x1 0xaa Write many bytes (starting from 0x13): $ bbram write backup_regs 0x13 0xa 0xb 0xc 0xd 0xe 0xf 0xaa 0xab 0xac Read whole BBRAM: $ bbram read backup_regs Read many bytes (4 bytes starting from address 0x14 in this case): $ bbram read backup_regs 0x14 4 Read one byte (from 0x14 address): $ bbram read backup_regs 0x14 Signed-off-by: Patryk Duda <pdk@semihalf.com>
This commit is contained in:
parent
e02456a52d
commit
f7fca220ba
|
@ -3,6 +3,8 @@
|
|||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BBRAM_SHELL bbram_shell.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BBRAM_NPCX bbram_npcx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_BBRAM_IT8XXX2 bbram_it8xxx2.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_BBRAM_EMUL bbram_emul.c)
|
||||
|
|
|
@ -12,6 +12,12 @@ module = BBRAM
|
|||
module-str = bbram
|
||||
source "subsys/logging/Kconfig.template.log_config"
|
||||
|
||||
config BBRAM_SHELL
|
||||
bool "Battery-backed RAM shell"
|
||||
depends on SHELL
|
||||
help
|
||||
Enable the BBRAM shell with read and write commands.
|
||||
|
||||
config BBRAM_INIT_PRIORITY
|
||||
int "Init priority"
|
||||
# In STM32, BBRAM is a part of RTC. In this case init priority must be
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Google Inc
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/drivers/bbram.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/shell/shell.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
/* Buffer is only needed for bytes that follow command, device and address. */
|
||||
#define BUF_ARRAY_CNT (CONFIG_SHELL_ARGC_MAX - 3)
|
||||
|
||||
static inline int parse_ul(const char *str, unsigned long *result)
|
||||
{
|
||||
char *end;
|
||||
unsigned long val;
|
||||
|
||||
val = strtoul(str, &end, 0);
|
||||
|
||||
if (*str == '\0' || *end != '\0') {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*result = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int parse_u32(const char *str, uint32_t *result)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
if (parse_ul(str, &val) || val > 0xffffffff) {
|
||||
return -EINVAL;
|
||||
}
|
||||
*result = (uint32_t)val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int parse_u8(const char *str, uint8_t *result)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
if (parse_ul(str, &val) || val > 0xff) {
|
||||
return -EINVAL;
|
||||
}
|
||||
*result = (uint8_t)val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int parse_device(const struct shell *sh, size_t argc, char *argv[],
|
||||
const struct device **bbram_dev)
|
||||
{
|
||||
if (argc < 2) {
|
||||
shell_error(sh, "Missing BBRAM device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*bbram_dev = device_get_binding(argv[1]);
|
||||
if (!*bbram_dev) {
|
||||
shell_error(sh, "Given BBRAM device was not found");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_read(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
const struct device *bbram_dev;
|
||||
uint32_t addr;
|
||||
size_t size;
|
||||
int part_size, ret;
|
||||
|
||||
ret = parse_device(sh, argc, argv, &bbram_dev);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (argc < 3) {
|
||||
/* Dump whole BBRAM if address not provided. */
|
||||
addr = 0;
|
||||
ret = bbram_get_size(bbram_dev, &size);
|
||||
if (ret < 0) {
|
||||
shell_error(sh, "Can't get BBRAM size: %d", ret);
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
/* Parse address if provided. */
|
||||
ret = parse_u32(argv[2], &addr);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If size not provided read one byte. */
|
||||
size = 1;
|
||||
|
||||
if (argc >= 4) {
|
||||
/* Parse size if provided. */
|
||||
ret = parse_u32(argv[3], &size);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int cnt = 0; cnt < size; cnt += part_size) {
|
||||
uint8_t data[SHELL_HEXDUMP_BYTES_IN_LINE];
|
||||
|
||||
part_size = MIN(size - cnt, SHELL_HEXDUMP_BYTES_IN_LINE);
|
||||
ret = bbram_read(bbram_dev, addr, part_size, data);
|
||||
if (ret != 0) {
|
||||
shell_error(sh, "BBRAM read error: %d", ret);
|
||||
return -EIO;
|
||||
}
|
||||
shell_hexdump_line(sh, addr, data, part_size);
|
||||
addr += part_size;
|
||||
}
|
||||
|
||||
shell_print(sh, "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_write(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
const struct device *bbram_dev;
|
||||
uint8_t buf[BUF_ARRAY_CNT];
|
||||
uint32_t addr;
|
||||
size_t size = 0;
|
||||
int ret;
|
||||
|
||||
ret = parse_device(sh, argc, argv, &bbram_dev);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (argc < 3) {
|
||||
shell_error(sh, "Missing address");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Parse address. */
|
||||
ret = parse_u32(argv[2], &addr);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Parse bytes and place them in the buffer. */
|
||||
for (int i = 3; i < argc; i++) {
|
||||
ret = parse_u8(argv[i], &buf[i - 3]);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
size++;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
shell_error(sh, "Missing data");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = bbram_write(bbram_dev, addr, size, buf);
|
||||
if (ret < 0) {
|
||||
shell_error(sh, "BBRAM write error: %d", ret);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void device_name_get(size_t idx, struct shell_static_entry *entry)
|
||||
{
|
||||
const struct device *dev = shell_device_lookup(idx, NULL);
|
||||
|
||||
entry->syntax = (dev != NULL) ? dev->name : NULL;
|
||||
entry->handler = NULL;
|
||||
entry->help = NULL;
|
||||
entry->subcmd = NULL;
|
||||
}
|
||||
|
||||
SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get);
|
||||
|
||||
SHELL_STATIC_SUBCMD_SET_CREATE(bbram_cmds,
|
||||
SHELL_CMD_ARG(read, &dsub_device_name,
|
||||
"<device> [<address>] [<count>]", cmd_read, 2, 2),
|
||||
SHELL_CMD_ARG(write, &dsub_device_name,
|
||||
"<device> <address> <byte> [<byte>...]", cmd_write, 4,
|
||||
BUF_ARRAY_CNT),
|
||||
SHELL_SUBCMD_SET_END);
|
||||
|
||||
static int cmd_bbram(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
shell_error(sh, "%s: unknown parameter: %s", argv[0], argv[1]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
SHELL_CMD_ARG_REGISTER(bbram, &bbram_cmds, "Battery-backed RAM shell commands", cmd_bbram, 2, 0);
|
Loading…
Reference in New Issue