init: Air780EPM 官方 LuatOS 项目代码基线

- 来源: 合宙 LuatOS 官方仓库 air780epm 模块完整代码
- 路径: luatos/air780epm/module/Air780EPM/demo 含官方 demo(含 mqtt/mqtts/socket/uart 等)
- 后续: 基于 demo 开发 UART<->MQTT 数据上报功能
This commit is contained in:
wangfq
2026-08-31 08:53:49 +08:00
commit 173dd6874f
813 changed files with 125484 additions and 0 deletions
@@ -0,0 +1,30 @@
--[[
@module hello_luatos
@summary hello_luatos应用功能模块
@version 1.0
@date 2025.07.19
@author 朱天华
@usage
本文件为hello_luatos应用功能模块,核心业务逻辑为:
1、创建一个task
2、在task的任务处理函数中,每隔一秒钟通过日志输出一次Hello, LuatOS
本文件没有对外接口,直接在main.lua中require "hello_luatos"就可以加载运行;
]]
-- hello_luatos的任务处理函数
local function hello_luatos_task_func()
while true do
-- 输出日志 Hello, LuatOS
log.info("Hello, LuatOS")
-- 延时1000毫秒
sys.wait(1000)
end
end
-- 创建并且启动一个task
-- 运行这个task的处理函数hello_luatos_task_func
sys.taskInit(hello_luatos_task_func)
@@ -0,0 +1,63 @@
--[[
@module main
@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
@version 1.0
@date 2025.07.19
@author 朱天华
@usage
本demo演示的核心功能为:
每隔一秒钟通过日志输出一次Hello, LuatOS
更多说明参考本目录下的readme.md文件
]]
--[[
必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
PROJECT:项目名,ascii string类型
可以随便定义,只要不使用,就行
VERSION:项目版本号,ascii string类型
如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为999
如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
]]
PROJECT = "luatos_framework_hello_luatos"
VERSION = "001.999.000"
-- 在日志中打印项目名和项目版本号
log.info("main", PROJECT, VERSION)
-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
-- 启动errDump日志存储并且上传功能,600秒上传一次
-- if errDump then
-- errDump.config(true, 600)
-- end
-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
-- 可以使用合宙的iot.openluat.com平台进行远程升级
-- 也可以使用客户自己搭建的平台进行远程升级
-- 远程升级的详细用法,可以参考fota的demo进行使用
-- 启动一个循环定时器
-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
-- 方便分析内存使用是否有异常
-- sys.timerLoopStart(function()
-- log.info("mem.lua", rtos.meminfo())
-- log.info("mem.sys", rtos.meminfo("sys"))
-- end, 3000)
-- 加载hello_luatos应用功能模块
require "hello_luatos"
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后不要加任何语句!!!!!因为添加的任何语句都不会被执行
@@ -0,0 +1,46 @@
## 演示功能概述
1、创建一个task
2、在task中的任务处理函数中,每隔一秒钟通过日志输出一次Hello, LuatOS
## 演示硬件环境
1、Air780EPM核心板一块
2、TYPE-C USB数据线一根
4、Air780EPM核心板和数据线的硬件接线方式为
- Air780EPM核心板通过TYPE-C USB口连接TYPE-C USB 数据线,数据线的另外一端连接电脑的USB口;
- 核心板正面的 ON/OFF 拨动开关 拨到ON一端;
## 演示软件环境
1、[Luatools下载调试工具](https://docs.openluat.com/air780epm/luatos/common/download/)
2、[Air780EPM 最新版本的内核固件](https://docs.openluat.com/air780epm/luatos/firmware/version/)
## 演示核心步骤
1、搭建好硬件环境
2、Luatools烧录内核固件和demo脚本代码
3、烧录成功后,自动开机运行
4、出现类似于下面的日志,每隔1秒输出1次Hello, LuatOS,就表示运行成功:
``` lua
[2025-07-19 23:19:04.944][000000015.256] I/user.Hello, LuatOS
[2025-07-19 23:19:05.954][000000016.256] I/user.Hello, LuatOS
[2025-07-19 23:19:06.956][000000017.256] I/user.Hello, LuatOS
[2025-07-19 23:19:07.947][000000018.256] I/user.Hello, LuatOS
[2025-07-19 23:19:08.955][000000019.256] I/user.Hello, LuatOS
[2025-07-19 23:19:09.944][000000020.256] I/user.Hello, LuatOS
```
@@ -0,0 +1,32 @@
--[[
@module global_msg_receiver1
@summary “使用sys.subscribe和sys.unsubscribe接口实现用户全局消息订阅和取消订阅”功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为global_msg_receiver1应用功能模块;
用来演示“使用sys.subscribe和sys.unsubscribe接口实现用户全局消息订阅和取消订阅”的功能,核心业务逻辑为:
1、开机初始化时,订阅"SEND_DATA_REQ"全局消息的回调函数init_subscribe_cbfunc
2、开机后延时5秒,订阅"SEND_DATA_REQ"全局消息的回调函数delay_subscribe_cbfunc
3、开机10秒后,取消订阅"SEND_DATA_REQ"全局消息的以上两个回调函数;
本文件没有对外接口,直接在main.lua中require "global_msg_receiver1"就可以加载运行;
]]
local function init_subscribe_cbfunc(tag, count)
log.info("init_subscribe_cbfunc", tag, count)
end
local function delay_subscribe_cbfunc(tag, count)
log.info("delay_subscribe_cbfunc", tag, count)
end
sys.subscribe("SEND_DATA_REQ", init_subscribe_cbfunc)
sys.timerStart(sys.subscribe, 5000, "SEND_DATA_REQ", delay_subscribe_cbfunc)
sys.timerStart(sys.unsubscribe, 10000, "SEND_DATA_REQ", init_subscribe_cbfunc)
sys.timerStart(sys.unsubscribe, 10000, "SEND_DATA_REQ", delay_subscribe_cbfunc)
@@ -0,0 +1,49 @@
--[[
@module global_msg_receiver2
@summary “使用sys.waitUntil接口实现task内用户全局消息接收”功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为global_msg_receiver2应用功能模块;
用来演示“使用sys.waitUntil接口实现task内用户全局消息接收”的功能,核心业务逻辑为:
1、创建一个基础task,演示“使用sys.waitUntil接口实现task内用户全局消息接收”的正确方法;
2、创建另一个基础task,演示“使用sys.waitUntil接口实现task内用户全局消息接收”的错误方法;
本文件没有对外接口,直接在main.lua中require "global_msg_receiver2"就可以加载运行;
]]
local function success_wait_until_base_task_func()
local result, tag, count
while true do
result, tag, count = sys.waitUntil("SEND_DATA_REQ")
if result then
log.info("success_wait_until_base_task_func", tag, count)
end
end
end
local function lost_wait_until_base_task_func()
local result, tag, count
while true do
-- 阻塞等待3秒钟
-- 在这段时间内,本task无法及时处理全局消息发送模块发布的"SEND_DATA_REQ"消息,会造成消息丢失
sys.wait(3000)
result, tag, count = sys.waitUntil("SEND_DATA_REQ")
if result then
log.info("lost_wait_until_base_task_func", tag, count)
end
end
end
-- 创建并且启动一个基础task
-- 运行这个task的任务处理函数success_wait_until_base_task_func
sys.taskInit(success_wait_until_base_task_func)
-- 创建并且启动一个基础task
-- 运行这个task的任务处理函数lost_wait_until_base_task_func
sys.taskInit(lost_wait_until_base_task_func)
@@ -0,0 +1,57 @@
--[[
@module global_msg_sender
@summary “用户全局消息发送”演示功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为global_msg_sender应用功能模块,用来演示“用户全局消息发送”功能,核心业务逻辑为:
1、创建并且启动一个基础task,每隔一秒钟发布一条全局消息;
2、创建并且启动一个循环定时器,每隔一秒钟发布一条全局消息;
本文件没有对外接口,直接在main.lua中require "global_msg_sender"就可以加载运行;
]]
local function global_sender_msg_task_func()
local count = 0
while true do
count = count+1
-- 发布一条全局消息
-- 消息名称为"SEND_DATA_REQ"
-- 消息携带两个参数:
-- 第一个参数是"from task"
-- 第二个参数是number类型的count
sys.publish("SEND_DATA_REQ", "from task", count)
-- 延时等待1秒
sys.wait(1000)
end
end
local timer_count = 0
local function global_sender_msg_timer_cbfunc()
timer_count = timer_count+1
-- 发布一条全局消息
-- 消息名称为"SEND_DATA_REQ"
-- 消息携带两个参数:
-- 第一个参数是"from timer"
-- 第二个参数是number类型的timer_count
sys.publish("SEND_DATA_REQ", "from timer", timer_count)
end
-- 创建并且启动一个基础task
-- 运行这个task的任务处理函数global_sender_msg_task_func
sys.taskInit(global_sender_msg_task_func)
-- 首先执行定时器的处理函数发布一条全局消息
global_sender_msg_timer_cbfunc()
-- 创建并且启动一个超时时长为1秒钟的循环定时器
sys.timerLoopStart(global_sender_msg_timer_cbfunc, 1000)
@@ -0,0 +1,101 @@
--[[
@module main
@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
@version 1.0
@date 2025.07.19
@author 朱天华
@usage
本demo演示的核心功能为:
基于sys核心库提供的api,演示LuatOS框架(taskmsgtimer,调度器)如何使用
更多说明参考本目录下的readme.md文件
]]
--[[
必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
PROJECT:项目名,ascii string类型
可以随便定义,只要不使用,就行
VERSION:项目版本号,ascii string类型
如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为999
如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
]]
PROJECT = "luatos_framework_luatos_task"
VERSION = "001.999.000"
-- 在日志中打印项目名和项目版本号
log.info("main", PROJECT, VERSION)
-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
-- 启动errDump日志存储并且上传功能,600秒上传一次
-- if errDump then
-- errDump.config(true, 600)
-- end
-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
-- 可以使用合宙的iot.openluat.com平台进行远程升级
-- 也可以使用客户自己搭建的平台进行远程升级
-- 远程升级的详细用法,可以参考fota的demo进行使用
-- 启动一个循环定时器
-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
-- 方便分析内存使用是否有异常
-- sys.timerLoopStart(function()
-- log.info("mem.lua", rtos.meminfo())
-- log.info("mem.sys", rtos.meminfo("sys"))
-- end, 3000)
-- 加载“task调度”演示功能模块
require "scheduling"
-- 加载“task访问共享资源”演示功能模块
-- require "shared_resource"
-- 加载“查看用户可用ram信息”演示功能模块
-- require "memory_valid"
-- 加载“单个task占用的ram资源”演示功能模块
-- require "memory_task"
-- 加载“创建task的数量”演示功能模块
-- require "task_count"
-- 加载“task任务处理函数”演示功能模块
-- require "task_func"
-- 加载“task创建时的可变参数”演示功能模块
-- require "variable_args"
-- 加载“非目标消息回调函数”演示功能模块
-- require "non_targeted_msg"
-- 加载“用户全局消息处理”演示功能模块
-- require "global_msg_receiver1"
-- require "global_msg_receiver2"
-- require "global_msg_sender"
-- 加载“用户定向消息处理”演示功能模块
-- require "tgted_msg_receiver"
-- require "targeted_msg_sender"
-- 加载“定时器”演示功能模块
-- require "timer_func"
-- 加载“task内外部运行环境典型错误”演示功能模块
-- require "task_inout_env_err"
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后不要加任何语句!!!!!因为添加的任何语句都不会被执行
@@ -0,0 +1,54 @@
--[[
@module memory_task
@summary “单个task占用的ram资源”演示功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为memory_task应用功能模块,用来演示“单个task占用的ram资源”,核心业务逻辑为:
1、在创建一个task前,打印下当前的ram信息;
2、创建并且启动一个task
3、在创建并且启动这个task后,打印下当前的ram信息;
本文件没有对外接口,直接在main.lua中require "memory_task"就可以加载运行;
]]
local function print_mem_info()
-- 这个接口可以强制执行一次垃圾内存回收,方便我们分析内存信息
-- 在实际项目开发中中,用户不需要主动使用这个接口,LuatOS内部的Lua虚拟机会自动进行垃圾回收
collectgarbage()
-- rtos.meminfo()有三个返回值:
-- 1、总ram大小(单位字节)
-- 2、运行过程中实时使用的ram大小(单位字节)
-- 3、运行过程中历史使用的最高ram大小(单位字节)
-- rtos.meminfo()是Lua虚拟机中的用户可用ram信息,用户开发的大部分LuatOS脚本程序都是自动从这里分配ram
log.info("mem.lua", rtos.meminfo())
-- rtos.meminfo("sys")是内核系统中的用户可用ram信息,用户使用zbuff核心库时,会用到这部分ram
-- 在这里我们就不展开讲这一部分了,等讲到zbuff的时候再做讨论
log.info("mem.sys", rtos.meminfo("sys"))
end
-- led task的任务处理函数
local function led_task_func()
while true do
log.info("led_task_func")
-- 永远等待一个不存在的消息
sys.waitUntil("INVALID_MESSAGE")
end
end
log.info("before led task")
-- 在创建一个task之前,打印下当前的ram信息
print_mem_info()
-- 创建并启动一个led task
-- 运行这个task的任务处理函数led_task_func
sys.taskInit(led_task_func)
log.info("after led task")
-- 在创建一个task之后,打印下当前的ram信息
print_mem_info()
@@ -0,0 +1,47 @@
--[[
@module memory_valid
@summary “查看用户可用ram信息”演示功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为memory_valid应用功能模块,用来演示:如何查看用户可用ram信息,核心业务逻辑为:
1、创建一个task
2、在task的任务处理函数中,每隔1秒查询一次当前的ram信息;
本文件没有对外接口,直接在main.lua中require "memory_valid"就可以加载运行;
]]
local function print_mem_info()
-- 这个接口可以强制执行一次垃圾内存回收,方便我们分析内存信息
-- 在实际项目开发中中,用户不需要主动使用这个接口,LuatOS内部的Lua虚拟机会自动进行垃圾回收
collectgarbage()
-- rtos.meminfo()有三个返回值:
-- 1、总ram大小(单位字节)
-- 2、运行过程中实时使用的ram大小(单位字节)
-- 3、运行过程中历史使用的最高ram大小(单位字节)
-- rtos.meminfo()是Lua虚拟机中的用户可用ram信息,用户开发的大部分LuatOS脚本程序都是自动从这里分配ram
log.info("mem.lua", rtos.meminfo())
-- rtos.meminfo("sys")是内核系统中的用户可用ram信息,用户使用zbuff核心库时,会用到这部分ram
-- 在这里我们就不展开讲这一部分了,等讲到zbuff的时候再做讨论
log.info("mem.sys", rtos.meminfo("sys"))
end
local function mem_task_func()
while true do
-- 打印当前的ram信息
print_mem_info()
-- 延时1秒
sys.wait(1000)
end
end
-- 创建并启动一个task
-- 运行这个task的任务处理函数mem_task_func
sys.taskInit(mem_task_func)
@@ -0,0 +1,133 @@
--[[
@module non_targeted_msg
@summary “非目标消息回调函数”演示功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为non_targeted_msg应用功能模块,用来演示“非目标消息回调函数”如何使用,核心业务逻辑为:
1、创建一个高级tasktask名称为"MQTT_CLINET_MAIN"task的非目标消息回调函数为mqtt_client_main_cbfunc
2、创建一个基础task,每隔一秒向名称为"MQTT_CLINET_MAIN"的高级task发送一条非目标消息;
3、创建一个高级tasktask名称为"SEND_MSG_TASK",每隔一秒向名称为"MQTT_CLINET_MAIN"的高级task发送一条目标消息;
本文件没有对外接口,直接在main.lua中require "non_targeted_msg"就可以加载运行;
]]
-- mqtt_client_main的任务名
local TASK_NAME = "MQTT_CLINET_MAIN"
-- 非目标消息回调函数
local function mqtt_client_main_cbfunc(msg)
log.info("mqtt_client_main_cbfunc", msg[1], msg[2], msg[3], msg[4])
end
-- mqtt main task 的任务处理函数
local function mqtt_client_main_task_func()
-- 连接、断开连接、订阅、取消订阅、异常等各种事件的处理调度逻辑
while true do
-- 等待"MQTT_EVENT"消息
msg = sys.waitMsg(TASK_NAME, "MQTT_EVENT")
log.info("mqtt_client_main_task_func waitMsg", msg[2], msg[3], msg[4])
-- connect连接结果
-- msg[3]表示连接结果,true为连接成功,false为连接失败
if msg[2] == "CONNECT" then
-- mqtt连接成功
if msg[3] then
log.info("mqtt_client_main_task_func", "connect success")
-- mqtt连接失败
else
log.info("mqtt_client_main_task_func", "connect error")
end
-- subscribe订阅结果
-- msg[3]表示订阅结果,true为订阅成功,false为订阅失败
elseif msg[2] == "SUBSCRIBE" then
-- 订阅成功
if msg[3] then
log.info("mqtt_client_main_task_func", "subscribe success", "qos: "..(msg[4] or "nil"))
-- 订阅失败
else
log.error("mqtt_client_main_task_func", "subscribe error", "code", msg[4])
end
-- 被动关闭了mqtt连接
-- 被网络或者服务器断开了连接
elseif msg[2] == "DISCONNECTED" then
log.info("mqtt_client_main_task_func", "disconnected")
end
end
end
local function send_non_targeted_msg_task_func()
local count = 0
while true do
count = count+1
-- 向TASK_NAME这个任务发送一条消息
-- 消息名称为"UNKNOWN_EVENT"
-- 消息携带一个number类型的参数count
sys.sendMsg(TASK_NAME, "UNKNOWN_EVENT", count)
-- 延时等待1秒
sys.wait(1000)
end
end
local function send_targeted_msg_task_func()
while true do
-- 向TASK_NAME这个任务发送一条消息
-- 消息名称为"MQTT_EVENT"
-- 消息携带两个参数
-- 第一个参数为"CONNECT"
-- 第二个参数为true
-- 这条消息的意思是MQTT连接成功
sys.sendMsg(TASK_NAME, "MQTT_EVENT", "CONNECT", true)
-- 延时等待1秒
sys.wait(1000)
-- 向TASK_NAME这个任务发送一条消息
-- 消息名称为"MQTT_EVENT"
-- 消息携带三个参数
-- 第一个参数为"SUBSCRIBE"
-- 第二个参数为true
-- 第三个参数为0
-- 这条消息的意思是MQTT订阅成功,qos为0
sys.sendMsg(TASK_NAME, "MQTT_EVENT", "SUBSCRIBE", true, 0)
-- 延时等待1秒
sys.wait(1000)
-- 向TASK_NAME这个任务发送一条消息
-- 消息名称为"MQTT_EVENT"
-- 消息携带一个参数"DISCONNECTED"
-- 这条消息的意思是MQTT连接被动断开
sys.sendMsg(TASK_NAME, "MQTT_EVENT", "DISCONNECTED")
-- 延时等待1秒
sys.wait(1000)
end
end
-- 创建并且启动一个高级task
-- task的任务处理函数为mqtt_client_main_task_func
-- task的名称为TASK_NAME变量的值"MQTT_CLINET_MAIN"
-- task的非目标消息回调函数为mqtt_client_main_cbfunc
-- 运行这个task的任务处理函数mqtt_client_main_task_func
sys.taskInitEx(mqtt_client_main_task_func, TASK_NAME, mqtt_client_main_cbfunc)
-- 创建并且启动一个基础task
-- 运行这个task的任务处理函数send_targeted_msg_task_func
sys.taskInit(send_non_targeted_msg_task_func)
-- 创建并且启动一个高级task
-- task的任务处理函数为send_targeted_msg_task_func
-- task的名称为SEND_TASK_NAME
-- 运行这个task的任务处理函数send_targeted_msg_task_func
sys.taskInitEx(send_targeted_msg_task_func, "SEND_MSG_TASK")
@@ -0,0 +1,134 @@
## 演示功能概述
演示LuatOS运行框架如何使用,包括:
1、LuatOS task如何使用;
2、LuatOS msg如何使用;
3、LuatOS timer如何使用;
4、LuatOS 调度器如何使用;
5、以上四项功能全部基于sys核心库提供的api才能正常运行,所以本demo本质是在演示sys核心库提供的所有api如何使用;
## 演示硬件环境
1、Air780EPM核心板一块
2、TYPE-C USB数据线一根
4、Air780EPM核心板和数据线的硬件接线方式为
- Air780EPM核心板通过TYPE-C USB口连接TYPE-C USB 数据线,数据线的另外一端连接电脑的USB口;
- 核心板正面的 ON/OFF 拨动开关 拨到ON一端;
## 演示软件环境
1、[Luatools下载调试工具](https://docs.openluat.com/air780epm/luatos/common/download/)
2、[Air780EPM 最新版本的内核固件](https://docs.openluat.com/air780epm/luatos/firmware/version/)
## 演示核心步骤
1、搭建好硬件环境
2、在main.lua中按需启动如下某一段代码,单独演示某一项功能,这样分析起来比较清晰
``` lua
-- 加载“task调度”演示功能模块
-- require "scheduling"
-- 加载“task访问共享资源”演示功能模块
-- require "shared_resource"
-- 加载“查看用户可用ram信息”演示功能模块
-- require "memory_valid"
-- 加载“单个task占用的ram资源”演示功能模块
-- require "memory_task"
-- 加载“创建task的数量”演示功能模块
-- require "task_count"
-- 加载“task任务处理函数”演示功能模块
-- require "task_func"
-- 加载“task创建时的可变参数”演示功能模块
-- require "variable_args"
-- 加载“非目标消息回调函数”演示功能模块
-- require "non_targeted_msg"
-- 加载“用户全局消息处理”演示功能模块
-- require "global_msg_receiver1"
-- require "global_msg_receiver2"
-- require "global_msg_sender"
-- 加载“用户定向消息处理”演示功能模块
-- require "tgted_msg_receiver"
-- require "targeted_msg_sender"
-- 加载“定时器”演示功能模块
-- require "timer"
-- 加载“task内外部运行环境典型错误”演示功能模块
-- require "task_inout_env_err"
```
2、Luatools烧录内核固件和修改main.lua后的demo脚本代码
3、烧录成功后,自动开机运行
4、在main.lua中打开不同的演示功能模块,对应在Luatools的日志窗口会出现不同的日志信息,例如:
``` lua
如果在main.lua中开启以下代码
-- 加载“task调度”演示功能模块
require "scheduling"
则日志信息如下:
[2025-08-28 12:04:33.469][00000000.228] I/user.task1_func 运行中,计数: 1
[2025-08-28 12:04:33.469][00000000.228] I/user.task_scheduling after task1 and before task2
[2025-08-28 12:04:33.469][00000000.228] I/user.task2_func 运行中,计数: 1
[2025-08-28 12:04:33.554][00000000.313] I/user.task2_func 运行中,计数: 2
[2025-08-28 12:04:33.748][00000000.507] I/user.task1_func 运行中,计数: 2
[2025-08-28 12:04:33.865][00000000.624] I/user.task2_func 运行中,计数: 3
[2025-08-28 12:04:34.179][00000000.938] I/user.task2_func 运行中,计数: 4
[2025-08-28 12:04:34.254][00000001.013] I/user.task1_func 运行中,计数: 3
[2025-08-28 12:04:34.494][00000001.253] I/user.task2_func 运行中,计数: 5
[2025-08-28 12:04:34.763][00000001.522] I/user.task1_func 运行中,计数: 4
[2025-08-28 12:04:34.808][00000001.567] I/user.task2_func 运行中,计数: 6
[2025-08-28 12:04:35.121][00000001.880] I/user.task2_func 运行中,计数: 7
[2025-08-28 12:04:35.274][00000002.033] I/user.task1_func 运行中,计数: 5
[2025-08-28 12:04:35.436][00000002.196] I/user.task2_func 运行中,计数: 8
[2025-08-28 12:04:35.739][00000002.499] I/user.task2_func 运行中,计数: 9
[2025-08-28 12:04:35.783][00000002.542] I/user.task1_func 运行中,计数: 6
[2025-08-28 12:04:36.046][00000002.806] I/user.task2_func 运行中,计数: 10
[2025-08-28 12:04:36.285][00000003.045] I/user.task1_func 运行中,计数: 7
[2025-08-28 12:04:36.357][00000003.116] I/user.task2_func 运行中,计数: 11
[2025-08-28 12:04:36.661][00000003.420] I/user.task2_func 运行中,计数: 12
[2025-08-28 12:04:36.797][00000003.556] I/user.task1_func 运行中,计数: 8
[2025-08-28 12:04:36.960][00000003.719] I/user.task2_func 运行中,计数: 13
[2025-08-28 12:04:37.275][00000004.034] I/user.task2_func 运行中,计数: 14
[2025-08-28 12:04:37.305][00000004.064] I/user.task1_func 运行中,计数: 9
[2025-08-28 12:04:37.579][00000004.338] I/user.task2_func 运行中,计数: 15
[2025-08-28 12:04:37.818][00000004.577] I/user.task1_func 运行中,计数: 10
[2025-08-28 12:04:37.889][00000004.648] I/user.task2_func 运行中,计数: 16
[2025-08-28 12:04:38.199][00000004.958] I/user.task2_func 运行中,计数: 17
[2025-08-28 12:04:38.325][00000005.084] I/user.task1_func 运行中,计数: 11
[2025-08-28 12:04:38.500][00000005.259] I/user.task2_func 运行中,计数: 18
[2025-08-28 12:04:38.812][00000005.571] I/user.task2_func 运行中,计数: 19
[2025-08-28 12:04:38.825][00000005.584] I/user.task1_func 运行中,计数: 12
[2025-08-28 12:04:39.113][00000005.872] I/user.task2_func 运行中,计数: 20
[2025-08-28 12:04:39.333][00000006.092] I/user.task1_func 运行中,计数: 13
[2025-08-28 12:04:39.414][00000006.173] I/user.task2_func 运行中,计数: 21
[2025-08-28 12:04:39.717][00000006.476] I/user.task2_func 运行中,计数: 22
[2025-08-28 12:04:39.835][00000006.594] I/user.task1_func 运行中,计数: 14
[2025-08-28 12:04:40.020][00000006.779] I/user.task2_func 运行中,计数: 23
```
@@ -0,0 +1,50 @@
--[[
@module scheduling
@summary task调度演示
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为scheduling应用功能模块,用来演示task协作式的调度方式,核心业务逻辑为:
1、创建两个tasktask1和task2
2、在task1的任务处理函数中,每隔500毫秒,task1的计数器加1,并且通过日志打印task1计数器的值;
3、在task2的任务处理函数中,每隔300毫秒,task2的计数器加1,并且通过日志打印task2计数器的值;
本文件没有对外接口,直接在main.lua中require "scheduling"就可以加载运行;
]]
-- 第一个task的任务处理函数
local function task1_func()
local count = 0
while true do
count = count + 1
log.info("task1_func", "运行中,计数:", count)
-- 等待500ms
sys.wait(500)
end
end
-- 第二个task的任务处理函数
local function task2_func()
local count = 0
while true do
count = count + 1
log.info("task2_func", "运行中,计数:", count)
-- 等待300ms
sys.wait(300)
end
end
-- 创建并启动第一个task
-- 运行这个task的任务处理函数task1_func
sys.taskInit(task1_func)
log.info("task_scheduling", "after task1 and before task2")
-- 创建并启动第二个task
-- 运行这个task的任务处理函数task2_func
sys.taskInit(task2_func)
@@ -0,0 +1,65 @@
--[[
@module shared_resource
@summary 共享资源访问演示
@version 1.0
@date 2025.08.15
@author 朱天华
@usage
本文件为shared_resource应用功能模块,用来演示多个task访问共享资源的功能,核心业务逻辑为:
1、创建一个全局共享变量global_shared_variable,变量值初始化为0
2、创建两个tasktask1和task2
3、在task1的任务处理函数中:
(1) 每隔1秒,执行一次for循环
(2) 循环体内循环100次,每次将全局共享变量global_shared_variable的值加1
4、在task2的任务处理函数中:
(1) 每隔1秒,执行一次for循环
(2) 循环体内循环100次,每次将全局共享变量global_shared_variable的值加1
本文件没有对外接口,直接在main.lua中require "task_scheduling"就可以加载运行;
]]
-- 全局共享变量,初始值为0
local global_shared_variable = 0
-- 第一个task的任务处理函数
local function task1_func()
while true do
log.info("task1_func", "for循环前,全局共享变量的值:", global_shared_variable)
for i=1,100 do
global_shared_variable = global_shared_variable + 1
-- sys.wait(5)
end
log.info("task1_func", "for循环后,全局共享变量的值:", global_shared_variable)
sys.wait(1000)
end
end
-- 第二个task的任务处理函数
local function task2_func()
while true do
log.info("task2_func", "for循环前,全局共享变量的值:", global_shared_variable)
for i=1,100 do
global_shared_variable = global_shared_variable + 1
-- sys.wait(5)
end
log.info("task2_func", "for循环后,全局共享变量的值:", global_shared_variable)
sys.wait(1000)
end
end
-- 创建并启动第一个task
-- 运行这个task的任务处理函数为task1_func
sys.taskInit(task1_func)
-- 创建并启动第二个task
-- 运行这个task的任务处理函数为task2_func
sys.taskInit(task2_func)
@@ -0,0 +1,44 @@
--[[
@module targeted_msg_sender
@summary “用户定向消息发送”演示功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为targeted_msg_sender应用功能模块,用来演示“用户定向消息发送”功能,核心业务逻辑为:
1、创建并且启动一个基础task,每隔一秒钟向两个高级task发布各发送一条定向消息;
本文件没有对外接口,直接在main.lua中require "targeted_msg_sender"就可以加载运行;
]]
local function targeted_msg_sender_task_func()
local count = 0
while true do
count = count+1
-- 发布一条定向消息到名称为"nromal_wait_msg_task"的高级task
-- 消息名称为"SEND_DATA_REQ"
-- 消息携带两个参数:
-- 第一个参数是"from task"
-- 第二个参数是number类型的count
sys.sendMsg("nromal_wait_msg_task", "SEND_DATA_REQ", "from task", count)
-- 发布一条定向消息到名称为"delay_wait_msg_task"的高级task
-- 消息名称为"SEND_DATA_REQ"
-- 消息携带两个参数:
-- 第一个参数是"from task"
-- 第二个参数是number类型的count
sys.sendMsg("delay_wait_msg_task", "SEND_DATA_REQ", "from task", count)
-- 延时等待1秒
sys.wait(1000)
end
end
-- 创建并且启动一个基础task
-- 运行这个task的任务处理函数targeted_msg_sender_task_func
sys.taskInit(targeted_msg_sender_task_func)
@@ -0,0 +1,32 @@
--[[
@module task_count
@summary “创建task的数量”演示功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为task_count应用功能模块,用来演示“可以创建多少个task”,核心业务逻辑为:
执行一个while true循环,每次执行到循环体内,执行以下两项动作:
1、创建并且启动一个task,启动后,task处于阻塞状态,永远不会死亡
2、task数量的计数器加一,并且打印当前已经创建的task总数量
本文件没有对外接口,直接在main.lua中require "task_count"就可以加载运行;
]]
local count = 0
-- task的任务处理函数
local function led_task_func()
while true do
log.info("led_task_func")
sys.waitUntil("INVALID_MESSAGE")
end
end
-- 不断地创建task,直到ram资源耗尽
while true do
sys.taskInit(led_task_func)
count = count+1
log.info("create task count", count)
end
@@ -0,0 +1,27 @@
--[[
@module task_func
@summary “task任务处理函数”演示功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为task_func应用功能模块,用来演示“如何设置task任务处理函数”,核心业务逻辑为:
1、创建一个task时,需要设置task任务处理函数;
2、演示一种常见的错误设置方式;
本文件没有对外接口,直接在main.lua中require "task_func"就可以加载运行;
]]
-- 创建并启动一个led task
-- 运行这个task的任务处理函数led_task_func
-- 此处运行会报错,因为执行到这行代码时,找不到led_task_func函数的定义,犯了“先使用,后定义”的错误
sys.taskInit(led_task_func)
local function led_task_func()
while true do
log.info("led_task_func")
sys.wait(1000)
end
end
@@ -0,0 +1,62 @@
--[[
@module targeted_msg_sender
@summary “task内和task外运行环境典型错误”演示功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为task_inout_env_err应用功能模块,用来演示“task内和task外运行环境典型错误”,核心业务逻辑为:
演示“task内外运行环境使用不当”而出现的典型错误
1、在用户全局消息订阅的回调函数中执行sys.wait接口;
2、在单次定时器的回调函数中执行sys.waitUntil接口;
3、在循环定时器的回调函数中执行sys.waitMsg接口;
4、以上三种都是在task外的运行环境中执行“必须在task内运行”的接口,还有其他类似的使用错误,不再一一列举;
本文件没有对外接口,直接在main.lua中require "task_inout_env_err"就可以加载运行;
]]
local function mqtt_event_cbfunc()
log.info("mqtt_event_cbfunc")
-- 在用户全局消息订阅的回调函数中执行sys.wait接口,会报错
sys.wait(1000)
end
-- sys.subscribe("MQTT_EVENT", mqtt_event_cbfunc)
-- sys.timerStart(sys.publish, 1000, "MQTT_EVENT")
local function timer_cbfunc()
log.info("timer_cbfunc")
-- 在单次定时器的回调函数中执行sys.waitUntil接口,会报错
sys.waitUntil("UNKNOWN_MSG", 1000)
end
-- sys.timerStart(timer_cbfunc, 1000)
local function loop_timer_cbfunc()
log.info("loop_timer_cbfunc")
-- 在循环定时器的回调函数中执行sys.waitMsg接口,会报错
sys.waitMsg("SEND_MSG_TASK", "UNKNOWN_MSG", 1000)
end
local function send_targeted_msg_task_func()
while true do
-- 延时等待1秒
sys.wait(1000)
end
end
-- 创建并且启动一个高级task
-- task的任务处理函数为send_targeted_msg_task_func
-- task的名称为SEND_TASK_NAME
-- 运行这个task的任务处理函数send_targeted_msg_task_func
sys.taskInitEx(send_targeted_msg_task_func, "SEND_MSG_TASK")
sys.timerLoopStart(loop_timer_cbfunc, 1000)
@@ -0,0 +1,48 @@
--[[
@module tgted_msg_receiver
@summary “使用sys.waitMsg接口实现task内用户定向消息接收”功能演示模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为tgted_msg_receiver应用功能模块;
用来演示“使用sys.waitMsg接口实现task内用户定向消息接收”的功能,核心业务逻辑为:
1、创建并且启动一个高级tasktask名称为"nromal_wait_msg_task",在task的任务处理函数内及时接收发送给自己的定向消息;
2、创建并且启动另一个高级tasktask名称为"delay_wait_msg_task",在task的任务处理函数内延时接收发送给自己的定向消息;
本文件没有对外接口,直接在main.lua中require "tgted_msg_receiver"就可以加载运行;
]]
local function normal_wait_msg_task_func()
local msg
while true do
msg = sys.waitMsg("nromal_wait_msg_task", "SEND_DATA_REQ")
if msg then
log.info("normal_wait_msg_task_func", msg[1], msg[2], msg[3], msg[4])
end
end
end
local function delay_wait_msg_task_func()
local msg
while true do
-- 阻塞等待3秒钟
-- 在这段时间内,本task无法及时处理定向消息发送模块发布的"SEND_DATA_REQ"消息
-- 但是不会造成消息丢失,消息会存储到本task绑定的定向消息队列中
-- 虽然不会造成消息丢失,但是业务逻辑中这样写明显也存在问题,因为消息处理的及时性很差
sys.wait(3000)
msg = sys.waitMsg("delay_wait_msg_task", "SEND_DATA_REQ")
if msg then
log.info("delay_wait_msg_task_func", msg[1], msg[2], msg[3], msg[4])
end
end
end
-- 创建并且启动一个高级tasktask名称为"nromal_wait_msg_task"
-- 运行这个task的任务处理函数normal_wait_msg_task_func
sys.taskInitEx(normal_wait_msg_task_func, "nromal_wait_msg_task")
-- 创建并且启动一个高级tasktask名称为"delay_wait_msg_task"
-- 运行这个task的任务处理函数delay_wait_msg_task_func
sys.taskInitEx(delay_wait_msg_task_func, "delay_wait_msg_task")
@@ -0,0 +1,72 @@
--[[
@module timer
@summary “定时器”演示功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为timer应用功能模块,用来演示“定时器”如何使用,核心业务逻辑为:
1、演示单次定时器,循环定时器,task内的延时定时器的创建,启动,停止和删除功能;
本文件没有对外接口,直接在main.lua中require "timer"就可以加载运行;
]]
local function timer_test_task_func()
-- 以下三行代码执行后,只有最后一个定时器存在
sys.timerStart(log.info, 1000, "red")
sys.timerStart(log.info, 2000, "red")
sys.timerStart(log.info, 3000, "red")
-- 阻塞等待3秒钟,实际上创建了一个3秒钟超时时长的单次定时器
-- 超时时长到达后,会控制本task退出阻塞状态,继续运行
sys.wait(3000)
-- 创建并且启动一个循环定时器,每隔1秒钟执行一次sys.publish("loop_timer_cbfunc_msg")
-- 相当于每隔1秒钟发布一条用户全局消息"loop_timer_cbfunc_msg"
sys.timerLoopStart(sys.publish, 1000, "loop_timer_cbfunc_msg")
-- 创建并且启动一个单次定时器,5.5秒后执行sys.timerStop(sys.publish, "loop_timer_cbfunc_msg")
-- 相当于5.5秒后主动停止并且删除了上一行代码创建的循环定时器
sys.timerStart(sys.timerStop, 5500, sys.publish, "loop_timer_cbfunc_msg")
while true do
-- 阻塞等待用户全局消息"loop_timer_cbfunc_msg",超时时长为2秒钟
-- 5秒内,每秒都会收到一次消息;
-- 5秒后,不再收到消息,超时2秒退出阻塞状态;
local result = sys.waitUntil("loop_timer_cbfunc_msg", 2000)
if result then
log.info("receive loop_timer_cbfunc_msg")
else
log.info("no loop_timer_cbfunc_msg, 2000ms timeout")
break
end
end
-- 以下五行代码执行后,创建并且启动了5个不同的定时器
local timer_id = sys.timerStart(log.info, 1000, "1")
sys.timerStart(log.info, 2000, "2")
sys.timerStart(log.info, 3000, "3")
sys.timerStart(log.info, 4000, "4")
sys.timerStart(log.info, 5000, "5")
-- 根据定时器id停止并且删除刚才创建的5个定时器中的第一个定时器
sys.timerStop(timer_id)
-- 阻塞等待2秒钟
sys.wait(2000)
-- 运行到这里
-- 刚才创建的5个定时器中的后4个定时器:
-- sys.timerStart(log.info, 2000, "2"),这个定时器已经超时,并且自动停止和删除
-- 还剩下另外3个定时器处于运行状态,超时时长未到达
-- 执行下面这行代码后,可以将这3个定时器全部停止并且删除
sys.timerStopAll(log.info)
end
-- 创建并且启动一个单次定时器,超时时长为3秒
-- 3秒后执行sys.taskInit(timer_test_task_func)
-- 相当于3秒后,创建并且启动一个基础task,然后执行这个task的任务处理函数timer_test_task_func
sys.timerStart(sys.taskInit, 3000, timer_test_task_func)
@@ -0,0 +1,27 @@
--[[
@module variable_args
@summary “task创建时的可变参数”演示功能模块
@version 1.0
@date 2025.08.12
@author 朱天华
@usage
本文件为variable_args应用功能模块,用来演示“task创建时的可变参数”如何使用,核心业务逻辑为:
1、创建一个task,可变参数部分携带5个参数;
2、在task的任务处理函数中打印传入的5个参数的值;
本文件没有对外接口,直接在main.lua中require "variable_args"就可以加载运行;
]]
local function led_task_func(arg1, arg2, arg3, arg4, arg5)
while true do
log.info("led_task_func", arg1, arg2, arg3, arg4, arg5)
sys.wait(1000)
end
end
-- 创建并启动一个task
-- 这个task的任务处理函数为led_task_func
-- 携带5个参数,分别为"arg1", 3, nil, true, led_task_func
-- 运行这个task的任务处理函数led_task_func时,会将这5个参数传递给任务处理函数使用
sys.taskInit(led_task_func, "arg1", 3, nil, true, led_task_func)