LUA移植到STM32F4,移植REPL,通过RTT Viewer交互

概述

站内移植LUA多数是使用C函数调用LUA,并没有移植REPL交互端口
本文将REPL也移植进去,做了简单的适配

LUA源码使用标准C库函数,如fgets,fwrite等,在嵌入式环境中要使用fgets,fwrite等C库函数,需要做的工作就是重定向。

本文重定向了STDIN和STDOUT数据流到J-Link RTT Viewer,可以通过 RTT Viewer向LUA虚拟机进行交互。
在这里插入图片描述

环境

MCU:STM32F407, 192KB RAM, 1MFLASH。建议运行平台至少有256KBRAM,256KB的FLASH,否则加载lib的时候会爆内存或者FLASH。
KEIL:527
编译器: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:打开文件,返回STDIN,STDOUT,STDERR的文件描述符,,普通文件流不处理
  • _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); // stdout
  fflush(stdout);
}

int _sys_istty(FILEHANDLE fh)
{
  return (fh==STDIN || fh==STDOUT || fh==STDERR);  
}

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:对接文件函数,调用本地文件

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/723952.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MATLAB源码-第227期】基于matlab的北方苍鹰优化算法(NGO)机器人栅格路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 鼠群优化算法&#xff08;Rat Swarm Optimization, RSO&#xff09; 简介 鼠群优化算法&#xff08;Rat Swarm Optimization, RSO&#xff09;是一种模仿鼠类群体觅食行为的优化算法。该算法属于群体智能算法&#xff0c;通…

mysql密码过期的修改(Your password has expired. ..)

参考文章&#xff1a;mysql密码过期的修改方法&#xff08;your password has expired&#xff09;_我是知青-RuoYi 若依 (csdn.net) 问题&#xff1a;Your password has expired. To log inyou must change it using a clientthat supports expired passwords. 解决方式&…

代码随想录第28天|回溯算法

491. 非递减子序列 思路: 不可以排序, 否则会改变元素的顺序对收获的结果有要求, num.size() > 2, 且 num[i - 1] < num[i]需要进行去重, 不能使用排序后的方法去重每一层可用 unordered_set 去重组合问题, for 遍历需要标记起始位置 bug: 一定要先判断元素是否重复, …

【干货】什么是客户裂变系统?它如何帮助saas企业实现业绩转化?

在数字化时代&#xff0c;客户裂变系统已成为SaaS企业实现业绩转化的重要工具。简而言之&#xff0c;客户裂变系统是一种通过现有客户吸引更多新客户的策略。 什么是客户裂变系统&#xff1f; 该系统基于用户行为和数据分析&#xff0c;通过精心设计的激励机制&#xff0c;如…

王思聪隐形女儿曝光

王思聪"隐形"女儿曝光&#xff01;黄一鸣独自面对怀孕风波&#xff0c;坚持生下爱情结晶近日&#xff0c;娱乐圈掀起了一场惊天波澜&#xff01;前王思聪绯闻女友黄一鸣在接受专访时&#xff0c;大胆揭露了她与王思聪之间的爱恨纠葛&#xff0c;并首度公开承认&#…

Suno AI如何解决制作多语言混合的歌曲~

导读 你想不想制作一首有中文和粤语混合的歌曲&#xff1f; 你想不想制作一首有中文和日语混合的歌曲&#xff1f; 你想不想制作一首有中文和英语混合的歌曲&#xff1f; 如果你想不知道怎么操作&#xff0c;可以阅读下本文。 说明 本文让AI唱一首中文和日语混合的歌曲&am…

OpenCV中的圆形标靶检测——findCirclesGrid()(三)

前面说到cv::findCirclesGrid2()内部先使用SimpleBlobDetector进行圆斑检测,然后使用CirclesGridClusterFinder算法类执行基于层次聚类的标靶检测。如下图所示,由于噪声的影响,SimpleBlobDetector检出的标靶可能包含噪声。 而CirclesGridClusterFinder算法类会执行基…

【CT】LeetCode手撕—手撕快排

目录 题目1-思路-快排1-1 快排的核心思想快速排序算法步骤优美的调整区间 1-2 ⭐快排的实现 2- 实现⭐912. 排序数组——题解思路 3- ACM 实现 题目 原题连接&#xff1a;912. 排序数组 1-思路-快排 1-1 快排的核心思想 选择一个基准 基准左侧的元素都小于该元素基准右侧的元…

