单片机移植Lua(STM32H743移植Lua-5.4.6)

文章目录

  • 目的
  • 移植演示
  • 示例链接
  • 更多说明
    • 合理设置内存大小
    • 按需加载标准库
    • 实现系统和IO接口
    • 设置引用路径
  • 总结

目的

通常单片机都是使用C/C++来开发的,任何修改都需要重新编译固件然后下载运行。在一些需要灵活性更强的场合中可以内嵌Lua解释器实现动态更新应用程序的功能。这篇文章将对相关内容做个简单说明。

移植演示

Lua本身就是纯C实现的,不管是移植到上位机程序还是单片机程序中本质上没有多大区别,单就移植以及Lua脚本和C代码交互等参考我之前的文章即可:
《Lua和C语言交互入门》https://blog.csdn.net/Naisu_kun/article/details/134000058

这里进行简单演示,使用NUCLEO-H743ZI2开发板,启用默认使能的串口,用来打印输出信息:
在这里插入图片描述

修改最小堆栈大小,生成初始化项目代码。

然后参考上面文章,直接引入Lua源码(排除 lua.cluac.c),接着改写 main.c 代码如下:

#include "main.h"#include <stdio.h> // 引入该库为了可以使用 printf 函数#include "src/lua.h"     // Lua数据类型与函数接口
#include "src/lauxlib.h" // Lua与C交互辅助函数接口
#include "src/lualib.h"  // Lua标准库打开接口UART_HandleTypeDef huart3;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);/* 以下代码用来实现putchar操作,以此可实现printf功能 */
/* With GCC, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch) // 实现__io_putchar函数
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */PUTCHAR_PROTOTYPE
{// 实际发送操作,这里可以改成自己真实需要操作的端口HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);return ch;
}
/* 以上代码用来实现putchar操作,以此可实现printf功能 */int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART3_UART_Init();lua_State* L = luaL_newstate(); // 创建Lua线程luaL_openlibs(L); // 打开标准库while (1){HAL_Delay(1000);luaL_dostring(L, "print('Naisu, Lua!')"); // 解析并执行Lua脚本字符串}lua_close(L); // 关闭Lua线程(虽然代码并不会运行到这里)
}void SystemClock_Config(void)
{// some code ...
}static void MX_USART3_UART_Init(void)
{// some code ...
}static void MX_GPIO_Init(void)
{// some code ...
}void Error_Handler(void)
{// some code ...
}

上面代码主要就两方面内容:

  • 实现了 putchar 操作,这样在 Lua 中就可以使用 print 函数了;
  • 创建Lua虚拟机初始化标准库,然后循环执行Lua脚本;

将上述代码编译后下载到开发板可以看到相关输出:
在这里插入图片描述

示例链接

仓库地址: https://github.com/NaisuXu/STM32_MCU_Examples

本文中的示例位于仓库中 Lua_H743

更多说明

从上面演示可以看到,移植本身很简单,不过相比在上位机上移植,在单片机中移植还有些需要注意的地方。

合理设置内存大小

单片机相比上位机一个比较大的问题是内存比较小,所以需要合理设计内存使用。

单片机本身设置合适的堆栈空间:
在这里插入图片描述

Lua源码 luaconf.h 文件中 #define LUAI_MAXSTACK 宏定义用于设置Lua使用的最大栈大小:

/*
@@ LUAI_MAXSTACK limits the size of the Lua stack.
** CHANGE it if you need a different limit. This limit is arbitrary;
** its only purpose is to stop Lua from consuming unlimited stack
** space (and to reserve some numbers for pseudo-indices).
** (It must fit into max(size_t)/32 and max(int)/2.)
*/
#if LUAI_IS32INT
#define LUAI_MAXSTACK		1000000
#else
#define LUAI_MAXSTACK		15000
#endif

按需加载标准库

上面演示中使用 luaL_openlibs(L); 方式加载了所有的Lua标准库,实际使用中完全可以按需加载。

在Lua源码 linit.c 中注释掉不需要的库即可:

/*
** these libs are loaded by lua.c and are readily available to any Lua
** program
*/
static const luaL_Reg loadedlibs[] = {{LUA_GNAME, luaopen_base},{LUA_LOADLIBNAME, luaopen_package},{LUA_COLIBNAME, luaopen_coroutine},{LUA_TABLIBNAME, luaopen_table},{LUA_IOLIBNAME, luaopen_io},{LUA_OSLIBNAME, luaopen_os},{LUA_STRLIBNAME, luaopen_string},{LUA_MATHLIBNAME, luaopen_math},{LUA_UTF8LIBNAME, luaopen_utf8},{LUA_DBLIBNAME, luaopen_debug},{NULL, NULL}
};

实现系统和IO接口

Lua中很多操作都是调用了操作系统相关的接口,这些接口单片机是不带的,如果需要用到相关功能的话要不就去实现相关接口(比如演示中的print函数就需要实现相关接口才可以使用),要不就直接改写Lua标准库相关函数。

设置引用路径

