当前位置: 首页 > news >正文

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

在这里插入图片描述

相关文章:

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

概述 站内移植LUA多数是使用C函数调用LUA&#xff0c;并没有移植REPL交互端口 本文将REPL也移植进去&#xff0c;做了简单的适配 LUA源码使用标准C库函数&#xff0c;如fgets&#xff0c;fwrite等&#xff0c;在嵌入式环境中要使用fgets&#xff0c;fwrite等C库函数&#xff…...

【GD32F303红枫派使用手册】第十九节

19.1 实验内容 通过本实验主要学习以下内容&#xff1a; SPI简介 GD32F303 SPI简介 SPI NOR FLASH——GD25Q32ESIGR简介 使用GD32F303 SPI接口实现对GD25Q32ESIGR的读写操作 19.2 实验原理 19.2.1 SPI简介 SPI&#xff08;Serial Peripheral interface&#xff09;&…...

【C语言】扫雷游戏

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…...

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

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

macOS聚集搜索功能开启与关闭

按下command空格弹出 使用搜索 关闭搜索 sudo mdutil -a -i off 启用搜索 sudo mdutil -a -i on...

大模型“诸神之战”,落地才是赛点

ChatGPT 诞生已经快一年&#xff0c;你还在与它对话吗&#xff1f; 有的人用来写报告、改代码&#xff0c;让它成为得力帮手&#xff1b;有的人却只是“调戏”个两三回&#xff0c;让它创作诗歌或故事&#xff0c;便不再“宠幸”。 根据网站分析工具 SimilarWeb 的数据&#…...

接口重放攻击

如何保证接口安全&#xff0c;做到防篡改防重放&#xff1f;_接口防止串改-CSDN博客 接口安全设计之防篡改和防重放_接口防篡改机制-CSDN博客 基于nonce timestamp 的方案 nonce的意思是仅一次有效的随机字符串&#xff0c;要求每次请求时该参数要保证不同。实际使用用户信息…...

MySQL学习笔记-进阶篇-SQL优化

SQL优化 插入数据 insert优化 1&#xff09;批量插入 insert into tb_user values(1,Tom),(2,Cat),(3,Jerry); 2&#xff09;手动提交事务 mysql 默认是自动提交事务&#xff0c;这样会导致频繁的开启和提交事务&#xff0c;影响性能 start transaction insert into tb_us…...

【机器学习】第2章 线性回归及最大熵模型

一、概念 1.回归就是用一条曲线对数据点进行拟合&#xff0c;该曲线称为最佳拟合曲线&#xff0c;这个拟合过程称为回归。 2.一个自变量 叫 一元线性回归&#xff0c;大于一个自变量 叫 多元线性回归。 &#xff08;1&#xff09;多元回归&#xff1a;两个x&#xff0c;一个…...

科技创新对农业发展的影响

科技创新对农业发展的影响深远且广泛&#xff0c;主要体现在以下几个方面&#xff1a; 一、提高农业生产效率 引入先进的农业机械设备&#xff1a;新型农业机械设备如无人机、机器人等的应用&#xff0c;显著减轻了农民的劳动强度&#xff0c;提高了农作物的种植效率。利用精…...

Linux 常用命令 - rm 【删除文件或目录】

简介 rm 命令源于英文单词 “remove”&#xff0c;它用于删除文件或目录。rm 是 Linux 系统中最基本的命令之一&#xff0c;用于删除指定的文件或目录。默认情况下&#xff0c;rm 不会删除目录&#xff0c;但可以通过递归删除选项来实现。 使用方式 rm [选项]... [文件]...常…...

一血c++

题目描述 每一个竞赛选手都无法拒绝拿一血 "一血"其实就是同学们在榜单上看到的深绿色的标记&#xff0c;代表着某道题目&#xff0c;他是第一个通过的。 叶苡朋老师是一名资深信奥选手&#xff0c;在大学多次获奖&#xff0c;也是一个资深抢一血爱好者&#xff0…...

无问芯穹Qllm-Eval:制作多模型、多参数、多维度的量化方案

前言 近年来&#xff0c;大语言模型&#xff08;Large Models, LLMs&#xff09;受到学术界和工业界的广泛关注&#xff0c;得益于其在各种语言生成任务上的出色表现&#xff0c;大语言模型推动了各种人工智能应用&#xff08;例如ChatGPT、Copilot等&#xff09;的发展。然而…...

2024-05-31T08:36:09.000+00:00 转换 YYYY-MM-DD HH-MM-SS

function formatDate(date) {// 处理ISO 8601字符串if (typeof date string) {date new Date(date);}// 处理时间戳else if (typeof date number) {date new Date(date * 1000); // 假设后端时间戳为秒&#xff0c;需要乘以1000转换为毫秒}// 自定义格式化&#xff0c;例如…...

reason: the Java file contained parse errors

今天用Maven打包项目时发生一个错误&#xff1a; file: D:\workspace\echoo2.0-xxx-xxx-portal\src\main\java\com\echoo\service\impl\DecDataServiceImpl.java; reason: the Java file contained parse errors 打包报错显示这个类解析错误 在IDEA中没有任何错误提示 问题所…...

使用密钥对登录服务器

目录 1、使用密钥文件登录服务器 2、登录成功画面&#xff1a; 3、如若出现以下状况&#xff0c;则说明密钥文件登录失败 1、使用密钥文件登录服务器 首先需要上传pem文件 2、登录成功画面&#xff1a; 3、如若出现以下状况&#xff0c;则说明密钥文件登录失败 解决方法&…...

面试_多线程

线程池 线程池的参数有哪些 线程池七大参数分别是corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler corePoolSize&#xff1a;线程池中常驻核心线程数maximumPoolSize&#xff1a;线程池能够容纳同时执行的最大线程数keepAliveTime&…...

跨境电商必备?揭秘原生IP的作用

一、什么是原生IP&#xff1f; 原生IP&#xff08;Native IP&#xff09;是指由互联网服务提供商&#xff08;ISP&#xff09;或服务器提供商直接分配给用户的IP地址&#xff0c;这种IP地址直接与用户设备或网络相连&#xff0c;也就是指这个IP的注册地址和服务器机房所在的国…...

mysql竖表变横表不含聚合

文章目录 前言一、vertical_table二、转换1.要将其转换为横表形式&#xff0c;例如&#xff1a;2.sql 总结 前言 在MySQL中将竖表转换为横表&#xff08;也称为行转列操作&#xff09;&#xff0c;不涉及聚合函数&#xff0c;通常可以通过使用条件判断和自连接来实现。假设有一…...

application/x-www-form-urlencoded和json的区别

application/x-www-form-urlencoded 和 application/json 是两种不同的数据格式&#xff0c;常用于HTTP请求中传递数据。 它们各自的特点和使用场景如下&#xff1a; 1. application/x-www-form-urlencoded •特点&#xff1a;这是一种传统的表单提交时采用的编码类型&#x…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)

UniApp 集成腾讯云 IM 富媒体消息全攻略&#xff08;地理位置/文件&#xff09; 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型&#xff0c;核心实现方式&#xff1a; 标准消息类型&#xff1a;直接使用 SDK 内置类型&#xff08;文件、图片等&#xff09;自…...

如何把工业通信协议转换成http websocket

1.现状 工业通信协议多数工作在边缘设备上&#xff0c;比如&#xff1a;PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发&#xff0c;当设备上用的是modbus从站时&#xff0c;采集设备数据需要开发modbus主站&#xff1b;当设备上用的是西门子PN协议时&#xf…...

Appium下载安装配置保姆教程(图文详解)

目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...