lua移植到STM32F4全过程

10 篇文章 0 订阅
5 篇文章 1 订阅

 

基于之前了解到的Lua脚本开发功能,尝试过多次都没有很认真的做到底。之前的尝试都没能很好的应用到自己的工程里。

elua东西太多并且是在linux下编译的,我很不适应,当然liunx涉及的不深。

本次移植的条件及目标:

本次的目标是能精简移植最纯洁版的lua框架,能够实现多文件(.lua)的联合调用 require / dofile。

开发工具:Keil V5.29

硬件平台:STM32F4探索者开发版

移植下来发现lua和平台真的关系不大,就内存上面我还没搞懂他需要多少合适。

单纯加入了一个测试lua-lib,具体编译空间MAP如下:

    Total RO  Size (Code + RO Data)               157208 ( 153.52kB)
    Total RW  Size (RW Data + ZI Data)             36904 (  36.04kB)
    Total ROM Size (Code + RO Data + RW Data)     157256 ( 153.57kB)

工作内容有:

1、lua库移植

2、FatFs文件系统的移植

3、多文件.lua的相互调用测试测试

这次捣鼓花了3天的时间,对lua语言和和lua库的函数库有初步了解。整个过程就不是很顺利,几经自闭。

程序源码会附件提供大家学习,以免大家多走弯路。欢迎下载。

下载链接:https://download.csdn.net/download/ai5945fei/12630346

 

整体参考博客,在此感谢给了很多的帮助

https://blog.csdn.net/zlm_space/article/details/50379980

 

工程整体内容:

移植步骤:

到gethub下载lua源码,当前使用版本 This is Lua 5.4.0, released on 18 Jun 2020.

解压并添加到自己的工程里,除lua.c和luac.c外全部添加。

添加后编译会出现几个未定义的函数,可以找到并全是实现成空函数,实际用到的时候再补充。

不用文件的话不出意外都能跑起来。

大概描述一下几个地方,方便以后快速上手。

1、添加预编译LUA_32BITS

2、注意此处不打勾

文件系统重定向

3、这里坑我比较久

#pragma import(__use_no_semihosting) 

不加入这一句会出现一个很郁闷的问题。程序进入DEBUG模式时能正常运行,真机运行就崩溃起不来。

 

 

4、lua搜索路径

根据自己挂载的路径修改lua搜索路径,主要提供 require查找文件。dofile默认可以查找到当前路径,可以不需要设置该路径。reuqire不行,需要指定。

5、在此处添加自己的驱动

6、文件系统配置

文件系统我使用的是系统RAM,分配了10k空间。自己可随意调整为内部FLASH或者存储卡等存储介质。

#define FF_MIN_SS		1024 // 扇区大小

7、注意屏蔽掉fputc的实现 

int fputc(int ch, FILE *f)该函数就不需要在外部实现,会造成发送混乱。重定向的功能已经在stdio.c里面实现了。

8、这几个实现文件系统的必要文件

收尾

至此,没有什么要特别注意的了。附上main.c文件,是不是你需要的东西,自行评估。

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "string.h"
//ALIENTEK 探索者STM32F407开发板 实验4
//串口通信实验 -库函数版本
//技术支持:www.openedv.com
//淘宝店铺:http://eboard.taobao.com
//广州市星翼电子科技有限公司
//作者:正点原子 @ALIENTEK

#include "lua.h"

#include "lauxlib.h"
#include "lualib.h"

#include <ff.h>
static FATFS fatfs;

//文件系统挂
static int file_system_init(void)
{
    char buffer[FF_MIN_SS];
    FRESULT fr;

    fr = f_mount(&fatfs, "0:/", 1); // 挂载磁盘
    if (fr == FR_OK)
    {
        printf("f_mount OK!\n");
        return 1;
    }
    if (fr == FR_NO_FILESYSTEM)
    {
        // 若磁盘没有格式化, 则格式化磁盘
        fr = f_mkfs("0:/", FM_FAT, 0, buffer, sizeof(buffer));
        if (fr == FR_OK)
        {
            printf("Disk is formatted!\n");
            return 1;
        }
        else
        {
            printf("Disk cannot be formatted! fr=%d\n", fr);
            return 0;
        }
    }
    else
    {
        printf("f_mount error! fr=%d\n", fr);
        return 0;
    }
}