如果单片机上跑了文件系统,将Lua脚本以文件的形式放到文件系统中,那么在执行这些文件的时候可能需要合理设置Lua相关路径。比如在Lua源码 luaconf.h 文件中 LUA_PATH_DEFAULT 宏定义就可以设置默认的路径。

总结

总体来说在单片机上移植Lua并不复杂,更多的是对内存的限制以及没有操作系统自带的各种接口问题上话时间去调试处理。

这些年单片机性能越来越强,约来越多的脚本语言和高级语言可以运行在单片机上,玩法真的是越来越多了。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Langchain Agent研究】SalesGPT项目介绍(二)

【Langchain Agent研究】SalesGPT项目介绍&#xff08;一&#xff09;-CSDN博客 上节课&#xff0c;我们介绍了SalesGPT他的业务流程和技术架构&#xff0c;这节课&#xff0c;我们来关注一下他的项目整体结构、poetry工具和一些工程项目相关的设计。 项目整体结构介绍 我们把…

java的面向对象编程(oop)——认识枚举

前言 打好基础&#xff0c;daydayup! 枚举 1&#xff0c;认识枚举&#xff1a; 枚举是一种特殊类&#xff0c;用enum语句修饰。与普通类不同的是&#xff1a;枚举类的第一行只能写一些合法的标识符&#xff08;名称&#xff09;&#xff0c;多个名称用逗号隔开。这些标识符&a…

Python学习路线图

防止忘记&#xff0c;温故知新 进阶路线

计算机设计大赛 深度学习YOLO抽烟行为检测 - python opencv

文章目录 1 前言1 课题背景2 实现效果3 Yolov5算法3.1 简介3.2 相关技术 4 数据集处理及实验5 部分核心代码6 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习YOLO抽烟行为检测 该项目较为新颖&#xff0c;适合作为竞赛课…

【C++初阶】第三站:类和对象(中) -- 日期计算器

目录 前言 日期类的声明.h 日期类的实现.cpp 获取某年某月的天数 全缺省的构造函数 拷贝构造函数 打印函数 日期 天数 日期 天数 日期 - 天数 日期 - 天数 前置 后置 前置 -- 后置-- 日期类中比较运算符的重载 <运算符重载 运算符重载 ! 运算符重载 …

19.Qt 组合框的实现和应用

目录 前言&#xff1a; 技能&#xff1a; 内容&#xff1a; 1. 界面 2.槽 3.样式表 参考&#xff1a; 前言&#xff1a; 学习QCombox控件的使用 技能&#xff1a; 简单实现组合框效果 内容&#xff1a; 1. 界面 在ui编辑界面找到input widget里面的comboBox&#xff…

AutoSAR(基础入门篇)10.3-BswM配置

目录 一、ECU State Handing(ESH) 二、Module Initialization 三、Communication Control 说起BswM的配置,其实博主问过很多朋友了,大家基本都只用自动配置;很少有用到手动配置的时候,对于刚刚入门的大家来说,掌握自动配置基 本也就足够了。 一、ECU State Handing(ESH…

暴力破解(if循环)解决leetcode数字转成罗马数字

1.题目描述 2.解题思路 刚看到这个题目的时候&#xff0c;感觉说的有点啰嗦&#xff0c;其实不难发现&#xff0c;这个题目和之前的给你多少钱&#xff0c;什么2元&#xff0c;5元的&#xff0c;给你一个数字&#xff0c;让你算各种钱币有多少张。无非就是从小到大进行判断&am…

智慧图书管理系统架构设计与实现

随着数字化时代的到来&#xff0c;智慧图书管理系统在图书馆和机构中扮演着重要的角色。一个优秀的图书管理系统不仅需要满足基本的借阅管理需求&#xff0c;还需要具备高效的性能、良好的扩展性和稳定的安全性。本文将讨论智慧图书管理系统的架构设计与实现&#xff0c;以满足…

js基础篇

javascript 1.1javascript是什么&#xff1f; 是运行在浏览器【客户端】的编程语言 1.2 js的组成 ECMAScript (基础语法) Web APIs (DOM BOM) 1.3 js的书写位置 内部&#xff0c;外部&#xff0c;行内 【代码写在标签内部】 // 内部 <script>alter("你好&…

Linux|centos7下的编译|ffmpeg的二进制安装

Windows版本的ffmpeg&#xff1a; ###注意&#xff0c;高版本可能必须要windows10以及以上才支持&#xff0c;win7估计是用不了的 下载地址&#xff1a;Builds - CODEX FFMPEG gyan.dev 或者这个下载地址&#xff1a;https://github.com/BtbN/FFmpeg-Builds/releases 这两个…

Code Composer Studio (CCS) - Breakpoint (断点)

Code Composer Studio [CCS] - Breakpoint [断点] 1. BreakpointReferences 1. Breakpoint 选中断点右键 -> Breakpoint Properties… Skip Count&#xff1a;跳过断点总数&#xff0c;在断点执行之前设置总数 Current Count&#xff1a;当前跳过断电累计值 References […