[MM32软件] 【EV Board (MM32L0136C7P)测评】+ 简易SHELL实现

[复制链接]
 楼主| aple0807 发表于 2022-12-15 18:34 | 显示全部楼层 |阅读模式
本帖最后由 aple0807 于 2022-12-15 18:36 编辑

开发MCU软件最常用的调试方式就是利用调试工具在线调试,打断点观察程序运行数据。但在部分场合不方便一直连接调试工具,特别是产测阶段或者现场维护等操作。此时为程序添加SHELL接口可以极大改善调试速度。
本次使用MM32L0136开发板的串口实现SHELL功能。
本程序SHELL的原理主要借助与编译工具 section 属性特征实现,即链接器会按照section属性值的字符顺序来排列变量。

SHELL核心宏如下:
  1. typedef struct
  2. {
  3.         const char *name;
  4.         int (*func)(int, void *[]);
  5. } func_info_type;

  6. #define DBG_FUN_BASE_EXPORT(fn, level)                                                \
  7.         extern int fn(int argc, void *argv[]);                                            \
  8.         OBJ_USED const func_info_type __dbg_func_##fn OBJ_SECTION(".app_fn.dbg." level) = \
  9.                 {                                                                             \
  10.                         #fn,                                                                      \
  11.                         (void *)fn,                                                               \
  12.         }

  13. #if DBG_EN > 0
  14. #define DBG_FUN_EXPORT(fn) DBG_FUN_BASE_EXPORT(fn, "2." #fn)
  15. #else
  16. #define DBG_FUN_EXPORT(...)
  17. #endif

  18. #define SHELL_FUN_EXPORT(fn) DBG_FUN_BASE_EXPORT(fn, "2." #fn)
使用SHELL_FUN_EXPORT处理的函数,会创建一个结构,包括函数地址和函数名。串口接收到一行数据后会搜索函数名,命中则使用绝对地址调用该函数。

  1. /*******************************************************************************
  2. * [url=home.php?mod=space&uid=247401]@brief[/url] 搜索指令索引
  3. * @param cmd
  4. * [url=home.php?mod=space&uid=266161]@return[/url] 目标索引,-1标示未搜索到
  5. ******************************************************************************/
  6. int dbg_fun_list_find(const char *cmd)
  7. {
  8.         int low, high, mid, des = -1;
  9.         volatile const func_info_type *volatile funlist_start = &__dbg_func_dbg_fun_list_start;
  10.         volatile const func_info_type *volatile funlist_end = &__dbg_func_dbg_fun_list_end;

  11.         low = 1;
  12.         high = (funlist_end - funlist_start);

  13.         while (low <= high)
  14.         {
  15.                 ii8 cval;

  16.                 mid = (low + high) >> 1;
  17.                 cval = comp_string(cmd, (funlist_start + mid)->name, 256);
  18.                 if (cval > 0)
  19.                 {
  20.                         low = mid + 1;
  21.                 }
  22.                 else if (cval < 0)
  23.                 {
  24.                         high = mid - 1;
  25.                 }
  26.                 else
  27.                 {
  28.                         des = mid;
  29.                         break;
  30.                 }
  31.         }

  32.         return des;
  33. }

  34. /*******************************************************************************
  35. * @brief: 执行命令
  36. * @param *cmd
  37. * [url=home.php?mod=space&uid=266161]@return[/url] {*}
  38. ******************************************************************************/
  39. int dbg_fun_list_exe(const char *cmd)
  40. {
  41.         int argc, site;
  42.         char *argv[10];
  43.         char cbuff[256];
  44.         volatile const func_info_type *volatile funlist_start = &__dbg_func_dbg_fun_list_start;

  45.         copy_str(cmd, cbuff, sizeof(cbuff) - 1);
  46.         str_remove_l20_ascii(cbuff);

  47.         argc = str_split(cbuff, ' ', argv, arr_len(argv));

  48.         site = dbg_fun_list_find(argv[0]);

  49.         if (site > 0)
  50.         {
  51.                 (funlist_start + site)->func(argc, (void **)argv);
  52.         }

  53.         return site;
  54. }
经过以上处理后,如下书写函数就可以在串口助手调用程序的函数了:
  1. int sh_func1(int argc, void *argv[])
  2. {
  3.         printf("shell fun1 is called\n");
  4.         return 0;
  5. }
  6. SHELL_FUN_EXPORT(sh_func1);

  7. int sh_func2(int argc, void *argv[])
  8. {
  9.         printf("shell fun2 is called\n");
  10.         return 0;
  11. }
  12. SHELL_FUN_EXPORT(sh_func2);


下面附上工程,有兴趣的小伙伴可以一起研究,改善功能!
L0136DEMO.rar (1.43 MB, 下载次数: 1)

示例程序使用UART2作为SHELL串口,演示如下:
SHELL.png

tpgf 发表于 2023-1-5 10:16 | 显示全部楼层
在计算机科学中,Shell俗称壳(用来区别于核),是指"为使用者提供操作界面"的软件(command interpreter,命令解析器)。它类似于DOS下的COMMAND.COM和后来的cmd.exe。它接收用户命令,然后调用相应的应用程序。
木木guainv 发表于 2023-1-5 10:37 | 显示全部楼层
传统意义上的shell指的是命令行式的shell,以后如果不特别注明,shell是指命令行式的shell。
晓伍 发表于 2023-1-5 10:48 | 显示全部楼层
文字操作系统与外部最主要的接口就叫做shell。shell是操作系统最外面的一层。shell管理与操作系统之间的交互:等待你输入,向操作系统解释你的输入,并且处理各种各样的操作系统的输出结果。
八层楼 发表于 2023-1-5 11:23 | 显示全部楼层
Shell基本上是一个命令解释器,类似于DOS下的COMMAND.COM。它接收用户输入的命令(如ls等),然后调用相应的应用程序。较为通用的shell有标准的Bourne shell和C Shell。
guanjiaer 发表于 2023-1-5 12:47 | 显示全部楼层
交互式模式就是shell等待用户的输入,并且执行用户提交的命令。这种模式被称作交互式是因为shell与用户进行交互。这种模式也是大多数用户非常熟悉的:登录、执行一些命令、签退。当用户签退后,shell也终止了。
heimaojingzhang 发表于 2023-1-5 12:55 | 显示全部楼层
shell也可以运行在另外一种模式:非交互式模式。在这种模式下,shell不与用户进行交互,而是读取存放在文件中的命令,并且执行它们。当它读到文件的结尾,shell也就终止了。
Jacquetry 发表于 2023-1-5 17:07 | 显示全部楼层
一个可以嵌入在程序中的嵌入式shell
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

326

帖子

2

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