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

news2024/11/17 6:00:49

概述

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

发论文idea来了!强化学习+Transformer,29个创新点汇总

基于Transformer的强化学习&#xff08;TRL&#xff09;是一种利用Transformer模型架构来改进和增强强化学习算法性能的方法。 这种方法通过结合Transformer模型强大的表示能力和强化学习的决策优化框架&#xff0c;显著提升了智能体的学习能力和适应能力&#xff0c;为我们解…

逻辑蕴含、函数依赖集的闭包、Armstrong公理、属性集闭包

一、引言 Armstrong公理-从给定的函数依赖集得到关系模式的完整依赖集 二、逻辑蕴含 1、定义 设F是关系模式R上的函数依赖集&#xff0c;X、Y是R的属性子集&#xff0c;对于R的每个满足F的关系实例r&#xff0c;若函数 依赖都成立&#xff0c;则称F逻辑蕴含。 记为&#…

今日分享:能源行业数据大屏与界面设计~

能源行业数据大屏设计时要紧扣行业主题&#xff0c;关注视觉效果、实时数据与动态效果、数据可视化和图表、布局与字体、交互性、告警功能、故事叙述、易读性和可维护性等多个方面。大家设计时可以从这几个方面进行检查调整&#xff0c;这样就可以设计出既美观又实用的能源行业…

支持的 Google Pixel 设备

Android 15 OTA 和下载内容适用于以下 Pixel 设备&#xff1a; Pixel 6 和 Pixel 6 ProPixel 6aPixel 7 和 Pixel 7 ProPixel 7aPixel FoldPixel TabletPixel 8 和 Pixel 8 ProPixel 8a 获取 Android 15 Beta 版 1 、HONOR Android 15 Beta 2 Magic6 Pro Android 15 Beta …

【Redis技术进阶之路】「原理分析系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)

揭秘高效存储模型与数据结构底层实现 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 SDS&#xff08;简单动态字符串&#xff09;C字符串C字符串存在的问题字符串存储局限性不存储字符串长度…

【区块链】以太坊白皮书深度解读:构建智能合约的分布式平台

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 以太坊白皮书深度解读&#xff1a;构建智能合约的分布式平台引言1. 以太坊的诞生…

对比4090及4090D:国区“特供”与原版相比有何区别?

2023年12月28日 英伟达宣布正式发布GeForce RTX 4090D&#xff0c;对比于一年前上市的4090芯片&#xff0c;两者的区别与差异在哪&#xff1f;而在当前比较火热的大模型推理、AI绘画场景方面 两者各自的表现又如何呢&#xff1f; 规格与参数信息对比现在先来看看GeForce RT…

Deflate内部实现(LZ77无损压缩算法)超详细图解算法版~

无损压缩算法 第一阶段&#xff1a;重复消除 — LZ77无损压缩算法算法介绍举例压缩算法思路图解压缩过程 第二阶段&#xff1a;位减少huffman位减少 概览 Gzip Deflate 编码&#xff08;LZ77哈夫曼&#xff09; Brotli LZ77哈夫曼二阶上下文建模 Deflate 分两个阶段压缩数据…

系统架构——Spring Framework

目录 &#xff08;1&#xff09;基本介绍 &#xff08;2&#xff09;基本发展历史 &#xff08;3&#xff09;了解和学习 Spring 4.x 系列的系统架构 1、第一个模块&#xff1a;做核心容器&#xff08;Core Contaner&#xff09; 2、第二个模块&#xff1a;AOP与Aspects(这…

怎么用AI生成逼真的图片?

以 SD 为例&#xff0c;选择一个写实的大模型就可以了&#xff0c;比如以下是我用 XXMix_9realisticSDXL 大模型生成的图片&#xff1a; xxmixgirl,((((melt)))),(((((black and white melt))))),(((wear Black and white Taoist robes))),((((gold and silver lace)))),(((gol…

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. 解决方式&…

智慧体育场馆:视频孪生引领体育场馆智能化

随着数字经济时代的发展&#xff0c;技术的迭代跃迁加速了体育场馆运营革新的步调&#xff0c;在技术赋能理念的驱动下&#xff0c;体育场馆逐步由复合化发展姿态&#xff0c;升级为物联感知式的智能场馆&#xff0c;并迈向了智慧体育场馆的发展之路。《“十四五”时期全民健身…

Sui的Fastcrypto加密库刷新速度记录

Sui使用的加密库Fastcrypto打破了许多速度记录&#xff0c;Mysten Labs在基准测试和安全分析中的工作修复了许多安全漏洞&#xff0c;同时通过识别新的优化技巧为创新开辟了道路。 最近在伦敦帝国理工学院举行的国际性能工程会议&#xff08;ICPE&#xff09;基准测试研讨会上…

成都爱尔周进院长提醒毕业生摘镜,术式如何挑

高考完迎来一个悠长假期&#xff0c;考后放松的同时&#xff0c;也有不少同学开始“准备”。 为奔赴梦想&#xff0c;为了理想的专业和学校&#xff0c;不少人决定摘镜。 不少专业有视力要求&#xff0c;且不同专业方向的要求各有不同。我们先来看看有视力要求的专业有哪些&am…

Linux终端玩转bastet俄罗斯方块小游戏

Linux终端玩转bastet俄罗斯方块小游戏 一、bastet小游戏介绍1.1 bastet小游戏简介1.2 项目预览 二、本次实践介绍2.1 本地环境规划2.2 本次实践介绍 三、检查系统镜像源3.1 检查系统镜像源3.2 更新软件列表3.3 查询软件 四、安装bastet小游戏4.1 安装bastet4.2 启动bastet游戏 …

Clickhouse监控_监控的指标以及Grafana配置Clickhouse指标异常时触发报警

使用PrometheusGrafana来监控Clickhouse服务和性能指标 Clickhouse监控指标的官方文档https://clickhouse.com/docs/zh/operations/monitoring 建议使用PrometheusGrafana组合监控Clickhouse服务和性能指标&#xff0c;数据流向&#xff1a;Prometheus的clickhouse_exporter组件…

jpg格式图片无法打开可以修复吗?有哪些方法?

JPG的图片打不开怎么办呢&#xff1f;当JPG图片打不开的时候&#xff0c;我们需要先了解下具体的原因&#xff0c;是因为格式不支持&#xff0c;还是因为图片文件损坏。不同的原因&#xff0c;解决的方法也会不同&#xff0c;比如图片损坏&#xff0c;我们就需要对图片修复处理…

Maven相关知识

maven 继承与聚合 聚合&#xff1a;聚合多个模块&#xff08;可以一起构建&#xff09; &#xff0c;各模块之间单独打包 继承: 为了消除重复&#xff0c;将相同的配置提取&#xff0c;子模块默认继承全部父模块的依赖dependencies节点&#xff0c;通过它来管理jar包的版本&am…

汽车IVI中控开发入门及进阶(三十一):视频知识扫盲

有效的视频资源管理需要集成许多不同的底层技术,共同为用户提供给定应用程序的最佳体验。其中许多技术是从早期电视广播中使用的技术演变而来的。其他方法,如用于通过网络流式传输视频的压缩方法,相对较新且不断发展。 以下详细概述了与图形和视频处理和传输相关的一些基本…

智能合约开发的过程

智能合约是一种运行在区块链上的程序&#xff0c;可以自动执行预先设定的条款和条件。智能合约具有去中心化、透明、不可篡改等特点&#xff0c;因此被广泛应用于金融、供应链、物联网等领域。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流…