查看: 818|回复: 8

【极光LPC845】+串口移植letter-shell

[复制链接]
  • TA的每日心情
    奋斗
    昨天 09:21
  • 签到天数: 1954 天

    [LV.Master]伴坛终老

    61

    主题

    1万

    帖子

    3

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    17447
    最后登录
    2024-5-10
    发表于 2023-6-15 16:32:02 | 显示全部楼层 |阅读模式
    本帖最后由 流水源 于 2023-6-15 16:58 编辑

        本次研究移植letter-shell。letter-shell一个功能强大的嵌入式shell,是一个C语言编写的,可以嵌入在程序中的嵌入式shell,主要面向嵌入式设备,以C语言函数为运行单位,可以通过命令行调用,运行程序中的函数。地址:https://github.com/NevermindZZT/letter-shell

    功能
    • 命令自动补全
    • 快捷键功能定义
    • 命令权限管理
    • 用户管理
    • 变量支持
    • 代理函数和参数代理解析
    下面开始移植:移植流程官方仓库说明的很清晰,看说明照着做一遍基本就可以了。

    //初始化接口,对接串口。
    1. #include "shell_cfg_user.h"
    2. #include "drv_uart.h"
    3. #include "shell.h"


    4. Shell shell;
    5. char shellBuffer[512];


    6. /**
    7. * @brief 用户shell写
    8. *
    9. * @param data 数据
    10. * @param len 数据长度
    11. *
    12. * @return short 实际写入的数据长度
    13. */
    14. short userShellWrite(char *data, unsigned short len)
    15. {
    16.     for(uint32_t i=0;i<len;i++)
    17.         stdout_putchar(data[i]);
    18.     return len;
    19. }


    20. /**
    21. * @brief 用户shell读
    22. *
    23. * @param data 数据
    24. * @param len 数据长度
    25. *
    26. * @return short 实际读取到
    27. */
    28. short userShellRead(char *data, unsigned short len)
    29. {
    30.     uint32_t rlen = 0;
    31.     for(uint32_t i=0;i<len;i++)
    32.     {
    33.         if(shell_uart_rx.read_i != shell_uart_rx.write_i)
    34.         {
    35.             data[rlen++] = shell_uart_rx.buff[shell_uart_rx.read_i++];
    36.             shell_uart_rx.read_i &= 0x7f;
    37.         }
    38.     }
    39.     return rlen;
    40. }

    41. /**
    42. * @brief 用户shell上锁
    43. *
    44. * @param shell shell
    45. *
    46. * @return int 0
    47. */
    48. int userShellLock(Shell *shell)
    49. {
    50.     return 0;
    51. }

    52. /**
    53. * @brief 用户shell解锁
    54. *
    55. * @param shell shell
    56. *
    57. * @return int 0
    58. */
    59. int userShellUnlock(Shell *shell)
    60. {
    61.     return 0;
    62. }

    63. /**
    64. * @brief 用户shell初始化
    65. *
    66. */
    67. void userShellInit(void)
    68. {
    69.     shell.write = userShellWrite;
    70.     shell.read = userShellRead;
    71. //    shell.lock = userShellLock;
    72. //    shell.unlock = userShellUnlock;
    73.     shellInit(&shell, shellBuffer, 512);

    74. }
    复制代码

    串口部分:
    初始化调用:userShellInit(); //letter shell
    主循环中调用:shell_usart_loop();调用shellHandler()处理串口接收的字符。
    1. void drv_usart_gpio_init(void)
    2. {
    3.     usart_config_t   USART_InitStructure;
    4.    
    5.     CLOCK_Select(kUART0_Clk_From_MainClk);
    6.     RESET_PeripheralReset(kUART0_RST_N_SHIFT_RSTn);
    7.    
    8.     USART_GetDefaultConfig(&USART_InitStructure);
    9.     USART_InitStructure.baudRate_Bps = 115200;
    10.     USART_InitStructure.enableRx     = 1U;
    11.     USART_InitStructure.enableTx     = 1U;
    12.     USART_Init(USART0, &USART_InitStructure, CLOCK_GetMainClkFreq());
    13.    
    14.     //使能UARTx RC中断
    15.     USART_EnableInterrupts(USART0, kUSART_RxReadyInterruptEnable);
    16.     //优先级,无优先级分组
    17.     NVIC_SetPriority(USART0_IRQn, 0);
    18.     //UARTx中断使能
    19.     NVIC_EnableIRQ(USART0_IRQn);

    20. #if UART_SHELL == LETTER_SHELL
    21.     userShellInit(); //letter shell
    22. #elif UART_SHELL == NR_MICRO_SHELL
    23.     shell_init();
    24. #endif
    25. }

    26. int stdout_putchar (int ch)
    27. {
    28.     while (0 == (USART_GetStatusFlags(USART0) & USART_STAT_TXRDY_MASK));
    29.     USART_WriteByte(USART0, (uint8_t)ch);
    30.    
    31.     return ch;
    32. }

    33. int fputc(int ch,FILE *f)
    34. {
    35.     return stdout_putchar(ch);
    36. }

    37. fifo_buffer  shell_uart_rx=
    38. {
    39.     .read_i = 0,
    40.     .write_i = 0,
    41. };

    42. void shell_usart_loop(void)
    43. {
    44.     if(shell_uart_rx.read_i != shell_uart_rx.write_i)
    45.     {
    46.       #if UART_SHELL == LETTER_SHELL
    47.             shellHandler(&shell, shell_uart_rx.buff[shell_uart_rx.read_i++]); //letter shell
    48.         #elif UART_SHELL == NR_MICRO_SHELL
    49.             shell(shell_uart_rx.buff[shell_uart_rx.read_i++]);
    50.         #endif
    51.         shell_uart_rx.read_i &= 0x7f;
    52.     }
    53. }

    54. void USART0_IRQHandler(void)
    55. {
    56.     uint32_t statusFlag;
    57.     uint32_t ch;
    58.    
    59.     statusFlag = USART0->STAT;
    60.     if((statusFlag & USART_STAT_RXRDY_MASK) != 0)
    61.     {
    62.         ch = USART_ReadByte(USART0);
    63.         if(((shell_uart_rx.write_i+1)&0x7f) != shell_uart_rx.read_i)
    64.         {
    65.             shell_uart_rx.buff[shell_uart_rx.write_i++] = ch & 0xff;
    66.             shell_uart_rx.write_i &= 0x7f;
    67.         }
    68.     }
    69.     USART0->STAT |= statusFlag;
    70. }
    复制代码


    使用方法,仓库内也有说明和例子。
    例如添加用户的定义:
    //测试添加用户:
    SHELL_EXPORT_USER(SHELL_CMD_PERMISSION(0xFF), root, 666666, root user);
    SHELL_EXPORT_USER(SHELL_CMD_PERMISSION(0x01), LSY,  666666, test user);

    这里添加了2个用户,root和LSY。密码都是666666.但是2个用户权限不同。

    letter-shell有2种添加函数命令方式。
    第一种main函数形式。看如下例子,使用int argc, char *argv[]参数,并给函数添加不同权限。
    默认的letter用户是使用不了下面函数命令的,
    新加的root拥有下面2个函数func和func2权限.
    新加的LSY只拥有func的权限。
    1. //测试添加mian命令
    2. int func(int argc, char *argv[])
    3. {
    4.     printf("%d parameter(s)\r\n", argc);
    5.     for (char i = 1; i < argc; i++)
    6.     {
    7.         printf("%s\r\n", argv[i]);
    8.     }
    9.     return  0;
    10. }
    11. SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0x01)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), func, func, test1);
    12. SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0x02)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), func2, func, test2);
    13. //letter:/$ func "hello world"
    14. //2 parameter(s)
    15. //hello world
    复制代码


    第二种是普通C函数形式:
    如下例子:主要是函数参数方式不同。在输入命令参数时的方式就不同。
    这个例子设置函数权限为0,意思是所有用户都拥有这个函数权限。
    1. //测试添加func命令
    2. int func1(int i, char ch, char *str)
    3. {
    4.     printf("input int: %d, char: %c, string: %s\r\n", i, ch, str);
    5.     return  0;
    6. }
    7. SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), func1, func1, test3);
    8. //letter:/$ func1 666 'A' "hello world"
    9. //input int: 666, char: A, string: hello world

    复制代码


    添加变量方式:
    这里权限使用0xFF,标识除了权限为0的用户,其他用户都可以操作这个变量。
    1. uint32_t    muzhu_cnt;

    2. SHELL_EXPORT_VAR(SHELL_CMD_PERMISSION(0xFF) | SHELL_CMD_TYPE(SHELL_TYPE_VAR_INT),muzhu_cnt,&muzhu_cnt,muzhu-count);
    复制代码


    下面测试一下效果:
    这是默认用户letter时效果。
    1.jpg

    下面切换到root用户看看,直接输入root回车,然后输入密码666666.

    2.jpg

    下面切换LSY用户效果:
    3.jpg

    可以看到不同用户下,命令根据权限的不同。执行的命令也不同。

    工程添加的文件:shell_port.c,shell_port.h,shell_cfg_user.h为添加的接口文件。
    4.jpg

    shell_cfg_user.h添加的配置:

    1. #if 0
    2. #define     SHELL_TASK_WHILE                //是否使用默认shell任务while循环
    3. #define     SHELL_USING_CMD_EXPORT          //是否使用命令导出方式
    4. #define     SHELL_USING_COMPANION           //是否使用shell伴生对象功能
    5. #define     SHELL_SUPPORT_END_LINE          //是否支持shell尾行模式
    6. #define     SHELL_HELP_LIST_USER            //是否在输入命令列表中列出用户
    7. #define     SHELL_HELP_LIST_VAR             //是否在输入命令列表中列出变量
    8. #define     SHELL_HELP_LIST_KEY             //是否在输入命令列表中列出按键
    9. #define     SHELL_ENTER_LF                  //使用LF作为命令行回车触发
    10. #define     SHELL_ENTER_CR                  //使用CR作为命令行回车触发
    11. #define     SHELL_ENTER_CRLF                //使用CRLF作为命令行回车触发
    12. #define     SHELL_EXEC_UNDEF_FUNC           //使用执行未导出函数的功能
    13. #define     SHELL_COMMAND_MAX_LENGTH        //shell命令最大长度
    14. #define     SHELL_PARAMETER_MAX_NUMBER      //shell命令参数最大数量
    15. #define     SHELL_HISTORY_MAX_NUMBER        //历史命令记录数量
    16. #define     SHELL_DOUBLE_CLICK_TIME         //双击间隔(ms)
    17. #define     SHELL_QUICK_HELP                //快速帮助
    18. #define     SHELL_MAX_NUMBER                //管理的最大shell数量
    19. #define     SHELL_GET_TICK()                //获取系统时间(ms)
    20. #define     SHELL_USING_LOCK                //是否使用锁
    21. #define     SHELL_MALLOC(size)              //内存分配函数(shell本身不需要)
    22. #define     SHELL_FREE(obj)                 //内存释放函数(shell本身不需要)
    23. #define     SHELL_SHOW_INFO                 //是否显示shell信息
    24. #define     SHELL_CLS_WHEN_LOGIN            //是否在登录后清除命令行
    25. #define     SHELL_DEFAULT_USER              //shell默认用户
    26. #define     SHELL_DEFAULT_USER_PASSWORD     //默认用户密码
    27. #define     SHELL_LOCK_TIMEOUT              //shell自动锁定超时

    28. #endif

    29. /**
    30. * @brief 是否使用shell伴生对象
    31. *        一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象
    32. */
    33. #define     SHELL_USING_COMPANION       1


    34. /**
    35. * @brief 支持shell尾行模式
    36. */
    37. #define     SHELL_SUPPORT_END_LINE      1


    38. /**
    39. * @brief 使用LF作为命令行回车触发
    40. *        可以和SHELL_ENTER_CR同时开启
    41. */
    42. #define     SHELL_ENTER_LF              1

    43. /**
    44. * @brief 使用CR作为命令行回车触发
    45. *        可以和SHELL_ENTER_LF同时开启
    46. */
    47. #define     SHELL_ENTER_CR              1

    48. /**
    49. * @brief 使用CRLF作为命令行回车触发
    50. *        不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同时开启
    51. */
    52. #define     SHELL_ENTER_CRLF            0

    53. /**
    54. * @brief shell格式化输入的缓冲大小
    55. *        为0时不使用shell格式化输入
    56. * @note shell格式化输入会阻塞shellTask, 仅适用于在有操作系统的情况下使用
    57. */
    58. //#define     SHELL_SCAN_BUFFER          0

    59. /**
    60. * @brief 获取系统时间(ms)
    61. *        定义此宏为获取系统Tick,如`HAL_GetTick()`
    62. * @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定
    63. */
    64. //#define     SHELL_GET_TICK()            HAL_GetTick()

    65. /**
    66. * @brief 使用锁
    67. * @note 使用shell锁时,需要对加锁和解锁进行实现
    68. */
    69. //#define     SHELL_USING_LOCK            0

    70. /**
    71. * @brief shell内存分配
    72. *        shell本身不需要此接口,若使用shell伴生对象,需要进行定义
    73. */
    74. #define     SHELL_MALLOC(size)          malloc(size)

    75. /**
    76. * @brief shell内存释放
    77. *        shell本身不需要此接口,若使用shell伴生对象,需要进行定义
    78. */
    79. #define     SHELL_FREE(obj)             free(obj)

    复制代码





    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3311

    主题

    6565

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32194
    最后登录
    2024-5-10
    发表于 2023-6-15 16:50:25 | 显示全部楼层
    这篇很丰富,已经开始期待下一篇了。(坏笑)
    签到签到
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 09:21
  • 签到天数: 1954 天

    [LV.Master]伴坛终老

    61

    主题

    1万

    帖子

    3

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    17447
    最后登录
    2024-5-10
     楼主| 发表于 2023-6-15 17:00:40 | 显示全部楼层
    NXP管管 发表于 2023-6-15 16:50
    这篇很丰富,已经开始期待下一篇了。(坏笑)

    下一篇也会来的
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2016-12-2 08:40
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    97

    主题

    840

    帖子

    7

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    3995
    最后登录
    2024-5-10
    发表于 2023-6-15 18:21:17 | 显示全部楼层
    棒棒哒
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-2-8 09:39
  • 签到天数: 217 天

    [LV.7]常住居民III

    92

    主题

    1114

    帖子

    29

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    7801

    热心会员

    最后登录
    2024-5-6
    发表于 2023-6-15 19:45:16 | 显示全部楼层
    厉害呀,看起来不错
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    前天 16:53
  • 签到天数: 1338 天

    [LV.10]以坛为家III

    88

    主题

    4296

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    9065
    最后登录
    2024-5-10
    发表于 2023-6-16 09:25:51 | 显示全部楼层
    这个shell 看起来还是挺漂亮的
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    前天 10:12
  • 签到天数: 273 天

    [LV.8]以坛为家I

    31

    主题

    3002

    帖子

    38

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    5340

    活跃会员

    最后登录
    2024-5-9
    发表于 2023-6-18 13:27:51 | 显示全部楼层

    厉害呀,看起来不错
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    前天 10:58
  • 签到天数: 599 天

    [LV.9]以坛为家II

    51

    主题

    2248

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    7148
    最后登录
    2024-5-10
    发表于 2023-6-20 09:26:37 | 显示全部楼层
    学习了解下  感谢分享
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-3-15 14:42
  • 签到天数: 87 天

    [LV.6]常住居民II

    2

    主题

    130

    帖子

    0

    高级会员

    Rank: 4

    积分
    610
    最后登录
    2024-4-24
    发表于 2023-6-20 09:32:19 | 显示全部楼层
    666666666666666
    光而不耀,静水长流
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-5-11 00:18 , Processed in 0.178021 second(s), 28 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表