做图软件官方网站,杭州网站的优化,莱特币做空国外网站,yc011 wordpress主题概述
站内移植LUA多数是使用C函数调用LUA#xff0c;并没有移植REPL交互端口 本文将REPL也移植进去#xff0c;做了简单的适配
LUA源码使用标准C库函数#xff0c;如fgets#xff0c;fwrite等#xff0c;在嵌入式环境中要使用fgets#xff0c;fwrite等C库函数#xff…概述
站内移植LUA多数是使用C函数调用LUA并没有移植REPL交互端口 本文将REPL也移植进去做了简单的适配
LUA源码使用标准C库函数如fgetsfwrite等在嵌入式环境中要使用fgetsfwrite等C库函数需要做的工作就是重定向。
本文重定向了STDIN和STDOUT数据流到J-Link RTT Viewer可以通过 RTT Viewer向LUA虚拟机进行交互。
环境
MCUSTM32F407, 192KB RAM, 1MFLASH。建议运行平台至少有256KBRAM256KB的FLASH否则加载lib的时候会爆内存或者FLASH。 KEIL527 编译器AC6
准备工程
从https://www.lua.org/download.html网站下载LUA源码在KEIL中新建一个LUA文件夹将所有文件添加到里面。luac.c不要添加进去这个文件是用来编译lua脚本的我们不需要。
准备SEGGER RTT打印相关文件
新建一个空文件syscall.c后面的C库系统调用函数我们会写入到此文件中。
处理好所有文件的头文件包含路径问题。
对接C库系统调用函数
以下函数的编写参考了如下资源
rt_sys.h文件定义了函数头文件里面还有函数功能和返回值的描述Arm® C and C Libraries and Floating-Point Support User Guide一些函数描述
主要实现了
关闭半主机模式_sys_open打开文件返回STDINSTDOUTSTDERR的文件描述符普通文件流不处理_sys_write写文件向STDOUT写入的数据流流向SEGGER RTT普通文件流不处理_sys_read读文件SEGGER RTT读取的数据流向STDIN普通文件流不处理、_sys_istty判断文件描述符是否为终端time事件相关的函数对接的是hal_gettick,返回系统上电运行了多少ms
#include rt_sys.h
#include stdio.h
#include string.h
#include time.h#include SEGGER_RTT.h
#include main.h//关闭半主机模式
/********************************************************************************/
#if defined(__clang__)__asm(.global __use_no_semihosting\n\t);
#elif defined(__CC_ARM)#pragma import(__use_no_semihosting)
#endif#define STDOUT 0x00000001
#define STDIN 0x00000002
#define STDERR 0x00000003 const char __stdin_name[] STDIN;
const char __stdout_name[] STDOUT;
const char __stderr_name[] STDERR;FILEHANDLE _sys_open(const char *pcFile, int openmode)
{if(0 strncmp(pcFile, __stdin_name, strlen(__stdin_name))) return STDIN;if(0 strncmp(pcFile, __stdout_name, strlen(__stdout_name))) return STDOUT;if(0 strncmp(pcFile, __stderr_name, strlen(__stderr_name))) return STDERR;//pcFile :文件路径//openmode :文件打开模式//返回值 :文件描述符return 0;
}int _sys_close(FILEHANDLE fh)
{return 0;
}int _sys_write(FILEHANDLE fh, const unsigned char * buf, unsigned len, int mode)
{if (fh STDOUT){SEGGER_RTT_Write(0, (const char*)buf, len); return 0;}return 0;
}int _sys_read(FILEHANDLE fh, unsigned char * buf, unsigned len, int mode)
{
//读取一行数据回车结束。读取完毕之后在字符串末尾添加结束符static int count_p 0;if (fh STDIN){count_p 0;buf[count_p] SEGGER_RTT_WaitKey();while(buf[count_p] ! \n){count_p;buf[count_p] SEGGER_RTT_WaitKey();}buf[count_p 1] \0;return 0;}return 0; //EOF
}void _ttywrch(int ch)
{fputc(ch, stdout); // stdoutfflush(stdout);
}int _sys_istty(FILEHANDLE fh)
{return (fhSTDIN || fhSTDOUT || fhSTDERR);
}int _sys_seek(FILEHANDLE fh, long pos)
{return 0;
}int _sys_ensure(FILEHANDLE fh)
{return 0;
}long _sys_flen(FILEHANDLE fh)
{return 0;
}int _sys_tmpnam(char * name, int sig, unsigned maxlen)
{return 0;
}void _sys_exit(int returncode) /* never returns */
{
}char *_sys_command_string(char * cmd, int len)
{return 0;
}
int remove(const char *filename)
{return 0;
}
int system(const char *string)
{return 0;
}
int rename(const char *old, const char *new)
{return 0;
}
time_t time(time_t *timer)
{return HAL_GetTick();
}
clock_t clock(void)
{return 0;
}修改LUA源码
LUA源码中操作行数据使用fgets和puts这个函数我的对接始终有问题这里更改为fread和fwrite函数 在luaconf.h末尾添加如下代码
/* *//*
** Local configuration. You can use this space to add your redefinitions
** without modifying the main part of the file.
*/
#define LUA_MAXINPUT 128
#define lua_readline(L,b,p) ( fread(b, 1, LUA_MAXINPUT, stdin) ! 0)
#define lua_initreadline(L) ( (void)L )
#define lua_saveline(L,line) { (void)L; (void)line; }
#define lua_freeline(L,b) { (void)L; (void)b; }#define lua_writestring(s,l) fwrite(s, 1, l, stdout)
#define lua_writeline() fwrite(\n, 1, 1, stdout)
#define lua_writestringerror(...) printf(__VA_ARGS__)
lua.c中已经有一个main函数我们需要将这个main函数改名为lua_main在keil中的main函数调用lua_main来启动LUA
int lua_main (int argc, char **argv) { //修改函数名int status, result;lua_State *L luaL_newstate(); /* create state */if (L NULL) {l_message(argv[0], cannot create state: not enough memory);return EXIT_FAILURE;}lua_gc(L, LUA_GCSTOP); /* stop GC while building state */lua_pushcfunction(L, pmain); /* to call pmain in protected mode */lua_pushinteger(L, argc); /* 1st argument */lua_pushlightuserdata(L, argv); /* 2nd argument */status lua_pcall(L, 2, 1, 0); /* do the call */result lua_toboolean(L, -1); /* get result */report(L, status);lua_close(L);return (result status LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
}lua .h中增加lua_main的函数声明
int lua_main (int argc, char **argv);启动LUA虚拟机
main函数中增加如下代码 这里我们要给lua_main 传递两个假参数如下 int fake_argc 1;char *fake_argv NULL;lua_main (fake_argc, fake_argv);启动
启动前要先配置好RTT VIEWER复位启动即可. 测试指令如下 _VERSION print(hello world) print(abc..666) print(system run ..os.time().. msec)错误指令和提示如下 print(system run ..XXX.time().. msec)TODO其他
工程参考https://gitee.com/nwwhhh/stm32f407 TODO对接文件函数调用本地文件