diff --git a/CMakeLists.txt b/CMakeLists.txt index baf1911..9148d0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt new file mode 100644 index 0000000..b3dbd27 --- /dev/null +++ b/app/CMakeLists.txt @@ -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 + ) diff --git a/app/app_main.c b/app/app_main.c index b80f1d1..7464d0e 100644 --- a/app/app_main.c +++ b/app/app_main.c @@ -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) diff --git a/app/console.c b/app/console.c index ec3735c..a22dcd8 100644 --- a/app/console.c +++ b/app/console.c @@ -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); diff --git a/app/console.h b/app/console.h index 1b5e85c..cd4b170 100644 --- a/app/console.h +++ b/app/console.h @@ -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); diff --git a/app/drivers/ws2812_spi/ws2812_spi.c b/app/drivers/ws2812_spi/ws2812_spi.c new file mode 100755 index 0000000..e1b5580 --- /dev/null +++ b/app/drivers/ws2812_spi/ws2812_spi.c @@ -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 +#include +#include +#include + +#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; +} diff --git a/app/drivers/ws2812_spi/ws2812_spi.h b/app/drivers/ws2812_spi/ws2812_spi.h new file mode 100755 index 0000000..dcb7d76 --- /dev/null +++ b/app/drivers/ws2812_spi/ws2812_spi.h @@ -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 +#include + +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); diff --git a/app/drivers/ws2812_spi/ws2812_spi_shell.c b/app/drivers/ws2812_spi/ws2812_spi_shell.c new file mode 100644 index 0000000..6bcf1e7 --- /dev/null +++ b/app/drivers/ws2812_spi/ws2812_spi_shell.c @@ -0,0 +1,95 @@ +#include "ws2812_spi_shell.h" +#include "ws2812_spi.h" +#include "shell/sh.h" +#include "sh_vset.h" + +#include + +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; +} diff --git a/app/drivers/ws2812_spi/ws2812_spi_shell.h b/app/drivers/ws2812_spi/ws2812_spi_shell.h new file mode 100644 index 0000000..cc733ad --- /dev/null +++ b/app/drivers/ws2812_spi/ws2812_spi_shell.h @@ -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); diff --git a/app/drivers/ws2812_spi/ws2812b中文资料-数据手册-参数.pdf b/app/drivers/ws2812_spi/ws2812b中文资料-数据手册-参数.pdf new file mode 100755 index 0000000..09da939 Binary files /dev/null and b/app/drivers/ws2812_spi/ws2812b中文资料-数据手册-参数.pdf differ diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt new file mode 100644 index 0000000..6da7f0a --- /dev/null +++ b/components/CMakeLists.txt @@ -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} +) diff --git a/components/system/include/drivers/chip/misc.h b/components/system/include/drivers/chip/misc.h index e8a486f..1ff12e9 100755 --- a/components/system/include/drivers/chip/misc.h +++ b/components/system/include/drivers/chip/misc.h @@ -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 } diff --git a/components/system/include/os/os_work.h b/components/system/include/os/os_work.h index f0ff94d..ecdbafc 100755 --- a/components/system/include/os/os_work.h +++ b/components/system/include/os/os_work.h @@ -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); diff --git a/components/system/source/k_kit/k_kit.c b/components/system/source/k_kit/k_kit.c index e6c7c4a..c42e0bf 100755 --- a/components/system/source/k_kit/k_kit.c +++ b/components/system/source/k_kit/k_kit.c @@ -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,24 +1424,26 @@ k_tick_t k_work_q_handler(k_work_q_t *work_q_handle) } work_q->curr_work = last_work; - if (exec_work->delete_flag == 0) + if (k_work_is_valid(exec_work->work_handle)) { - _ASSERT_FALSE(!k_work_is_valid(exec_work->work_handle), "exec_work->work_handle maybe be deleted"); - - exec_work->exec_flag = 0; - if (exec_work->obj_flag_type == 0 && exec_work->obj_data.mbox_list != NULL) + if (exec_work->delete_flag == 0) { - if (_slist_peek_head(&exec_work->obj_data.mbox_list->mbox_idle) != NULL) + exec_work->exec_flag = exec_flag; + if (exec_work->obj_flag_type == 0 && exec_work->obj_data.mbox_list != NULL) { - _K_DIS_SCHED(); - _k_work_mbox_clr_list(&exec_work->obj_data.mbox_list->mbox_idle); - _K_EN_SCHED(); + if (_slist_peek_head(&exec_work->obj_data.mbox_list->mbox_idle) != NULL) + { + _K_DIS_SCHED(); + _k_work_mbox_clr_list(&exec_work->obj_data.mbox_list->mbox_idle); + _K_EN_SCHED(); + } } } - } - else - { - k_work_delete(exec_work->work_handle); + else + { + exec_work->exec_flag = 0; + k_work_delete(exec_work->work_handle); + } } } } @@ -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,24 +2102,26 @@ void k_work_sleep(k_tick_t delay_ticks) } _WORK_Q->curr_work = work_handle; - if (exec_work->delete_flag == 0) + if (k_work_is_valid(exec_work->work_handle)) { - _ASSERT_FALSE(!k_work_is_valid(exec_work->work_handle), "exec_work->work_handle maybe be deleted"); - - exec_work->exec_flag = 0; - if (exec_work->obj_flag_type == 0 && exec_work->obj_data.mbox_list != NULL) + if (exec_work->delete_flag == 0) { - if (_slist_peek_head(&exec_work->obj_data.mbox_list->mbox_idle) != NULL) + exec_work->exec_flag = exec_flag; + if (exec_work->obj_flag_type == 0 && exec_work->obj_data.mbox_list != NULL) { - _K_DIS_SCHED(); - _k_work_mbox_clr_list(&exec_work->obj_data.mbox_list->mbox_idle); - _K_EN_SCHED(); + if (_slist_peek_head(&exec_work->obj_data.mbox_list->mbox_idle) != NULL) + { + _K_DIS_SCHED(); + _k_work_mbox_clr_list(&exec_work->obj_data.mbox_list->mbox_idle); + _K_EN_SCHED(); + } } } - } - else - { - k_work_delete(exec_work->work_handle); + else + { + exec_work->exec_flag = 0; + k_work_delete(exec_work->work_handle); + } } } } @@ -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,11 +2778,12 @@ 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_do_submit(work->work_q_handle, (k_work_t *)timer_handle, _K_PORT->get_sys_ticks() + delay_ticks, _FALSE); - } + 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); } /** @@ -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,26 +3104,27 @@ 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 (;;) { - for (;;) + __slist_node_t *node = _slist_take_head(&fifo_q->list); + if (node == NULL) { - __slist_node_t *node = _slist_take_head(&fifo_q->list); - if (node == NULL) - { - break; - } - else - { - k_fifo_handle_t *fifo_data = _K_CONTAINER_OF(node, k_fifo_handle_t, ctrl.state_node); - _K_PORT->free(fifo_data); - } + break; + } + else + { + k_fifo_handle_t *fifo_data = _K_CONTAINER_OF(node, k_fifo_handle_t, ctrl.state_node); + _K_PORT->free(fifo_data); } - _K_PORT->free(fifo_q); - fifo_handle->hdl = NULL; } + _K_PORT->free(fifo_q); + fifo_handle->hdl = NULL; + _K_EN_SCHED(); } @@ -3108,25 +3138,25 @@ 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 (;;) { - for (;;) + __slist_node_t *node = _slist_take_head(&fifo_q->list); + if (node == NULL) { - __slist_node_t *node = _slist_take_head(&fifo_q->list); - if (node == NULL) - { - break; - } - else - { - k_fifo_handle_t *fifo_data = _K_CONTAINER_OF(node, k_fifo_handle_t, ctrl.state_node); - _K_PORT->free(fifo_data); - } + break; + } + else + { + k_fifo_handle_t *fifo_data = _K_CONTAINER_OF(node, k_fifo_handle_t, ctrl.state_node); + _K_PORT->free(fifo_data); } } + _K_EN_SCHED(); } @@ -3159,12 +3189,13 @@ 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) - { - fifo_q->resume_work = work_handle; - fifo_q->resume_delay = delay_ticks; - } + 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; } /** @@ -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,12 +3550,13 @@ 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) - { - queue->resume_work = work_handle; - queue->resume_delay = delay_ticks; - } + k_queue_handle_t *queue; + + _TEST_HANDLE(queue_handle, return); + + queue = queue_handle->hdl; + queue->resume_work = work_handle; + queue->resume_delay = delay_ticks; } /** @@ -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_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,12 +3973,13 @@ 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) - { - pipe->resume_work = work_handle; - pipe->resume_delay = delay_ticks; - } + k_pipe_handle_t *pipe; + + _TEST_HANDLE(pipe_handle, return); + + pipe = pipe_handle->hdl; + pipe->resume_work = work_handle; + pipe->resume_delay = delay_ticks; } /** @@ -3971,34 +4002,34 @@ 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) + _TEST_HANDLE(pipe_handle, return 0); + + pipe = (k_pipe_handle_t *)pipe_handle->hdl; + wid = pipe->wid; + if (++wid >= pipe->size) { - pipe_id_t wid = pipe->wid; + wid = 0; + } - if (++wid >= pipe->size) + if (wid != pipe->rid) + { + ((uint8_t *)&pipe[1])[pipe->wid] = data; + + _K_DIS_INT(); + resume_flag = (pipe->wid == pipe->rid); + pipe->wid = wid; + _K_EN_INT(); + + if (resume_flag) { - wid = 0; + _k_ipc_resume(pipe->resume_work, pipe->resume_delay, 0); } - if (wid != pipe->rid) - { - ((uint8_t *)&pipe[1])[pipe->wid] = data; - - _K_DIS_INT(); - resume_flag = (pipe->wid == pipe->rid); - pipe->wid = wid; - _K_EN_INT(); - - if (resume_flag) - { - _k_ipc_resume(pipe->resume_work, pipe->resume_delay, 0); - } - - return 1; - } + return 1; } return 0; @@ -4015,57 +4046,57 @@ 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) + _TEST_HANDLE(pipe_handle, return 0); + + pipe = (k_pipe_handle_t *)pipe_handle->hdl; + wid = pipe->wid; + resume_flag = (wid == pipe->rid); + + while (size) { - pipe_id_t wid = pipe->wid; + pipe_id_t rid = *(volatile pipe_id_t *)&pipe->rid; + pipe_id_t min; + pipe_id_t remain; - resume_flag = (wid == pipe->rid); - - while (size) + if (wid >= rid) { - pipe_id_t rid = *(volatile pipe_id_t *)&pipe->rid; - pipe_id_t min; - pipe_id_t remain; - - if (wid >= rid) - { - remain = pipe->size - wid - (rid == 0); - } - else - { - remain = rid - wid - 1; - } - if (remain == 0) - { - break; - } - min = size < remain ? size : remain; - - if (data) - { - memcpy(&((uint8_t *)&pipe[1])[wid], &((uint8_t *)data)[ret], min); - } - - if ((wid += min) >= pipe->size) - { - wid = 0; - } - - size -= min; - ret += min; + remain = pipe->size - wid - (rid == 0); } - _K_DIS_INT(); - resume_flag = (pipe->wid == pipe->rid); - pipe->wid = wid; - _K_EN_INT(); - - if (resume_flag && ret) + else { - _k_ipc_resume(pipe->resume_work, pipe->resume_delay, 0); + remain = rid - wid - 1; } + if (remain == 0) + { + break; + } + min = size < remain ? size : remain; + + if (data) + { + memcpy(&((uint8_t *)&pipe[1])[wid], &((uint8_t *)data)[ret], min); + } + + if ((wid += min) >= pipe->size) + { + wid = 0; + } + + size -= min; + ret += min; + } + _K_DIS_INT(); + resume_flag = (pipe->wid == pipe->rid); + pipe->wid = wid; + _K_EN_INT(); + + if (resume_flag && ret) + { + _k_ipc_resume(pipe->resume_work, pipe->resume_delay, 0); } return ret; @@ -4080,24 +4111,25 @@ 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) + _TEST_HANDLE(pipe_handle, return 0); + + pipe = (k_pipe_handle_t *)pipe_handle->hdl; + rid = pipe->rid; + if (rid != pipe->wid) { - pipe_id_t rid = pipe->rid; - if (rid != pipe->wid) + data[0] = ((uint8_t *)&pipe[1])[rid++]; + if (rid < pipe->size) { - data[0] = ((uint8_t *)&pipe[1])[rid++]; - if (rid < pipe->size) - { - pipe->rid = rid; - } - else - { - pipe->rid = 0; - } - return 1; + pipe->rid = rid; } + else + { + pipe->rid = 0; + } + return 1; } return 0; @@ -4114,46 +4146,47 @@ 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) + _TEST_HANDLE(pipe_handle, return 0); + + pipe = (k_pipe_handle_t *)pipe_handle->hdl; + rid = pipe->rid; + while (size) { - pipe_id_t rid = pipe->rid; - while (size) + pipe_id_t wid = *(volatile pipe_id_t *)&pipe->wid; + pipe_id_t min; + pipe_id_t remain; + + if (rid > wid) { - pipe_id_t wid = *(volatile pipe_id_t *)&pipe->wid; - pipe_id_t min; - pipe_id_t remain; - - if (rid > wid) - { - remain = pipe->size - rid; - } - else - { - remain = wid - rid; - } - if (remain == 0) - { - break; - } - min = size < remain ? size : remain; - - if (data) - { - memcpy(&((uint8_t *)data)[ret], &((uint8_t *)&pipe[1])[rid], min); - } - - if ((rid += min) >= pipe->size) - { - rid = 0; - } - - size -= min; - ret += min; + remain = pipe->size - rid; } - pipe->rid = rid; + else + { + remain = wid - rid; + } + if (remain == 0) + { + break; + } + min = size < remain ? size : remain; + + if (data) + { + memcpy(&((uint8_t *)data)[ret], &((uint8_t *)&pipe[1])[rid], min); + } + + if ((rid += min) >= pipe->size) + { + rid = 0; + } + + size -= min; + ret += min; } + pipe->rid = rid; return ret; } @@ -4167,21 +4200,18 @@ 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) + 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; } else { - k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl; - if (pipe->rid == pipe->wid) - { - return _FALSE; - } - else - { - return _TRUE; - } + return _TRUE; } } @@ -4193,21 +4223,18 @@ 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) + 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 0; + return pipe->size + pipe->wid - pipe->rid; } else { - k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl; - if (pipe->wid < pipe->rid) - { - return pipe->size + pipe->wid - pipe->rid; - } - else - { - return pipe->wid - pipe->rid; - } + return pipe->wid - pipe->rid; } } @@ -4219,15 +4246,12 @@ 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; - return pipe->size - (k_pipe_get_valid_size(pipe_handle) + 1); - } + 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); } /** @@ -4242,25 +4266,26 @@ 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; + + _TEST_HANDLE(pipe_handle, return); + + pipe = (k_pipe_handle_t *)pipe_handle->hdl; + if (dst_base) { - k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl; - if (dst_base) + *dst_base = (&((uint8_t *)&pipe[1])[pipe->rid]); + } + if (dst_size) + { + pipe_id_t rid = pipe->rid; + pipe_id_t wid = pipe->wid; + if (rid > wid) { - *dst_base = (&((uint8_t *)&pipe[1])[pipe->rid]); + *dst_size = pipe->size - rid; } - if (dst_size) + else { - pipe_id_t rid = pipe->rid; - pipe_id_t wid = pipe->wid; - if (rid > wid) - { - *dst_size = pipe->size - rid; - } - else - { - *dst_size = wid - rid; - } + *dst_size = wid - rid; } } } @@ -4277,25 +4302,26 @@ 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; + + _TEST_HANDLE(pipe_handle, return); + + pipe = (k_pipe_handle_t *)pipe_handle->hdl; + if (dst_base) { - k_pipe_handle_t *pipe = (k_pipe_handle_t *)pipe_handle->hdl; - if (dst_base) + *dst_base = (&((uint8_t *)&pipe[1])[pipe->wid]); + } + if (dst_size) + { + pipe_id_t rid = pipe->rid; + pipe_id_t wid = pipe->wid; + if (wid >= rid) { - *dst_base = (&((uint8_t *)&pipe[1])[pipe->wid]); + *dst_size = pipe->size - wid - (rid == 0); } - if (dst_size) + else { - pipe_id_t rid = pipe->rid; - pipe_id_t wid = pipe->wid; - if (wid >= rid) - { - *dst_size = pipe->size - wid - (rid == 0); - } - else - { - *dst_size = rid - wid - 1; - } + *dst_size = rid - wid - 1; } } } diff --git a/components/system/source/shell/README.md b/components/system/source/shell/README.md index 29e3827..f5be8e4 100755 --- a/components/system/source/shell/README.md +++ b/components/system/source/shell/README.md @@ -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() diff --git a/components/system/source/shell/sh.c b/components/system/source/shell/sh.c index 6d579d5..edabf34 100755 --- a/components/system/source/shell/sh.c +++ b/components/system/source/shell/sh.c @@ -10,6 +10,7 @@ */ #include "sh.h" +#include "sh_vset.h" #include #include @@ -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(); } } diff --git a/components/system/source/shell/sh.h b/components/system/source/shell/sh.h index 44b8b28..c7c1ecc 100755 --- a/components/system/source/shell/sh.h +++ b/components/system/source/shell/sh.h @@ -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); // 取消所有已注册命令 /* 现成终端协议初始化 ----------------------------------------------------------------- */ @@ -337,7 +339,7 @@ void sh_set_prompt(sh_t *sh_hdl, const char *prompt); // 设置提示符 void sh_reset_line(sh_t *sh_hdl); // 清除命令接收缓存 -int sh_echo(sh_t *sh_hdl, const char *fmt, ...); // 回显到终端 +int sh_echo(sh_t *sh_hdl, const char *fmt, ...); // 回显到终端 sh_parse_t sh_parse_value(const char *str); // 参数工具:解析字符串表示的数值 @@ -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() 中可用,根据当前命令行内容,逐个给出可供查找的提示符。内部将根据所提供的数据自动补全 diff --git a/components/system/source/shell/sh_vset.c b/components/system/source/shell/sh_vset.c index 1e59d1c..8e8a955 100755 --- a/components/system/source/shell/sh_vset.c +++ b/components/system/source/shell/sh_vset.c @@ -25,11 +25,11 @@ #define _TYPE_FLAG_FLOAT (1 << 2) #define _TYPE_FLAG_STRING (1 << 3) -#define _PARAM_CB() \ - do \ - { \ - if (param->cb) \ - param->cb(s_sh_hdl, &value); \ +#define _PARAM_CB() \ + do \ + { \ + 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: // 待设置的参数格式是无符号整型 { diff --git a/components/system/source/shell/sh_vset.h b/components/system/source/shell/sh_vset.h index cff3158..0cc67bf 100755 --- a/components/system/source/shell/sh_vset.h +++ b/components/system/source/shell/sh_vset.h @@ -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,71 +114,41 @@ 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); bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const sh_vset_param_t *p, unsigned size); /* 自动分析并设置变量的值,带设置回调 */ -#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_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 || \ - __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 || \ - __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) +#define SET_VAR_CB(NAME, LOW, HIGH, CB) \ + ((__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U8 || \ + __GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U16 || \ + __GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U32 || \ + __GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_U64) \ + ? 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) \ + ? vset_integer(NAME, __GENERIC_ATTR(*(NAME)), CB, argv, LOW, HIGH) \ + : ((__GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_FLOAT || \ + __GENERIC_ATTR(*(NAME)) == __TYPE_ATTR_DOUBLE) \ + ? 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 diff --git a/components/system/test/os_test.c b/components/system/test/os_test.c index 41d375e..81933fc 100755 --- a/components/system/test/os_test.c +++ b/components/system/test/os_test.c @@ -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() diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 421eeb0..07a58a7 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -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} + ) diff --git a/main/main.c b/main/main.c index b04faee..e9cc13f 100755 --- a/main/main.c +++ b/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); } diff --git a/sal/CMakeLists.txt b/sal/CMakeLists.txt new file mode 100644 index 0000000..0084825 --- /dev/null +++ b/sal/CMakeLists.txt @@ -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 +) diff --git a/sal/esp32s3/chip/uart_esp32.c b/sal/esp32/chip/uart_esp32.c similarity index 100% rename from sal/esp32s3/chip/uart_esp32.c rename to sal/esp32/chip/uart_esp32.c diff --git a/sal/esp32s3/kernel/os_debug.h b/sal/esp32/kernel/os_debug.h similarity index 100% rename from sal/esp32s3/kernel/os_debug.h rename to sal/esp32/kernel/os_debug.h diff --git a/sal/esp32s3/kernel/os_heap.c b/sal/esp32/kernel/os_heap.c similarity index 100% rename from sal/esp32s3/kernel/os_heap.c rename to sal/esp32/kernel/os_heap.c diff --git a/sal/esp32s3/kernel/os_hook.c b/sal/esp32/kernel/os_hook.c similarity index 100% rename from sal/esp32s3/kernel/os_hook.c rename to sal/esp32/kernel/os_hook.c diff --git a/sal/esp32s3/kernel/os_kit.c b/sal/esp32/kernel/os_kit.c similarity index 93% rename from sal/esp32s3/kernel/os_kit.c rename to sal/esp32/kernel/os_kit.c index 700f94c..450cf6d 100755 --- a/sal/esp32s3/kernel/os_kit.c +++ b/sal/esp32/kernel/os_kit.c @@ -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(); diff --git a/sal/esp32s3/kernel/os_mutex.c b/sal/esp32/kernel/os_mutex.c similarity index 100% rename from sal/esp32s3/kernel/os_mutex.c rename to sal/esp32/kernel/os_mutex.c diff --git a/sal/esp32s3/kernel/os_semaphore.c b/sal/esp32/kernel/os_semaphore.c similarity index 100% rename from sal/esp32s3/kernel/os_semaphore.c rename to sal/esp32/kernel/os_semaphore.c diff --git a/sal/esp32s3/kernel/os_service.c b/sal/esp32/kernel/os_service.c similarity index 100% rename from sal/esp32s3/kernel/os_service.c rename to sal/esp32/kernel/os_service.c diff --git a/sal/esp32s3/kernel/os_thread.c b/sal/esp32/kernel/os_thread.c similarity index 99% rename from sal/esp32s3/kernel/os_thread.c rename to sal/esp32/kernel/os_thread.c index 1f78185..72aa079 100755 --- a/sal/esp32s3/kernel/os_thread.c +++ b/sal/esp32/kernel/os_thread.c @@ -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); diff --git a/sal/esp32s3/kernel/os_timer.c b/sal/esp32/kernel/os_timer.c similarity index 100% rename from sal/esp32s3/kernel/os_timer.c rename to sal/esp32/kernel/os_timer.c diff --git a/sal/esp32s3/kernel/os_util.h b/sal/esp32/kernel/os_util.h similarity index 100% rename from sal/esp32s3/kernel/os_util.h rename to sal/esp32/kernel/os_util.h diff --git a/sal/esp32/os_entry.c b/sal/esp32/os_entry.c new file mode 100644 index 0000000..cfee036 --- /dev/null +++ b/sal/esp32/os_entry.c @@ -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; +} diff --git a/sal/esp32s3/soc_shell.c b/sal/esp32/soc_shell.c similarity index 100% rename from sal/esp32s3/soc_shell.c rename to sal/esp32/soc_shell.c diff --git a/sal/esp32s3/soc_shell_base.c b/sal/esp32/soc_shell_base.c similarity index 100% rename from sal/esp32s3/soc_shell_base.c rename to sal/esp32/soc_shell_base.c diff --git a/sal/esp32s3/soc_shell_nvs.c b/sal/esp32/soc_shell_nvs.c similarity index 97% rename from sal/esp32s3/soc_shell_nvs.c rename to sal/esp32/soc_shell_nvs.c index 201f8bd..d059b01 100644 --- a/sal/esp32s3/soc_shell_nvs.c +++ b/sal/esp32/soc_shell_nvs.c @@ -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); diff --git a/sal/os_entry.h b/sal/os_entry.h new file mode 100644 index 0000000..9259c46 --- /dev/null +++ b/sal/os_entry.h @@ -0,0 +1,5 @@ +#pragma once + +#include "os/os.h" + +int os_entry(os_work_fn work_route); diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 6ea7a4f..14f4ff1 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -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