剖析RT-Thread中console与finsh组件实现(3)

剖析RT-Thread中console与finsh组件实现(2)

最后,我们看一下一个cmd命令是怎么加入到命令空间里的:
在这里插入图片描述
关键在于宏定义 MSH_CMD_EXPORT ,内容如下:
在这里插入图片描述
这里在cmd名称前加了 __cmd_ 刚好可以与之前匹配代码相印证。
tips

关于预编译中#和##的两个用法
首先说#,它可以为传入参数加上引号,如下面的代码
///
#include <stdio.h>
#define STR(a)	#a
int main()
{
  char str[] = STR(ABCD);//等效于 char str[] = "ABCD";
  printf("%s\n",str);
}
///
很容易看出来,其实就是给ABCD加了一个引号变成字符串了。
而##相当于分隔符的作用,当你想给变量加前缀你可能会这么做
///
#include <stdio.h>
#define AddPrefix(a)	__a
int main()
{
  int tmp = 1;
  int __tmp = 2;
  tmp = AddPrefix(tmp);//本意是tmp = __tmp;
  printf("%d\n",tmp);
}
///
运行上面的代码会报错,因为__a是一个整体,编译器不会把__a中的a单独去替换前面的参数,所以这时候就需要##去把它们先分隔开
///
#include <stdio.h>
#define AddPrefix(a) __##a
int main()
{
  int tmp = 1;
  int __tmp = 2;
  tmp = AddPrefix(tmp);
  printf("%d\n",tmp);
}
///
这样替换的时候编译器会认为__a是__+a,会替换a再拼接。

宏定义 FINSH_FUNCTION_EXPORT_CMD 内容如下:
在这里插入图片描述
和之前自动初始化那里很相似,这里是把cmd的名字和注释变量的数组存于段.rodata.name内。而把cmd结构体填充之后存于段名FSymTab内。
为了更加直观,我把参数都替换一下,实际内容如下:

#define FINSH_FUNCTION_EXPORT_CMD(led, __cmd_led, RT-Thread first led sample)      							\
       const char __fsym___cmd_led_name[] SECTION(".rodata.name") = "__cmd_led";   					\
       const char __fsym___cmd_led_desc[] SECTION(".rodata.name") = "RT-Thread first led sample";  \
       const struct finsh_syscall __fsym___cmd_led SECTION("FSymTab")= 									\
       {                           																	\
           __fsym___cmd_led_name,   						 										\
           __fsym___cmd_led_desc,    																\
           (syscall_func)&led     																	\
       };

对照之前的匹配cmd代码,可以看出当名字匹配成功时调用led函数指针执行实际的函数。

tips
最后补充一个知识点,关于什么是终端?什么是控制台?什么是tty?什么是shell?
终端(terminal)=tty=文本的输入输出环境
控制台(console)=物理终端
shell=命令行解释器

StackChange原回答

总结

整个finsh实现有几个很有意思的点:
1.自动初始化
2.设备–总线–驱动设计思路
抛去这些,其实就是finsh线程接收来自串口接收回调的信号量,然后调用相应函数。

最近在调试nrf52系列的SDK,发现nrf不开源的蓝牙协议栈写法有异曲同工的地方,但是不得不说,这种方法只适用于很成熟的代码,比如官方SDK,如果自己在项目中也这样写,调试的时候太费劲。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值