| 本帖最后由 夜声 于 2023-1-2 10:05 编辑 
 
 Lua移植 一、前言
 本篇文章将Lua在MDK环境移植到AT32F437ZMT7开发板,记录移植过程并通过Lua点亮开发板上的LED灯作为演示。
 二、Lua简介
 Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。
 Lua 是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组于 1993 年开发的,该小组成员有:Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo。
 特点:
 轻量级: 它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。
 可扩展: Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
 三、AT32F437ZMT7简介
 雅特力科技AT32F437系列超高效能微控制器,搭载32位ARM® Cortex®-M4内核,配合先进工艺与整合技术缔造业界Cortex®-M4最高主频效能288MHz的运算速度。内建的单精度浮点运算单元(FPU)、数字信号处理器(DSP)及存储器保护单元(MPU),搭配丰富的外设及灵活的时钟控制机制,能满足多种领域应用。最高可支持超大容量4032KB的闪存(Flash)和高达512KB的SRAM,超越业界同级芯片水平。
 3.1芯片资源
 定时器:
 3个16位带死区控制PWM高级控制定时器
 2个32位, 8个16位通用定时器
 2个16位基本定时器
 2个看门狗定时器(独立和窗口型)
 1个系统时间定时器: 24位自减型
 3.1通信接口
 3 x I²C (支持SMBus/PMBus)
 4 x SPI / I²S (SPI可达36MHz)(其中I²S2/I²S3支持全双工)
 4 x USART + 4 x UART (支持ISO7816,LIN,IrDA接口和调制解调控制)
 2 x SDIO
 2 x OTG全速控制器, 设备模式时支持无晶振(Crystal-less)
 2 x CAN 2.0B
 红外发射器
 10/100M以太网MAC:具有专用DMA和4 K字节SRAM,支持IEEE 1588硬件,MII/RMII接口
 3.3开发板外观
 
 四、移植准备
 4.1 Lua源码下载
 官网地址:http://www.lua.org/ftp/
 
   4.2 KEIL工程准备
 官网下载AT32F437的BSP,以其中的tamplates为例。
 
   打开工程,是通过按键控制LED快闪和慢闪两种模式,进行简单调整,只需留着GPIO的即可。
 
   调整过后如下所示,查看整个工程编译的大小,方便查看Lua移植后所需的内存大小。
 
   五、移植过程
 在KEIL工程中添加Lua源码
 
   排除“lua.c”、“luac.c”这2个文件,两个是一个Lua Shell,和平台相关,单片机用不上。
 添加头文件路径:
 
   添加头文件
 
   添加底层函数处理接口:
 typedef int FILEHANDLE;
 
 #pragma import(__use_no_semihosting_swi)
 
 #pragma import(_main_redirection)
 
 const char __stdin_name[150];
 
 const char __stdout_name[150];
 
 const char __stderr_name[150];
 
 FILEHANDLE _sys_open(const char *name, int openmode)
 
 {
 
 return 0;
 
 }
 
 int _sys_close(FILEHANDLE fh)
 
 {
 
 return 0;
 
 }
 
 int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode)
 
 {
 
 return 0;
 
 }
 
 int _sys_read(FILEHANDLE fh, unsigned char*buf, unsigned len, int mode)
 
 {
 
 return 0;
 
 }
 
 //检查句柄是否为终端
 
 int _sys_istty(FILEHANDLE fh)
 
 {
 
 return 0;
 
 }
 
 int _sys_seek(FILEHANDLE fh, long pos)
 
 {
 
 return 0;
 
 }
 
 //刷新句柄关联的缓冲区
 
 int _sys_ensure(FILEHANDLE fh)
 
 {
 
 return 0;
 
 }
 
 //返回文件当前长度
 
 long _sys_flen(FILEHANDLE fh)
 
 {
 
 return 0;
 
 }
 
 void _sys_exit(int status)
 
 {
 
 
 
 }
 
 int _sys_tmpnam(char *name, int fileno, unsigned maxlength)
 
 {
 
 return 0;
 
 }
 
 //将一个字符写入控制台
 
 void _ttywrch(int ch)
 
 {
 
 }
 
 int remove(const char *filename)
 
 {
 
 return 0;
 
 }
 
 char *_sys_command_string(char *cmd, int len)
 
 {
 
 return NULL;
 
 }
 
 time_t time(time_t * time)
 {
 return 0;
 }
 添加led控制处理:
 static int lua_led_on(lua_State *L)
 {
 gpio_bits_write(GPIOD,GPIO_PINS_14,TRUE);
 return 1;
 }
 
 static int lua_led_off(lua_State *L)
 {
 gpio_bits_write(GPIOD,GPIO_PINS_14,FALSE);
 return 1;
 }
 static int lua_delay(lua_State *L)
 {
 uint16_t ms;
 ms = (uint16_t)lua_tointeger(L,1);
 delay_ms(ms);
 return 1;
 }
 
 static const struct luaL_Reg lib[]=
 {
 {"delay",lua_delay},
 {"led_on",lua_led_on},
 {"led_off",lua_led_off},
 {NULL,NULL}
 };
 
 const char LUA_GLOBAL[]="\
 off = 500    \
 on = 500     \
 while 1 do   \
 led_on() \
 delay(off)\
 led_off() \
 delay(on) \
 end";
 
 static lua_State *luaL;
 void lua_run(void)
 {
 luaL = luaL_newstate();
 luaopen_base(luaL);
 luaL_setfuncs(luaL,lib,0);
 luaL_dostring(luaL,LUA_GLOBAL);
 
 while(1);
 }
 主函数:
 int main(void)
 {
 system_clock_config();
 at32_board_init();
 uart_print_init(115200);
 lua_run();
 }
 修改启动文件:
 
   编译了一下,报了110个错误和36个警告,慢慢的一个一个解决吧!!!
 
   选择C99Mode模式,编译错误解决
 
   再次编译,还有错误,同时需要将工程串口打印例程,或者自己添加串口打印。
 
   原因分析:
 在luaconfig.h 中有 luai_writestring 和 luai_writeline 两个宏,这两个宏关系到了 lua 中 print 的输出,需要针对平台重定向,一般定向到调试串口就行。所以需要将GPIO工程替换串口打印工程。
 我工程中使用了MicroLIB
 
   同时在at32f435_437_board.c中已经定义,同时在进行添加底层接口时也进行了定义。
 
   解决方法:
 不使用MicroLIB,同时将at32f435_437_board.c所定义的部分屏蔽掉。
 六、结果
 Lua已经在板子上正常跑起来了
 
   
 
 |