当前位置:   article > 正文

STM32+FreeRtos 移植letter-shell工具_freertos shell

freertos shell

前言

        Rt-thread系统有非常好用的FinSH调试工具,考虑在FreeRtos也移植一款类似的嵌入式Shell工具,经过资料查找,开源的letter-shell库满足此需求,搞起。

1、平台

       开发环境:vscode+STM32CubeMX+MDKV5

        芯片:STM32F429

        操作系统:FreeRTOS

        STM32库:HAL

2、串口初始化

通过STM32CubeMX软件直接生成,配置参数如下:

  1. huart7.Instance = UART7;
  2. huart7.Init.BaudRate = 9600;
  3. huart7.Init.WordLength = UART_WORDLENGTH_8B;
  4. huart7.Init.StopBits = UART_STOPBITS_1;
  5. huart7.Init.Parity = UART_PARITY_NONE;
  6. huart7.Init.Mode = UART_MODE_TX_RX;
  7. huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  8. huart7.Init.OverSampling = UART_OVERSAMPLING_16;

3、源码移植

源码下载:

letter-shell: letter shell一个嵌入式小型shell,特别适用于单片机系统。https://gitee.com/zhang-ge/letter-shell.git解压得到下列文件

文件移植

 把文件添加如MDK工程里面

 参照作者的移植步骤,我们重点修改shell_port.c文件:

  • 定义shell对象
Shell shell;
  • 定义shell读,写函数
  1. /**
  2. * @brief 用户shell写
  3. *
  4. * @param data 数据
  5. * @param len 数据长度
  6. *
  7. * @return short 实际写入的数据长度
  8. */
  9. short userShellWrite(char *data, unsigned short len)
  10. {
  11. HAL_UART_Transmit(&huart7, (uint8_t *)data, len, 0x1FF);
  12. return len;
  13. }
  14. /**
  15. * @brief 用户shell读
  16. *
  17. * @param data 数据
  18. * @param len 数据长度
  19. *
  20. * @return short 实际读取到
  21. */
  22. short userShellRead(char *data, unsigned short len)
  23. {
  24. if(HAL_UART_Receive(&huart7, (uint8_t *)data, len, 0xFFFF) != HAL_OK)
  25. {
  26. return 0;
  27. }
  28. else
  29. {
  30. return 1;
  31. }
  32. //return HAL_UART_Receive(&huart7, (uint8_t *)data, len, 0);
  33. }
  • 申请一片缓冲区
char shellBuffer[512];
  • 定义互斥锁
static SemaphoreHandle_t shellMutex;
  • 实现上锁解锁功能
  1. /**
  2. * @brief 用户shell上锁
  3. *
  4. * @param shell shell
  5. *
  6. * @return int 0
  7. */
  8. int userShellLock(Shell *shell)
  9. {
  10. xSemaphoreTake(shellMutex, portMAX_DELAY);
  11. return 0;
  12. }
  13. /**
  14. * @brief 用户shell解锁
  15. *
  16. * @param shell shell
  17. *
  18. * @return int 0
  19. */
  20. int userShellUnlock(Shell *shell)
  21. {
  22. xSemaphoreGive(shellMutex);
  23. return 0;
  24. }
  • 初始化函数实现
  1. /**
  2. * @brief 用户shell初始化
  3. *
  4. */
  5. void userShellInit(void)
  6. {
  7. shellMutex = xSemaphoreCreateMutex();
  8. shell.write = userShellWrite;
  9. shell.read = userShellRead;
  10. shell.lock = userShellLock;
  11. shell.unlock = userShellUnlock;
  12. shellInit(&shell, shellBuffer, 512);
  13. xTaskCreate(shellTask, "shell", 256, &shell, 5, NULL);
  14. }
  • 配置文件修改

