From e8d775f888f14e4fe3cc7bd57740fda0caaf4ece Mon Sep 17 00:00:00 2001 From: xfwangqiang <164877907@qq.com> Date: Mon, 30 May 2022 18:00:26 +0800 Subject: [PATCH] [componnets][pin]add pin operate command in MSH (#5892) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 1. 在AT32的BSP的drv_gpio中增加了at32_pin_get函数,用于实现rt_pin_ops对象中的pin_get 2. 在MSH中增加了PIN的操作命令 3. 为了方便在MSH命令中解析字符串,增加了一些字符串相关的函数 --- bsp/at32/libraries/rt_drivers/drv_gpio.c | 39 ++- bsp/stm32/libraries/HAL_Drivers/drv_gpio.c | 1 + components/drivers/misc/pin.c | 263 +++++++++++++++++++-- components/finsh/SConscript | 1 + components/finsh/finsh.h | 12 +- components/finsh/msh_parse.c | 96 ++++++++ components/finsh/msh_parse.h | 20 ++ 7 files changed, 403 insertions(+), 29 deletions(-) create mode 100644 components/finsh/msh_parse.c create mode 100644 components/finsh/msh_parse.h diff --git a/bsp/at32/libraries/rt_drivers/drv_gpio.c b/bsp/at32/libraries/rt_drivers/drv_gpio.c index b4fa19408d..9417446367 100644 --- a/bsp/at32/libraries/rt_drivers/drv_gpio.c +++ b/bsp/at32/libraries/rt_drivers/drv_gpio.c @@ -102,6 +102,43 @@ static uint32_t pin_irq_enable_mask = 0; #define ITEM_NUM(items) sizeof(items) / sizeof(items[0]) +static rt_base_t at32_pin_get(const char *name) +{ + rt_base_t pin = 0; + int hw_port_num, hw_pin_num = 0; + int i, name_len; + + name_len = rt_strlen(name); + + if ((name_len < 4) || (name_len >= 6)) + { + return -RT_EINVAL; + } + if ((name[0] != 'P') || (name[2] != '.')) + { + return -RT_EINVAL; + } + + if ((name[1] >= 'A') && (name[1] <= 'Z')) + { + hw_port_num = (int)(name[1] - 'A'); + } + else + { + return -RT_EINVAL; + } + + for (i = 3; i < name_len; i++) + { + hw_pin_num *= 10; + hw_pin_num += name[i] - '0'; + } + + pin = PIN_NUM(hw_port_num, hw_pin_num); + + return pin; +} + static void at32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) { gpio_type *gpio_port; @@ -423,7 +460,7 @@ const static struct rt_pin_ops _at32_pin_ops = at32_pin_attach_irq, at32_pin_dettach_irq, at32_pin_irq_enable, - RT_NULL, + at32_pin_get, }; rt_inline void pin_irq_handler(int irqno) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_gpio.c b/bsp/stm32/libraries/HAL_Drivers/drv_gpio.c index ee06f26003..b50819f579 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_gpio.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_gpio.c @@ -161,6 +161,7 @@ static uint32_t pin_irq_enable_mask = 0; #define ITEM_NUM(items) sizeof(items) / sizeof(items[0]) +/* e.g. PE.7 */ static rt_base_t stm32_pin_get(const char *name) { rt_base_t pin = 0; diff --git a/components/drivers/misc/pin.c b/components/drivers/misc/pin.c index f12dffdcfc..91913dccfd 100644 --- a/components/drivers/misc/pin.c +++ b/components/drivers/misc/pin.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,14 +7,11 @@ * Date Author Notes * 2015-01-20 Bernard the first version * 2021-02-06 Meco Man fix RT_ENOSYS code in negative + * 2022-04-29 WangQiang add pin operate command in MSH */ #include -#ifdef RT_USING_FINSH -#include -#endif - static struct rt_device_pin _hw_pin; static rt_size_t _pin_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) { @@ -24,8 +21,9 @@ static rt_size_t _pin_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_ /* check parameters */ RT_ASSERT(pin != RT_NULL); - status = (struct rt_device_pin_status *) buffer; - if (status == RT_NULL || size != sizeof(*status)) return 0; + status = (struct rt_device_pin_status *)buffer; + if (status == RT_NULL || size != sizeof(*status)) + return 0; status->status = pin->ops->pin_read(dev, status->pin); return size; @@ -39,8 +37,9 @@ static rt_size_t _pin_write(rt_device_t dev, rt_off_t pos, const void *buffer, r /* check parameters */ RT_ASSERT(pin != RT_NULL); - status = (struct rt_device_pin_status *) buffer; - if (status == RT_NULL || size != sizeof(*status)) return 0; + status = (struct rt_device_pin_status *)buffer; + if (status == RT_NULL || size != sizeof(*status)) + return 0; pin->ops->pin_write(dev, (rt_base_t)status->pin, (rt_base_t)status->status); @@ -55,8 +54,9 @@ static rt_err_t _pin_control(rt_device_t dev, int cmd, void *args) /* check parameters */ RT_ASSERT(pin != RT_NULL); - mode = (struct rt_device_pin_mode *) args; - if (mode == RT_NULL) return -RT_ERROR; + mode = (struct rt_device_pin_mode *)args; + if (mode == RT_NULL) + return -RT_ERROR; pin->ops->pin_mode(dev, (rt_base_t)mode->pin, (rt_base_t)mode->mode); @@ -102,10 +102,10 @@ int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void } rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, - void (*hdr)(void *args), void *args) + void (*hdr)(void *args), void *args) { RT_ASSERT(_hw_pin.ops != RT_NULL); - if(_hw_pin.ops->pin_attach_irq) + if (_hw_pin.ops->pin_attach_irq) { return _hw_pin.ops->pin_attach_irq(&_hw_pin.parent, pin, mode, hdr, args); } @@ -115,7 +115,7 @@ rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, rt_err_t rt_pin_detach_irq(rt_int32_t pin) { RT_ASSERT(_hw_pin.ops != RT_NULL); - if(_hw_pin.ops->pin_detach_irq) + if (_hw_pin.ops->pin_detach_irq) { return _hw_pin.ops->pin_detach_irq(&_hw_pin.parent, pin); } @@ -125,7 +125,7 @@ rt_err_t rt_pin_detach_irq(rt_int32_t pin) rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled) { RT_ASSERT(_hw_pin.ops != RT_NULL); - if(_hw_pin.ops->pin_irq_enable) + if (_hw_pin.ops->pin_irq_enable) { return _hw_pin.ops->pin_irq_enable(&_hw_pin.parent, pin, enabled); } @@ -138,32 +138,251 @@ void rt_pin_mode(rt_base_t pin, rt_base_t mode) RT_ASSERT(_hw_pin.ops != RT_NULL); _hw_pin.ops->pin_mode(&_hw_pin.parent, pin, mode); } -FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_mode, pinMode, set hardware pin mode); void rt_pin_write(rt_base_t pin, rt_base_t value) { RT_ASSERT(_hw_pin.ops != RT_NULL); _hw_pin.ops->pin_write(&_hw_pin.parent, pin, value); } -FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_write, pinWrite, write value to hardware pin); int rt_pin_read(rt_base_t pin) { RT_ASSERT(_hw_pin.ops != RT_NULL); return _hw_pin.ops->pin_read(&_hw_pin.parent, pin); } -FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_read, pinRead, read status from hardware pin); + rt_base_t rt_pin_get(const char *name) { RT_ASSERT(_hw_pin.ops != RT_NULL); - RT_ASSERT(name[0] == 'P'); - if(_hw_pin.ops->pin_get == RT_NULL) + if (name[0] != 'P' && name[0] != 'p') + { + return -RT_EINVAL; + } + if (_hw_pin.ops->pin_get == RT_NULL) { return -RT_ENOSYS; } - return _hw_pin.ops->pin_get(name); } -FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_get, pinGet, get pin number from hardware pin); + +#ifdef RT_USING_FINSH +#include +#include +#include +#include +#include + +/* + * convert function for port name + * support PE02, PE2, PE.02, PE.2, pe02, pe2, pe.02, pe.2 + */ +static rt_base_t _pin_cmd_conv(const char *name) +{ + int size = 0; + char format_name[6] = { 0 }; + format_name[0] = toupper(name[0]); + format_name[1] = toupper(name[1]); + + size = rt_strlen(name); + size = (size > 5) ? 5 : size; + size -= 2; + if (name[2] != '.') + { + format_name[2] = '.'; + } + strncat(format_name, name + 2, size); + return rt_pin_get(format_name); +} + +static void _pin_cmd_print_usage(void) +{ + rt_kprintf("pin [option]\n"); + rt_kprintf(" num: get pin number from hardware pin\n"); + rt_kprintf(" num can be PE02, PE2, PE.02, PE.2, pe02, pe2, pe.02, pe.2\n"); + rt_kprintf(" e.g. MSH >pin num PA.16\n"); + rt_kprintf(" mode: set pin mode to output/input/input_pullup/input_pulldown/output_od\n e.g. MSH >pin mode PA.16 output\n"); + rt_kprintf(" read: read pin level of hardware pin\n e.g. MSH >pin read PA.16\n"); + rt_kprintf(" write: write pin level(high/low or on/off) to hardware pin\n e.g. MSH >pin write PA.16 high\n"); + rt_kprintf(" help: this help list\n"); +} + +/* e.g. MSH >pin num PA.16 */ +static void _pin_cmd_get(int argc, char *argv[]) +{ + rt_base_t pin; + if (argc < 3) + { + _pin_cmd_print_usage(); + return; + } + pin = _pin_cmd_conv(argv[2]); + if (pin < 0) + { + rt_kprintf("Parameter invalid : %s!\n", argv[2]); + _pin_cmd_print_usage(); + return ; + } + rt_kprintf("%s : %d\n", argv[2], pin); +} + +/* e.g. MSH >pin mode PA.16 output */ +static void _pin_cmd_mode(int argc, char *argv[]) +{ + rt_base_t pin; + rt_base_t mode; + if (argc < 4) + { + _pin_cmd_print_usage(); + return; + } + if (!msh_isint(argv[2])) + { + pin = _pin_cmd_conv(argv[2]); + if (pin < 0) + { + rt_kprintf("Parameter invalid : %s!\n", argv[2]); + _pin_cmd_print_usage(); + return; + } + } + else + { + pin = atoi(argv[2]); + } + if (0 == rt_strcmp("output", argv[3])) + { + mode = PIN_MODE_OUTPUT; + } + else if (0 == rt_strcmp("input", argv[3])) + { + mode = PIN_MODE_INPUT; + } + else if (0 == rt_strcmp("input_pullup", argv[3])) + { + mode = PIN_MODE_INPUT_PULLUP; + } + else if (0 == rt_strcmp("input_pulldown", argv[3])) + { + mode = PIN_MODE_INPUT_PULLDOWN; + } + else if (0 == rt_strcmp("output_od", argv[3])) + { + mode = PIN_MODE_OUTPUT_OD; + } + else + { + _pin_cmd_print_usage(); + return; + } + + rt_pin_mode(pin, mode); +} + +/* e.g. MSH >pin read PA.16 */ +static void _pin_cmd_read(int argc, char *argv[]) +{ + rt_base_t pin; + rt_base_t value; + if (argc < 3) + { + _pin_cmd_print_usage(); + return; + } + if (!msh_isint(argv[2])) + { + pin = _pin_cmd_conv(argv[2]); + if (pin < 0) + { + rt_kprintf("Parameter invalid : %s!\n", argv[2]); + _pin_cmd_print_usage(); + return; + } + } + else + { + pin = atoi(argv[2]); + } + value = rt_pin_read(pin); + if (value == PIN_HIGH) + { + rt_kprintf("pin[%d] = on\n", pin); + } + else + { + rt_kprintf("pin[%d] = off\n", pin); + } +} + +/* e.g. MSH >pin write PA.16 high */ +static void _pin_cmd_write(int argc, char *argv[]) +{ + rt_base_t pin; + rt_base_t value; + if (argc < 4) + { + _pin_cmd_print_usage(); + return; + } + if (!msh_isint(argv[2])) + { + pin = _pin_cmd_conv(argv[2]); + if (pin < 0) + { + rt_kprintf("Parameter invalid : %s!\n", argv[2]); + _pin_cmd_print_usage(); + return; + } + } + else + { + pin = atoi(argv[2]); + } + if ((0 == rt_strcmp("high", argv[3])) || (0 == rt_strcmp("on", argv[3]))) + { + value = PIN_HIGH; + } + else if ((0 == rt_strcmp("low", argv[3])) || (0 == rt_strcmp("off", argv[3]))) + { + value = PIN_LOW; + } + else + { + _pin_cmd_print_usage(); + return; + } + rt_pin_write(pin, value); +} + +static void _pin_cmd(int argc, char *argv[]) +{ + if (argc < 3) + { + _pin_cmd_print_usage(); + return ; + } + if (0 == rt_strcmp("num", argv[1])) + { + _pin_cmd_get(argc, argv); + } + else if (0 == rt_strcmp("mode", argv[1])) + { + _pin_cmd_mode(argc, argv); + } + else if (0 == rt_strcmp("read", argv[1])) + { + _pin_cmd_read(argc, argv); + } + else if (0 == rt_strcmp("write", argv[1])) + { + _pin_cmd_write(argc, argv); + } + else + { + _pin_cmd_print_usage(); + return; + } +} +MSH_CMD_EXPORT_ALIAS(_pin_cmd, pin, pin [option]); +#endif /* RT_USING_FINSH */ diff --git a/components/finsh/SConscript b/components/finsh/SConscript index 9b2faa2283..70f8e5608c 100644 --- a/components/finsh/SConscript +++ b/components/finsh/SConscript @@ -4,6 +4,7 @@ cwd = GetCurrentDir() src = Split(''' shell.c msh.c +msh_parse.c ''') if GetDepend('MSH_USING_BUILT_IN_COMMANDS'): diff --git a/components/finsh/finsh.h b/components/finsh/finsh.h index 05399e1863..a26b26fb7e 100644 --- a/components/finsh/finsh.h +++ b/components/finsh/finsh.h @@ -10,17 +10,17 @@ #ifndef __FINSH_H__ #define __FINSH_H__ -#include +#include -#if defined(_MSC_VER) - #pragma section("FSymTab$f",read) -#endif +#ifdef _MSC_VER +#pragma section("FSymTab$f",read) +#endif /* _MSC_VER */ typedef long (*syscall_func)(void); #ifdef FINSH_USING_SYMTAB #ifdef __TI_COMPILER_VERSION__ - #define __TI_FINSH_EXPORT_FUNCTION(f) PRAGMA(DATA_SECTION(f,"FSymTab")) -#endif +#define __TI_FINSH_EXPORT_FUNCTION(f) PRAGMA(DATA_SECTION(f,"FSymTab")) +#endif /* __TI_COMPILER_VERSION__ */ #ifdef FINSH_USING_DESCRIPTION #ifdef _MSC_VER #define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \ diff --git a/components/finsh/msh_parse.c b/components/finsh/msh_parse.c new file mode 100644 index 0000000000..a0f5f5e96d --- /dev/null +++ b/components/finsh/msh_parse.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-25 WangQiang the first verion for msh parse + */ + +#include +#include + +#define forstrloop(str) for (; '\0' != *(str); (str)++) + +/** + * This function will check integer. + * + * @param strvalue string + * + * @return true or false + */ +rt_bool_t msh_isint(char *strvalue) +{ + if ((RT_NULL == strvalue) || ('\0' == strvalue[0])) + { + return RT_FALSE; + } + if (('+' == *strvalue) || ('-' == *strvalue)) + { + strvalue++; + } + forstrloop(strvalue) + { + if (!isdigit((int)(*strvalue))) + { + return RT_FALSE; + } + } + return RT_TRUE; +} + +/** + * This function will check hex. + * + * @param strvalue string + * + * @return true or false + */ +rt_bool_t msh_ishex(char *strvalue) +{ + int c; + if ((RT_NULL == strvalue) || ('\0' == strvalue[0])) + { + return RT_FALSE; + } + if ('0' != *(strvalue++)) + { + return RT_FALSE; + } + if ('x' != *(strvalue++)) + { + return RT_FALSE; + } + + forstrloop(strvalue) + { + c = tolower(*strvalue); + if (!isxdigit(c)) + { + return RT_FALSE; + } + } + return RT_TRUE; +} + +/** + * This function will transform for string to hex. + * + * @param strvalue string + * + * @return true or false + */ +int msh_strtohex(char *strvalue) +{ + char c = 0; + int value = 0; + strvalue += 2; + forstrloop(strvalue) + { + value *= 16; + c = tolower(*strvalue); + value += isdigit(c) ? c - '0' : c - 'a' + 10; + } + return value; +} diff --git a/components/finsh/msh_parse.h b/components/finsh/msh_parse.h new file mode 100644 index 0000000000..ba14625e92 --- /dev/null +++ b/components/finsh/msh_parse.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-25 WangQiang the first verion for msh parse + */ + +#ifndef MSH_PARSE_H +#define MSH_PARSE_H + +#include + +rt_bool_t msh_isint(char *strvalue); +rt_bool_t msh_ishex(char *strvalue); +int msh_strtohex(char *strvalue); + +#endif /* MSH_PARSE_H */