RT-Thread的Finsh实现学习

学习原因

        工作中,使用同事开发的调试软件,输入参数打印的函数名就可以打印参数,但看不到代码实现,只能用自己微薄的知识积累去猜一下,之前尝试过,专门写一个函数,去解析编译生成的map文件,就可以通过函数名去找到函数的地址,然后用函数指针去运行就可以了,最近工作之余在学习RT-Thread的内核源码,刚好看到了Finsh组件,可以在命令行输入函数名运行,所以就简单学习了下;

自定义MSH命令

举例引入

        如下是最简单的“hello world"函数, 在函数定义下面有一行宏,纸面意思是Finsh函数导出,下面对宏进行分析:

void hello(void)
{
    printf("hello RT-Thread!\n");
}
FINSH_FUNCTION_EXPORT(hello, say hello world);

宏定义说明

        先看下RT-Thread官方文档对如下宏定义的说明:

FINSH_FUNCTION_EXPORT(hello, say hello world);

 

宏定义源码分析

#define FINSH_FUNCTION_EXPORT(name, desc)   \
    FINSH_FUNCTION_EXPORT_CMD(name, name, desc)

/* else分支下的宏定义 */
#define FINSH_FUNCTION_EXPORT_CMD(name, cmd, desc)                      \
        const char __fsym_##cmd##_name[] SECTION(".rodata.name") = #cmd;    \
        const char __fsym_##cmd##_desc[] SECTION(".rodata.name") = #desc;   \
        RT_USED const struct finsh_syscall __fsym_##cmd SECTION("FSymTab")= \
        {                           \
            __fsym_##cmd##_name,    \
            __fsym_##cmd##_desc,    \
            (syscall_func)&name     \
        };

/* 上面宏定义中调用的宏的定义 */
#define SECTION(x)    __attribute__((section(x)))
#define RT_USED       __attribute__((used))

/* 上面宏定义中使用的结构体定义 */
struct finsh_syscall
{
    const char*     name;       /* the name of system call */
    const char*     desc;       /* description of system call */
    syscall_func    func;       /* the function address of system call */
};

/* 上面宏定义中使用的函数指针定义 */
typedef long (*syscall_func)(void);

宏展开后的真相

        可以看到展开之后,是一个finsh_syscall结构体类型的变量"__fsym_hello",在后续章节可以得到证实;

### STM32 RT-Thread Nano 移植教程及 Finish 实现 #### 准备工作 在移植 RT-Thread Nano 到 STM32 前,需准备一个能够正常运行的裸机工程[^1]。此过程可以通过使用 ST 提供的工具 CubeMX 来完成硬件初始化配置以及生成基础代码框架[^2]。 #### 安装 Nano 软件包 通过官方文档或其他资源获取 RT-Thread Nano 的软件包,并将其集成至项目中[^4]。这一步通常涉及解压文件并将必要的源码目录复制到项目的指定位置。 #### 配置编译环境 确保开发环境中已正确设置交叉编译器路径,并调整链接脚本以适配目标 MCU 的内存布局。此外,在 Makefile 或 IDE 中添加 RT-Thread Nano 所需头文件和库文件的搜索路径。 #### 初始化线程调度功能 根据具体需求修改 `rtconfig.h` 文件中的宏定义选项,例如开启/关闭调试模式、设定最大优先级数量等参数。随后调用 rtthread_startup() 函数启动操作系统核心服务。 #### 添加 FinSH 支持 为了实现命令行交互界面 (Console),需要引入 FinSH 模块[^3]: 1. 将 finsh.c 和 shell.c 等关联文件加入工程项目; 2. 在系统初始化阶段注册标准输入输出设备驱动程序; 3. 创建默认的任务用于监听串口数据流并与用户通信; 以下是简化版示例代码片段展示如何创建一个简单的任务来处理来自 USART 的字符接收事件: ```c #include "finsh.h" void console_task(void *parameter){ char ch; while(1){ if(HAL_UART_Receive(&huart1, &ch, 1, HAL_MAX_DELAY)==HAL_OK){ finsh_input(ch); // 把接收到的数据交给 FINSH 处理 } } } int main(){ ... /* 启动 RT-Thread */ rt_thread_t tid_console; tid_console = rt_thread_create("console", console_task, RT_NULL, 512, 8, 20); if(tid_console != RT_NULL) rt_thread_startup(tid_console); rtthread_startup(); } ``` 以上即为整个流程概述,实际操作过程中可能还需要针对特定板卡做更多细节上的定制化改动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值