初识finsh

在大部分嵌入式系统中,一般开发调试都使用硬件调试器和printf日志打印,在有些情况下,这两种方式并不是那么好用。比如对于RT-Thread这个多线程系统,我们想知道某个时刻系统中的线程运行状态、手动控制系统状态。如果有一个shell,就可以输入命令,直接执行相应的函数获得需要的信息,或者控制程序的行为,这无疑会十分方便。

finsh(C-Style)

在嵌入式领域,C语言是最常用的开发语言,如果shell程序的命令是C语言的风格,那无疑是非常易用且有趣。

嵌入式设备通常采用交叉编译,一般需要将开发板与PC机连接起来通讯,常见连接方式包括,串口、USB、以太网、wifi等。一个灵活的shell也应该可以在多种连接方式上工作。

finsh正是基于这些考虑而诞生的,finsh可以发音为[ˈfɪnʃ]。finsh运行于开发板,它可以使用串口/以太网/USB等与PC机进行通信。其运行时的finsh工作原理图 所示。

finsh工作原理

下图是finsh的实际运行运行效果图。开发板运行RT-Thread,并使能了finsh组件,通过串口与PC机连接,PC上运行Secure CRT。

finsh运行界面

按下回车,然后输入list_thread()将会打印系统当前所有线程,及其状态。关于这个命令的详细解释请参考本章最后一节。

WARNING: 此模式下,finsh是一个C语言风格的Shell,与Linux/Unix以及Windows下的cmd 的风格不同。在finsh shell中使用命令(即C语言中的函数),必须类似C语言中的函数调用方式,即必须携带()符号。最后finsh命令的输出为此函数的返回值。对于一些不存在返回值的函数(void返回值),这个打印输出没有意义。

finsh(msh)

实际上,一开始finsh仅支持C-Style模式。后来随着RT-Thread的不断发展,尤其支持app module之后(请参考本书应用模块一章了解相关内容),C-Style模式执行app module时操作起来不太方便,而传统的shell则更方便些。另外,C-Style模式下,finsh占用体积较大。出于这些考虑,在RT-Thread 1.2.0中为finsh增加了msh模式。

msh模式下,finsh与传统shell(dos/bash)执行方式一致,其命令执行格式如下

  1. command [arg1] [arg2] [...]

其中command既可以RT-Thread内置的命令,也可以是编译出的app module(类似于dos里的exe可执行文件)。finsh(msh)内置的命令风格采用bash的风格,内置命令将在本章后续章节详细介绍。

finsh中的按键

finsh支持TAB键自动补全,当没有输入任何字符时按下TAB键将会打印当前所有的符号,包括当前导出的所有命令和变量。若已经输入部分字符时按下TAB键,将会查找匹配的命令,并自动补全,并可以继续输入,多次补全。如果是msh状态,输入一个字符后,不仅仅会按系统导出函数命令方式自动补全,也会按照文件系统的当前目录下的文件名进行补全。

上下键可以回溯最近输入的历史命令,左右键可移动光标,退格键删除。

目前finsh的按键处理还比较薄弱。不支持CTRL+C等控制键中断命令,也不支持DELETE键删除。

finsh特性

finsh(c-style)的数据类型

finsh支持基本的C语言数据类型,包括:

finsh特性

在finsh的命令行上,输入上述数据类型的C表达式可以被识别。浮点类型以及复合数据类型unin与struct等暂不支持。此外,finsh也不支持if, for, while, goto, switch等分支、跳转语句。