去掉了shell伴生对象配置和设置命令触发条件(0x0d)

  1. /**
  2. * @file shell_cfg.h
  3. * @author Letter (nevermindzzt@gmail.com)
  4. * @brief shell config
  5. * @version 3.0.0
  6. * @date 2019-12-31
  7. *
  8. * @copyright (c) 2019 Letter
  9. *
  10. */
  11. #ifndef __SHELL_CFG_H__
  12. #define __SHELL_CFG_H__
  13. #include "stm32f4xx_hal.h"
  14. #include "FreeRTOS.h"
  15. #include "portable.h"
  16. /**
  17. * @brief 是否使用默认shell任务while循环,使能宏`SHELL_USING_TASK`后此宏有意义
  18. * 使能此宏,则`shellTask()`函数会一直循环读取输入,一般使用操作系统建立shell
  19. * 任务时使能此宏,关闭此宏的情况下,一般适用于无操作系统,在主循环中调用`shellTask()`
  20. */
  21. #define SHELL_TASK_WHILE 1
  22. /**
  23. * @brief 是否使用命令导出方式
  24. * 使能此宏后,可以使用`SHELL_EXPORT_CMD()`等导出命令
  25. * 定义shell命令,关闭此宏的情况下,需要使用命令表的方式
  26. */
  27. #define SHELL_USING_CMD_EXPORT 1
  28. /**
  29. * @brief 是否使用shell伴生对象
  30. * 一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象
  31. */
  32. #define SHELL_USING_COMPANION 0
  33. /**
  34. * @brief 支持shell尾行模式
  35. */
  36. #define SHELL_SUPPORT_END_LINE 1
  37. /**
  38. * @brief 是否在输出命令列表中列出用户
  39. */
  40. #define SHELL_HELP_LIST_USER 0
  41. /**
  42. * @brief 是否在输出命令列表中列出变量
  43. */
  44. #define SHELL_HELP_LIST_VAR 0
  45. /**
  46. * @brief 是否在输出命令列表中列出按键
  47. */
  48. #define SHELL_HELP_LIST_KEY 1
  49. /**
  50. * @brief 是否在输出命令列表中展示命令权限
  51. */
  52. #define SHELL_HELP_SHOW_PERMISSION 1
  53. /**
  54. * @brief 使用LF作为命令行回车触发
  55. * 可以和SHELL_ENTER_CR同时开启
  56. */
  57. #define SHELL_ENTER_LF 0
  58. /**
  59. * @brief 使用CR作为命令行回车触发
  60. * 可以和SHELL_ENTER_LF同时开启
  61. */
  62. #define SHELL_ENTER_CR 1
  63. /**
  64. * @brief 使用CRLF作为命令行回车触发
  65. * 不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同时开启
  66. */
  67. #define SHELL_ENTER_CRLF 0
  68. /**
  69. * @brief 使用执行未导出函数的功能
  70. * 启用后,可以通过`exec [addr] [args]`直接执行对应地址的函数
  71. * @attention 如果地址错误,可能会直接引起程序崩溃
  72. */
  73. #define SHELL_EXEC_UNDEF_FUNC 0
  74. /**
  75. * @brief shell命令参数最大数量
  76. * 包含命令名在内,超过16个参数并且使用了参数自动转换的情况下,需要修改源码
  77. */
  78. #define SHELL_PARAMETER_MAX_NUMBER 8
  79. /**
  80. * @brief 历史命令记录数量
  81. */
  82. #define SHELL_HISTORY_MAX_NUMBER 5
  83. /**
  84. * @brief 双击间隔(ms)
  85. * 使能宏`SHELL_LONG_HELP`后此宏生效,定义双击tab补全help的时间间隔
  86. */
  87. #define SHELL_DOUBLE_CLICK_TIME 200
  88. /**
  89. * @brief 管理的最大shell数量
  90. */
  91. #define SHELL_MAX_NUMBER 5
  92. /**
  93. * @brief shell格式化输出的缓冲大小
  94. * 为0时不使用shell格式化输出
  95. */
  96. #define SHELL_PRINT_BUFFER 128
  97. /**
  98. * @brief shell格式化输入的缓冲大小
  99. * 为0时不使用shell格式化输入
  100. * @note shell格式化输入会阻塞shellTask, 仅适用于在有操作系统的情况下使用
  101. */
  102. #define SHELL_SCAN_BUFFER 128
  103. /**
  104. * @brief 获取系统时间(ms)
  105. * 定义此宏为获取系统Tick,如`HAL_GetTick()`
  106. * @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定
  107. */
  108. #define SHELL_GET_TICK() HAL_GetTick()
  109. /**
  110. * @brief 使用锁
  111. * @note 使用shell锁时,需要对加锁和解锁进行实现
  112. */
  113. #define SHELL_USING_LOCK 1
  114. /**
  115. * @brief shell内存分配
  116. * shell本身不需要此接口,若使用shell伴生对象,需要进行定义
  117. */
  118. #define SHELL_MALLOC(size) pvPortMalloc(size)
  119. /**
  120. * @brief shell内存释放
  121. * shell本身不需要此接口,若使用shell伴生对象,需要进行定义
  122. */
  123. #define SHELL_FREE(obj) vPortFree(obj)
  124. /**
  125. * @brief 是否显示shell信息
  126. */
  127. #define SHELL_SHOW_INFO 1
  128. /**
  129. * @brief 是否在登录后清除命令行
  130. */
  131. #define SHELL_CLS_WHEN_LOGIN 1
  132. /**
  133. * @brief shell默认用户
  134. */
  135. #define SHELL_DEFAULT_USER "letter"
  136. /**
  137. * @brief shell默认用户密码
  138. * 若默认用户不需要密码,设为""
  139. */
  140. #define SHELL_DEFAULT_USER_PASSWORD ""
  141. /**
  142. * @brief shell自动锁定超时
  143. * shell当前用户密码有效的时候生效,超时后会自动重新锁定shell
  144. * 设置为0时关闭自动锁定功能,时间单位为`SHELL_GET_TICK()`单位
  145. * @note 使用超时锁定必须保证`SHELL_GET_TICK()`有效
  146. */
  147. #define SHELL_LOCK_TIMEOUT 0 * 60 * 1000
  148. #endif

4、测试

测试代码如下:

  1. void TestEasyTask(void const *argument)
  2. {
  3. userShellInit();
  4. while(1)
  5. {
  6. osDelay(1000);
  7. }
  8. }
  9. void shell_test(uint32_t num)
  10. {
  11. printf("shell:%d",num);
  12. }
  13. SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), func, shell_test, test);

打开Mobaxterm软件,设备上电即有信息打印出来 

按下”TAB“键,调出帮助信息

如图输入命令,得到结果

 我们即可通过串口测试shell_test函数

总结

 letter shell是一个C语言编写的,可以嵌入在程序中的嵌入式shell,主要面向嵌入式设备,以C语言函数为运行单位,可以通过命令行调用,运行程序中的函数。通过移植这个工具,方便我们进行模块的单元测试。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/918751
推荐阅读
相关标签
  

闽ICP备14008679号