数据分析必备:一步步教你如何用matplotlib做数据可视化(6)

1、Matplotlib 网格 axes对象的grid()函数将图中网格的可见性设置为on或off。还可以显示网格的主要/次要(或两者)刻度。另外&#xff0c;可以在grid()函数中设置color&#xff0c;linestyle和linewidth属性。 参考以下示例代码 import matplotlib.pyplot as plt import numpy…

GLib库内存块数据类型简单用法

代码; #include <glib.h> int main() {GMemChunk *chunk; // 定义内存块gchar *mem[10]; // 定义指向原子的指针数组gint i, j;chunk g_mem_chunk_new( // 创建内存块"Test MemChunk", // 名称5, // 原子的长度50, …

在3dmax软件中如何快速创建毛发?---模大狮模型网

在3D建模和渲染中&#xff0c;为角色或物体添加逼真的毛发效果是提升场景真实感的重要步骤之一。然而&#xff0c;手动一根一根创建毛发是非常繁琐的&#xff0c;因此掌握如何在软件中快速生成和调整毛发效果至关重要。模大狮将详细介绍如何利用3ds Max 2018创建毛发&#xff0…

上市公司-社会责任报告、ESG报告文本(2006-2023年)

上市公司社会责任报告是企业对外公布的一份关于其社会责任实践和成果的详细文件&#xff0c;涵盖环境保护、社会贡献和公司治理等方面的表现。通常包含公司在减少环境影响、提升社会福祉、维护员工权益、促进社区发展以及确保透明和道德的管理实践等方面的信息和数据。有助于了…

宠物空气净化器爆火的背后...小米、希喂、安德迈性能大揭秘?

广东省 猫友们都清楚&#xff0c;猫咪虽然魅力无穷&#xff0c;但它们掉毛的问题确实令人头疼。家具、衣物上、空气中都散布着猫浮毛&#xff0c;给铲屎官造成困扰。其中最难处理的便是空气中的浮毛啦&#xff0c;如果不及时处理会对家庭成员造成健康威胁。接下来&#xff0c;我…

MySQL8,Navicat能登陆成功,密码却忘记了

执行成功的图&#xff1a; 以下为步骤&#xff1a;本文一共8个简单步骤。 环境&#xff1a;mysql8、window10、navicat11 1、打开本地电脑window10的命令窗&#xff08;俗称黑窗口&#xff09;&#xff0c;windowR 2、输入regegit&#xff0c;回车&#xff0c;打开注册表 3、…

判断单链表是否带环且返回节点

今天鄙人为大家带来的是一道简单的逻辑运算题。用用到了一个我们在链表中提及过的方法快慢法。这道题其实没啥考的实际意义。只是我们如果能了解这道题的解决方法的话。对我们后面梳理逻辑会有很大的帮助。 单链表的题目 我们可以看到上面的题目。就是让我们判断是否带环。也许…

深入了解 Android 中的 ViewStub

在 Android 开发中&#xff0c;性能优化一直是一个重要的话题。ViewStub 作为一种轻量级视图容器&#xff0c;可以帮助我们在合适的时机延迟加载视图&#xff0c;从而优化应用性能。本文将详细介绍 ViewStub 的概念、使用方法以及在实际开发中的应用场景。 什么是 ViewStub&am…

船舶行业信息安全解决方案介绍

船舶行业信息安全背景&#xff1a; 近年来随着经济复苏、疫情与国际形势影响国内外船舶海运业务蓬勃发展&#xff0c;在业务量激增的背景下出现多类信息安全事件。其中2017年&#xff0c;马士基集团遭到勒索软件攻击&#xff0c;内部业务系统和码头操作系统均受到严重影响&…

【计算机视觉(11)】

基于Python的OpenCV基础入门——图像梯度变换 图像梯度变换Sobel算子Scharr算子Laplacian算子 图像梯度变换的代码实现以及效果图 图像梯度变换 图像梯度变换可以用于边缘检测、特征提取、增强图像和压缩图像等多种任务。图图像梯度可以把图像看成二维离散函数&#xff0c;图像…

深入二进制安全:全面解析Protobuf

前言 近两年&#xff0c;Protobuf结构体与Pwn结合的题目越来越多。 23年和24年Ciscn都出现了Protobuf题目&#xff0c;24年甚至还出现了2道。 与常规的Pwn题利用相比&#xff0c;只是多套了一层Protobuf的Unpack操作。 本文包含Protobuf环境安装、相关语法、编译运行以及pb…