const char LUA_SCRIPT_HELLO[] = " \
print('this is hello.lua')\
gloabl_param = 'this is gloabl param' \
function say_hello()\
	print('this is function:say hello')\
end	\
";

const char LUA_SCRIPT_GLOBAL[] = "  \
print('this is main.lua') \
off = 500     \
on = 500       \
require('module')\
print(module.constant)\
print('into while')\
while true do \
 led.led_on() \
 led.delay(off)    \
 led.led_off()        \
 led.delay(on)      \
end";


const char LUA_SCRIPT_GLOBAL_STR[] = "  \
print('this is main.lua') \
off = 500     \
on = 500       \
print('into while')\
while true do \
 led.led_on() \
 led.delay(off)    \
 led.led_off()        \
 led.delay(on)      \
end";

const char LUA_SCRIPT_MODULE[] = " \
module ={}  \
module.constant='这是一个模块常量'\
return module";

void file_write_string(const char *filename,const char *strdata)
{
    FILE *fp = NULL;

    fp = fopen(filename, "w");
    if(fp)
    {
        fputs(strdata, fp);
        fclose(fp);
        printf("file %s create success\r\n",filename);
    }
    else
    {
        printf("file %s create err\r\n",filename);
    }
}

static void file_create_test(void)
{
    file_write_string("main.lua",LUA_SCRIPT_GLOBAL);
    file_write_string("hello.lua",LUA_SCRIPT_HELLO);
    file_write_string("module.lua",LUA_SCRIPT_MODULE);
}

FRESULT scan_files(char *path)
{
    FRESULT res; //定义结果对象
    DIR dir; //定义目录对象
    UINT i; //定义变量
    static FILINFO fno; //定义静态文件信息结构对象
    res = f_opendir(&dir, path); //打开目录,返回状态 和 目录对象的指针
    char pathBuff[256]; //定义路径数组
    if (res == FR_OK) //打开成功
    {
        for (;;) //遍历
        {
            res = f_readdir(&dir, &fno); //读取目录,返回状态 和 文件信息的指针
            if (res != FR_OK || fno.fname[0] == 0)
                break; //若打开失败 或 到结尾,则退出

            if (fno.fattrib & AM_DIR) //是目录
            {
                i = strlen(path); //获取原目录长度
                sprintf(&path[i], "/%s", fno.fname); //将新目录添加在原目录后面
                printf("是目录::%s\r\n", path);
                res = scan_files(path); //将新目录进行递归调用
                if (res != FR_OK)
                    break; //打开失败则退出
                path[i] = 0;
            }
            else
            {
                printf("是文件:%s/%s\r\n", path, fno.fname); //是文件
                //strcpy(pathBuff, fno.fname); //将文件目录存储起来
            }
        }
    }
    else
    {
        printf("失败 - %s", &res); //打开失败
    }
    f_closedir(&dir); //关闭目录
    return res; //返回状态
}

int main(void)
{
    uart_init(115200);

    delay_init(168);                                //延时初始化

    LED_Init();                                     //初始化与LED连接的硬件接口

    file_system_init();//加载文件系统

    file_create_test();//创建lua脚本文件

    scan_files("0:");

    lua_State *L  = luaL_newstate();

    if (L == NULL)
    {
        printf("LUA ERR\r\n");
    }
    else
    {
        printf("Lua init ok\r\n");

        luaL_openlibs(L);//加载Lua库

				//重复写文件测试
        file_write_string("autorun.lua","print('autorun file <1>  2')");

        luaL_dofile(L,"autorun.lua");

        file_write_string("autorun.lua","print('autorun file <2> s ')");

        luaL_dofile(L,"autorun.lua");
			
        luaL_dofile(L, "main.lua");
    }

    printf("exit\r\n");
}


运行结果:

led灯正产闪烁

其他:

启动文件再执行 __main 和 mian()函数之间会执行 __rt_entry函数,该函数会加载和执行

_sys_open 函数,配置STDIN  STDOUT STDERR等相关初始化工作。

 

 

 

  • 4
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值