common/shell/shell_platform.c (357 lines of code) (raw):
/*
NAME: PLATFORM COMMAND
FILE: shell_platform.c
DESCRIPTION: OEM commands including gpio, sensor relative function access.
CHIP/OS: AST1030 - Zephyr
Note:
(1) User command table
[topic] [description] [support] [command]
* GPIO O
* List group List gpios' info in group o platform gpio list_group <gpio_device>
* List all List all gpios' info o platform gpio list_all
* List multifnctl List multi-fn-ctl regs o platform gpio multifnctl
* Get Get one gpio info o platform gpio get <gpio_num>
* Set value Set one gpio value o platform gpio set val <gpio_num> <value>
* Set direction Set one gpio direction x TODO
* Set INT type Set one gpio interrupt T o platform gpio set int_type <gpio_num> <type>
* SENSOR O
* List all List all sensors' info o platform sensor list_all
* Get Get one sensor info o platform sensor get <sensor_num>
* Set polling en Set one sensor polling x TODO
* Set mbr Set one sensor mbr x TODO
* Set threshold Set one sensor threshold x TODO
(2) Some hard code features need to be modified if CHIP is different
(3) GPIO List all/Get/Set value/Set direction are not protected by PINMASK_RESERVE_CHECK. It might cause system-hang problem!
(4) "List multifnctl" command only lists relative registers mentioned in chip spec
chapter "5.Multi-function Pins Mapping and Control"
*/
#include <zephyr.h>
#include <sys/printk.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <shell/shell.h>
#include <device.h>
#include <devicetree.h>
/* Include GPIO */
#include <drivers/gpio.h>
#include "plat_gpio.h"
#include "hal_gpio.h"
/* Include SENSOR */
#include "sensor.h"
/* Include config settings */
#include "shell_platform.h"
/*********************************************************************************************************
* TOOL SECTION
**********************************************************************************************************/
/*
Command GPIO
*/
#if PINMASK_RESERVE_CHECK
enum CHECK_RESV { CHECK_BY_GROUP_IDX, CHECK_BY_GLOBAL_IDX };
static int gpio_check_reserve(const struct device *dev, int gpio_idx, enum CHECK_RESV mode)
{
if (!dev)
return 1;
const struct gpio_driver_config *const cfg = (const struct gpio_driver_config *)dev->config;
if (!cfg->port_pin_mask)
return 1;
int gpio_idx_in_group;
if (mode == CHECK_BY_GROUP_IDX) {
gpio_idx_in_group = gpio_idx;
} else if (mode == CHECK_BY_GLOBAL_IDX) {
gpio_idx_in_group = gpio_idx % GPIO_GROUP_SIZE;
} else
return 1;
if ((cfg->port_pin_mask & (gpio_port_pins_t)BIT(gpio_idx_in_group)) == 0U)
return 1;
return 0;
}
#endif
static int gpio_access_cfg(const struct shell *shell, int gpio_idx, enum GPIO_ACCESS mode,
int *data)
{
if (!shell)
return 1;
if (gpio_idx >= GPIO_CFG_SIZE || gpio_idx < 0) {
shell_error(shell, "gpio_access_cfg - gpio index out of bound!");
return 1;
}
switch (mode) {
case GPIO_READ:
if (gpio_cfg[gpio_idx].is_init == DISABLE)
return 1;
uint32_t g_val = sys_read32(GPIO_GROUP_REG_ACCESS[gpio_idx / 32]);
uint32_t g_dir = sys_read32(GPIO_GROUP_REG_ACCESS[gpio_idx / 32] + 0x4);
char *pin_prop = (gpio_cfg[gpio_idx].property == OPEN_DRAIN) ? "OD" : "PP";
char *pin_dir = (gpio_cfg[gpio_idx].direction == GPIO_INPUT) ? "input" : "output";
char *pin_dir_reg = "I";
if (g_dir & BIT(gpio_idx % 32))
pin_dir_reg = "O";
int val = gpio_get(gpio_idx);
if (val == 0 || val == 1)
shell_print(shell, "[%-3d] %-35s: %-3s | %-6s(%s) | %d(%d)", gpio_idx,
gpio_name[gpio_idx], pin_prop, pin_dir, pin_dir_reg, val,
GET_BIT_VAL(g_val, gpio_idx % 32));
else
shell_print(shell, "[%-3d] %-35s: %-3s | %-6s(%s) | %s", gpio_idx,
gpio_name[gpio_idx], pin_prop, pin_dir, pin_dir_reg, "resv");
break;
case GPIO_WRITE:
if (!data) {
shell_error(shell, "gpio_access_cfg - GPIO_WRITE value empty!");
return 1;
}
if (*data != 0 && *data != 1) {
shell_error(
shell,
"gpio_access_cfg - GPIO_WRITE value should only accept 0 or 1!");
return 1;
}
if (gpio_set(gpio_idx, *data)) {
shell_error(shell, "gpio_access_cfg - GPIO_WRITE failed!");
return 1;
}
break;
default:
shell_error(shell, "gpio_access_cfg - No such mode %d!", mode);
break;
}
return 0;
}
static int gpio_get_group_idx_by_dev_name(const char *dev_name)
{
if (!dev_name)
return -1;
int group_idx = -1;
for (int i = 0; i < ARRAY_SIZE(GPIO_GROUP_NAME_LST); i++) {
if (!strcmp(dev_name, GPIO_GROUP_NAME_LST[i]))
group_idx = i;
}
return group_idx;
}
static const char *gpio_get_name(const char *dev_name, int pin_num)
{
if (!dev_name)
return NULL;
int name_idx = -1;
name_idx = pin_num + 32 * gpio_get_group_idx_by_dev_name(dev_name);
if (name_idx == -1)
return NULL;
if (name_idx >= GPIO_CFG_SIZE)
return "Undefined";
return gpio_name[name_idx];
}
/*
Command SENSOR
*/
static bool sensor_access_check(uint8_t sensor_num)
{
bool (*access_checker)(uint8_t);
access_checker = sensor_config[SensorNum_SensorCfg_map[sensor_num]].access_checker;
return (access_checker)(sensor_config[SensorNum_SensorCfg_map[sensor_num]].num);
}
static int sensor_get_idx_by_sensor_num(uint16_t sensor_num)
{
for (int sen_idx = 0; sen_idx < SDR_NUM; sen_idx++) {
if (sensor_num == sensor_config[sen_idx].num)
return sen_idx;
}
return -1;
}
static int sensor_access(const struct shell *shell, int sensor_num, enum SENSOR_ACCESS mode)
{
if (!shell)
return 1;
if (sensor_num >= SENSOR_NUM_MAX || sensor_num < 0)
return 1;
switch (mode) {
/* Get sensor info by "sensor_config" table */
case SENSOR_READ:;
int sen_idx = sensor_get_idx_by_sensor_num(sensor_num);
if (sen_idx == -1) {
shell_error(shell, "No such sensor number!");
return 1;
}
char *check_access =
(sensor_access_check(sensor_config[sen_idx].num) == true) ? "O" : "X";
shell_print(shell, "[0x%-2x] %-35s: %-5s | access[%s] | %-20s | %-8d",
sensor_config[sen_idx].num, "Unsupported name",
sensor_type_name[sensor_config[sen_idx].type], check_access,
sensor_status_name[sensor_config[sen_idx].cache_status],
sensor_config[sen_idx].cache);
break;
case SENSOR_WRITE:
/* TODO */
break;
default:
break;
}
return 0;
}
/*********************************************************************************************************
* COMMAND FUNCTION SECTION
**********************************************************************************************************/
/*
Command header
*/
static int cmd_info_print(const struct shell *shell, size_t argc, char **argv)
{
shell_print(
shell,
"========================{SHELL COMMAND INFO}========================================");
shell_print(shell, "* NAME: Platform command");
shell_print(shell, "* DESCRIPTION: Commands that could be used to debug or validate.");
shell_print(shell, "* DATE/VERSION: none");
shell_print(shell, "* CHIP/OS: AST1030 - Zephyr");
shell_print(shell, "* Note: none");
shell_print(
shell,
"========================{SHELL COMMAND INFO}========================================");
return 0;
}
/*
Command GPIO
*/
static void cmd_gpio_cfg_list_group(const struct shell *shell, size_t argc, char **argv)
{
if (argc != 2) {
shell_warn(shell, "Help: platform gpio list_group <gpio_device>");
return;
}
const struct device *dev;
dev = device_get_binding(argv[1]);
if (!dev) {
shell_error(shell, "Device [%s] not found!", argv[1]);
return;
}
int g_idx = gpio_get_group_idx_by_dev_name(dev->name);
int max_group_pin = num_of_pin_in_one_group_lst[g_idx];
uint32_t g_val = sys_read32(GPIO_GROUP_REG_ACCESS[g_idx]);
uint32_t g_dir = sys_read32(GPIO_GROUP_REG_ACCESS[g_idx] + 0x4);
int rc;
for (int index = 0; index < max_group_pin; index++) {
if (gpio_cfg[g_idx * 32 + index].is_init == DISABLE) {
shell_print(shell, "[%-3d][%s %-3d] %-35s: -- | %-9s | NA",
g_idx * 32 + index, dev->name, index, "gpio_disable", "i/o");
continue;
}
#if PINMASK_RESERVE_CHECK
/* avoid pin_mask from devicetree "gpio-reserved" */
if (gpio_check_reserve(dev, index, CHECK_BY_GROUP_IDX)) {
shell_print(shell, "[%-3d][%s %-3d] %-35s: -- | %-9s | NA",
g_idx * 32 + index, dev->name, index, "gpio_reserve", "i/o");
continue;
}
#endif
char *pin_dir = "output";
if (gpio_cfg[g_idx * 32 + index].direction == GPIO_INPUT)
pin_dir = "input";
char *pin_dir_reg = "I";
if (g_dir & BIT(index))
pin_dir_reg = "O";
char *pin_prop =
(gpio_cfg[g_idx * 32 + index].property == OPEN_DRAIN) ? "OD" : "PP";
rc = gpio_pin_get(dev, index);
if (rc >= 0) {
shell_print(shell, "[%-3d][%s %-3d] %-35s: %2s | %-6s(%s) | %d(%d)",
g_idx * 32 + index, dev->name, index,
gpio_get_name(dev->name, index), pin_prop, pin_dir, pin_dir_reg,
rc, GET_BIT_VAL(g_val, index));
} else {
shell_error(shell, "[%-3d][%s %-3d] %-35s: %2s | %-6s | err[%d]",
g_idx * 32 + index, dev->name, index,
gpio_get_name(dev->name, index), pin_prop, pin_dir, rc);
}
}
return;
}
static void cmd_gpio_cfg_list_all(const struct shell *shell, size_t argc, char **argv)
{
if (argc != 1) {
shell_warn(shell, "Help: platform gpio list_all");
return;
}
for (int gpio_idx = 0; gpio_idx < GPIO_CFG_SIZE; gpio_idx++)
gpio_access_cfg(shell, gpio_idx, GPIO_READ, NULL);
return;
}
static void cmd_gpio_cfg_get(const struct shell *shell, size_t argc, char **argv)
{
if (argc != 2) {
shell_warn(shell, "Help: platform gpio get <gpio_idx>");
return;
}
int gpio_index = strtol(argv[1], NULL, 10);
if (gpio_access_cfg(shell, gpio_index, GPIO_READ, NULL))
shell_error(shell, "gpio[%d] get failed!", gpio_index);
return;
}
static void cmd_gpio_cfg_set_val(const struct shell *shell, size_t argc, char **argv)
{
if (argc != 3) {
shell_warn(shell, "Help: platform gpio set val <gpio_idx> <data>");
return;
}
int gpio_index = strtol(argv[1], NULL, 10);
int data = strtol(argv[2], NULL, 10);
if (gpio_access_cfg(shell, gpio_index, GPIO_WRITE, &data))
shell_error(shell, "gpio[%d] --> %d ,failed!", gpio_index, data);
else
shell_print(shell, "gpio[%d] --> %d ,success!", gpio_index, data);
return;
}
static void cmd_gpio_cfg_set_int_type(const struct shell *shell, size_t argc, char **argv)
{
if (argc != 3) {
shell_warn(shell, "Help: platform gpio set int_type <gpio_idx> <type>");
shell_warn(
shell,
" type: [0]disable [1]edge-rise [2]edge-fall [3]edge-both [4]low [5]high");
return;
}
int gpio_index = strtol(argv[1], NULL, 10);
int type_idx = strtol(argv[2], NULL, 10);
if (type_idx >= ARRAY_SIZE(int_type_table) || type_idx < 0) {
shell_error(shell, "Wrong index of type!");
shell_warn(
shell,
"type: [0]disable [1]edge-rise [2]edge-fall [3]edge-both [4]low [5]high");
return;
}
if (gpio_interrupt_conf(gpio_index, int_type_table[type_idx]))
shell_error(shell, "gpio[%d] --> type[%d] failed!", gpio_index, type_idx);
else
shell_print(shell, "gpio[%d] --> type[%d] success!", gpio_index, type_idx);
return;
}
static void cmd_gpio_muti_fn_ctl_list(const struct shell *shell, size_t argc, char **argv)
{
if (argc != 1) {
shell_warn(shell, "Help: platform gpio multifnctl");
return;
}
printf("[ REG ] hi lo\n");
for (int lst_idx = 0; lst_idx < ARRAY_SIZE(GPIO_MULTI_FUNC_PIN_CTL_REG_ACCESS); lst_idx++) {
uint32_t cur_status = sys_read32(GPIO_MULTI_FUNC_PIN_CTL_REG_ACCESS[lst_idx]);
printf("[0x%x]", GPIO_MULTI_FUNC_PIN_CTL_REG_ACCESS[lst_idx]);
for (int i = 32; i > 0; i--) {
if (!(i % 4))
printf(" ");
if (!(i % 8))
printf(" ");
printf("%d", (int)GET_BIT_VAL(cur_status, i - 1));
}
printf("\n");
}
shell_print(shell, "\n");
}
/*
Command SENSOR
*/
static void cmd_sensor_cfg_list_all(const struct shell *shell, size_t argc, char **argv)
{
if (argc != 1) {
shell_warn(shell, "Help: platform sensor list_all");
return;
}
shell_print(
shell,
"---------------------------------------------------------------------------------");
for (int sen_idx = 0; sen_idx < SDR_NUM; sen_idx++)
sensor_access(shell, sensor_config[sen_idx].num, SENSOR_READ);
shell_print(
shell,
"---------------------------------------------------------------------------------");
}
static void cmd_sensor_cfg_get(const struct shell *shell, size_t argc, char **argv)
{
if (argc != 2) {
shell_warn(shell, "Help: platform sensor get <sensor_num>");
return;
}
int sen_num = strtol(argv[1], NULL, 16);
sensor_access(shell, sen_num, SENSOR_READ);
}
/*********************************************************************************************************
* COMMAND DECLARE SECTION
**********************************************************************************************************/
/* GPIO sub command */
static void device_gpio_name_get(size_t idx, struct shell_static_entry *entry)
{
const struct device *dev = shell_device_lookup(idx, GPIO_DEVICE_PREFIX);
entry->syntax = (dev != NULL) ? dev->name : NULL;
entry->handler = NULL;
entry->help = NULL;
entry->subcmd = NULL;
}
SHELL_DYNAMIC_CMD_CREATE(gpio_device_name, device_gpio_name_get);
SHELL_STATIC_SUBCMD_SET_CREATE(sub_gpio_set_cmds,
SHELL_CMD(val, NULL, "Set pin value.", cmd_gpio_cfg_set_val),
SHELL_CMD(int_type, NULL, "Set interrupt pin type.",
cmd_gpio_cfg_set_int_type),
SHELL_SUBCMD_SET_END);
SHELL_STATIC_SUBCMD_SET_CREATE(
sub_gpio_cmds,
SHELL_CMD(list_group, &gpio_device_name, "List all GPIO config from certain group.",
cmd_gpio_cfg_list_group),
SHELL_CMD(list_all, NULL, "List all GPIO config.", cmd_gpio_cfg_list_all),
SHELL_CMD(get, NULL, "Get GPIO config", cmd_gpio_cfg_get),
SHELL_CMD(set, &sub_gpio_set_cmds, "Set GPIO config", NULL),
SHELL_CMD(multifnctl, NULL, "List all GPIO multi-function control regs.",
cmd_gpio_muti_fn_ctl_list),
SHELL_SUBCMD_SET_END);
/* Sensor sub command */
SHELL_STATIC_SUBCMD_SET_CREATE(sub_sensor_cmds,
SHELL_CMD(list_all, NULL, "List all SENSOR config.",
cmd_sensor_cfg_list_all),
SHELL_CMD(get, NULL, "Get SENSOR config", cmd_sensor_cfg_get),
SHELL_SUBCMD_SET_END);
/* MAIN command */
SHELL_STATIC_SUBCMD_SET_CREATE(sub_platform_cmds,
SHELL_CMD(note, NULL, "Note list.", cmd_info_print),
SHELL_CMD(gpio, &sub_gpio_cmds, "GPIO relative command.", NULL),
SHELL_CMD(sensor, &sub_sensor_cmds, "SENSOR relative command.",
NULL),
SHELL_SUBCMD_SET_END);
SHELL_CMD_REGISTER(platform, &sub_platform_cmds, "Platform commands", NULL);