杨蕾蕾1,慕福奇2,张文明2,吕欣岩2
(1.中国科学院大学 微电子学院,北京 100049;2.江苏中科羿链通信技术有限公司,江苏 无锡 214135)摘要:针对嵌入式设备的配置管理需求,利用Lua脚本语言设计了一种灵活的嵌入式设备配置管理方法。实现了通过串口服务、Telnet服务和Web服务对嵌入式设备进行配置管理。该方法通过在QiLINK(Queue Information LINK)链状网节点(使用TMS320C6670芯片开发)上实际验证,证明了其可行性,符合预期效果。为嵌入式设备提供了一种移植性强、多方式的配置管理方法。
关键词:嵌入式;配置管理;Lua语言;Web;Telnet;串口;MVC框架
中图分类号:TP311文献标识码:ADOI: 10.19358/j.issn.1674-7720.2017.03.026
引用格式:杨蕾蕾,慕福奇,张文明,等.一种灵活的嵌入式设备配置管理方法[J].微型机与应用,2017,36(3):88-92.
0引言
随着计算机技术和集成电路的发展,嵌入式技术日渐普及。嵌入式设备由于体积小、功耗低、成本低廉的特点在通信、家电、医疗以及军事等领域中的应用越来越广泛。
无论是以单片机为主的中低端嵌入式应用,还是以ARM、DSP、MIPS为主的高端嵌入式设备,都需要提供一种或几种方式供开发人员或其他使用者对其进行配置和管理。常用的方式可以分为以下3种:利用串口通信或Telnet远程登录服务直接输入指令[1];通过发送指定格式的UDP包 [2];使用Web可视化界面[3]。目前嵌入式设备的配置管理方法多采用以上3种方式中的一种,不够全面。此外,实现方式也不够理想,如自定义的命令格式以及自定义的配置数据文件容易出现解析错误等[4]。综上,没有一个移植性较强的、比较完备的配置管理方法可以应用在不同的嵌入式设备中。
Lua语言是一种轻量级的语言,适用于多种操作系统以及用ANSI C开发的平台,它在嵌入式设备中的应用已经屡见不鲜[57]。此外,Lua脚本可以直接用来存储配置数据,占用空间小并且容易解析,不易出错。在这种前提下,本文考虑依托Lua语言,实现一套集Web服务、Telnet服务和串口服务为一体的嵌入式设备配置管理方法。
1整体结构设计
本嵌入式设备配置管理方法的系统结构如图1所示,嵌入式设备提供网口和串口供PC管理机可以通过远程登录、访问Web页面以及输入串口命令的方式对嵌入式设备进行配置管理。
本方法的实现依赖于Lua源码,它提供解释Lua脚本的解释器,同时还可以灵活地修改以满足不同接口的需求。在系统结构中,Lua源码的下层是底层驱动函数,它们可以注册到Lua中,供Lua脚本调用。Lua源码的上层是本方法实现所依赖的三大服务:串口服务、Telnet服务以及Web服务。串口服务直接由Lua串口处理程序实现,而其他两种服务均依赖于嵌入式TCP/IP协议栈。NDK(Network Developer’s Kit)是德州仪器公司(Texas Instruments,TI)开发的TCP/IP协议栈,它在提供Telnet服务的基础上,增加了解释Lua指令的功能。而Web服务利用Lua社区提供的相关Http模块实现,它们由纯Lua脚本实现,修改十分简单,避免了传统的C语言编写的CGI(Common Gateway Interface)程序每次修改都需要重新编译代码的问题。这些模块又依赖于Luasocket,Luasocket是将NDK的Socket函数封装给Lua使用的一个接口层。系统的最上层即是配置管理操作的对象、配置数据以及代码文件等。在系统实现过程中还移植了Fatfs文件系统,用来更好地存放和管理这些文件。
2具体方法及实现
2.1文件系统移植及IO操作实现
嵌入式文件系统选择Fatfs。它使用ANSI C编写,不依赖于硬件平台,并且代码量小、移植简单[89],适用于小型的嵌入式设备。Lua源码中的io库的实现依赖于标准C的文件操作函数,与Fatfs提供的函数不同,因此需要将Fatfs提供的相关API函数封装成一套新的Lua io库。
2.1.1Fatfs文件系统的移植
以MX25U25635F SPI FLASH为例阐述Fatfs在嵌入式存储设备中的移植过程。
MX25U25635擦除的最小单位是4 K,所以将Fatfs的簇(最小文件单位)大小设置为4 K。一个扇区大小为512 B,一个簇8个扇区。移植Fatfs需要修改的是diskio.c文件,其中,需要特别注意的是磁盘写函数。
如图2所示,写一个文件时会将这个文件分成两部分:整扇区和最后不足一个扇区的部分。整扇区的写操作是由用户缓冲区直接写入物理磁盘,最后不足一扇区的部分,先从磁盘读取相应扇区的内容到文件缓冲区,修改缓冲区内容,并设置回写标记,最终在调用文件关闭函数或再一次写文件时,再将文件缓冲区的内容回写到物理磁盘中。这样就一共调用了两次磁盘写函数,磁盘写函数调用SPI写函数,而每次调用SPI写函数时都会根据写入数据的长度擦除所在的整个簇。如果文件缓冲区写入的扇区和之前已经写好的整扇区在一个簇内,则第二次调用SPI写函数时会再一次把整个簇擦掉,因此之前写入的整扇区内容也被擦掉了。为了避免这种情况,在SPI写函数中加了一个判断,在擦之前判断擦除的地址是否是一个簇的起始地址,如果是则进行擦除操作,否则直接写入。
2.1.2IO库的封装及本地文件到Flash的映射
IO库主要实现对文件的打开、关闭以及读、写这几个函数。其中需要注意的是,Fatfs对外提供的每一个文件操作函数的第一个参数都是一个文件指针,以此来确定操作对象。但是Lua中并没有指针变量,因此封装时在文件打开函数的末尾返回所打开的文件的指针,此后调用读、写、关闭函数时都直接将得到的这个文件指针作为第一个参数使用。
当写入Flash的文件数量较多时,逐个写入太过麻烦,因此用一个简单的Lua脚本实现文件从PC端指定路径到Flash指定路径的映射。它完成的操作有:定义一个目录查找函数,将PC端指定目录下的指定格式文件的绝对路径全部存入到table变量input_table{}中;使用字符串匹配替换函数string.gsub()将input_table{}中的文件路径替换为Flash文件系统中的指定路径,存入另一个table变量save_table{}中;利用Lua原有的io库从input_table{}中依次读取文件,利用封装Fatfs函数的io库按照save_table{}中的路径依次创建文件并将读到的内容写入。
2.2Web服务器设计
嵌入式Web服务器的实现借助于Lua社区提供的相关模块,包括Xavante、Wsapi、Copas、Cgilua、Sailor。Xavante是基于URI模块化架构的HTTP1.1 Web服务器映射处理程序,提供文件处理、重定向处理和Wsapi处理。Wsapi将抽象的Lua程序映射为具体的Web应用,解决了Lua代码的平台依赖性,使之可以应用于主流的平台。Copas是一个基于协程的调度器,可以用于调度TCP或UDP服务。Cgilua是一个用于创建动态Web页面和Web表单的工具,支持界面和数据分离。Sailor是一个MVC框架,用于组织Web界面和数据。这些模块依赖于Luasocket,它是用C封装的提供给Lua使用的Socket函数。
2.2.1Web服务器结构及处理流程
Web服务器的结构如图3所示。
Copas模块完成Tcp Socket的调度工作,负责接收请求、建立连接,并监视Socket套接字的状态变化,当监听到有数据后,交给Xavante模块处理。Xavante模块将接收到的数据包进行解析,得到包头信息,并根据解析出来的Url请求使用不同的处理函数进行处理,包括Index页面处理函数、文件处理函数以及Cgi处理函数。Cgi处理函数调用Cgilua模块进行处理。处理完毕后将处理结果交给Wsapi模块,它将抽象的Lua语句转换为规范的html语句。最后Xavante模块将处理结果加上包头信息发送给客户端。其中,Web页面的组织方式使用Sailor MVC框架。具体处理流程如图4所示。
2.2.2Socket接口层
Lua的Http服务模块依赖于Luasocket提供的tcp socket函数。Lua官网提供的Luasocket是以动态库的格式供用户使用,并且依赖于Linux/Windows操作系统,不适用于所有的嵌入式设备(例如TMS320C6670所依赖的CCS开发平台)。因此需要将所使用的TCP/IP协议栈提供的Socket函数封装成Luasocket的tcp socket格式,并注册到Lua源码中供Lua Http相关模块使用。在封装Luasocket库时,尽量保持函数结构和依赖关系不变,只替换内部实现函数,减少使用Luasocket的Http模块的改动。
2.2.3MVC框架
为了更好地组织Web,使用了Sailor MVC框架。MVC指的是Model、View、Controller三部分。MVC框架可扩展性强、易于维护[10]。
Sailor的视图是lp文件,它与Html文件的区别是可以直接插入Lua代码(Wsapi模块将解释处理这些Lua代码)。Lua代码的插入方法有两种:和。如果是连续的一段Lua代码,则按代码块的格式插入,如果是单独的一句Lua语句,则按Lua表达式的格式插入。
Sailor通过定义一些页面操作函数来实现Controller对视图的控制,如视图加载函数、输出函数以及重定向操作函数等。
Sailor同样定义了模型操作函数。Controller对模型的控制从新建模型开始,Sailor提供的模型新建函数将用户定义的模型NewObj作为参数,在继承模型通用函数的同时,引入用户在NewObj中自定义的函数及数据格式规范。Model部分通常采用数据库存储,但由于本系统数据量不是很大,也为了尽量减少不必要的模块,所以配置数据直接以Lua的table数据类型存储在Lua脚本中,因为C和Lua极强的交互性,所以在C代码中解析Lua配置脚本也很容易。
2.3Telnet串口服务设计
Telnet服务和串口服务均是通过直接输入Lua命令来对嵌入式设备进行配置管理,它们共用一套配置管理接口。Telnet实现了对嵌入式设备的远程控制,并且操作简单,只要PC管理机与嵌入式设备在同一网段即可。同时,对一个完整的嵌入式设备配置管理方法而言,不可缺少的配置方式是通过串口服务进行配置。它在嵌入式设备没有入网、默认IP也没有生效的情况下仍然可以使用,保证了本配置方法的完备性。串口处理程序与Lua结合还可以避免不同格式的串口数据帧给嵌入式设备软件带来的解析困难[11],提高了交互的灵活性。
2.3.1配置管理接口
Telnet服务和串口服务除了可使用规范的Lua语句直接对Lua配置脚本进行修改外,本方法还增添了快捷配置方式以及直接调用某些管理函数的功能,将它们统称为配置管理接口。配置管理接口是由相关C函数注册到Lua源码中实现的。调用格式与普通的Lua函数一样:库名.函数名(参数1,参数2,参数3…)。
2.3.2Telnet服务
NDK协议栈提供的Telnet服务的用户指令包含多个关键字,它们被存放在大小为10的字符指针数组tok中,各命令需要匹配多少个关键字,就从tok数组中依次取出相应的元素进行匹配。Lua命令只需输入“Lua”一个关键字,因此将tok[0]指向的字符串和“Lua”比较,如果相同,则进入Lua命令输入模式(即调用Lua解释器),等待用户输入Lua指令,以回车键作为一次输入的截止标志。Lua解释器将输入的字符串作为一段Lua代码载入并编译,然后作为一个代码块(称为chunk)压入栈中。此后,调用Lua的异常处理函数去执行这个代码块。图5为Telnet解析Lua指令流程图。
2.3.3串口服务
串口命令的解析过程与Telnet不同,Telnet是通过直接调用Lua解释器来执行Lua命令,而串口服务的解析过程经过了一个中间函数即串口数据收发函数,它被注册到Lua中。设备初始化时完成对串口的配置并启动加载Lua串口处理脚本。当PC管理机通过串口调试助手给嵌入式设备发来Lua命令时,串口处理程序对接收到的数据进行处理,然后将其传给串口数据接收函数。Lua串口处理脚本检测到串口数据接收函数接收到数据后,将这些接收到的内容作为Lua代码执行。执行完毕后,通过调用串口数据发送函数将执行结果发送给串口处理程序,串口处理程序将之处理完毕后通过串口线发送给PC管理机,反馈给用户。其中,串口配置数据也被存放在一个Lua脚本中,初始化时由C解析这个配置脚本完成对串口的配置。
3实验结果
使用本方法在QiLINK链状网其中一个节点(使用TMS320C6670芯片开发)上进行测试,测试拓扑图如图6所示。所有节点的默认IP为192.168.1.3,入网后的IP为10.9.X.2,其中X为节点号乘以9,比如节点4的IP为10.9.36.2。
图7是将PC管理机与节点4用串口线相连,使用串口调试助手对INTCof文件成功进行配置的结果图。
4结束语
本文提出了一种灵活的嵌入式设备配置管理方法,实现了利用串口服务、Telnet服务、Web服务3种方式对嵌入式设备进行配置及管理。本方法适用于用ANSI C开发的嵌入式设备,并提供对外网口或串口。本方法与传统的嵌入式设备配置管理方法相比,提高了灵活性,对配置数据或Web界面的修改只需修改相关脚本文件,无需重新修改编译软件代码;此外,提高了完备性,无论嵌入式设备是否入网都可以对它进行配置管理;更为重要的一点是,本方法通用性强,不依赖开发平台和操作系统,为各式各样的嵌入式设备的配置管理提供了很好的解决方案。
参考文献
[1] 周家绪, 鄢萍, 张研. 一种嵌入式系统BootLoader参数自动配置方法[J/OL].[2016-09-25].http://www.docin.com/p390606777.html.
[2] 王晓东. 基于以太网和Uboot远程配置嵌入式系统启动参数[J]. 现代科学仪器, 2010(2):6770.
[3] 谭海, 潘绍明. 嵌入式系统中配置参数修改研究及其实现[J/OL]. (20060829)[2016-09-25].http://www.paper.edu.com.
[4] 李长春, 张磊. 基于嵌入式Web门禁控制器的网络配置实现[J]. 工业控制计算机, 2009, 22(4):58-59.
[5] 汪君鹏, 李宥谋. 基于Lua脚本技术的网络化测控系统设计[J]. 西安邮电大学学报, 2013, 18(1):90-94.
[6] 段鑫, 陈宇, 孙伟力. Lua远程调试协议研究与实现[J]. 自动化应用, 2011,25(6):3-5.
[7] 沙俊星. 在嵌入式环境中使用Lua和SQLite扩展NetSNMP代理[J]. 北京联合大学学报:自然科学版, 2011,25(1):9-13.
[8] 秦伟. STM32的FatFS在数据采集系统中的应用[J]. 单片机与嵌入式系统应用, 2015,15(6):55-58.
[9] 洪岳炜, 王百鸣, 谢超英. 一种易于移植和使用的文件系统FatFs Module[J]. 单片机与嵌入式系统应用, 2008,8(5):29-31.
[10] 闫志贵, 孟操. MVC模式在嵌入式调试工具开发中的研究与实现[J]. 电子设计工程, 2010, 18(4):85-87.
[11] 李英明, 闫志辉, 周水斌. 基于Lua脚本语言的嵌入式UART通信方案设计[J]. 单片机与嵌入式系统应用, 2012, 12(4):29-32.