更新模板到最新状态
This commit is contained in:
@@ -5,4 +5,8 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "${CMAKE_SOURCE_DIR}/app")
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "${CMAKE_SOURCE_DIR}/sal")
|
||||
|
||||
project(project)
|
||||
|
||||
18
app/CMakeLists.txt
Normal file
18
app/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
list(APPEND incs ".")
|
||||
list(APPEND incs "../components/system/include")
|
||||
list(APPEND incs "../components/system/source")
|
||||
list(APPEND incs "../components/system/source/k_kit")
|
||||
list(APPEND incs "../components/system/source/shell")
|
||||
|
||||
list(APPEND srcs "../app/app_main.c")
|
||||
list(APPEND srcs "../app/console.c")
|
||||
list(APPEND srcs "../app/drivers/data_port/sb_data_port.c")
|
||||
list(APPEND srcs "../app/drivers/data_port/uart/uart_port.c")
|
||||
list(APPEND srcs "../app/button/button_event.c")
|
||||
list(APPEND srcs "../app/config/board_config.c")
|
||||
|
||||
idf_component_register(
|
||||
INCLUDE_DIRS ${incs}
|
||||
SRCS ${srcs}
|
||||
REQUIRES driver nvs_flash
|
||||
)
|
||||
@@ -47,7 +47,7 @@ void work_app_main(void *arg)
|
||||
SYS_LOG_INF("app start");
|
||||
vset_init(&g_uart_handle_vt100, _vset_cb);
|
||||
os_thread_sleep(100);
|
||||
shell_start();
|
||||
shell_start(NULL);
|
||||
}
|
||||
|
||||
static void _init_nvs(void)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "driver/uart.h"
|
||||
#include "console.h"
|
||||
#include "shell/sh.h"
|
||||
#include "shell/sh_vset.h"
|
||||
#include "os/os.h"
|
||||
#include "drivers/chip/uart.h"
|
||||
#include "config/board_config.h"
|
||||
@@ -83,7 +84,7 @@ static int _port_sh_vprint_fn(const char *format, va_list va)
|
||||
* 1. 执行对应的初始化
|
||||
* 2. 自动默认工作队列中创建一个解析数据的后台
|
||||
*/
|
||||
void shell_start(void)
|
||||
void shell_start(void *arg)
|
||||
{
|
||||
static uint8_t start_flag = 0;
|
||||
|
||||
@@ -94,6 +95,7 @@ void shell_start(void)
|
||||
|
||||
/* 执行 shell 内部的初始化 */
|
||||
sh_register_external(_port_sh_vprint_fn);
|
||||
vset_init(&g_uart_handle_vt100, arg);
|
||||
|
||||
/* 注册系统命令 */
|
||||
extern void soc_shell_register(void);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
typedef void (*shell_input_cb)(sh_t *sh_hdl, char c);
|
||||
|
||||
void shell_start();
|
||||
void shell_start(void *arg);
|
||||
|
||||
void shell_input_set(shell_input_cb cb);
|
||||
void shell_input_restore(void);
|
||||
|
||||
251
app/drivers/ws2812_spi/ws2812_spi.c
Executable file
251
app/drivers/ws2812_spi/ws2812_spi.c
Executable file
@@ -0,0 +1,251 @@
|
||||
/**
|
||||
* @file ws2812_spi.c
|
||||
* @author your name (you@domain.com)
|
||||
* @brief 通过 SPI 硬件模拟 PWM 信号,驱动 WS2812 的程序
|
||||
* @version 0.1
|
||||
* @date 2023-10-05
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
|
||||
#include "ws2812_spi.h"
|
||||
#include "drivers/pin_io/pin_io.h"
|
||||
|
||||
#include "os/os.h"
|
||||
|
||||
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF
|
||||
#define SYS_LOG_DOMAIN "LED_STRIP_SPI"
|
||||
#include "sys_log.h"
|
||||
|
||||
#define SPI_CLK_HZ 8000000
|
||||
#define WS_HIGH 0x3
|
||||
#define WS_LOW 0x3F
|
||||
#define WS_RESET ~0
|
||||
#define RESET_TIME_US 50
|
||||
#define RESET_BIT_LENGTH (SPI_CLK_HZ * (RESET_TIME_US) / 1000000)
|
||||
#define _POW_Y 1.3
|
||||
|
||||
static struct
|
||||
{
|
||||
os_mutex_t mutex_hdl;
|
||||
} s_cm;
|
||||
|
||||
/**
|
||||
* @brief 初始化工作环境。这将初始化 SPI 驱动并申请显示缓存到对象中。可重初始化
|
||||
*
|
||||
* @param led_strip[out] 灯带驱动对象
|
||||
* @param spi_host SPI peripheral that controls this bus @ref spi_host_device_t
|
||||
* @param max_led_num 最大可驱动灯条共多少个灯珠
|
||||
*/
|
||||
void ws2812_spi_led_strip_init(ws2812_spi_led_strip_t *led_strip, uint8_t spi_host, uint16_t max_led_num)
|
||||
{
|
||||
static spi_device_handle_t s_spi_hdl;
|
||||
|
||||
SYS_ASSERT(max_led_num > 0, "");
|
||||
|
||||
if (led_strip->led_dma_buffer)
|
||||
{
|
||||
heap_caps_free(led_strip->led_dma_buffer);
|
||||
led_strip->led_dma_buffer = NULL;
|
||||
|
||||
spi_bus_remove_device(led_strip->spi_handle);
|
||||
|
||||
spi_bus_free(led_strip->spi_host);
|
||||
}
|
||||
|
||||
int max_transfer_sz = max_led_num * 24 + RESET_BIT_LENGTH * 2;
|
||||
|
||||
if (s_spi_hdl == NULL)
|
||||
{
|
||||
esp_err_t ret;
|
||||
spi_bus_config_t buscfg = {
|
||||
.miso_io_num = -1,
|
||||
.mosi_io_num = -1,
|
||||
.sclk_io_num = -1,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = max_transfer_sz};
|
||||
|
||||
// Initialize the SPI bus
|
||||
ret = spi_bus_initialize(spi_host, &buscfg, SPI_DMA_CH_AUTO);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.clock_speed_hz = SPI_CLK_HZ,
|
||||
.mode = 0,
|
||||
.spics_io_num = -1,
|
||||
.queue_size = 1,
|
||||
.pre_cb = NULL,
|
||||
.command_bits = 0,
|
||||
.address_bits = 0};
|
||||
// Attach the LCD to the SPI bus
|
||||
ret = spi_bus_add_device(spi_host, &devcfg, &s_spi_hdl);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
}
|
||||
|
||||
if (!os_mutex_is_valid(&s_cm.mutex_hdl))
|
||||
{
|
||||
os_mutex_create(&s_cm.mutex_hdl);
|
||||
}
|
||||
|
||||
led_strip->led_dma_buffer = heap_caps_malloc(max_transfer_sz, MALLOC_CAP_DMA); // Critical to be DMA memory.
|
||||
memset(led_strip->led_dma_buffer, WS_RESET, max_transfer_sz);
|
||||
led_strip->buffer_size = max_transfer_sz;
|
||||
led_strip->spi_host = spi_host;
|
||||
led_strip->spi_pin = -1;
|
||||
led_strip->spi_handle = s_spi_hdl;
|
||||
led_strip->max_led_num = max_led_num;
|
||||
float max = pow(0x100, _POW_Y) / 0x100;
|
||||
for (int i = 0; i < 0x100; i++)
|
||||
{
|
||||
led_strip->pow_tbl[i] = (int)(pow(i, _POW_Y) / max) + 1;
|
||||
if (led_strip->pow_tbl[i] > 0xFF)
|
||||
{
|
||||
led_strip->pow_tbl[i] = 0xFF;
|
||||
}
|
||||
}
|
||||
led_strip->pow_tbl[0] = 0;
|
||||
|
||||
/* 使所有数据合法化 */
|
||||
ws2812_spi_led_strip_clear(led_strip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 使所有显存清零。注意需要通过 ws2812_spi_led_strip_refresh() 方可把数据刷新到灯带中。
|
||||
*
|
||||
* @param led_strip 灯带驱动对象
|
||||
*/
|
||||
void ws2812_spi_led_strip_clear(ws2812_spi_led_strip_t *led_strip)
|
||||
{
|
||||
if (led_strip->led_dma_buffer == NULL)
|
||||
{
|
||||
SYS_LOG_WRN("led strip buffer is null");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(led_strip->led_dma_buffer, WS_RESET, led_strip->buffer_size);
|
||||
for (int i = 0; i < led_strip->max_led_num; i++)
|
||||
{
|
||||
ws2812_spi_led_strip_set_pixel(led_strip, i, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设一个灯珠为一个像素,设置单个像素的颜色。注意需要通过 ws2812_spi_led_strip_refresh() 方可把数据刷新到灯带中。
|
||||
*
|
||||
* @param led_strip 灯带驱动对象
|
||||
* @param index 灯像素序号,0 .. led_strip->max_led_num - 1
|
||||
* @param red 红基色亮度,0 .. 255
|
||||
* @param green 绿基色亮度,0 .. 255
|
||||
* @param blue 蓝基色亮度,0 .. 255
|
||||
*/
|
||||
void ws2812_spi_led_strip_set_pixel(ws2812_spi_led_strip_t *led_strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue)
|
||||
{
|
||||
if (led_strip->led_dma_buffer == NULL)
|
||||
{
|
||||
SYS_LOG_WRN("led strip buffer is null");
|
||||
return;
|
||||
}
|
||||
|
||||
if (index > led_strip->max_led_num)
|
||||
{
|
||||
SYS_LOG_WRN("index: %u > led_strip->max_led_num: %u", index, led_strip->max_led_num);
|
||||
return;
|
||||
}
|
||||
|
||||
if (red > 255 || green > 255 || blue > 255)
|
||||
{
|
||||
SYS_LOG_WRN("param over range");
|
||||
return;
|
||||
}
|
||||
|
||||
/* 套指数表 */
|
||||
red = led_strip->pow_tbl[red];
|
||||
green = led_strip->pow_tbl[green];
|
||||
blue = led_strip->pow_tbl[blue];
|
||||
uint32_t color = (green & 0xFF) << 16 | (red & 0xFF) << 8 | (blue & 0xFF);
|
||||
|
||||
/* PWM 编码 */
|
||||
for (int i = 0; i < 24; i++)
|
||||
{
|
||||
int pos = RESET_BIT_LENGTH + index * 24 + i;
|
||||
led_strip->led_dma_buffer[pos] = ((color << i) & 0x800000) ? WS_HIGH : WS_LOW;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行把显示缓存刷新到灯带
|
||||
*
|
||||
* @param led_strip 灯带驱动对象
|
||||
* @param leds 实际刷新的灯珠数
|
||||
* @param pin 使用的引脚
|
||||
* @retval 0 操作成功
|
||||
* @retval != 0 操作失败
|
||||
*/
|
||||
int ws2812_spi_led_strip_refresh(ws2812_spi_led_strip_t *led_strip, uint32_t leds, uint8_t pin)
|
||||
{
|
||||
if (led_strip == NULL || led_strip->spi_handle == NULL)
|
||||
{
|
||||
SYS_LOG_ERR("led strip spi handler is null");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (leds > led_strip->max_led_num)
|
||||
{
|
||||
SYS_LOG_WRN("leds > led_strip->max_led_num");
|
||||
leds = led_strip->max_led_num;
|
||||
}
|
||||
|
||||
os_mutex_lock(&s_cm.mutex_hdl, OS_WAIT_FOREVER);
|
||||
|
||||
uint32_t empty_bytes = (led_strip->max_led_num - leds) * 24;
|
||||
if (empty_bytes)
|
||||
{
|
||||
memset(&led_strip->led_dma_buffer[led_strip->buffer_size - empty_bytes], WS_RESET, empty_bytes);
|
||||
}
|
||||
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.length = led_strip->buffer_size * 8 - empty_bytes; // length is in bits
|
||||
t.tx_buffer = led_strip->led_dma_buffer;
|
||||
|
||||
if (led_strip->spi_pin != pin)
|
||||
{
|
||||
if (led_strip->spi_pin > 0)
|
||||
{
|
||||
cfg_board_pin_io_t cfg_pin = {.pin = led_strip->spi_pin, .en_lev = 1};
|
||||
pin_cfg_output(&cfg_pin);
|
||||
pin_set_valid(&cfg_pin, true);
|
||||
}
|
||||
|
||||
if (pin > 0)
|
||||
{
|
||||
cfg_board_pin_io_t cfg_pin = {.pin = pin, .en_lev = 1};
|
||||
pin_cfg_output(&cfg_pin);
|
||||
gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT);
|
||||
esp_rom_gpio_connect_out_signal(pin, spi_periph_signal[led_strip->spi_host].spid_out, true, false);
|
||||
}
|
||||
led_strip->spi_pin = pin;
|
||||
}
|
||||
|
||||
esp_err_t err = spi_device_transmit(led_strip->spi_handle, &t);
|
||||
|
||||
os_mutex_unlock(&s_cm.mutex_hdl);
|
||||
|
||||
ESP_ERROR_CHECK(err);
|
||||
return err;
|
||||
}
|
||||
32
app/drivers/ws2812_spi/ws2812_spi.h
Executable file
32
app/drivers/ws2812_spi/ws2812_spi.h
Executable file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @file ws2812_spi.h
|
||||
* @author Azol
|
||||
* @brief 通过 SPI 的 MOSI 引脚驱动灯带的程序
|
||||
* @version 0.1
|
||||
* @date 2023-09-28
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct ws2812_spi_led_strip_s
|
||||
{
|
||||
uint8_t *led_dma_buffer;
|
||||
uint32_t buffer_size;
|
||||
uint8_t spi_host;
|
||||
int16_t spi_pin;
|
||||
void *spi_handle;
|
||||
uint32_t max_led_num;
|
||||
uint16_t pow_tbl[0x100];
|
||||
} ws2812_spi_led_strip_t;
|
||||
|
||||
void ws2812_spi_led_strip_init(ws2812_spi_led_strip_t *led_strip, uint8_t spi_host, uint16_t max_led_num);
|
||||
|
||||
void ws2812_spi_led_strip_clear(ws2812_spi_led_strip_t *led_strip);
|
||||
void ws2812_spi_led_strip_set_pixel(ws2812_spi_led_strip_t *led_strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue);
|
||||
int ws2812_spi_led_strip_refresh(ws2812_spi_led_strip_t *led_strip, uint32_t leds, uint8_t pin);
|
||||
95
app/drivers/ws2812_spi/ws2812_spi_shell.c
Normal file
95
app/drivers/ws2812_spi/ws2812_spi_shell.c
Normal file
@@ -0,0 +1,95 @@
|
||||
#include "ws2812_spi_shell.h"
|
||||
#include "ws2812_spi.h"
|
||||
#include "shell/sh.h"
|
||||
#include "sh_vset.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static ws2812_spi_led_strip_t *s_led_strip;
|
||||
static uint32_t s_value;
|
||||
|
||||
SH_CMD_FN(set);
|
||||
SH_CMD_FN(clr);
|
||||
|
||||
SH_DEF_SUB_CMD(
|
||||
sub_led,
|
||||
SH_SETUP_CMD("set", "点亮灯珠 <引脚号> <灯珠号> [红] [绿] [蓝]", set, NULL), //
|
||||
SH_SETUP_CMD("clr", "熄灭全部灯珠 <引脚号>", clr, NULL), //
|
||||
);
|
||||
|
||||
SH_DEF_CMD(
|
||||
_register_cmd,
|
||||
SH_SETUP_CMD("led", "操作灯带驱动", NULL, sub_led), //
|
||||
);
|
||||
|
||||
void ws2812_spi_shell_register(ws2812_spi_led_strip_t *led_strip)
|
||||
{
|
||||
s_led_strip = led_strip;
|
||||
sh_register_cmd(&_register_cmd);
|
||||
}
|
||||
|
||||
void ws2812_spi_shell_unregister(void)
|
||||
{
|
||||
sh_unregister_cmd(&_register_cmd);
|
||||
}
|
||||
|
||||
static int _set_value(const char *argv[]) { return SET_VAR(&s_value, 0, 0x100); }
|
||||
|
||||
SH_CMD_FN(set)
|
||||
{
|
||||
uint32_t pin = 0, index = 0, red = 0, green = 0, blue = 0;
|
||||
if (argc < 2)
|
||||
{
|
||||
sh_echo(sh_hdl, "输入少于 2 个参数\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc >= 1 && _set_value(&argv[0]))
|
||||
return -1;
|
||||
pin = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
if (argc >= 2 && _set_value(&argv[1]))
|
||||
return -1;
|
||||
index = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
if (argc >= 3 && _set_value(&argv[2]))
|
||||
return -1;
|
||||
red = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
if (argc >= 4 && _set_value(&argv[3]))
|
||||
return -1;
|
||||
green = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
if (argc >= 5 && _set_value(&argv[4]))
|
||||
return -1;
|
||||
blue = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
ws2812_spi_led_strip_set_pixel(s_led_strip, index, red, green, blue);
|
||||
#if (CONFIG_LED_STRIP_MAX_LEDS)
|
||||
ws2812_spi_led_strip_refresh(s_led_strip, CONFIG_LED_STRIP_MAX_LEDS, pin);
|
||||
#else
|
||||
ws2812_spi_led_strip_refresh(s_led_strip, 126, pin);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
SH_CMD_FN(clr)
|
||||
{
|
||||
uint32_t pin = 0;
|
||||
if (argc < 1)
|
||||
{
|
||||
sh_echo(sh_hdl, "输入少于 1 个参数\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
_set_value(&argv[0]);
|
||||
pin = *(volatile __typeof(s_value) *)&s_value;
|
||||
|
||||
ws2812_spi_led_strip_clear(s_led_strip);
|
||||
#if (CONFIG_LED_STRIP_MAX_LEDS)
|
||||
ws2812_spi_led_strip_refresh(s_led_strip, CONFIG_LED_STRIP_MAX_LEDS, pin);
|
||||
#else
|
||||
ws2812_spi_led_strip_refresh(s_led_strip, 126, pin);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
6
app/drivers/ws2812_spi/ws2812_spi_shell.h
Normal file
6
app/drivers/ws2812_spi/ws2812_spi_shell.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "ws2812_spi.h"
|
||||
|
||||
void ws2812_spi_shell_register(ws2812_spi_led_strip_t *led_strip);
|
||||
void ws2812_spi_strip_shell_unregister(void);
|
||||
BIN
app/drivers/ws2812_spi/ws2812b中文资料-数据手册-参数.pdf
Executable file
BIN
app/drivers/ws2812_spi/ws2812b中文资料-数据手册-参数.pdf
Executable file
Binary file not shown.
11
components/CMakeLists.txt
Normal file
11
components/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
list(APPEND incs "system/include")
|
||||
|
||||
list(APPEND srcs "system/source/k_kit/k_kit.c")
|
||||
list(APPEND srcs "system/source/shell/sh_vt100.c")
|
||||
list(APPEND srcs "system/source/shell/sh_vset.c")
|
||||
list(APPEND srcs "system/source/shell/sh.c")
|
||||
|
||||
idf_component_register(
|
||||
INCLUDE_DIRS ${incs}
|
||||
SRCS ${srcs}
|
||||
)
|
||||
@@ -21,15 +21,6 @@ void drv_misc_busy_wait(unsigned us);
|
||||
*/
|
||||
unsigned *drv_misc_bitband(void *mem);
|
||||
|
||||
/**
|
||||
* @brief 读取 MCU 身份信息的 MD5 值
|
||||
*
|
||||
* @param out[out] 输出
|
||||
* @retval 0 成功
|
||||
* @retval -1 失败
|
||||
*/
|
||||
int drv_misc_read_id_md5(unsigned char out[16]);
|
||||
|
||||
/**
|
||||
* @brief 设置中断向量地址
|
||||
*
|
||||
@@ -44,22 +35,6 @@ void drv_misc_set_vector(void *vector);
|
||||
*/
|
||||
void *drv_misc_get_vector(void);
|
||||
|
||||
/**
|
||||
* @brief 根据具体平台,以尽可能快的速度把内存置0
|
||||
*
|
||||
* @param src 内存地址
|
||||
* @param len 内存长度
|
||||
*/
|
||||
void mem_reset(void *src, unsigned len);
|
||||
|
||||
/**
|
||||
* @brief 根据具体平台,以尽可能快的速度复制内存数据
|
||||
*
|
||||
* @param dest[out] 目录内存
|
||||
* @param src 源内存
|
||||
* @param len 长度
|
||||
*/
|
||||
void mem_cpy(void *dest, const void *src, unsigned len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ typedef struct
|
||||
|
||||
typedef void (*os_work_fn)(void *arg);
|
||||
|
||||
os_state os_work_create_default(os_work_t *work_handle, const char *name, os_work_fn work_route, void *arg, uint8_t sub_prior, os_time_t delay_ms);
|
||||
os_state os_work_create(os_work_t *work_handle, const char *name, os_work_fn work_route, void *arg, uint8_t sub_prior);
|
||||
void os_work_delete(os_work_t *work_handle);
|
||||
|
||||
|
||||
@@ -194,6 +194,18 @@
|
||||
#define _DLIST_SET(Value1, Value2) (Value1 = (__list_node_t)Value2)
|
||||
#define _DLIST_GET(Value) ((__dlist_node_t *)(Value))
|
||||
|
||||
#define _TEST_HANDLE(HANDLE, RETURN) \
|
||||
if (HANDLE == NULL) \
|
||||
{ \
|
||||
_DBG_WRN(#HANDLE " nul"); \
|
||||
RETURN; \
|
||||
} \
|
||||
if (*(void **)HANDLE == NULL) \
|
||||
{ \
|
||||
_DBG_WRN(#HANDLE " invalid"); \
|
||||
RETURN; \
|
||||
}
|
||||
|
||||
typedef void *__list_node_t;
|
||||
|
||||
typedef struct
|
||||
@@ -1172,20 +1184,15 @@ static void _k_work_log(void *arg)
|
||||
*/
|
||||
static void _k_work_do_submit(k_work_q_t *work_q_handle, k_work_t *work_handle, k_tick_t timeout, bool wait_forever)
|
||||
{
|
||||
k_work_handle_t *work = work_handle->hdl;
|
||||
k_work_q_handle_t *work_q = work_q_handle->hdl;
|
||||
k_work_handle_t *work;
|
||||
k_work_q_handle_t *work_q;
|
||||
int resume_flag = 1;
|
||||
|
||||
if (work_handle == NULL || work == NULL)
|
||||
{
|
||||
_DBG_WRN("work_handle invalid");
|
||||
return;
|
||||
}
|
||||
if (work_q_handle == NULL || work_q == NULL)
|
||||
{
|
||||
_DBG_WRN("work_q_handle invalid");
|
||||
return;
|
||||
}
|
||||
_TEST_HANDLE(work_q_handle, return);
|
||||
_TEST_HANDLE(work_handle, return);
|
||||
|
||||
work = work_handle->hdl;
|
||||
work_q = work_q_handle->hdl;
|
||||
|
||||
if (wait_forever)
|
||||
{
|
||||
@@ -1294,11 +1301,10 @@ static void _k_timer_end(k_work_q_t *work_q_handle, k_work_handle_t *exec_work)
|
||||
{
|
||||
if (exec_work->obj_flag_auto_del)
|
||||
{
|
||||
k_work_t work_handle;
|
||||
|
||||
work_handle.hdl = exec_work;
|
||||
exec_work->work_handle = &work_handle;
|
||||
k_work_t work_handle = {.hdl = exec_work};
|
||||
exec_work->exec_flag = 0;
|
||||
k_work_delete(&work_handle);
|
||||
exec_work->work_handle = NULL;
|
||||
}
|
||||
else if (exec_work->obj_flag_periodic)
|
||||
{
|
||||
@@ -1368,18 +1374,12 @@ k_tick_t k_work_q_handler(k_work_q_t *work_q_handle)
|
||||
k_work_t *last_work;
|
||||
k_tick_t ret;
|
||||
|
||||
if (s_kit_init_struct.malloc == NULL)
|
||||
if (s_kit_init_struct.malloc == NULL || work_q_handle == NULL || work_q_handle->hdl == NULL)
|
||||
{
|
||||
return -1u;
|
||||
}
|
||||
|
||||
work_q = work_q_handle->hdl;
|
||||
|
||||
if (work_q == NULL)
|
||||
{
|
||||
return -1u;
|
||||
}
|
||||
|
||||
last_work = work_q->curr_work;
|
||||
|
||||
if (last_work != NULL)
|
||||
@@ -1396,6 +1396,7 @@ k_tick_t k_work_q_handler(k_work_q_t *work_q_handle)
|
||||
exec_work = _k_work_q_handler_take_ready_work(work_q_handle);
|
||||
if (exec_work != NULL)
|
||||
{
|
||||
uint8_t exec_flag = exec_work->exec_flag;
|
||||
exec_work->exec_flag = 1;
|
||||
|
||||
if (exec_work->obj_flag_type)
|
||||
@@ -1423,11 +1424,11 @@ k_tick_t k_work_q_handler(k_work_q_t *work_q_handle)
|
||||
}
|
||||
work_q->curr_work = last_work;
|
||||
|
||||
if (k_work_is_valid(exec_work->work_handle))
|
||||
{
|
||||
if (exec_work->delete_flag == 0)
|
||||
{
|
||||
_ASSERT_FALSE(!k_work_is_valid(exec_work->work_handle), "exec_work->work_handle maybe be deleted");
|
||||
|
||||
exec_work->exec_flag = 0;
|
||||
exec_work->exec_flag = exec_flag;
|
||||
if (exec_work->obj_flag_type == 0 && exec_work->obj_data.mbox_list != NULL)
|
||||
{
|
||||
if (_slist_peek_head(&exec_work->obj_data.mbox_list->mbox_idle) != NULL)
|
||||
@@ -1440,10 +1441,12 @@ k_tick_t k_work_q_handler(k_work_q_t *work_q_handle)
|
||||
}
|
||||
else
|
||||
{
|
||||
exec_work->exec_flag = 0;
|
||||
k_work_delete(exec_work->work_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exec_work = NULL;
|
||||
@@ -1558,7 +1561,7 @@ void k_work_q_delete(k_work_q_t *work_q_handle)
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
|
||||
_K_DIS_SCHED();
|
||||
if (work_q_handle->hdl != NULL)
|
||||
if (work_q_handle != NULL && work_q_handle->hdl != NULL)
|
||||
{
|
||||
k_work_q_handle_t *work_q = work_q_handle->hdl;
|
||||
|
||||
@@ -1659,7 +1662,11 @@ bool k_work_q_is_valid(k_work_q_t *work_q_handle)
|
||||
*/
|
||||
void k_work_hook(k_work_q_t *work_q_handle, k_work_fn hook)
|
||||
{
|
||||
k_work_q_handle_t *work_q = work_q_handle->hdl;
|
||||
k_work_q_handle_t *work_q;
|
||||
|
||||
_TEST_HANDLE(work_q_handle, return);
|
||||
|
||||
work_q = work_q_handle->hdl;
|
||||
work_q->hook_entry = hook;
|
||||
}
|
||||
|
||||
@@ -1671,7 +1678,11 @@ void k_work_hook(k_work_q_t *work_q_handle, k_work_fn hook)
|
||||
*/
|
||||
bool k_work_q_delayed_state(k_work_q_t *work_q_handle)
|
||||
{
|
||||
k_work_q_handle_t *work_q = work_q_handle->hdl;
|
||||
k_work_q_handle_t *work_q;
|
||||
|
||||
_TEST_HANDLE(work_q_handle, return _FALSE);
|
||||
|
||||
work_q = work_q_handle->hdl;
|
||||
if (_dlist_peek_head(&work_q->event_list) != NULL)
|
||||
{
|
||||
return _TRUE;
|
||||
@@ -1785,6 +1796,8 @@ void k_work_delete(k_work_t *work_handle)
|
||||
_k_read_curr_handle(&work_q_handle, &work_handle);
|
||||
}
|
||||
|
||||
_TEST_HANDLE(work_handle, return);
|
||||
|
||||
_K_DIS_SCHED();
|
||||
k_work_handle_t *work = work_handle->hdl;
|
||||
if (work->exec_flag == 0)
|
||||
@@ -2061,6 +2074,7 @@ void k_work_sleep(k_tick_t delay_ticks)
|
||||
k_work_handle_t *exec_work = _k_work_q_handler_take_ready_work(_WORK->work_q_handle);
|
||||
if (exec_work != NULL)
|
||||
{
|
||||
uint8_t exec_flag = exec_work->exec_flag;
|
||||
exec_work->exec_flag = 1;
|
||||
|
||||
if (exec_work->obj_flag_type)
|
||||
@@ -2088,11 +2102,11 @@ void k_work_sleep(k_tick_t delay_ticks)
|
||||
}
|
||||
_WORK_Q->curr_work = work_handle;
|
||||
|
||||
if (k_work_is_valid(exec_work->work_handle))
|
||||
{
|
||||
if (exec_work->delete_flag == 0)
|
||||
{
|
||||
_ASSERT_FALSE(!k_work_is_valid(exec_work->work_handle), "exec_work->work_handle maybe be deleted");
|
||||
|
||||
exec_work->exec_flag = 0;
|
||||
exec_work->exec_flag = exec_flag;
|
||||
if (exec_work->obj_flag_type == 0 && exec_work->obj_data.mbox_list != NULL)
|
||||
{
|
||||
if (_slist_peek_head(&exec_work->obj_data.mbox_list->mbox_idle) != NULL)
|
||||
@@ -2105,10 +2119,12 @@ void k_work_sleep(k_tick_t delay_ticks)
|
||||
}
|
||||
else
|
||||
{
|
||||
exec_work->exec_flag = 0;
|
||||
k_work_delete(exec_work->work_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (work_handle->hdl == NULL)
|
||||
{
|
||||
@@ -2159,7 +2175,11 @@ void k_work_sleep(k_tick_t delay_ticks)
|
||||
*/
|
||||
k_work_t *k_get_curr_work_handle(k_work_q_t *work_q_handle)
|
||||
{
|
||||
k_work_q_handle_t *work_q = work_q_handle->hdl;
|
||||
k_work_q_handle_t *work_q;
|
||||
|
||||
_TEST_HANDLE(work_q_handle, return NULL);
|
||||
|
||||
work_q = work_q_handle->hdl;
|
||||
return work_q->curr_work;
|
||||
}
|
||||
|
||||
@@ -2181,9 +2201,10 @@ k_err_t k_work_mbox_create(k_work_t *work_handle)
|
||||
k_work_mb_list_t *mbox_list;
|
||||
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
_TEST_HANDLE(work_handle, return -1);
|
||||
|
||||
work = work_handle->hdl;
|
||||
if (work == NULL || work->obj_flag_type != 0)
|
||||
if (work->obj_flag_type != 0)
|
||||
{
|
||||
_DBG_WRN("work_handle invalid");
|
||||
return -1;
|
||||
@@ -2233,13 +2254,9 @@ void k_work_mbox_delete(k_work_t *work_handle)
|
||||
k_work_handle_t *work;
|
||||
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
_TEST_HANDLE(work_handle, return);
|
||||
|
||||
work = work_handle->hdl;
|
||||
if (work == NULL)
|
||||
{
|
||||
_DBG_WRN("work_handle invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
if (work->obj_flag_type != 0)
|
||||
{
|
||||
@@ -2283,13 +2300,9 @@ void *k_work_mbox_alloc(k_work_t *work_handle, size_t size)
|
||||
k_work_mb_handle_t *mbox_data;
|
||||
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
_TEST_HANDLE(work_handle, return NULL);
|
||||
|
||||
work = work_handle->hdl;
|
||||
if (work == NULL)
|
||||
{
|
||||
_DBG_WRN("work_handle invalid");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (work->work_q_handle == NULL)
|
||||
{
|
||||
@@ -2339,6 +2352,12 @@ k_err_t k_work_mbox_cancel(void *mbox)
|
||||
k_work_mb_handle_t *mbox_data = &((k_work_mb_handle_t *)mbox)[-1];
|
||||
k_err_t ret = 0;
|
||||
|
||||
if (mbox == NULL)
|
||||
{
|
||||
_DBG_WRN("mbox invalid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
k_work_handle_t *work = mbox_data->ctrl.work_handle->hdl;
|
||||
if (work == NULL)
|
||||
{
|
||||
@@ -2381,6 +2400,11 @@ k_err_t k_work_mbox_submit(void *mbox)
|
||||
k_work_handle_t *work = mbox_data->ctrl.work_handle->hdl;
|
||||
k_err_t ret = 0;
|
||||
|
||||
if (mbox == NULL)
|
||||
{
|
||||
_DBG_WRN("mbox invalid");
|
||||
return -1;
|
||||
}
|
||||
if (work == NULL)
|
||||
{
|
||||
_DBG_WRN("work_handle invalid");
|
||||
@@ -2670,12 +2694,7 @@ k_err_t k_timer_create(k_timer_t *timer_handle,
|
||||
uint8_t priority)
|
||||
{
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
|
||||
if (timer_q_handle == NULL || timer_q_handle->hdl == NULL)
|
||||
{
|
||||
_DBG_WRN("timer_q_handle invalid");
|
||||
return -1;
|
||||
}
|
||||
_TEST_HANDLE(timer_q_handle, return -1);
|
||||
|
||||
if (k_work_create((k_work_t *)timer_handle, "", (k_work_fn)timer_route, arg, priority) == 0)
|
||||
{
|
||||
@@ -2701,6 +2720,7 @@ k_err_t k_timer_create(k_timer_t *timer_handle,
|
||||
void k_timer_delete(k_timer_t *timer_handle)
|
||||
{
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
_TEST_HANDLE(timer_handle, return);
|
||||
|
||||
if (timer_handle == NULL)
|
||||
{
|
||||
@@ -2758,12 +2778,13 @@ void k_timer_set_period(k_timer_t *timer_handle, bool periodic, k_tick_t period)
|
||||
*/
|
||||
void k_timer_start(k_timer_t *timer_handle, k_tick_t delay_ticks)
|
||||
{
|
||||
k_work_handle_t *work = timer_handle->hdl;
|
||||
if (work)
|
||||
{
|
||||
k_work_handle_t *work;
|
||||
|
||||
_TEST_HANDLE(timer_handle, return);
|
||||
|
||||
work = timer_handle->hdl;
|
||||
_k_work_do_submit(work->work_q_handle, (k_work_t *)timer_handle, _K_PORT->get_sys_ticks() + delay_ticks, _FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 挂起定时器,定时器不会被删除
|
||||
@@ -2788,6 +2809,8 @@ k_err_t k_timer_newsubmit(k_timer_q_t *timer_q_handle, k_timer_fn timer_route, v
|
||||
{
|
||||
k_timer_t timer_handle;
|
||||
|
||||
_TEST_HANDLE(timer_q_handle, return -1);
|
||||
|
||||
memset(&timer_handle, 0, sizeof(timer_handle));
|
||||
|
||||
if (k_timer_create(
|
||||
@@ -2834,6 +2857,8 @@ void k_timer_cancel(k_timer_q_t *timer_q_handle, k_timer_fn timer_route)
|
||||
{
|
||||
k_work_q_handle_t *work_q;
|
||||
|
||||
_TEST_HANDLE(timer_q_handle, return);
|
||||
|
||||
_K_DIS_SCHED();
|
||||
|
||||
work_q = timer_q_handle->hdl;
|
||||
@@ -3012,7 +3037,11 @@ bool k_timer_is_periodic(k_timer_t *timer_handle)
|
||||
*/
|
||||
k_tick_t k_timer_get_period(k_timer_t *timer_handle)
|
||||
{
|
||||
k_work_handle_t *work = timer_handle->hdl;
|
||||
k_work_handle_t *work;
|
||||
|
||||
_TEST_HANDLE(timer_handle, return -1u);
|
||||
|
||||
work = timer_handle->hdl;
|
||||
return work->obj_data.period;
|
||||
}
|
||||
|
||||
@@ -3075,10 +3104,11 @@ void k_fifo_q_delete(k_fifo_t *fifo_handle)
|
||||
{
|
||||
k_fifo_q_handle_t *fifo_q;
|
||||
|
||||
_TEST_HANDLE(fifo_handle, return);
|
||||
|
||||
_K_DIS_SCHED();
|
||||
|
||||
fifo_q = fifo_handle->hdl;
|
||||
if (fifo_q != NULL)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
__slist_node_t *node = _slist_take_head(&fifo_q->list);
|
||||
@@ -3094,7 +3124,7 @@ void k_fifo_q_delete(k_fifo_t *fifo_handle)
|
||||
}
|
||||
_K_PORT->free(fifo_q);
|
||||
fifo_handle->hdl = NULL;
|
||||
}
|
||||
|
||||
_K_EN_SCHED();
|
||||
}
|
||||
|
||||
@@ -3108,11 +3138,11 @@ void k_fifo_q_clr(k_fifo_t *fifo_handle)
|
||||
k_fifo_q_handle_t *fifo_q;
|
||||
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
_TEST_HANDLE(fifo_handle, return);
|
||||
|
||||
_K_DIS_SCHED();
|
||||
|
||||
fifo_q = fifo_handle->hdl;
|
||||
if (fifo_q != NULL)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
__slist_node_t *node = _slist_take_head(&fifo_q->list);
|
||||
@@ -3126,7 +3156,7 @@ void k_fifo_q_clr(k_fifo_t *fifo_handle)
|
||||
_K_PORT->free(fifo_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_K_EN_SCHED();
|
||||
}
|
||||
|
||||
@@ -3159,13 +3189,14 @@ bool k_fifo_q_is_valid(k_fifo_t *fifo_handle)
|
||||
*/
|
||||
void k_fifo_q_regist(k_fifo_t *fifo_handle, k_work_t *work_handle, k_tick_t delay_ticks)
|
||||
{
|
||||
k_fifo_q_handle_t *fifo_q = fifo_handle->hdl;
|
||||
if (fifo_q != NULL)
|
||||
{
|
||||
k_fifo_q_handle_t *fifo_q;
|
||||
|
||||
_TEST_HANDLE(fifo_handle, return);
|
||||
|
||||
fifo_q = fifo_handle->hdl;
|
||||
fifo_q->resume_work = work_handle;
|
||||
fifo_q->resume_delay = delay_ticks;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取消注册任务
|
||||
@@ -3174,7 +3205,11 @@ void k_fifo_q_regist(k_fifo_t *fifo_handle, k_work_t *work_handle, k_tick_t dela
|
||||
*/
|
||||
void k_fifo_q_unregist(k_fifo_t *fifo_handle)
|
||||
{
|
||||
k_fifo_q_handle_t *fifo_q = fifo_handle->hdl;
|
||||
k_fifo_q_handle_t *fifo_q;
|
||||
|
||||
_TEST_HANDLE(fifo_handle, return);
|
||||
|
||||
fifo_q = fifo_handle->hdl;
|
||||
fifo_q->resume_work = NULL;
|
||||
}
|
||||
|
||||
@@ -3220,6 +3255,11 @@ k_err_t k_fifo_free(void *data)
|
||||
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
_DBG_WRN("data invalid");
|
||||
return -1;
|
||||
}
|
||||
fifo_data = &((k_fifo_handle_t *)data)[-1];
|
||||
|
||||
_K_DIS_SCHED();
|
||||
@@ -3251,17 +3291,22 @@ k_err_t k_fifo_free(void *data)
|
||||
*/
|
||||
k_err_t k_fifo_put(k_fifo_t *fifo_handle, void *data)
|
||||
{
|
||||
k_fifo_q_handle_t *fifo_q = fifo_handle->hdl;
|
||||
k_fifo_handle_t *fifo_data = &((k_fifo_handle_t *)data)[-1];
|
||||
bool resume_flag = false;
|
||||
k_fifo_q_handle_t *fifo_q;
|
||||
k_fifo_handle_t *fifo_data;
|
||||
bool resume_flag = _FALSE;
|
||||
|
||||
if (fifo_q == NULL)
|
||||
_TEST_HANDLE(fifo_handle, return -1);
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
_DBG_WRN("fifo_handle invalid");
|
||||
_DBG_WRN("data invalid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data == NULL || fifo_data->ctrl.free_flag != _K_FIFO_FREE)
|
||||
fifo_q = fifo_handle->hdl;
|
||||
fifo_data = &((k_fifo_handle_t *)data)[-1];
|
||||
|
||||
if (fifo_data->ctrl.free_flag != _K_FIFO_FREE)
|
||||
{
|
||||
_DBG_WRN("fifo_data invalid");
|
||||
return -1;
|
||||
@@ -3271,7 +3316,7 @@ k_err_t k_fifo_put(k_fifo_t *fifo_handle, void *data)
|
||||
_K_DIS_INT();
|
||||
if (_slist_peek_head(&fifo_q->list) == NULL)
|
||||
{
|
||||
resume_flag = true;
|
||||
resume_flag = _TRUE;
|
||||
}
|
||||
_slist_insert_tail(&fifo_q->list, &fifo_data->ctrl.state_node);
|
||||
_K_EN_INT();
|
||||
@@ -3292,14 +3337,12 @@ k_err_t k_fifo_put(k_fifo_t *fifo_handle, void *data)
|
||||
*/
|
||||
void *k_fifo_take(k_fifo_t *fifo_handle)
|
||||
{
|
||||
k_fifo_q_handle_t *fifo_q = fifo_handle->hdl;
|
||||
k_fifo_q_handle_t *fifo_q;
|
||||
__slist_node_t *node;
|
||||
|
||||
if (fifo_q == NULL)
|
||||
{
|
||||
_DBG_WRN("fifo_handle invalid");
|
||||
return NULL;
|
||||
}
|
||||
_TEST_HANDLE(fifo_handle, return NULL);
|
||||
|
||||
fifo_q = fifo_handle->hdl;
|
||||
|
||||
_K_DIS_INT();
|
||||
node = _slist_take_head(&fifo_q->list);
|
||||
@@ -3328,10 +3371,7 @@ void *k_fifo_peek_head(k_fifo_t *fifo_handle)
|
||||
k_fifo_q_handle_t *fifo_q;
|
||||
__slist_node_t *node;
|
||||
|
||||
if (fifo_handle->hdl == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
_TEST_HANDLE(fifo_handle, return NULL);
|
||||
|
||||
fifo_q = fifo_handle->hdl;
|
||||
node = _slist_peek_head(&fifo_q->list);
|
||||
@@ -3357,10 +3397,7 @@ void *k_fifo_peek_tail(k_fifo_t *fifo_handle)
|
||||
k_fifo_q_handle_t *fifo_q;
|
||||
__slist_node_t *node;
|
||||
|
||||
if (fifo_handle->hdl == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
_TEST_HANDLE(fifo_handle, return NULL);
|
||||
|
||||
fifo_q = fifo_handle->hdl;
|
||||
node = _slist_peek_tail(&fifo_q->list);
|
||||
@@ -3438,6 +3475,8 @@ void k_queue_delete(k_queue_t *queue_handle)
|
||||
{
|
||||
k_queue_handle_t *queue;
|
||||
|
||||
_TEST_HANDLE(queue_handle, return);
|
||||
|
||||
_K_DIS_SCHED();
|
||||
queue = queue_handle->hdl;
|
||||
if (queue != NULL)
|
||||
@@ -3459,6 +3498,7 @@ void k_queue_clr(k_queue_t *queue_handle)
|
||||
__slist_node_t *node;
|
||||
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
_TEST_HANDLE(queue_handle, return);
|
||||
|
||||
queue = queue_handle->hdl;
|
||||
if (queue != NULL)
|
||||
@@ -3510,13 +3550,14 @@ bool k_queue_is_valid(k_queue_t *queue_handle)
|
||||
*/
|
||||
void k_queue_regist(k_queue_t *queue_handle, k_work_t *work_handle, k_tick_t delay_ticks)
|
||||
{
|
||||
k_queue_handle_t *queue = queue_handle->hdl;
|
||||
if (queue != NULL)
|
||||
{
|
||||
k_queue_handle_t *queue;
|
||||
|
||||
_TEST_HANDLE(queue_handle, return);
|
||||
|
||||
queue = queue_handle->hdl;
|
||||
queue->resume_work = work_handle;
|
||||
queue->resume_delay = delay_ticks;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取消注册任务
|
||||
@@ -3525,7 +3566,11 @@ void k_queue_regist(k_queue_t *queue_handle, k_work_t *work_handle, k_tick_t del
|
||||
*/
|
||||
void k_queue_unregist(k_queue_t *queue_handle)
|
||||
{
|
||||
k_queue_handle_t *queue = queue_handle->hdl;
|
||||
k_queue_handle_t *queue;
|
||||
|
||||
_TEST_HANDLE(queue_handle, return);
|
||||
|
||||
queue = queue_handle->hdl;
|
||||
queue->resume_work = NULL;
|
||||
}
|
||||
|
||||
@@ -3588,16 +3633,13 @@ k_err_t k_queue_send(k_queue_t *queue_handle, const void *src)
|
||||
*/
|
||||
void *k_queue_alloc(k_queue_t *queue_handle)
|
||||
{
|
||||
k_queue_handle_t *queue = queue_handle->hdl;
|
||||
k_queue_handle_t *queue;
|
||||
__slist_node_t *node;
|
||||
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
_TEST_HANDLE(queue_handle, return NULL);
|
||||
|
||||
if (queue == NULL)
|
||||
{
|
||||
_DBG_WRN("queue_handle invalid");
|
||||
return NULL;
|
||||
}
|
||||
queue = queue_handle->hdl;
|
||||
|
||||
_K_DIS_INT();
|
||||
node = _slist_take_head(&queue->list_idle);
|
||||
@@ -3636,19 +3678,21 @@ k_err_t k_queue_free(void *data)
|
||||
}
|
||||
|
||||
queue_data = &((k_queue_data_t *)data)[-1];
|
||||
queue = (k_queue_handle_t *)queue_data->queue_handle->hdl;
|
||||
|
||||
if (queue == NULL)
|
||||
if (queue_data->queue_handle == NULL || queue_data->queue_handle->hdl == NULL)
|
||||
{
|
||||
_DBG_WRN("queue_handle invalid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (queue_data->ctrl.free_flag != _K_QUEUE_FREE)
|
||||
{
|
||||
_DBG_WRN("%p was freed", data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
queue = (k_queue_handle_t *)queue_data->queue_handle->hdl;
|
||||
|
||||
_slist_init_node(&queue_data->ctrl.state_node);
|
||||
_K_DIS_INT();
|
||||
_slist_insert_font(&queue->list_idle, &queue_data->ctrl.state_node);
|
||||
@@ -3667,7 +3711,7 @@ k_err_t k_queue_put(void *data)
|
||||
{
|
||||
k_queue_data_t *queue_data;
|
||||
k_queue_handle_t *queue;
|
||||
bool resume_flag = false;
|
||||
bool resume_flag = _FALSE;
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
@@ -3676,9 +3720,8 @@ k_err_t k_queue_put(void *data)
|
||||
}
|
||||
|
||||
queue_data = &((k_queue_data_t *)data)[-1];
|
||||
queue = (k_queue_handle_t *)queue_data->queue_handle->hdl;
|
||||
|
||||
if (queue == NULL)
|
||||
if (queue_data->queue_handle == NULL || queue_data->queue_handle->hdl == NULL)
|
||||
{
|
||||
_DBG_WRN("queue_handle invalid");
|
||||
return -1;
|
||||
@@ -3689,11 +3732,13 @@ k_err_t k_queue_put(void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
queue = (k_queue_handle_t *)queue_data->queue_handle->hdl;
|
||||
|
||||
_slist_init_node(&queue_data->ctrl.state_node);
|
||||
_K_DIS_INT();
|
||||
if (_slist_peek_head(&queue->list_valid) == NULL)
|
||||
{
|
||||
resume_flag = true;
|
||||
resume_flag = _TRUE;
|
||||
}
|
||||
_slist_insert_tail(&queue->list_valid, &queue_data->ctrl.state_node);
|
||||
_K_EN_INT();
|
||||
@@ -3714,14 +3759,12 @@ k_err_t k_queue_put(void *data)
|
||||
*/
|
||||
void *k_queue_take(k_queue_t *queue_handle)
|
||||
{
|
||||
k_queue_handle_t *queue = queue_handle->hdl;
|
||||
k_queue_handle_t *queue;
|
||||
__slist_node_t *node;
|
||||
|
||||
if (queue == NULL)
|
||||
{
|
||||
_DBG_WRN("queue_handle invalid");
|
||||
return NULL;
|
||||
}
|
||||
_TEST_HANDLE(queue_handle, return NULL);
|
||||
|
||||
queue = queue_handle->hdl;
|
||||
|
||||
_K_DIS_INT();
|
||||
node = _slist_take_head(&queue->list_valid);
|
||||
@@ -3750,10 +3793,7 @@ void *k_queue_peek_head(k_queue_t *queue_handle)
|
||||
k_queue_handle_t *queue;
|
||||
__slist_node_t *node;
|
||||
|
||||
if (queue_handle == NULL || queue_handle->hdl == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
_TEST_HANDLE(queue_handle, return NULL);
|
||||
|
||||
queue = queue_handle->hdl;
|
||||
node = _slist_peek_head(&queue->list_valid);
|
||||
@@ -3779,10 +3819,7 @@ void *k_queue_peek_tail(k_queue_t *queue_handle)
|
||||
k_queue_handle_t *queue;
|
||||
__slist_node_t *node;
|
||||
|
||||
if (queue_handle == NULL || queue_handle->hdl == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
_TEST_HANDLE(queue_handle, return NULL);
|
||||
|
||||
queue = queue_handle->hdl;
|
||||
node = _slist_peek_tail(&queue->list_valid);
|
||||
@@ -3827,10 +3864,7 @@ size_t k_queue_get_item_size(k_queue_t *queue_handle)
|
||||
{
|
||||
k_queue_handle_t *queue;
|
||||
|
||||
if (queue_handle == NULL || queue_handle->hdl == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
_TEST_HANDLE(queue_handle, return 0);
|
||||
|
||||
queue = queue_handle->hdl;
|
||||
return queue->item_size;
|
||||
@@ -3883,13 +3917,11 @@ k_err_t k_pipe_create(k_pipe_t *pipe_handle, size_t pipe_size)
|
||||
void k_pipe_delete(k_pipe_t *pipe_handle)
|
||||
{
|
||||
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
|
||||
_TEST_HANDLE(pipe_handle, return);
|
||||
|
||||
_K_DIS_SCHED();
|
||||
if (pipe_handle->hdl != NULL)
|
||||
{
|
||||
_K_PORT->free(pipe_handle->hdl);
|
||||
pipe_handle->hdl = NULL;
|
||||
}
|
||||
_K_EN_SCHED();
|
||||
}
|
||||
|
||||
@@ -3900,13 +3932,11 @@ void k_pipe_delete(k_pipe_t *pipe_handle)
|
||||
*/
|
||||
void k_pipe_clr(k_pipe_t *pipe_handle)
|
||||
{
|
||||
k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
k_pipe_handle_t *pipe;
|
||||
|
||||
if (pipe == NULL)
|
||||
{
|
||||
_DBG_WRN("fifo_handle invalid");
|
||||
return;
|
||||
}
|
||||
_TEST_HANDLE(pipe_handle, return);
|
||||
|
||||
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
|
||||
_K_DIS_SCHED();
|
||||
pipe->wid = 0;
|
||||
@@ -3943,13 +3973,14 @@ bool k_pipe_is_valid(k_pipe_t *pipe_handle)
|
||||
*/
|
||||
void k_pipe_regist(k_pipe_t *pipe_handle, k_work_t *work_handle, k_tick_t delay_ticks)
|
||||
{
|
||||
k_pipe_handle_t *pipe = pipe_handle->hdl;
|
||||
if (pipe != NULL)
|
||||
{
|
||||
k_pipe_handle_t *pipe;
|
||||
|
||||
_TEST_HANDLE(pipe_handle, return);
|
||||
|
||||
pipe = pipe_handle->hdl;
|
||||
pipe->resume_work = work_handle;
|
||||
pipe->resume_delay = delay_ticks;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取消注册任务
|
||||
@@ -3971,13 +4002,14 @@ void k_pipe_unregist(k_pipe_t *pipe_handle)
|
||||
*/
|
||||
size_t k_pipe_poll_write(k_pipe_t *pipe_handle, uint8_t data)
|
||||
{
|
||||
k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
k_pipe_handle_t *pipe;
|
||||
pipe_id_t wid;
|
||||
bool resume_flag;
|
||||
|
||||
if (pipe)
|
||||
{
|
||||
pipe_id_t wid = pipe->wid;
|
||||
_TEST_HANDLE(pipe_handle, return 0);
|
||||
|
||||
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
wid = pipe->wid;
|
||||
if (++wid >= pipe->size)
|
||||
{
|
||||
wid = 0;
|
||||
@@ -3999,7 +4031,6 @@ size_t k_pipe_poll_write(k_pipe_t *pipe_handle, uint8_t data)
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4015,13 +4046,14 @@ size_t k_pipe_poll_write(k_pipe_t *pipe_handle, uint8_t data)
|
||||
size_t k_pipe_fifo_fill(k_pipe_t *pipe_handle, const void *data, size_t size)
|
||||
{
|
||||
size_t ret = 0;
|
||||
k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
k_pipe_handle_t *pipe;
|
||||
pipe_id_t wid;
|
||||
bool resume_flag;
|
||||
|
||||
if (pipe)
|
||||
{
|
||||
pipe_id_t wid = pipe->wid;
|
||||
_TEST_HANDLE(pipe_handle, return 0);
|
||||
|
||||
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
wid = pipe->wid;
|
||||
resume_flag = (wid == pipe->rid);
|
||||
|
||||
while (size)
|
||||
@@ -4066,7 +4098,6 @@ size_t k_pipe_fifo_fill(k_pipe_t *pipe_handle, const void *data, size_t size)
|
||||
{
|
||||
_k_ipc_resume(pipe->resume_work, pipe->resume_delay, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -4080,11 +4111,13 @@ size_t k_pipe_fifo_fill(k_pipe_t *pipe_handle, const void *data, size_t size)
|
||||
*/
|
||||
size_t k_pipe_poll_read(k_pipe_t *pipe_handle, uint8_t *data)
|
||||
{
|
||||
k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
k_pipe_handle_t *pipe;
|
||||
pipe_id_t rid;
|
||||
|
||||
if (pipe)
|
||||
{
|
||||
pipe_id_t rid = pipe->rid;
|
||||
_TEST_HANDLE(pipe_handle, return 0);
|
||||
|
||||
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
rid = pipe->rid;
|
||||
if (rid != pipe->wid)
|
||||
{
|
||||
data[0] = ((uint8_t *)&pipe[1])[rid++];
|
||||
@@ -4098,7 +4131,6 @@ size_t k_pipe_poll_read(k_pipe_t *pipe_handle, uint8_t *data)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4114,11 +4146,13 @@ size_t k_pipe_poll_read(k_pipe_t *pipe_handle, uint8_t *data)
|
||||
size_t k_pipe_fifo_read(k_pipe_t *pipe_handle, void *data, size_t size)
|
||||
{
|
||||
size_t ret = 0;
|
||||
k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
k_pipe_handle_t *pipe;
|
||||
pipe_id_t rid;
|
||||
|
||||
if (pipe)
|
||||
{
|
||||
pipe_id_t rid = pipe->rid;
|
||||
_TEST_HANDLE(pipe_handle, return 0);
|
||||
|
||||
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
rid = pipe->rid;
|
||||
while (size)
|
||||
{
|
||||
pipe_id_t wid = *(volatile pipe_id_t *)&pipe->wid;
|
||||
@@ -4153,7 +4187,6 @@ size_t k_pipe_fifo_read(k_pipe_t *pipe_handle, void *data, size_t size)
|
||||
ret += min;
|
||||
}
|
||||
pipe->rid = rid;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -4167,13 +4200,11 @@ size_t k_pipe_fifo_read(k_pipe_t *pipe_handle, void *data, size_t size)
|
||||
*/
|
||||
bool k_pipe_is_ne(k_pipe_t *pipe_handle)
|
||||
{
|
||||
if (pipe_handle->hdl == NULL)
|
||||
{
|
||||
return _FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
k_pipe_handle_t *pipe;
|
||||
|
||||
_TEST_HANDLE(pipe_handle, return _FALSE);
|
||||
|
||||
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
if (pipe->rid == pipe->wid)
|
||||
{
|
||||
return _FALSE;
|
||||
@@ -4183,7 +4214,6 @@ bool k_pipe_is_ne(k_pipe_t *pipe_handle)
|
||||
return _TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取管道的数据大小(字节数)
|
||||
@@ -4193,13 +4223,11 @@ bool k_pipe_is_ne(k_pipe_t *pipe_handle)
|
||||
*/
|
||||
size_t k_pipe_get_valid_size(k_pipe_t *pipe_handle)
|
||||
{
|
||||
if (pipe_handle->hdl == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
k_pipe_handle_t *pipe;
|
||||
|
||||
_TEST_HANDLE(pipe_handle, return 0);
|
||||
|
||||
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
if (pipe->wid < pipe->rid)
|
||||
{
|
||||
return pipe->size + pipe->wid - pipe->rid;
|
||||
@@ -4209,7 +4237,6 @@ size_t k_pipe_get_valid_size(k_pipe_t *pipe_handle)
|
||||
return pipe->wid - pipe->rid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取管道的剩余空间(字节数)
|
||||
@@ -4219,16 +4246,13 @@ size_t k_pipe_get_valid_size(k_pipe_t *pipe_handle)
|
||||
*/
|
||||
size_t k_pipe_get_empty_size(k_pipe_t *pipe_handle)
|
||||
{
|
||||
if (pipe_handle->hdl == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
k_pipe_handle_t *pipe;
|
||||
|
||||
_TEST_HANDLE(pipe_handle, return 0);
|
||||
|
||||
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
return pipe->size - (k_pipe_get_valid_size(pipe_handle) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前已写入的连续的内存信息。
|
||||
@@ -4242,9 +4266,11 @@ size_t k_pipe_get_empty_size(k_pipe_t *pipe_handle)
|
||||
*/
|
||||
void k_pipe_peek_valid(k_pipe_t *pipe_handle, void **dst_base, size_t *dst_size)
|
||||
{
|
||||
if (pipe_handle->hdl)
|
||||
{
|
||||
k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
k_pipe_handle_t *pipe;
|
||||
|
||||
_TEST_HANDLE(pipe_handle, return);
|
||||
|
||||
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
if (dst_base)
|
||||
{
|
||||
*dst_base = (&((uint8_t *)&pipe[1])[pipe->rid]);
|
||||
@@ -4263,7 +4289,6 @@ void k_pipe_peek_valid(k_pipe_t *pipe_handle, void **dst_base, size_t *dst_size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前空闲的连续的内存信息。
|
||||
@@ -4277,9 +4302,11 @@ void k_pipe_peek_valid(k_pipe_t *pipe_handle, void **dst_base, size_t *dst_size)
|
||||
*/
|
||||
void k_pipe_peek_empty(k_pipe_t *pipe_handle, void **dst_base, size_t *dst_size)
|
||||
{
|
||||
if (pipe_handle->hdl)
|
||||
{
|
||||
k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
k_pipe_handle_t *pipe;
|
||||
|
||||
_TEST_HANDLE(pipe_handle, return);
|
||||
|
||||
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
|
||||
if (dst_base)
|
||||
{
|
||||
*dst_base = (&((uint8_t *)&pipe[1])[pipe->wid]);
|
||||
@@ -4298,7 +4325,6 @@ void k_pipe_peek_empty(k_pipe_t *pipe_handle, void **dst_base, size_t *dst_size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前系统时间
|
||||
|
||||
@@ -83,8 +83,7 @@ SH_REGISTER_CMD(
|
||||
|
||||
### 补全勾子的可用接口
|
||||
- sh_putstr_quiet()
|
||||
- sh_cmd_info()
|
||||
- sh_completion_cmd()
|
||||
- sh_cmd_test()
|
||||
- sh_completion_param()
|
||||
- sh_completion_resource()
|
||||
- sh_get_cp_result()
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "sh.h"
|
||||
#include "sh_vset.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -127,7 +128,7 @@ static const sh_key_t *_find_key(sh_t *sh_hdl, const char *code)
|
||||
* 如果当前为模块模式,由优先在模块中查找。
|
||||
*
|
||||
* @param dest_reg_struct[out] 保存根命令结构的定义地址
|
||||
* @param sub_cmd NULL -- 从根命令中历遍查找; ! NULL 从已知的父命令节点中查找
|
||||
* @param sub_cmd NULL -- 从根命令中遍历查找; ! NULL 从已知的父命令节点中查找
|
||||
* @param cmd 单元命令字符串
|
||||
* @return const sh_cmd_t* NULL -- 没有记录这个命令; ! NULL 找到的命令节点
|
||||
*/
|
||||
@@ -399,8 +400,9 @@ static void _insert_str(sh_t *sh_hdl, const char *str)
|
||||
*/
|
||||
static void _read_param(int *argc, const char *argv[CONFIG_SH_MAX_PARAM], char *dest, const char *src)
|
||||
{
|
||||
bool end = false;
|
||||
*argc = 0;
|
||||
while (*argc < CONFIG_SH_MAX_PARAM)
|
||||
while (end == false && *argc < CONFIG_SH_MAX_PARAM)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
@@ -485,6 +487,13 @@ static void _read_param(int *argc, const char *argv[CONFIG_SH_MAX_PARAM], char *
|
||||
++src;
|
||||
dest[len] = '\0';
|
||||
}
|
||||
else if (dest[len] == '#' && split_char == ' ') /* 注释 */
|
||||
{
|
||||
++src;
|
||||
dest[len] = '\0';
|
||||
end = true;
|
||||
}
|
||||
|
||||
if (dest[len] == '\0')
|
||||
{
|
||||
break;
|
||||
@@ -719,6 +728,16 @@ int sh_unregister_cmd(const sh_cmd_reg_t *sh_reg)
|
||||
return -!ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取消所有已注册命令
|
||||
*/
|
||||
void sh_unregister_all(sh_t *sh_hdl)
|
||||
{
|
||||
sys_pslist_init(&s_cmd_list);
|
||||
sys_pslist_init(&s_cmd_list_hide);
|
||||
sys_pslist_init(&sh_hdl->cmd_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 注册一组热键
|
||||
* 适用于动态加载/卸载
|
||||
@@ -1563,7 +1582,7 @@ static bool _do_completion_cmd(sh_t *sh_hdl, sh_cp_info_t *info, const sh_cmd_in
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (sub_cmd == NULL) // 历遍根命令链
|
||||
if (sub_cmd == NULL) // 遍历根命令链
|
||||
{
|
||||
const sh_cmd_reg_t *sh_reg;
|
||||
sys_pslist_t *cmd_list[] = {
|
||||
@@ -1587,7 +1606,7 @@ static bool _do_completion_cmd(sh_t *sh_hdl, sh_cp_info_t *info, const sh_cmd_in
|
||||
}
|
||||
}
|
||||
}
|
||||
else // 历遍子命令数据
|
||||
else // 遍历子命令数据
|
||||
{
|
||||
sub_cmd = sub_cmd->sub_fn.sub_cmd;
|
||||
for (int i = 0; sub_cmd[i].cmd != NULL; i++)
|
||||
@@ -1603,7 +1622,7 @@ static bool _do_completion_cmd(sh_t *sh_hdl, sh_cp_info_t *info, const sh_cmd_in
|
||||
info->print_count == 0 && // 没有打印任何可选项
|
||||
err_status != _SH_CMD_STATUS_Incomplete && // 如果正在输出当前模块下的子命令,则只继续补全子命令
|
||||
print_match == true && // 只打印匹配的备选项
|
||||
flag_parent == 0 // 目前仅在 _cmd_select_param() 被置起,此时不再历遍根命令链
|
||||
flag_parent == 0 // 目前仅在 _cmd_select_param() 被置起,此时不再遍历根命令链
|
||||
)
|
||||
{
|
||||
sub_cmd = NULL; // 使从根命令链重新查找
|
||||
@@ -1614,7 +1633,7 @@ static bool _do_completion_cmd(sh_t *sh_hdl, sh_cp_info_t *info, const sh_cmd_in
|
||||
if (sh_hdl->select_cmd != NULL && // 当前状态为模块模式
|
||||
info->match_num == 0 && // 没有找到可匹配的命令
|
||||
err_status != _SH_CMD_STATUS_Incomplete && // 如果正在输出当前模块下的子命令,则只继续补全子命令
|
||||
sub_cmd != NULL // 未历遍过根命令链
|
||||
sub_cmd != NULL // 未遍历过根命令链
|
||||
)
|
||||
{
|
||||
sub_cmd = NULL; // 使从根命令链重新查找
|
||||
@@ -1739,7 +1758,7 @@ static int _calc_list_algin(sh_cp_info_t *info)
|
||||
* @param argv 命令字符串指针
|
||||
* @return sh_cmd_info_t 命令信息
|
||||
*/
|
||||
sh_cmd_info_t sh_cmd_info(sh_t *sh_hdl, int argc, const char *argv[])
|
||||
sh_cmd_info_t sh_cmd_test(sh_t *sh_hdl, int argc, const char *argv[])
|
||||
{
|
||||
SYS_ASSERT(sh_hdl != NULL, "");
|
||||
|
||||
@@ -1808,12 +1827,12 @@ static sh_cp_op_t _sh_completion_cmd(sh_t *sh_hdl, int argc, const char *argv[],
|
||||
/* 初始化 cmd_info 和 cp_info */
|
||||
if (_arg_is_end(sh_hdl))
|
||||
{
|
||||
cmd_info = sh_cmd_info(sh_hdl, argc, argv);
|
||||
cmd_info = sh_cmd_test(sh_hdl, argc, argv);
|
||||
cp_info = _completion_init("");
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd_info = sh_cmd_info(sh_hdl, --argc, argv);
|
||||
cmd_info = sh_cmd_test(sh_hdl, --argc, argv);
|
||||
if (cmd_info.err_status == _SH_CMD_STATUS_Success)
|
||||
{
|
||||
cp_info = _completion_init(argv[argc++]);
|
||||
@@ -1892,7 +1911,7 @@ static sh_cp_op_t _sh_completion_cmd(sh_t *sh_hdl, int argc, const char *argv[],
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd_info = sh_cmd_info(sh_hdl, argc, argv);
|
||||
cmd_info = sh_cmd_test(sh_hdl, argc, argv);
|
||||
cp_info = _completion_init(""); // 没有任何命令时直接打印所有根命令
|
||||
}
|
||||
|
||||
@@ -1923,20 +1942,6 @@ static sh_cp_op_t _sh_completion_cmd(sh_t *sh_hdl, int argc, const char *argv[],
|
||||
return sh_hdl->cp_operate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 根据输入的参数,结合当前命令行的状态,在已注册命令中查找并自执行一次自动补全命令/打印备选命令的全过程
|
||||
*
|
||||
* @param argc 命令数量
|
||||
* @param argv 命令字符串指针
|
||||
* @return sh_cp_op_t 自动补全命令/打印备选命令的执行结果
|
||||
*/
|
||||
sh_cp_op_t sh_completion_cmd(sh_t *sh_hdl, int argc, const char *argv[])
|
||||
{
|
||||
SYS_ASSERT(sh_hdl != NULL, "");
|
||||
|
||||
return _sh_completion_cmd(sh_hdl, argc, argv, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 仅在 cp_fn() 中可用,根据当前命令行内容,在给出的参数结构中查找并自动补全参数/打印备选参数的全过程
|
||||
*
|
||||
@@ -1998,7 +2003,8 @@ sh_cp_op_t sh_completion_param(sh_t *sh_hdl, const sh_cp_param_t *param)
|
||||
* 自动补全/打印备行项 将在 cp_fn() 退出后自动执行。
|
||||
* @ref @c fatfs_shell.c@_scan_files()/@_cmd_df_cp()
|
||||
*
|
||||
* @param arg_str 指定已输入的待自动补全的字符串,当为NULL时表示按当前命令行自动填充
|
||||
* @param arg_str 指定已输入的待自动补全的字符串,当为NULL时表示按当前命令行自动填充。
|
||||
* 使用场景:在自动补全路径时, arg_str 表示仅关注路径的最后一部分,而不是整个路径,以便于在补全时只显示当前目录下的文件。
|
||||
* @param res_str 候选字符串
|
||||
* @param help 帮助描述信息。如果值为 NULL 则不会被打印
|
||||
*/
|
||||
@@ -2106,7 +2112,7 @@ void sh_ctrl_tab(sh_t *sh_hdl)
|
||||
_read_param(&argc, argv, cmd_param, cmd_param);
|
||||
|
||||
/* 自动补全命令 */
|
||||
sh_completion_cmd(sh_hdl, argc, argv);
|
||||
_sh_completion_cmd(sh_hdl, argc, argv, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2133,7 +2139,7 @@ bool sh_ctrl_enter(sh_t *sh_hdl)
|
||||
_apply_history(sh_hdl);
|
||||
|
||||
/* 根据 argc, argv,解析出 info */
|
||||
sh_cmd_info_t info = sh_cmd_info(sh_hdl, argc, argv);
|
||||
sh_cmd_info_t info = sh_cmd_test(sh_hdl, argc, argv);
|
||||
if (info.err_status == _SH_CMD_STATUS_Success)
|
||||
{
|
||||
_clear_argv(argc, argv);
|
||||
@@ -2791,7 +2797,7 @@ SH_CMD_FN(_cmd_select)
|
||||
{
|
||||
if (argc)
|
||||
{
|
||||
sh_cmd_info_t cmd_info = sh_cmd_info(sh_hdl, argc, argv);
|
||||
sh_cmd_info_t cmd_info = sh_cmd_test(sh_hdl, argc, argv);
|
||||
if (cmd_info.err_status == _SH_CMD_STATUS_Incomplete)
|
||||
{
|
||||
sh_hdl->select_reg_struct = cmd_info.reg_struct;
|
||||
@@ -2875,7 +2881,7 @@ SH_CMD_FN(_cmd_exit)
|
||||
|
||||
SH_CMD_FN(_cmd_print_help)
|
||||
{
|
||||
sh_cmd_info_t info = sh_cmd_info(sh_hdl, argc, argv);
|
||||
sh_cmd_info_t info = sh_cmd_test(sh_hdl, argc, argv);
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
@@ -2905,7 +2911,7 @@ SH_CMD_FN(_cmd_print_help)
|
||||
total_len += 3;
|
||||
for (int i = 1; i <= info.match_count; i++)
|
||||
{
|
||||
sh_cmd_info_t tmp = sh_cmd_info(sh_hdl, i, argv);
|
||||
sh_cmd_info_t tmp = sh_cmd_test(sh_hdl, i, argv);
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
@@ -2949,7 +2955,7 @@ SH_CMD_FN(_cmd_print_help)
|
||||
|
||||
SH_CMD_CP_FN(_cmd_print_help_param)
|
||||
{
|
||||
sh_completion_cmd(sh_hdl, argc, argv);
|
||||
_sh_completion_cmd(sh_hdl, argc, argv, 0);
|
||||
}
|
||||
|
||||
SH_CMD_FN(_cmd_echo_on)
|
||||
@@ -3025,6 +3031,13 @@ SH_REGISTER_CMD(
|
||||
SH_SETUP_CMD("exit", "Exit parent command or disconnect", _cmd_exit, NULL), //
|
||||
);
|
||||
|
||||
static int _vset_init(void)
|
||||
{
|
||||
vset_init(&g_uart_handle_vt100, NULL);
|
||||
return 0;
|
||||
}
|
||||
INIT_EXPORT_COMPONENT(_vset_init);
|
||||
|
||||
/**
|
||||
* @brief 用于显式初始化内部函数。
|
||||
* 当自动初始化函数不适用时,使用此函数可强制初始化内部的一些功能。包含:
|
||||
@@ -3047,5 +3060,7 @@ void sh_register_external(sh_vprint_fn out)
|
||||
static uint8_t bank_mem[CONFIG_SH_MAX_LINE_LEN];
|
||||
sh_config_history_mem(&g_uart_handle_vt100, history_mem, sizeof(history_mem));
|
||||
sh_config_backup_mem(&g_uart_handle_vt100, bank_mem, sizeof(bank_mem));
|
||||
|
||||
_vset_init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +244,8 @@ typedef struct sh_obj_def // 对象内存结构
|
||||
* 1. 如果 FUNC 取值为 NULL 时, SUB_NAME 必须指向 SH_DEF_SUB_CMD 定义的子命令列表名;
|
||||
* 2. 如果 FUNC 取值为函数时:
|
||||
* 2.1 SUB_NAME 可为 NULL;
|
||||
* 2.1 SUB_NAME 指向 void (*cp_fn)(sh_t *sh_hdl, int argc, const char *argv[]) 表示按 TAB 键时被执行的函数,用于参数补全。
|
||||
* 2.1 SUB_NAME 指向 void (*cp_fn)(sh_t *sh_hdl, int argc, const char *argv[]) 表示按 TAB 键时被执行的函数,
|
||||
* 这个函数内部允许执行 cp_fn 应用,用于帮助对 FUNC 命令参数补全。
|
||||
*
|
||||
* @verbatim
|
||||
* @c sh.c
|
||||
@@ -316,6 +317,7 @@ SH_CMD_CP_FN(_sh_generic_cp_fn) {}
|
||||
int sh_register_cmd(const sh_cmd_reg_t *sh_reg); // 可用自动初始化宏执行 @ref SH_REGISTER_CMD
|
||||
int sh_register_cmd_hide(const sh_cmd_reg_t *sh_reg); // 可用自动初始化宏执行 @ref SH_REGISTER_CMD
|
||||
int sh_unregister_cmd(const sh_cmd_reg_t *sh_reg); // 取消注册一个根命令
|
||||
void sh_unregister_all(sh_t *sh_hdl); // 取消所有已注册命令
|
||||
|
||||
/* 现成终端协议初始化 ----------------------------------------------------------------- */
|
||||
|
||||
@@ -347,12 +349,10 @@ int sh_get_cmd_result(sh_t *sh_hdl); // 获取上一条有效命令的返回值
|
||||
|
||||
void sh_refresh_line(sh_t *sh_hdl); // 执行刷一次当前命令行显示
|
||||
|
||||
sh_cmd_info_t sh_cmd_test(sh_t *sh_hdl, int argc, const char *argv[]); // 根据参数,完整解析命令并获取命令信息
|
||||
|
||||
/* cp_fn 应用 ---------------------------------------------------------------------- */
|
||||
|
||||
sh_cmd_info_t sh_cmd_info(sh_t *sh_hdl, int argc, const char *argv[]); // 根据参数,获取完全匹配的命令信息
|
||||
|
||||
sh_cp_op_t sh_completion_cmd(sh_t *sh_hdl, int argc, const char *argv[]); // 根据参数,在已注册命令中查找并自动补全命令
|
||||
|
||||
sh_cp_op_t sh_completion_param(sh_t *sh_hdl, const sh_cp_param_t *param); // 仅在 cp_fn() 中可用,根据当前命令行内容,在给出的参数结构中查找并自动补全参数。参数允许为 NULL
|
||||
|
||||
void sh_completion_resource(sh_t *sh_hdl, const char *arg_str, const char *res_str, const char *help); // 仅在 cp_fn() 中可用,根据当前命令行内容,逐个给出可供查找的提示符。内部将根据所提供的数据自动补全
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#define _PARAM_CB() \
|
||||
do \
|
||||
{ \
|
||||
if (param->cb) \
|
||||
param->cb(s_sh_hdl, &value); \
|
||||
if (cb) \
|
||||
cb(s_sh_hdl, &value); \
|
||||
} while (0)
|
||||
|
||||
static sh_t *s_sh_hdl;
|
||||
@@ -40,19 +40,19 @@ static const sh_vset_param_t *_find_option(const char *input, const sh_vset_para
|
||||
static bool _do_completing_option(sh_t *sh_hdl, int argc, const char *argv[], const sh_vset_param_t *p, unsigned size);
|
||||
static bool _do_completing_enum(const char *option, const sh_vset_param_t *p, unsigned size);
|
||||
|
||||
static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, unsigned int low, unsigned int high);
|
||||
static int _set_dest_integer(const __vset_param_t *param, signed int value, signed int low, signed int high);
|
||||
static int _set_dest_float(const __vset_param_t *param, float value, float low, float high);
|
||||
static int _set_dest_string(const __vset_param_t *param, const char *str, unsigned bufsize);
|
||||
static int _set_dest_enum(const __vset_param_t *param, const char *value, int type_flag);
|
||||
static int _set_dest_unsigned(void *dest, __type_attr_t attr, vset_cb cb, unsigned int value, unsigned int low, unsigned int high);
|
||||
static int _set_dest_integer(void *dest, __type_attr_t attr, vset_cb cb, signed int value, signed int low, signed int high);
|
||||
static int _set_dest_float(void *dest, __type_attr_t attr, vset_cb cb, float value, float low, float high);
|
||||
static int _set_dest_string(void *dest, __type_attr_t attr, vset_cb cb, const char *str, unsigned bufsize);
|
||||
static int _set_dest_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *value, int type_flag);
|
||||
|
||||
static unsigned int _get_unsigned(const __vset_param_t *param);
|
||||
static signed int _get_integer(const __vset_param_t *param);
|
||||
static float _get_float(const __vset_param_t *param);
|
||||
static char *_get_string(const __vset_param_t *param);
|
||||
static unsigned int _get_unsigned(void *dest, __type_attr_t attr);
|
||||
static signed int _get_integer(void *dest, __type_attr_t attr);
|
||||
static float _get_float(void *dest, __type_attr_t attr);
|
||||
static char *_get_string(void *dest, __type_attr_t attr);
|
||||
static int _enum_format(char *enum_buf, int buf_len, const char *enum_str);
|
||||
static int _get_enum_by_key(const char *key, char **match_value, char *enum_buf);
|
||||
static int _get_enum_by_param(const __vset_param_t *param, char **match_key, char **match_value, char *enum_buf, bool print_list, bool print_cp);
|
||||
static int _get_enum_by_param(void *dest, __type_attr_t attr, char **match_key, char **match_value, char *enum_buf, bool print_list, bool print_cp);
|
||||
|
||||
/**
|
||||
* @brief s_attr_to_type_tbl
|
||||
@@ -78,12 +78,12 @@ static int const s_attr_to_type_tbl[] = {
|
||||
* @brief 初始化设置
|
||||
*
|
||||
* @param sh_hdl 设置 shell 的句柄
|
||||
* @param cb 当任意一个值被修改时回调此函数,可设为 NULL
|
||||
* @param global_cb 当任意一个值被修改时回调此函数,可设为 NULL
|
||||
*/
|
||||
void vset_init(sh_t *sh_hdl, vset_global_cb cb)
|
||||
void vset_init(sh_t *sh_hdl, vset_global_cb global_cb)
|
||||
{
|
||||
s_sh_hdl = sh_hdl;
|
||||
s_global_cb = cb;
|
||||
s_global_cb = global_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,10 +92,10 @@ void vset_init(sh_t *sh_hdl, vset_global_cb cb)
|
||||
*/
|
||||
void vset_force_cb(void)
|
||||
{
|
||||
vset_global_cb cb = s_global_cb;
|
||||
if (cb)
|
||||
vset_global_cb global_cb = s_global_cb;
|
||||
if (global_cb)
|
||||
{
|
||||
cb(s_sh_hdl);
|
||||
global_cb(s_sh_hdl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +147,10 @@ int vset_option_set(sh_t *sh_hdl, int *argc, const char *argv[], const sh_vset_p
|
||||
{
|
||||
flag = true;
|
||||
sh_echo(s_sh_hdl, "选项: %s\r\n", pset->option);
|
||||
if (pset->help)
|
||||
{
|
||||
sh_echo(s_sh_hdl, "说明: %s\r\n", pset->help);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,22 +239,22 @@ bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const
|
||||
}
|
||||
}
|
||||
|
||||
int vset_unsigned(const __vset_param_t *param, const char *argv[], unsigned int low, unsigned int high)
|
||||
int vset_unsigned(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned int low, unsigned int high)
|
||||
{
|
||||
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
|
||||
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");
|
||||
|
||||
if (s_sh_hdl == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
{
|
||||
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
return -1;
|
||||
}
|
||||
if (s_attr_to_type_tbl[param->attr] != _PARSE_TYPE_UNSIGNED)
|
||||
if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_UNSIGNED)
|
||||
{
|
||||
sh_echo(s_sh_hdl, "待设置的参数类型不是正整数\r\n");
|
||||
return -1;
|
||||
@@ -271,7 +275,7 @@ int vset_unsigned(const __vset_param_t *param, const char *argv[], unsigned int
|
||||
low ^= high;
|
||||
}
|
||||
sh_echo(s_sh_hdl, "有效范围: %d .. %d\r\n", low, high);
|
||||
sh_echo(s_sh_hdl, "当前值: %u\r\n", _get_unsigned(param));
|
||||
sh_echo(s_sh_hdl, "当前值: %u\r\n", _get_unsigned(dest, attr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -279,7 +283,7 @@ int vset_unsigned(const __vset_param_t *param, const char *argv[], unsigned int
|
||||
switch (pv.type)
|
||||
{
|
||||
case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
|
||||
return _set_dest_unsigned(param, pv.value.val_unsigned, low, high);
|
||||
return _set_dest_unsigned(dest, attr, cb, pv.value.val_unsigned, low, high);
|
||||
|
||||
default:
|
||||
sh_echo(s_sh_hdl, "参数 '%s' 格式错误, 请输入正整数\r\n", argv[0]);
|
||||
@@ -287,22 +291,22 @@ int vset_unsigned(const __vset_param_t *param, const char *argv[], unsigned int
|
||||
}
|
||||
}
|
||||
|
||||
int vset_integer(const __vset_param_t *param, const char *argv[], signed int low, signed int high)
|
||||
int vset_integer(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], signed int low, signed int high)
|
||||
{
|
||||
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
|
||||
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");
|
||||
|
||||
if (s_sh_hdl == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
{
|
||||
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
return -1;
|
||||
}
|
||||
if (s_attr_to_type_tbl[param->attr] != _PARSE_TYPE_INTEGER)
|
||||
if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_INTEGER)
|
||||
{
|
||||
sh_echo(s_sh_hdl, "待设置的参数类型不是带符号整数\r\n");
|
||||
return -1;
|
||||
@@ -323,7 +327,7 @@ int vset_integer(const __vset_param_t *param, const char *argv[], signed int low
|
||||
low ^= high;
|
||||
}
|
||||
sh_echo(s_sh_hdl, "有效范围: %d .. %d\r\n", low, high);
|
||||
sh_echo(s_sh_hdl, "当前值: %d\r\n", _get_integer(param));
|
||||
sh_echo(s_sh_hdl, "当前值: %d\r\n", _get_integer(dest, attr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -331,7 +335,7 @@ int vset_integer(const __vset_param_t *param, const char *argv[], signed int low
|
||||
switch (pv.type)
|
||||
{
|
||||
case _PARSE_TYPE_INTEGER: // 解析出的参数格式是带符号整型
|
||||
return _set_dest_integer(param, pv.value.val_integer, low, high);
|
||||
return _set_dest_integer(dest, attr, cb, pv.value.val_integer, low, high);
|
||||
|
||||
case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
|
||||
if (pv.value.val_unsigned > (1u << (sizeof(pv.value.val_unsigned) * 8 - 1)) - 1)
|
||||
@@ -339,7 +343,7 @@ int vset_integer(const __vset_param_t *param, const char *argv[], signed int low
|
||||
sh_echo(s_sh_hdl, "参数 %u 溢出\r\n", pv.value.val_unsigned);
|
||||
return -1;
|
||||
}
|
||||
return _set_dest_integer(param, pv.value.val_unsigned, low, high);
|
||||
return _set_dest_integer(dest, attr, cb, pv.value.val_unsigned, low, high);
|
||||
|
||||
default:
|
||||
sh_echo(s_sh_hdl, "参数 '%s' 格式错误, 请输入整数\r\n", argv[0]);
|
||||
@@ -347,22 +351,22 @@ int vset_integer(const __vset_param_t *param, const char *argv[], signed int low
|
||||
}
|
||||
}
|
||||
|
||||
int vset_float(const __vset_param_t *param, const char *argv[], float low, float high)
|
||||
int vset_float(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], float low, float high)
|
||||
{
|
||||
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
|
||||
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");
|
||||
|
||||
if (s_sh_hdl == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
{
|
||||
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
return -1;
|
||||
}
|
||||
if (s_attr_to_type_tbl[param->attr] != _PARSE_TYPE_FLOAT)
|
||||
if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_FLOAT)
|
||||
{
|
||||
sh_echo(s_sh_hdl, "待设置的参数类型不是浮点数\r\n");
|
||||
return -1;
|
||||
@@ -383,7 +387,7 @@ int vset_float(const __vset_param_t *param, const char *argv[], float low, float
|
||||
high = tmp;
|
||||
}
|
||||
sh_echo(s_sh_hdl, "有效范围: %f .. %f\r\n", low, high);
|
||||
sh_echo(s_sh_hdl, "当前值: %f\r\n", _get_float(param));
|
||||
sh_echo(s_sh_hdl, "当前值: %f\r\n", _get_float(dest, attr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -391,13 +395,13 @@ int vset_float(const __vset_param_t *param, const char *argv[], float low, float
|
||||
switch (pv.type)
|
||||
{
|
||||
case _PARSE_TYPE_INTEGER: // 解析出的参数格式是带符号整型
|
||||
return _set_dest_float(param, pv.value.val_integer, low, high);
|
||||
return _set_dest_float(dest, attr, cb, pv.value.val_integer, low, high);
|
||||
|
||||
case _PARSE_TYPE_UNSIGNED: // 解析出的参数格式是无符号整型
|
||||
return _set_dest_float(param, pv.value.val_unsigned, low, high);
|
||||
return _set_dest_float(dest, attr, cb, pv.value.val_unsigned, low, high);
|
||||
|
||||
case _PARSE_TYPE_FLOAT: // 解析出的参数格式是浮点数
|
||||
return _set_dest_float(param, pv.value.val_float, low, high);
|
||||
return _set_dest_float(dest, attr, cb, pv.value.val_float, low, high);
|
||||
|
||||
default:
|
||||
sh_echo(s_sh_hdl, "参数 '%s' 格式错误, 请输入数值\r\n", argv[0]);
|
||||
@@ -405,22 +409,22 @@ int vset_float(const __vset_param_t *param, const char *argv[], float low, float
|
||||
}
|
||||
}
|
||||
|
||||
int vset_str(const __vset_param_t *param, const char *argv[], unsigned bufsize)
|
||||
int vset_str(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned bufsize)
|
||||
{
|
||||
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
|
||||
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");
|
||||
|
||||
if (s_sh_hdl == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
{
|
||||
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
return -1;
|
||||
}
|
||||
if (s_attr_to_type_tbl[param->attr] != _PARSE_TYPE_STRING)
|
||||
if (s_attr_to_type_tbl[attr] != _PARSE_TYPE_STRING)
|
||||
{
|
||||
sh_echo(s_sh_hdl, "待设置的参数类型不是字符串\r\n");
|
||||
return -1;
|
||||
@@ -435,7 +439,7 @@ int vset_str(const __vset_param_t *param, const char *argv[], unsigned bufsize)
|
||||
if (strcmp(argv[0], "?") == 0)
|
||||
{
|
||||
sh_echo(s_sh_hdl, "最大长度: %d\r\n", bufsize - 1);
|
||||
sh_echo(s_sh_hdl, "当前值: %s\r\n", _get_string(param));
|
||||
sh_echo(s_sh_hdl, "当前值: %s\r\n", _get_string(dest, attr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -445,21 +449,21 @@ int vset_str(const __vset_param_t *param, const char *argv[], unsigned bufsize)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _set_dest_string(param, argv[0], bufsize);
|
||||
return _set_dest_string(dest, attr, cb, argv[0], bufsize);
|
||||
}
|
||||
|
||||
int vset_enum(const __vset_param_t *param, const char *argv[], const char *enum_str)
|
||||
int vset_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], const char *enum_str)
|
||||
{
|
||||
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
|
||||
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
|
||||
if (s_sh_hdl == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
{
|
||||
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -484,7 +488,7 @@ int vset_enum(const __vset_param_t *param, const char *argv[], const char *enum_
|
||||
if (strcmp(argv[0], "?") == 0)
|
||||
{
|
||||
sh_echo(s_sh_hdl, "可选值:\r\n");
|
||||
_get_enum_by_param(param, &match_key, &match_value, enum_buf, true, false);
|
||||
_get_enum_by_param(dest, attr, &match_key, &match_value, enum_buf, true, false);
|
||||
if (match_value)
|
||||
{
|
||||
sh_echo(s_sh_hdl, "当前值:\t%s\r\n", match_key);
|
||||
@@ -504,7 +508,7 @@ int vset_enum(const __vset_param_t *param, const char *argv[], const char *enum_
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _set_dest_enum(param, match_value, type_flag);
|
||||
return _set_dest_enum(dest, attr, cb, match_value, type_flag);
|
||||
}
|
||||
|
||||
void vset_cp_enum(int argc, bool flag, const char *enum_str)
|
||||
@@ -528,15 +532,10 @@ void vset_cp_enum(int argc, bool flag, const char *enum_str)
|
||||
return;
|
||||
}
|
||||
|
||||
__vset_param_t param = {
|
||||
.dest = enum_buf,
|
||||
.attr = __GENERIC_ATTR(enum_buf),
|
||||
};
|
||||
|
||||
/* 分割字符串 str_buf 并穷举匹配到的值,输出 match_key, match_value, type_flag */
|
||||
char *match_key = NULL;
|
||||
char *match_value = NULL;
|
||||
_get_enum_by_param(¶m, &match_key, &match_value, enum_buf, false, true);
|
||||
_get_enum_by_param(enum_buf, __GENERIC_ATTR(enum_buf), &match_key, &match_value, enum_buf, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -667,11 +666,9 @@ static bool _do_completing_enum(const char *option, const sh_vset_param_t *p, un
|
||||
return false;
|
||||
}
|
||||
|
||||
static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, unsigned int low, unsigned int high)
|
||||
static int _set_dest_unsigned(void *dest, __type_attr_t attr, vset_cb cb, unsigned int value, unsigned int low, unsigned int high)
|
||||
{
|
||||
void *dest = param->dest;
|
||||
__type_attr_t attr = param->attr;
|
||||
vset_global_cb cb = NULL;
|
||||
vset_global_cb global_cb = NULL;
|
||||
int ret = -1;
|
||||
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
@@ -703,7 +700,7 @@ static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, u
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((uint8_t *)dest) = value;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -721,7 +718,7 @@ static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, u
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((uint16_t *)dest) = value;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -733,7 +730,7 @@ static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, u
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((uint32_t *)dest) = value;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -745,7 +742,7 @@ static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, u
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((uint64_t *)dest) = value;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -755,23 +752,21 @@ static int _set_dest_unsigned(const __vset_param_t *param, unsigned int value, u
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cb)
|
||||
if (global_cb)
|
||||
{
|
||||
cb(s_sh_hdl);
|
||||
global_cb(s_sh_hdl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _set_dest_integer(const __vset_param_t *param, signed int value, signed int low, signed int high)
|
||||
static int _set_dest_integer(void *dest, __type_attr_t attr, vset_cb cb, signed int value, signed int low, signed int high)
|
||||
{
|
||||
#define _MAX_S8 127
|
||||
#define _MIN_S8 -128
|
||||
#define _MAX_S16 32767
|
||||
#define _MIN_S16 -32768
|
||||
|
||||
void *dest = param->dest;
|
||||
__type_attr_t attr = param->attr;
|
||||
vset_global_cb cb = NULL;
|
||||
vset_global_cb global_cb = NULL;
|
||||
int ret = -1;
|
||||
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
@@ -803,7 +798,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((char *)dest) = data;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -821,7 +816,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((bool *)dest) = data;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -841,7 +836,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((int8_t *)dest) = value;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -861,7 +856,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((int16_t *)dest) = value;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -873,7 +868,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((int32_t *)dest) = value;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -885,7 +880,7 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((int64_t *)dest) = value;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -895,18 +890,16 @@ static int _set_dest_integer(const __vset_param_t *param, signed int value, sign
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cb)
|
||||
if (global_cb)
|
||||
{
|
||||
cb(s_sh_hdl);
|
||||
global_cb(s_sh_hdl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _set_dest_float(const __vset_param_t *param, float value, float low, float high)
|
||||
static int _set_dest_float(void *dest, __type_attr_t attr, vset_cb cb, float value, float low, float high)
|
||||
{
|
||||
void *dest = param->dest;
|
||||
__type_attr_t attr = param->attr;
|
||||
vset_global_cb cb = NULL;
|
||||
vset_global_cb global_cb = NULL;
|
||||
int ret = -1;
|
||||
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
@@ -932,7 +925,7 @@ static int _set_dest_float(const __vset_param_t *param, float value, float low,
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((float *)dest) = value;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -943,7 +936,7 @@ static int _set_dest_float(const __vset_param_t *param, float value, float low,
|
||||
{
|
||||
_PARAM_CB();
|
||||
*((double *)dest) = value;
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -953,19 +946,17 @@ static int _set_dest_float(const __vset_param_t *param, float value, float low,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cb)
|
||||
if (global_cb)
|
||||
{
|
||||
cb(s_sh_hdl);
|
||||
global_cb(s_sh_hdl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _set_dest_string(const __vset_param_t *param, const char *str, unsigned bufsize)
|
||||
static int _set_dest_string(void *dest, __type_attr_t attr, vset_cb cb, const char *str, unsigned bufsize)
|
||||
{
|
||||
void *dest = param->dest;
|
||||
int str_size = strlen(str) + 1;
|
||||
__type_attr_t attr = param->attr;
|
||||
vset_global_cb cb = NULL;
|
||||
vset_global_cb global_cb = NULL;
|
||||
int ret = -1;
|
||||
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
@@ -974,6 +965,7 @@ static int _set_dest_string(const __vset_param_t *param, const char *str, unsign
|
||||
if (str_size > bufsize)
|
||||
{
|
||||
sh_echo(s_sh_hdl, "注意: '%s' 大于最大长度 %d\r\n", str, bufsize - 1);
|
||||
str_size = bufsize;
|
||||
}
|
||||
|
||||
switch (attr)
|
||||
@@ -982,14 +974,15 @@ static int _set_dest_string(const __vset_param_t *param, const char *str, unsign
|
||||
memset(dest, 0, bufsize);
|
||||
if (memcmp(dest, str, str_size))
|
||||
{
|
||||
if (param->cb)
|
||||
if (cb)
|
||||
{
|
||||
char value[0x100];
|
||||
memcpy(dest, str, str_size);
|
||||
char value[str_size + 1];
|
||||
memset(value, 0, str_size + 1);
|
||||
memcpy(value, str, str_size);
|
||||
_PARAM_CB();
|
||||
}
|
||||
memcpy(dest, str, str_size);
|
||||
cb = s_global_cb;
|
||||
global_cb = s_global_cb;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -998,17 +991,17 @@ static int _set_dest_string(const __vset_param_t *param, const char *str, unsign
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cb)
|
||||
if (global_cb)
|
||||
{
|
||||
cb(s_sh_hdl);
|
||||
global_cb(s_sh_hdl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _set_dest_enum(const __vset_param_t *param, const char *value, int type_flag)
|
||||
static int _set_dest_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *value, int type_flag)
|
||||
{
|
||||
sh_parse_t pv = sh_parse_value(value);
|
||||
switch (s_attr_to_type_tbl[param->attr])
|
||||
switch (s_attr_to_type_tbl[attr])
|
||||
{
|
||||
case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
|
||||
{
|
||||
@@ -1020,7 +1013,7 @@ static int _set_dest_enum(const __vset_param_t *param, const char *value, int ty
|
||||
switch (pv.type)
|
||||
{
|
||||
case _PARSE_TYPE_UNSIGNED: // 当前匹配的参数格式是无符号整型
|
||||
return _set_dest_unsigned(param, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
|
||||
return _set_dest_unsigned(dest, attr, cb, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
@@ -1038,10 +1031,10 @@ static int _set_dest_enum(const __vset_param_t *param, const char *value, int ty
|
||||
switch (pv.type)
|
||||
{
|
||||
case _PARSE_TYPE_INTEGER: // 当前匹配的参数格式是带符号整型
|
||||
return _set_dest_integer(param, pv.value.val_integer, pv.value.val_integer, pv.value.val_integer);
|
||||
return _set_dest_integer(dest, attr, cb, pv.value.val_integer, pv.value.val_integer, pv.value.val_integer);
|
||||
|
||||
case _PARSE_TYPE_UNSIGNED: // 当前匹配的参数格式是无符号整型
|
||||
return _set_dest_integer(param, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
|
||||
return _set_dest_integer(dest, attr, cb, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
@@ -1059,13 +1052,13 @@ static int _set_dest_enum(const __vset_param_t *param, const char *value, int ty
|
||||
switch (pv.type)
|
||||
{
|
||||
case _PARSE_TYPE_INTEGER: // 当前匹配的参数格式是带符号整型
|
||||
return _set_dest_float(param, pv.value.val_integer, pv.value.val_integer, pv.value.val_integer);
|
||||
return _set_dest_float(dest, attr, cb, pv.value.val_integer, pv.value.val_integer, pv.value.val_integer);
|
||||
|
||||
case _PARSE_TYPE_UNSIGNED: // 当前匹配的参数格式是无符号整型
|
||||
return _set_dest_float(param, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
|
||||
return _set_dest_float(dest, attr, cb, pv.value.val_unsigned, pv.value.val_unsigned, pv.value.val_unsigned);
|
||||
|
||||
case _PARSE_TYPE_FLOAT: // 当前匹配的参数格式是浮点数
|
||||
return _set_dest_float(param, pv.value.val_float, pv.value.val_float, pv.value.val_float);
|
||||
return _set_dest_float(dest, attr, cb, pv.value.val_float, pv.value.val_float, pv.value.val_float);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
@@ -1075,96 +1068,96 @@ static int _set_dest_enum(const __vset_param_t *param, const char *value, int ty
|
||||
|
||||
case _PARSE_TYPE_STRING: // 待设置的参数格式是字符串
|
||||
{
|
||||
return _set_dest_string(param, value, strlen(value) + 1);
|
||||
return _set_dest_string(dest, attr, cb, value, strlen(value) + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed int _get_integer(const __vset_param_t *param)
|
||||
static signed int _get_integer(void *dest, __type_attr_t attr)
|
||||
{
|
||||
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
|
||||
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_INTEGER, "待设置的参数类型不是带符号整数");
|
||||
|
||||
switch (param->attr)
|
||||
switch (attr)
|
||||
{
|
||||
case __TYPE_ATTR_CHR:
|
||||
return *((char *)param->dest);
|
||||
return *((char *)dest);
|
||||
|
||||
case __TYPE_ATTR_BOOL:
|
||||
return *((bool *)param->dest);
|
||||
return *((bool *)dest);
|
||||
|
||||
case __TYPE_ATTR_S8:
|
||||
return *((int8_t *)param->dest);
|
||||
return *((int8_t *)dest);
|
||||
|
||||
case __TYPE_ATTR_S16:
|
||||
return *((int16_t *)param->dest);
|
||||
return *((int16_t *)dest);
|
||||
|
||||
case __TYPE_ATTR_S32:
|
||||
return *((int32_t *)param->dest);
|
||||
return *((int32_t *)dest);
|
||||
|
||||
case __TYPE_ATTR_S64:
|
||||
return *((int64_t *)param->dest);
|
||||
return *((int64_t *)dest);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static float _get_float(const __vset_param_t *param)
|
||||
static float _get_float(void *dest, __type_attr_t attr)
|
||||
{
|
||||
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
|
||||
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_FLOAT, "待设置的参数类型不是浮点数");
|
||||
|
||||
switch (param->attr)
|
||||
switch (attr)
|
||||
{
|
||||
case __TYPE_ATTR_FLOAT:
|
||||
return *((float *)param->dest);
|
||||
return *((float *)dest);
|
||||
|
||||
case __TYPE_ATTR_DOUBLE:
|
||||
return *((double *)param->dest);
|
||||
return *((double *)dest);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static char *_get_string(const __vset_param_t *param)
|
||||
static char *_get_string(void *dest, __type_attr_t attr)
|
||||
{
|
||||
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
|
||||
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_STRING, "待设置的参数类型不是字符串");
|
||||
|
||||
return param->dest;
|
||||
return dest;
|
||||
}
|
||||
|
||||
static unsigned int _get_unsigned(const __vset_param_t *param)
|
||||
static unsigned int _get_unsigned(void *dest, __type_attr_t attr)
|
||||
{
|
||||
SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化");
|
||||
SYS_ASSERT(param->attr < __ARR_SIZE(s_attr_to_type_tbl), "param->attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[param->attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");
|
||||
SYS_ASSERT(attr < __ARR_SIZE(s_attr_to_type_tbl), "attr 的值不在 __type_attr_t 所定义的范围");
|
||||
SYS_ASSERT(s_attr_to_type_tbl[attr] == _PARSE_TYPE_UNSIGNED, "待设置的参数类型不是正整数");
|
||||
|
||||
switch (param->attr)
|
||||
switch (attr)
|
||||
{
|
||||
case __TYPE_ATTR_U8:
|
||||
return *((uint8_t *)param->dest);
|
||||
return *((uint8_t *)dest);
|
||||
|
||||
case __TYPE_ATTR_U16:
|
||||
return *((uint16_t *)param->dest);
|
||||
return *((uint16_t *)dest);
|
||||
|
||||
case __TYPE_ATTR_U32:
|
||||
return *((uint32_t *)param->dest);
|
||||
return *((uint32_t *)dest);
|
||||
|
||||
case __TYPE_ATTR_U64:
|
||||
return *((uint64_t *)param->dest);
|
||||
return *((uint64_t *)dest);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
@@ -1318,37 +1311,37 @@ static int _get_enum_by_key(const char *key, char **match_value, char *enum_buf)
|
||||
* _TYPE_FLAG_FLOAT 掩码表示在 enum_buf 中包含浮点数
|
||||
* _TYPE_FLAG_STRING 掩码表示在 enum_buf 中包含字符串
|
||||
*/
|
||||
static int _get_enum_by_param(const __vset_param_t *param, char **match_key, char **match_value, char *enum_buf, bool print_list, bool print_cp)
|
||||
static int _get_enum_by_param(void *dest, __type_attr_t attr, char **match_key, char **match_value, char *enum_buf, bool print_list, bool print_cp)
|
||||
{
|
||||
char param_value_str[0x100];
|
||||
int type_flag = 0; // 在 match_value 中出现过的数据类型
|
||||
|
||||
if (param->attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
if (attr >= __ARR_SIZE(s_attr_to_type_tbl))
|
||||
{
|
||||
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (s_attr_to_type_tbl[param->attr])
|
||||
switch (s_attr_to_type_tbl[attr])
|
||||
{
|
||||
case _PARSE_TYPE_INTEGER: // 待设置的参数格式是带符号整型
|
||||
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%d", _get_integer(param));
|
||||
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%d", _get_integer(dest, attr));
|
||||
break;
|
||||
|
||||
case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
|
||||
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%u", _get_unsigned(param));
|
||||
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%u", _get_unsigned(dest, attr));
|
||||
break;
|
||||
|
||||
case _PARSE_TYPE_FLOAT: // 待设置的参数格式是浮点数
|
||||
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%f", _get_float(param));
|
||||
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%f", _get_float(dest, attr));
|
||||
break;
|
||||
|
||||
case _PARSE_TYPE_STRING: // 待设置的参数格式是字符串
|
||||
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%s", _get_string(param));
|
||||
SYS_SNPRINT(param_value_str, sizeof(param_value_str), "%s", _get_string(dest, attr));
|
||||
break;
|
||||
|
||||
default:
|
||||
sh_echo(s_sh_hdl, "param->attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
sh_echo(s_sh_hdl, "attr 的值不在 __type_attr_t 所定义的范围\r\n");
|
||||
return -1;
|
||||
}
|
||||
param_value_str[__ARR_SIZE(param_value_str) - 1] = '\0';
|
||||
@@ -1378,7 +1371,7 @@ static int _get_enum_by_param(const __vset_param_t *param, char **match_key, cha
|
||||
type_flag |= _TYPE_FLAG_UNSIGNED;
|
||||
if (*match_key == NULL)
|
||||
{
|
||||
switch (s_attr_to_type_tbl[param->attr])
|
||||
switch (s_attr_to_type_tbl[attr])
|
||||
{
|
||||
case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
|
||||
SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%u", pv.value.val_unsigned);
|
||||
@@ -1402,7 +1395,7 @@ static int _get_enum_by_param(const __vset_param_t *param, char **match_key, cha
|
||||
type_flag |= _TYPE_FLAG_INTEGER;
|
||||
if (*match_key == NULL)
|
||||
{
|
||||
switch (s_attr_to_type_tbl[param->attr])
|
||||
switch (s_attr_to_type_tbl[attr])
|
||||
{
|
||||
case _PARSE_TYPE_INTEGER: // 待设置的参数格式是带符号整型
|
||||
SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%d", pv.value.val_integer);
|
||||
@@ -1423,7 +1416,7 @@ static int _get_enum_by_param(const __vset_param_t *param, char **match_key, cha
|
||||
type_flag |= _TYPE_FLAG_FLOAT;
|
||||
if (*match_key == NULL)
|
||||
{
|
||||
switch (s_attr_to_type_tbl[param->attr])
|
||||
switch (s_attr_to_type_tbl[attr])
|
||||
{
|
||||
case _PARSE_TYPE_FLOAT: // 待设置的参数格式是浮点数
|
||||
SYS_SNPRINT(key_value_str, sizeof(key_value_str), "%f", (float)pv.value.val_float);
|
||||
@@ -1481,7 +1474,7 @@ static int _get_enum_by_param(const __vset_param_t *param, char **match_key, cha
|
||||
token = strtok_r(NULL, ",", &save_token);
|
||||
}
|
||||
|
||||
switch (s_attr_to_type_tbl[param->attr])
|
||||
switch (s_attr_to_type_tbl[attr])
|
||||
{
|
||||
case _PARSE_TYPE_UNSIGNED: // 待设置的参数格式是无符号整型
|
||||
{
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
* - @b PSET_CP 根据一个已定义的 const sh_vset_param_t* 执行自动补选项
|
||||
*
|
||||
* 实例1: 以下这些函数可被 SH_SETUP_CMD 中定义的 FUNC 执行,或者作为 sh_vset_param_t::set_func 的成员
|
||||
* static int _value_set_u8(const char *argv[]) { SET_VAR(&var_u8, 1, 200); }
|
||||
* static int _value_set_s16(const char *argv[]) { SET_VAR(&var_s16, -1000, 1000); }
|
||||
* static int _value_set_float(const char *argv[]) { SET_VAR(&var_float, -1000, var_u8); }
|
||||
* static int _value_set_str(const char *argv[]) { SET_VAR(&var_str, 0, 0); }
|
||||
* static int _value_set_enum(const char *argv[]) { SET_ENUM(&var_s32, "enable=1,disable=0"); }
|
||||
* static int _value_set_u8(const char *argv[]) { return SET_VAR(&var_u8, 1, 200); }
|
||||
* static int _value_set_s16(const char *argv[]) { return SET_VAR(&var_s16, -1000, 1000); }
|
||||
* static int _value_set_float(const char *argv[]) { return SET_VAR(&var_float, -1000, var_u8); }
|
||||
* static int _value_set_str(const char *argv[]) { return SET_VAR(&var_str, 0, 0); }
|
||||
* static int _value_set_enum(const char *argv[]) { return SET_ENUM(&var_s32, "enable=1,disable=0"); }
|
||||
*
|
||||
* 实例2: 实现选项+参数的格式
|
||||
* static sh_vset_param_t const s_param_template[] = {
|
||||
@@ -77,14 +77,6 @@ typedef enum
|
||||
*/
|
||||
typedef void (*vset_cb)(sh_t *sh_hdl, void *new_value);
|
||||
|
||||
/* 待设置变量数据结构 */
|
||||
typedef struct
|
||||
{
|
||||
void *dest;
|
||||
__type_attr_t attr;
|
||||
vset_cb cb;
|
||||
} __vset_param_t;
|
||||
|
||||
#define __GENERIC_ATTR(VAR) (__builtin_types_compatible_p(__typeof(VAR), char) ? __TYPE_ATTR_CHR \
|
||||
: __builtin_types_compatible_p(__typeof(VAR), volatile char) ? __TYPE_ATTR_CHR \
|
||||
: __builtin_types_compatible_p(__typeof(VAR), bool) ? __TYPE_ATTR_BOOL \
|
||||
@@ -122,11 +114,11 @@ typedef struct // 用于长选项设置的描述结构
|
||||
const char *enum_str; // 仅在类型为 vset_enum_fn 时有效,为对应的选项提供可选的补全参数选项,值为 NULL 或 "" 时默认候选参数为 '?'
|
||||
} sh_vset_param_t;
|
||||
|
||||
int vset_unsigned(const __vset_param_t *param, const char *argv[], unsigned int low, unsigned int high);
|
||||
int vset_integer(const __vset_param_t *param, const char *argv[], signed int low, signed int high);
|
||||
int vset_float(const __vset_param_t *param, const char *argv[], float low, float high);
|
||||
int vset_str(const __vset_param_t *param, const char *argv[], unsigned bufsize);
|
||||
int vset_enum(const __vset_param_t *param, const char *argv[], const char *enum_str);
|
||||
int vset_unsigned(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned int low, unsigned int high);
|
||||
int vset_integer(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], signed int low, signed int high);
|
||||
int vset_float(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], float low, float high);
|
||||
int vset_str(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned bufsize);
|
||||
int vset_enum(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], const char *enum_str);
|
||||
void vset_cp_enum(int argc, bool flag, const char *enum_str);
|
||||
|
||||
int vset_option_set(sh_t *sh_hdl, int *argc, const char *argv[], const sh_vset_param_t *p, unsigned size);
|
||||
@@ -134,59 +126,29 @@ bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const
|
||||
|
||||
/* 自动分析并设置变量的值,带设置回调 */
|
||||
#define SET_VAR_CB(NAME, LOW, HIGH, CB) \
|
||||
do \
|
||||
{ \
|
||||
static __vset_param_t const param = { \
|
||||
.dest = NAME, \
|
||||
.attr = __GENERIC_ATTR(*(NAME)), \
|
||||
.cb = CB, \
|
||||
}; \
|
||||
if ( \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U8 || \
|
||||
((__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U8 || \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U16 || \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U32 || \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U64) \
|
||||
{ \
|
||||
return vset_unsigned(¶m, argv, LOW, HIGH); \
|
||||
} \
|
||||
else if ( \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_CHR || \
|
||||
? vset_unsigned(NAME, __GENERIC_ATTR(*(NAME)), CB, argv, LOW, HIGH) \
|
||||
: ((__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_CHR || \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_BOOL || \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S8 || \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S16 || \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S32 || \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_S64) \
|
||||
{ \
|
||||
return vset_integer(¶m, argv, LOW, HIGH); \
|
||||
} \
|
||||
else if ( \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_FLOAT || \
|
||||
? vset_integer(NAME, __GENERIC_ATTR(*(NAME)), CB, argv, LOW, HIGH) \
|
||||
: ((__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_FLOAT || \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_DOUBLE) \
|
||||
{ \
|
||||
return vset_float(¶m, argv, LOW, HIGH); \
|
||||
} \
|
||||
else if ( \
|
||||
__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_STR) \
|
||||
{ \
|
||||
return vset_str(¶m, argv, sizeof(*(NAME))); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
? vset_float(NAME, __GENERIC_ATTR(*(NAME)), CB, argv, LOW, HIGH) \
|
||||
: ((__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_STR) \
|
||||
? vset_str(NAME, __GENERIC_ATTR(*(NAME)), CB, argv, sizeof(*(NAME))) \
|
||||
: -1))))
|
||||
|
||||
/* 设置数据类型为 枚举型 的变量,带设置回调 */
|
||||
#define SET_ENUM_CB(NAME, ENUM_STR, CB) \
|
||||
do \
|
||||
{ \
|
||||
static __vset_param_t const param = { \
|
||||
.dest = NAME, \
|
||||
.attr = __GENERIC_ATTR(*(NAME)), \
|
||||
.cb = CB, \
|
||||
}; \
|
||||
return vset_enum(¶m, argv, ENUM_STR); \
|
||||
} while (0)
|
||||
(vset_enum(NAME, __GENERIC_ATTR(*(NAME)), CB, \
|
||||
argv, ENUM_STR))
|
||||
|
||||
/* 自动分析并设置变量的值 */
|
||||
#define SET_VAR(NAME, LOW, HIGH) SET_VAR_CB(NAME, LOW, HIGH, NULL)
|
||||
@@ -194,16 +156,6 @@ bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const
|
||||
/* 设置数据类型为 枚举型 的变量 */
|
||||
#define SET_ENUM(NAME, ENUM_STR) SET_ENUM_CB(NAME, ENUM_STR, NULL)
|
||||
|
||||
/* 对应 SET_VAR 所设置的变量的可用自动补全函数 */
|
||||
#define SET_CP_VAR() \
|
||||
do \
|
||||
{ \
|
||||
if (argc + flag == 1) \
|
||||
{ \
|
||||
sh_completion_resource(sh_hdl, NULL, "? ", NULL); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* 对应 SET_ENUM 所设置的变量的可用自动补全函数 */
|
||||
#define SET_CP_ENUM(ENUM_STR) \
|
||||
do \
|
||||
@@ -216,8 +168,67 @@ bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const
|
||||
|
||||
typedef void (*vset_global_cb)(sh_t *sh_hdl);
|
||||
|
||||
void vset_init(sh_t *sh_hdl, vset_global_cb cb);
|
||||
void vset_init(sh_t *sh_hdl, vset_global_cb global_cb);
|
||||
|
||||
void vset_force_cb(void);
|
||||
|
||||
/**
|
||||
* @note 对本函数的进一步说明。
|
||||
*
|
||||
* 在 sh 模块设计完成后,发现除了用于执行某些定义好的的操作外,更多情况下是用于设置变量。
|
||||
* 为了更好的支持这种需求,本模块应运而生。
|
||||
* 本模块的设计目标是通过命令行的形式设置变量,同时支持对变量的取值范围限制。
|
||||
* 本模块的设计思路是通过宏定义,将变量的类型和取值范围传递给 SET_VAR() 或 SET_ENUM() 进行具体的设置。
|
||||
* 本模块主要使用到的宏定义有:
|
||||
* - @b SET_VAR()
|
||||
* - @b SET_ENUM()
|
||||
* - @b SET_CP_ENUM()
|
||||
* - @b PSET_FN()
|
||||
* - @b PSET_CP()
|
||||
*
|
||||
* 这些都是根据实际的使用场景定义的。
|
||||
* 根据 sh 模块的主体功能,分为两个部分(可在使用 SH_SETUP_CMD() 定义命令时的第三和第四个参数来体现):
|
||||
* - 一个是用于执行某些操作的函数。
|
||||
* - 另一个是用于像 bash 一样,按 Tab 键自动补全的函数。
|
||||
* 对于前者,可在实际执行函数中直接使用 SET_VAR() 或 SET_ENUM() 来设置变量。
|
||||
* 对于后者,可在实际补全函数中直接使用 SET_CP_ENUM() 来提示可选项和可选值。
|
||||
*
|
||||
* 为什么设置宏要分两种?
|
||||
* SET_VAR() 和 SET_ENUM() 的本质区别是, SET_VAR() 用于设置无符号整形、带符号整型、单精度的浮点数和字符串的变量,它们的取值范围是连续的。
|
||||
* 值得注意的是: SET_VAR() 也支持字符串的设置,但是字符串的取值范围是无法限制的。
|
||||
* 而 SET_ENUM() 用于设置枚举型的变量,它的取值范围是允许离散的,并且可用一些字符串来表示具体的取值。
|
||||
*
|
||||
* 为什么补全函数只有 SET_CP_ENUM() ?
|
||||
* 因为 SET_ENUM() 的取值范围是离散的,所以需要一个额外的函数来提供可选的补全参数选项。对于连续的取值范围,不需要这个函数。
|
||||
*
|
||||
* 设置宏较为独立,虽然它是为了配合本模块而设计的,但是它的功能是独立的,在传输的参数中的 sh_hdl 主要是为了回显一些错误信息。
|
||||
* 补全宏则是为了配合 sh 模块的补全功能而设计的,它的功能是为了提供可选的补全参数选项。
|
||||
*
|
||||
* 小结:
|
||||
* - SET_VAR() 和 SET_ENUM() 用于设置变量的值。
|
||||
* - SET_CP_ENUM() 用于提供可选的补全参数选项。
|
||||
* - 它们可能在命令执行函数和补全函数中直接使用。
|
||||
*
|
||||
* 接着新问题来了,使用 SET_VAR() 或 SET_ENUM() 时,只能设置一个变量,如果这个命令要包含多种设置,该怎么办?
|
||||
* 为了解决这个问题,本模块引入了 sh_vset_param_t 结构体,它是一个数组,用于描述支待的待设置变量的具体类型。
|
||||
* 它统一描述了该命令的所有选项,包括选项的名称、选项的描述、选项的设置函数和选项的可选值。
|
||||
* 在命令执行函数和补全函数中,通过调用 PSET_FN() 和 PSET_CP() 来执行具体的设置。
|
||||
* 这两个宏的参数就是 sh_vset_param_t 结构体的数组。
|
||||
* 这个结构体的定义是固定的,它的成员包括:
|
||||
* - 选项,如 "--value"
|
||||
* - 对该选项的描述
|
||||
* - 与 option 对应的,使用宏 SET_VAR() 或 SET_ENUM() 设置变量的函数。如果值为 NULL 表示该选项无参数,同时对应的输入参数被保留
|
||||
* - 仅在类型为 vset_enum_fn 时有效,为对应的选项提供可选的补全参数选项,值为 NULL 或 "" 时默认候选参数为 '?'
|
||||
* 通过设置这个结构,便可得到一个完整的命令格式: <命令> [选项 <参数>] [选项 <参数>] ...
|
||||
*
|
||||
* 其他一些细节:
|
||||
* - 这些宏都是以最简约的形式定义的,以便在有大量数据的情况下降低阅读难度。在一些特殊情况下,可根据这些提及到的宏的定义展开理解再灵活使用。
|
||||
*
|
||||
* 总结:
|
||||
* SET_VAR(), SET_ENUM() 和 SET_CP_ENUM() 是用于单个变量的设置和补全,它们可以直接在命令执行函数和补全函数中使用,也可以在 sh_vset_param_t 结构体中对应的函数使用。
|
||||
* PSET_FN() 和 PSET_CP() 是用于多个变量的设置和补全,它们可以直接在命令执行函数和补全函数中被调用。
|
||||
* sh_vset_param_t 结构体是用于描述支待的待设置变量的具体类型,它可以直接在命令执行函数和补全函数中被调用。
|
||||
*
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -43,6 +43,12 @@ static test_single_t const test_tab_ipc[] = {
|
||||
os_test_pipe,
|
||||
};
|
||||
|
||||
INIT_EXPORT_APP(99)
|
||||
{
|
||||
SYS_LOG_INF("success");
|
||||
os_thread_sleep(200);
|
||||
}
|
||||
|
||||
void os_test_main(void)
|
||||
{
|
||||
rand(); // rand() 用到 malloc()
|
||||
|
||||
@@ -1,47 +1,14 @@
|
||||
# INCS
|
||||
list(APPEND incs "../sal")
|
||||
|
||||
set(srcs-app
|
||||
)
|
||||
|
||||
# 基础程序
|
||||
set(srcs-common
|
||||
"ota.c"
|
||||
"../app/app_main.c"
|
||||
"../app/console.c"
|
||||
"../app/drivers/data_port/sb_data_port.c"
|
||||
"../app/drivers/data_port/uart/uart_port.c"
|
||||
"../app/button/button_event.c"
|
||||
)
|
||||
# SRCS
|
||||
list(APPEND srcs "main.c")
|
||||
list(APPEND srcs "ota.c")
|
||||
|
||||
# 自定义框架抽象层
|
||||
set(srcs-components
|
||||
"../components/system/source/k_kit/k_kit.c"
|
||||
"../components/system/source/shell/sh_vt100.c"
|
||||
"../components/system/source/shell/sh_vset.c"
|
||||
"../components/system/source/shell/sh.c"
|
||||
"../sal/esp32s3/kernel/os_heap.c"
|
||||
"../sal/esp32s3/kernel/os_mutex.c"
|
||||
"../sal/esp32s3/kernel/os_hook.c"
|
||||
"../sal/esp32s3/kernel/os_timer.c"
|
||||
"../sal/esp32s3/kernel/os_semaphore.c"
|
||||
"../sal/esp32s3/kernel/os_thread.c"
|
||||
"../sal/esp32s3/kernel/os_kit.c"
|
||||
"../sal/esp32s3/kernel/os_service.c"
|
||||
"../sal/esp32s3/chip/uart_esp32.c"
|
||||
"../sal/esp32s3/soc_shell.c"
|
||||
"../app/config/board_config.c"
|
||||
)
|
||||
set(incs
|
||||
"../app"
|
||||
"../components/system/include"
|
||||
"../components/system/source"
|
||||
"../components/system/source/k_kit"
|
||||
"../components/system/source/shell"
|
||||
"../sal/esp32s3"
|
||||
"../sal/esp32s3/kernel"
|
||||
"${IDF_PATH}/components/freertos/FreeRTOS-Kernel/include/freertos"
|
||||
)
|
||||
|
||||
idf_component_register(SRCS "main.c"
|
||||
${srcs-components}
|
||||
${srcs-common}
|
||||
INCLUDE_DIRS "." ${incs})
|
||||
# idf_component_register
|
||||
idf_component_register(
|
||||
INCLUDE_DIRS ${incs}
|
||||
SRCS ${srcs}
|
||||
)
|
||||
|
||||
77
main/main.c
77
main/main.c
@@ -9,83 +9,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "os/os.h"
|
||||
#include "os_entry.h"
|
||||
#include "app_main.h"
|
||||
|
||||
#include "ota.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#undef SYS_LOG_DOMAIN
|
||||
#define SYS_LOG_DOMAIN "OS"
|
||||
#include "os_util.h"
|
||||
|
||||
#ifndef CONFIG_OS_THREAD_MAIN_STACK_SIZE
|
||||
#define CONFIG_OS_THREAD_MAIN_STACK_SIZE 0x1C00
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_OS_THREAD_MAIN_PRIORITY
|
||||
#define CONFIG_OS_THREAD_MAIN_PRIORITY OS_PRIORITY_NORMAL
|
||||
#endif
|
||||
|
||||
static unsigned s_int_nest;
|
||||
|
||||
static unsigned _port_interrupt_save(void)
|
||||
{
|
||||
if (s_int_nest == 0)
|
||||
{
|
||||
os_interrupt_disable();
|
||||
}
|
||||
return s_int_nest++;
|
||||
}
|
||||
|
||||
static void _port_interrupt_restore(unsigned nest)
|
||||
{
|
||||
s_int_nest = nest;
|
||||
if (nest == 0)
|
||||
{
|
||||
os_interrupt_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static k_work_q_t *_port_get_work_q_hdl(void)
|
||||
{
|
||||
struct os_thread_handle *thread_handle = os_thread_get_self();
|
||||
os_work_q_list_t *work_q_list = thread_handle->work_q_list;
|
||||
return &work_q_list->work_q_handle;
|
||||
}
|
||||
|
||||
static void _port_thread_sleep(k_tick_t sleep_ticks)
|
||||
{
|
||||
vTaskDelay(sleep_ticks);
|
||||
}
|
||||
|
||||
static void _os_init(void)
|
||||
{
|
||||
static k_init_t const init_struct = {
|
||||
.malloc = os_malloc,
|
||||
.free = os_free,
|
||||
.get_sys_ticks = os_get_sys_ticks,
|
||||
.interrupt_save = _port_interrupt_save,
|
||||
.interrupt_restore = _port_interrupt_restore,
|
||||
.scheduler_disable = os_scheduler_suspend,
|
||||
.scheduler_enable = os_scheduler_resume,
|
||||
.get_work_q_hdl = _port_get_work_q_hdl,
|
||||
.thread_sleep = _port_thread_sleep,
|
||||
};
|
||||
k_init(&init_struct);
|
||||
|
||||
os_work_q_create(default_os_work_q_hdl,
|
||||
"app-work_q",
|
||||
CONFIG_OS_THREAD_MAIN_STACK_SIZE,
|
||||
CONFIG_OS_THREAD_MAIN_PRIORITY);
|
||||
|
||||
extern void work_app_main(void *arg);
|
||||
static os_work_t _work_hdl_init;
|
||||
os_work_create(&_work_hdl_init, "work-main", work_app_main, NULL, 3);
|
||||
os_work_submit(default_os_work_q_hdl, &_work_hdl_init, 0);
|
||||
}
|
||||
|
||||
static void _init_prev_nvs(void)
|
||||
{
|
||||
esp_err_t err = nvs_flash_init();
|
||||
@@ -110,7 +40,6 @@ int app_main(void)
|
||||
_init_prev_nvs();
|
||||
|
||||
/* 初始化 os 抽象层 */
|
||||
_os_init();
|
||||
|
||||
return 0;
|
||||
extern void work_app_main(void *arg);
|
||||
return os_entry(work_app_main);
|
||||
}
|
||||
|
||||
27
sal/CMakeLists.txt
Normal file
27
sal/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
list(APPEND incs ".")
|
||||
list(APPEND incs "${IDF_PATH}/components/freertos/FreeRTOS-Kernel/include/freertos")
|
||||
list(APPEND incs "../components/system/include")
|
||||
list(APPEND incs "../components/system/source")
|
||||
list(APPEND incs "../components/system/source/k_kit")
|
||||
list(APPEND incs "../components/system/source/shell")
|
||||
|
||||
list(APPEND srcs "esp32/kernel/os_heap.c")
|
||||
list(APPEND srcs "esp32/kernel/os_mutex.c")
|
||||
list(APPEND srcs "esp32/kernel/os_hook.c")
|
||||
list(APPEND srcs "esp32/kernel/os_timer.c")
|
||||
list(APPEND srcs "esp32/kernel/os_semaphore.c")
|
||||
list(APPEND srcs "esp32/kernel/os_thread.c")
|
||||
list(APPEND srcs "esp32/kernel/os_kit.c")
|
||||
list(APPEND srcs "esp32/kernel/os_service.c")
|
||||
list(APPEND srcs "esp32/chip/uart_esp32.c")
|
||||
list(APPEND srcs "esp32/soc_shell.c")
|
||||
list(APPEND srcs "esp32/os_entry.c")
|
||||
|
||||
idf_component_register(
|
||||
INCLUDE_DIRS ${incs}
|
||||
SRCS ${srcs}
|
||||
REQUIRES
|
||||
driver
|
||||
nvs_flash
|
||||
spi_flash
|
||||
)
|
||||
@@ -211,6 +211,23 @@ os_state os_work_create(os_work_t *work_handle, const char *name, os_work_fn wor
|
||||
}
|
||||
}
|
||||
|
||||
os_state os_work_create_default(os_work_t *work_handle, const char *name, os_work_fn work_route, void *arg, uint8_t sub_prior, os_time_t delay_ms)
|
||||
{
|
||||
if (!os_work_is_valid(work_handle))
|
||||
{
|
||||
os_state ret = os_work_create(work_handle, name, work_route, arg, sub_prior);
|
||||
if (ret == OS_OK)
|
||||
{
|
||||
os_work_submit(default_os_work_q_hdl, work_handle, delay_ms);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void os_work_delete(os_work_t *work_handle)
|
||||
{
|
||||
OS_ASS_ISR();
|
||||
@@ -127,7 +127,7 @@ os_state os_thread_create(os_thread_t *thread,
|
||||
thread_handle,
|
||||
OS_KERNEL_PRIO(priority),
|
||||
&thread_handle->pxCreatedTask,
|
||||
1);
|
||||
0);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
OS_ERR("err %d\r\n", ret);
|
||||
72
sal/esp32/os_entry.c
Normal file
72
sal/esp32/os_entry.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "os_entry.h"
|
||||
|
||||
#undef SYS_LOG_DOMAIN
|
||||
#define SYS_LOG_DOMAIN "OS"
|
||||
#include "kernel/os_util.h"
|
||||
|
||||
#ifndef CONFIG_OS_THREAD_MAIN_STACK_SIZE
|
||||
#define CONFIG_OS_THREAD_MAIN_STACK_SIZE 0x1C00
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_OS_THREAD_MAIN_PRIORITY
|
||||
#define CONFIG_OS_THREAD_MAIN_PRIORITY OS_PRIORITY_NORMAL
|
||||
#endif
|
||||
|
||||
static unsigned s_int_nest;
|
||||
|
||||
static unsigned _port_interrupt_save(void)
|
||||
{
|
||||
if (s_int_nest == 0)
|
||||
{
|
||||
os_interrupt_disable();
|
||||
}
|
||||
return s_int_nest++;
|
||||
}
|
||||
|
||||
static void _port_interrupt_restore(unsigned nest)
|
||||
{
|
||||
s_int_nest = nest;
|
||||
if (nest == 0)
|
||||
{
|
||||
os_interrupt_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static k_work_q_t *_port_get_work_q_hdl(void)
|
||||
{
|
||||
struct os_thread_handle *thread_handle = os_thread_get_self();
|
||||
os_work_q_list_t *work_q_list = thread_handle->work_q_list;
|
||||
return &work_q_list->work_q_handle;
|
||||
}
|
||||
|
||||
static void _port_thread_sleep(k_tick_t sleep_ticks)
|
||||
{
|
||||
vTaskDelay(sleep_ticks);
|
||||
}
|
||||
|
||||
int os_entry(os_work_fn work_route)
|
||||
{
|
||||
static k_init_t const init_struct = {
|
||||
.malloc = os_malloc,
|
||||
.free = os_free,
|
||||
.get_sys_ticks = os_get_sys_ticks,
|
||||
.interrupt_save = _port_interrupt_save,
|
||||
.interrupt_restore = _port_interrupt_restore,
|
||||
.scheduler_disable = os_scheduler_suspend,
|
||||
.scheduler_enable = os_scheduler_resume,
|
||||
.get_work_q_hdl = _port_get_work_q_hdl,
|
||||
.thread_sleep = _port_thread_sleep,
|
||||
};
|
||||
k_init(&init_struct);
|
||||
|
||||
os_work_q_create(default_os_work_q_hdl,
|
||||
"app-work_q",
|
||||
CONFIG_OS_THREAD_MAIN_STACK_SIZE,
|
||||
CONFIG_OS_THREAD_MAIN_PRIORITY);
|
||||
|
||||
static os_work_t _work_hdl_init;
|
||||
os_work_create(&_work_hdl_init, "work-main", work_route, NULL, 3);
|
||||
os_work_submit(default_os_work_q_hdl, &_work_hdl_init, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
static char s_nvs_str_buf[0x40];
|
||||
|
||||
static int _value_set_str(const char *argv[]) { SET_VAR(&s_nvs_str_buf, 0, 0); }
|
||||
static int _value_set_str(const char *argv[]) { return SET_VAR(&s_nvs_str_buf, 0, 0); }
|
||||
|
||||
SH_CMD_FN(_nvs_dump);
|
||||
SH_CMD_FN(_nvs_erase);
|
||||
5
sal/os_entry.h
Normal file
5
sal/os_entry.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "os/os.h"
|
||||
|
||||
int os_entry(os_work_fn work_route);
|
||||
@@ -1,23 +1,23 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
# Espressif IoT Development Framework (ESP-IDF) 5.2.1 Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32c3"
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PRODUCT_TYPE_LEDSTRIP=y
|
||||
CONFIG_CAP_LED_STRIP=y
|
||||
CONFIG_LED_STRIP_SKIP_PWRUP=y
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_LOG_HCI_TRACE_LEVEL_ERROR=y
|
||||
CONFIG_BT_LOG_APPL_TRACE_LEVEL_ERROR=y
|
||||
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
|
||||
CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y
|
||||
CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y
|
||||
CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=18
|
||||
CONFIG_ESP_IPC_TASK_STACK_SIZE=1536
|
||||
CONFIG_ESP_TIMER_TASK_STACK_SIZE=2048
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=768
|
||||
CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y
|
||||
CONFIG_FREERTOS_TIMER_TASK_PRIORITY=25
|
||||
CONFIG_FREERTOS_TIMER_TASK_PRIORITY=24
|
||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=1536
|
||||
CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y
|
||||
CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
|
||||
|
||||
Reference in New Issue
Block a user