lua在stm32上的移植

1.下载lua源码从官网,本文使用的是lua5.3.2,将加载到自己的工程中(不用添加lua.c和luac.c),修改luaconf.h,在其中增加宏定义#define LUA_32BITS;

2.增加文件stm32_lua_config.c,其内容如下,主要是重定义lua中文件操作的底层函数(即fopen、fread、fclose等函数要调用的函数):

#include "includes.h"
#include "LCD_Get_Res.h"
#include "ff.h"


#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];
typedef int FILEHANDLE;

void _sys_exit(int status)
{
	while(1);
}
FILEHANDLE _sys_open(const char *name, int openmode)
{
	uint32_t mode = 0;
	int ret;

	if(openmode == 0)
	{
		mode |= FA_READ;
	}
	if(openmode & 0x01)
	{
		mode |= FA_WRITE;
	}
	if(openmode & 0x10)
	{
		mode |= FA_READ | FA_WRITE;
	}
	if(openmode & 0x0100)
	{
		mode |= FA_CREATE_NEW;
	}
	ret = f_open(&sd_file, name,  mode);
	if(ret != FR_OK)
	{
		return 0;
	}
	return 1;
}

int _sys_close(FILEHANDLE fh)
{
	f_close(&sd_file);
	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)
{
	int res,i = 0;
//	int cou_sd;
//	int size;
//	int read_len = len;

//	while(1)
//	{
//		(read_len > 512)? (size = 512) : (size = read_len);
//		res = f_read(&sd_file, &buf[i], size, &cou_sd);
//		if(res != FR_OK)
//		{
//			return EOF;
//		}
//		read_len -=cou_sd;
//		i += cou_sd;
//		if(read_len <= 0 || cou_sd == 0)
//		{
//			break;
//		}
//	}
	return i;
}
//若此处重定义了fgetc则fread不会调用_sys_read
int fgetc(FILE *stream)
{
	char ch = 0;
	int res;
	int cou_sd;
	res = f_read(&sd_file, &ch, 1, &cou_sd);
	if(res != FR_OK || cou_sd == 0)
	{
		return EOF;
	}
		
	return ch;
}

int _sys_seek(FILEHANDLE fh, long pos)
{
	int res;
	res = f_lseek(&sd_file, pos);
	if(res != FR_OK)
	{
		return res;
	}
	return 0;
}

int _sys_istty(FILEHANDLE fh)
{
	return 0;
}

int _sys_ensure(FILEHANDLE fh)

{
	return 0;
}

long _sys_flen(FILEHANDLE fh)
{
	return 0;
}

int _sys_tmpnam(char *name, int fileno, unsigned maxlength)
{
	return 0;
}

void _ttywrch(int ch)
{
}
time_t time(time_t *t)
{
	return 0;
}
int remove(const char *filename)
{
	return 0;
}

char *_sys_command_string(char *cmd, int len)
{
	return 0;
}

clock_t clock(void)
{
	return 0;
}

int system(const char* a)
{
	return 0;
}

int rename(const char *a, const char *b)
{
	return 0;
}


3.在2中已经重新定义了lua中的文件操作的底层函数,但是lua中有一些函数如luaL_dofile需要从文件目录中加载.lua程序,这时我们只需实现上面的_sys_open、_sys_close、fgetc等函数再修改luaconf.h即可,在2中我已经实现文件操作一些函数的接口,修改luaconf.h:

在luaconf.h 190行左右有如下代码:

#define LUA_ROOT "/usr/local/"
#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/"
#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/"
#define LUA_PATH_DEFAULT  \
LUA_LDIR"?.lua;"  LUA_LDIR"?/init.lua;" \
LUA_CDIR"?.lua;"  LUA_CDIR"?/init.lua;" \
"./?.lua;" "./?/init.lua"
#define LUA_CPATH_DEFAULT \
LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"


上面及时lua寻找文件的一个默认路径,因我们不存在这些路径,把它修改为我们自己的sd卡路径或其他存储设备路径即可,这里我用的是sd卡,把上面注释,修改如下:

#define LUA_PATH_DEFAULT  "1:/LUALib/?.lua;"
#define LUA_CPATH_DEFAULT "1:/LUALib/?.so;"


4.上面的工作做完就可以执行在sd卡中的lua程序了,举例如下:

c程序:

static int Delay_ms(lua_State *L)
{
    delay_ms(luaL_checkinteger(L, -1));
    return 0;
}
static int print(lua_State *L)
{
    int n=lua_gettop(L);
    int i;
    for (i=1; i<=n; i++)
    {
        if (lua_isstring(L,i))
            printf("%s",lua_tostring(L,i));
        else if (lua_isnil(L,i))
            printf("%s","nil");
        else if (lua_isboolean(L,i))
            printf("%s",lua_toboolean(L,i) ? "true" : "false");
        else
            printf("%s:%p",luaL_typename(L,i),lua_topointer(L,i));
     }
     return 0;
}
static luaL_Reg LuaLib1_0[] = 
{ 
    //c接口函数都可以放在这里在lua中声明
    {"Delay_ms", Delay_ms},
    {"print", print},

    {NULL, NULL} 
};
void Lua_task(void)
{ 
    lua_State* L;
    L = luaL_newstate();
    luaL_openlibs(L);

    luaL_newlibtable(L, LuaLib1_0);
    luaL_setfuncs(L, LuaLib1_0, 0);
    //这里定义全局变量把栈顶的table赋值给LuaLib1_0,这个方式使用模块是因为无法将c模块生成动态链接库.so或.dll给LUA_CPATH_DEFAULT加载
    lua_setglobal(L, "LuaLib1_0");
    if (luaL_dofile(L, "1:/Lua.lua")!=0)//加载sd卡中的Lua.lua并运行
          printf(lua_tostring(L,-1));

}


Lua.lua中程序:

local LuaLib1_0 = require("LuaLib1_0")

Windows = {
    WINDOW1 = 0,
    WINDOW2 = 1,
}

local i = 0
function window2()
    i = i + 1;
    if i == 256 then
        i = 0
    end 
end

function window1()
    i = i + 1;
    if i == 256 then
        i = 0
    end
end

function window_handle()
    Window_Cur = WINDOW1 
    if Window_Cur == Windows.WINDOW1 then
        window1()
    elseif Window_Cur == Windows.WINDOW2 then
        window2()
    end 
end

function Lua_main()

    while true do
        window_handle()
        LuaLib1_0.Delay_ms(200)
    end
end

Lua_main()


这样就可以把c和lua分开,在lua中写自己的应用程序了,lua中想要什么数据由c提供。

以上内容均为自己理解,如有错误,欢迎指正

你可能感兴趣的:(lua,移植,lua,stm32)