最近一直在搞STM32F4的一些小东西,因一些比较郁闷的原因,经常需要修改底层程序逻辑,某天忽然间想到为什么总是翻来覆去地这些底层的东西,难道没有一种比较方便的方法来做吗?于是想到了是否可以用脚本处理业务逻辑,通过驱动与应用分离的方式来处理程序,让上位机去折腾吧,想到就试。
因为有一些linux的基础,也有一些编译器的基础,网上搜索了一下,觉得用LUA做脚本比较合理。
LUA特点不介绍了。
记录一下关键信息:
目标:实现无操作系统下,通过应用与驱动分离的设计思想,C语言实现基础驱动直接烧录进STM32芯片,LUA编写应用程序,存放在SD卡中,实现自动加载并运行LUA程序。
注意:
1、while(1);这个大循环已经变得可有可无了,可以在STM32中实现,也可以在Lua中实现,根据实际需要处理。
2、可以通过串口命令实现命令控制,如调用C函数等功能。
具体步骤如下:
1、下载最近的LUA版本Lua-5.3.5
2、二话不说,新建个STM32F4的工程,加进SRC源码,去掉lua.c 和 luac.c这两个源文件。
3、加上对SD卡的基础支持代码
4、加上FatFS的文件系统代码
5、对USART进行简单处理,实现串口的输入输出功能
6、对半主机模式、LUA的运行环境缺少的函数进行简单添加、改造
7、对While(1)进行简单改造,方便测试串口
好了,有了以上基础就可以正常读取SD卡中的LUA程序了。
关键代码如下:
//建立LUA运行环境
lua_State *L;
L = luaL_newstate(); /* 建立Lua运行环境 */
luaopen_base(L); //注册基础函数
luaL_setfuncs(L, mylib, 0); //注册自定义函数
//脚本自动执行,已测试OK
// luaL_dostring(L, lua_test); /* 运行Lua脚本 */
// while(1);
//文件程序自动执行,已测试OK
char strProgramName[] = "1:/LUALib/luaTest.lua";
if(luaL_dofile(L,strProgramName))
printf("Script has some error!\r\n");
while(1)
{
//串口命令控制LED,已测试OK
if(flagCmdCased) //0:已处理;1:待处理
{
luaL_dostring(L,USART1_RxBuff);
memset(USART1_RxBuff,0,USART1_RXBUFF_SIZE);
flagCmdCased = 0;
}
}
LUA的程序:打印一些字符,计算两个数相加的结果并输出到串口
直接用记事本写在SD卡中,保存为LuaTest.lua
代码如下:
print("====== This is a lua test ========\r\n")
print("Hello World!\r\n")
local res
res = Add(5,6)
print("Result = ",res)
这里调用了Add(x,y)这个C函数,所以有必要说一下Lua调用C函数的注意事项:
对于可被Lua调用的C函数而言,其接口必须遵循Lua要求的形式,即
typedef int (lua_CFunction)(lua_State L);
接收一个参数Lua_State*,即Lua的状态,返回值表示压入栈中的结果个数。
关于Add(x,y)这个C函数,代码如下:
static int Add(lua_State *L)
{
int count;
int x,y,res;
x = lua_tointeger(L,1); //获取Lua传递的参数
y = lua_tointeger(L,2);
res = x + y; //计算x+y
lua_pushnumber(L,res); //结果压入栈中,供Lua提取
return 1; //返回参数个数!!这是通知LUA调用者有一个值返回
}
在串口调试器是输入print(Add(5,7))就会得到计算结果
OK,关于Lua与C的交互,这篇文章写得很详细:
https://www.cnblogs.com/chenny7/p/3993456.html
关于LUA在STM32上的移植,网络上的文章讲得很详细,这里因为一些细节问题三言两语交待不清楚,我不做详细描述了,以免误导他人。
只讲几个原则:保障文件系统能识别出SD卡的文件,保障LUA需要的fopen\fclose\ferror之类的函数能正常工作,保障串口打印输出基础驱动正确,就OK了。