Forráskód Böngészése

update:更新pack、string、wdt demo

13917187172 4 hónapja
szülő
commit
715953c33b

+ 62 - 55
module/Air8000/demo/pack/main.lua

@@ -1,62 +1,69 @@
+--[[
+@module  main
+@summary LuatOS pack API演示主入口,负责加载功能模块
+@version 1.0
+@date    2025.10.27
+@author  陈媛媛
+@usage
+本demo演示的核心功能为:
+1、pack.pack API的各种格式演示
+2、pack.unpack API的各种用法演示
+3、大小端编码、字符串格式、数值类型等完整示例
 
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "LOG"
-VERSION = "2.0.0"
+更多说明参考本目录下的readme.md文件
+]]
 
 --[[
-本demo演示 string字符串的基本操作
-1. lua的字符串是带长度, 这意味着, 它不依赖0x00作为结束字符串, 可以包含任意数据
-2. lua的字符串是不可变的, 就不能直接修改字符串的一个字符, 修改字符会返回一个新的字符串
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
 ]]
+PROJECT = "PACK_DEMO"
+VERSION = "001.000.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进行使用
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+
+-- 仅加载必要的功能模块
+require "pack_demo"  -- pack API演示模块
 
--- sys库是标配
-_G.sys = require("sys")
-sysplus = require("sysplus")
-
-
-local netLed = require("netLed")
---GPIO18配置为输出,默认输出低电平,可通过setGpio18Fnc(0或者1)设置输出电平
-local LEDA= gpio.setup(27, 0, gpio.PULLUP)
-
-sys.taskInit(function ()
-    sys.wait(1000) -- 免得看不到日志
-    local tmp
-
-	--实验1:以小端方式编码
-	local data = string.pack("<I", 0xAABBCCDD)      --‘<’表示以小端方式编码,'I'表示,unsigned int , 4字节
-	log.info("pack:", 	string.format("%02X", data:byte(1)), 	--输出小端编码后的数据
-						string.format("%02X", data:byte(2)), 
-						string.format("%02X", data:byte(3)), 
-						string.format("%02X", data:byte(4)))
-	
-	--实验2:以大端方式编码
-	local data = string.pack(">I", 0xAABBCCDD)
-	log.info("pack:", 	string.format("%02X", data:byte(1)),   --输出大端编码后的数据
-						string.format("%02X", data:byte(2)), 
-						string.format("%02X", data:byte(3)), 
-						string.format("%02X", data:byte(4)))
-						
-	--实验3:对上面已经完成的大端编码,再次进行解包为每个字节					
-	local byte1,byte2,byte3,byte4 = string.unpack(">BBBB", data)  --将32位数据拆成4个8位字节数据
-    --log.info("Unpack", byte1,byte2,byte3,byte4)		
-	log.info("Unpack:", string.format("%02X", byte1),   --以十六进制形式输出拆解后的4个字节数据
-						string.format("%02X", byte2), 
-						string.format("%02X", byte3), 
-						string.format("%02X", byte4))
-end)
--- 这里演示4G模块上网后,会自动点亮网络灯,方便用户判断模块是否正常开机
-sys.taskInit(function()
-    while true do
-        sys.wait(6000)
-                if mobile.status() == 1 then
-                        gpio.set(27, 1)  
-                else
-                        gpio.set(27, 0) 
-                        mobile.reset()
-        end
-    end
-end)
 -- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
 sys.run()
--- sys.run()之后后面不要加任何语句!!!!!
+-- sys.run()之后不要加任何语句!!!!!

+ 165 - 0
module/Air8000/demo/pack/pack_demo.lua

@@ -0,0 +1,165 @@
+--[[
+@summary pack API演示脚本
+@version 1.0
+@date    2025.10.27
+@author  陈媛媛
+@usage
+本脚本演示pack.pack和pack.unpack API的各种用法:
+1、大小端编码演示:使用'<'和'>'格式符进行小端和大端编码
+2、多种数据类型打包:打包short、int、float等多种数据类型
+3、字符串格式演示:'a'格式(带长度前缀)和'z'格式(以null结尾)的字符串打包和解包
+4、An格式演示:An格式(如A2、A5)的打包行为,即打包前n个字符串参数
+5、指定位置解包:从指定位置开始解包数据
+6、复杂数据组合:打包和解包复杂的数据结构,包括整数、字符串和短整数
+7、边界情况测试:空数据打包和解包,以及数值边界测试
+]]
+
+-- 初始化函数
+local function init()
+    log.info("pack_demo", "脚本初始化完成")
+end
+
+-- 大小端编码演示
+local function demo_endian()
+    log.info("\n--- 实验1:大小端编码 ---")
+    
+    -- 小端编码
+    local data_le = pack.pack("<I", 0xAABBCCDD)
+    log.info("小端编码:", data_le:toHex())
+    
+    -- 大端编码  
+    local data_be = pack.pack(">I", 0xAABBCCDD)
+    log.info("大端编码:", data_be:toHex())
+    
+    -- 解包验证
+    local _, val_le = pack.unpack(data_le, "<I")
+    local _, val_be = pack.unpack(data_be, ">I")
+    log.info("解包验证 - 小端:", string.format("0x%08X", val_le))
+    log.info("解包验证 - 大端:", string.format("0x%08X", val_be))
+end
+
+-- 多种数据类型打包演示
+local function demo_mixed_types()
+    log.info("\n--- 实验2:多种数据类型打包 ---")
+    
+    -- 打包多个不同类型数据
+    local mixed_data = pack.pack("<hIf", 123, 456789, 3.14)
+    log.info("混合数据打包:", mixed_data:toHex())
+    
+    -- 解包混合数据
+    local _, short_val, int_val, float_val = pack.unpack(mixed_data, "<hIf")
+    log.info("解包混合数据:", short_val, int_val, float_val)
+end
+
+-- 字符串格式演示
+local function demo_string_formats()
+    log.info("\n--- 实验3:字符串格式演示 ---")
+    
+    -- 'a' 格式 - 带长度前缀的字符串
+    local str_data_a = pack.pack('a', "LuatOS")
+    log.info("'a'格式字符串:", str_data_a:toHex())
+    
+    -- 解包a格式
+    local _, str_a = pack.unpack(str_data_a, 'a')
+    log.info("'a'格式解包:", str_a)
+    
+    -- 'z' 格式 - 以null结尾的字符串
+    local str_data_z = pack.pack('z', "LuatOS")
+    log.info("'z'格式字符串:", str_data_z:toHex())
+    
+    -- 解包z格式
+    local _, str_z = pack.unpack(str_data_z, 'z')
+    log.info("'z'格式解包:", str_z)
+end
+
+-- An格式演示
+local function demo_An_format()
+    log.info("\n--- 实验4:'An'格式演示 ---")
+    
+    -- 'A' 格式 - 打包第一个参数的整个字符串
+    local str_data_A = pack.pack('A', "hezhou", "LuatOS")
+    log.info("'A'格式打包:", str_data_A:toHex())
+    log.info("'A'格式结果:", str_data_A)
+    
+    -- 'A5' 格式 - 打包前5个字符串参数
+    local str_data_A5 = pack.pack('A5', "he", "zhou", "LuatOS", "!", "!")
+    log.info("'A5'格式打包:", str_data_A5:toHex())
+    log.info("'A5'格式结果:", str_data_A5)
+end
+
+-- 指定位置解包演示
+local function demo_position_unpack()
+    log.info("\n--- 实验5:指定位置解包 ---")
+    
+    -- 打包多个数据
+    local multi_data = pack.pack("<hIh", 100, 200, 300)
+    log.info("多数据打包:", multi_data:toHex())
+    
+    -- 从指定位置开始解包
+    local pos, val1 = pack.unpack(multi_data, "<h", 1)  -- 从位置1开始解包
+    local pos, val2 = pack.unpack(multi_data, "<I", pos) -- 从上次结束位置开始
+    local pos, val3 = pack.unpack(multi_data, "<h", pos) -- 继续解包
+    log.info("分步解包结果:", val1, val2, val3)
+end
+
+-- 复杂数据组合演示
+local function demo_complex_data()
+    log.info("\n--- 实验6:复杂数据组合 ---")
+    
+    -- 打包复杂数据结构
+    local complex_data = pack.pack(">H a h", 0x1234, "Test", -50)
+    log.info("复杂数据打包:", complex_data:toHex())
+    
+    -- 解包复杂数据
+    local _, header, text, value = pack.unpack(complex_data, ">H a h")
+    log.info("复杂数据解包:", string.format("0x%04X", header), text, value)
+end
+
+-- 边界情况演示
+local function demo_edge_cases()
+    log.info("\n--- 实验7:边界情况 ---")
+    
+    -- 打包空数据
+    local empty_data = pack.pack("")
+    log.info("空格式打包:", empty_data:toHex())
+    
+    -- 解包空数据
+    local pos_empty = pack.unpack("", "")
+    log.info("空格式解包位置:", pos_empty)
+    
+    -- 数值边界测试
+    local max_short = pack.pack("<h", 32767)
+    local min_short = pack.pack("<h", -32768)
+    log.info("短整型边界 - 最大值:", max_short:toHex())
+    log.info("短整型边界 - 最小值:", min_short:toHex())
+    
+    local _, max_val = pack.unpack(max_short, "<h")
+    local _, min_val = pack.unpack(min_short, "<h")
+    log.info("边界值验证:", max_val, min_val)
+end
+
+-- 运行所有演示
+local function run_all_demos()
+    log.info("=== pack.pack 和 pack.unpack API 演示开始 ===")
+    
+    init()
+    demo_endian()
+    demo_mixed_types()
+    demo_string_formats()
+    demo_An_format()
+    demo_position_unpack()
+    demo_complex_data()
+    demo_edge_cases()
+    
+    log.info("=== pack API 演示完成 ===")
+end
+
+-- 主任务函数
+local function main()
+    log.info("pack_demo", "开始运行pack API演示")
+    run_all_demos()
+    log.info("pack_demo", "演示运行完毕")
+end
+
+-- 启动演示任务
+sys.taskInit(main)

+ 142 - 0
module/Air8000/demo/pack/readme.md

@@ -0,0 +1,142 @@
+# pack_DEMO 项目说明
+
+## 项目概述
+本项目演示了LuatOS的pack核心库的使用,pack核心库提供了二进制数据的打包和解包功能,支持多种数据格式和字节序。
+
+## 功能说明
+
+本demo通过7个实验演示pack核心库的主要功能:
+
+    大小端编码演示:使用'<'和'>'格式符进行小端和大端编码
+
+    多种数据类型打包:打包short、int、float等多种数据类型
+
+    字符串格式演示:'a'格式(带长度前缀)和'z'格式(以null结尾)的字符串打包和解包
+
+    An格式演示:An格式(如A2、A5)的打包行为,即打包前n个字符串参数
+
+    指定位置解包:从指定位置开始解包数据
+
+    复杂数据组合:打包和解包复杂的数据结构,包括整数、字符串和短整数
+
+    边界情况测试:空数据打包和解包,以及数值边界测试
+
+## 演示硬件环境
+
+1、Air8000开发板或者核心板
+
+![alt text](https://docs.openLuat.com/cdn/image/Air8000开发板1.jpg)
+ 
+![alt text]( https://docs.openLuat.com/cdn/image/Air8000核心板.png)
+
+
+2、TYPE-C USB数据线一根
+- Air8000开发板/核心板通过 TYPE-C USB 口供电;
+- TYPE-C USB 数据线直接插到核心板的 TYPE-C USB 座子,另外一端连接电脑 USB 口;
+
+
+## 演示软件环境
+1、Luatools下载调试工具 [https://docs.openluat.com/air780epm/common/Luatools/]
+
+2、Air8000 V2016版本固件。不同版本区别请见https://docs.openluat.com/air8000/luatos/firmware/
+
+3、lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;
+
+4、准备好软件环境之后,接下来查看[如何烧录项目文件到 Air8000核心板中]
+(https://docs.openluat.com/air8000/luatos/common/download/)或者查看 [Air8000 产品手册](https://docs.openluat.com/air8000/product/shouce/)中“Air8000 整机开发板使用手册 -> 使用说明”,将本篇文章中演示使用的项目文件烧录到 Air8000 开发板中。
+
+
+
+
+## 相关软件资料
+pack 核心库文档:https://docs.openluat.com/osapi/core/pack/
+## 演示核心步骤
+1、搭建好硬件环境
+
+2、Luatools烧录内核固件和demo脚本代码
+
+3、烧录成功后,自动开机运行
+
+4、在日志中查看演示结果
+
+本demo包含7个实验,运行后会在日志中输出每一步的结果:
+
+- 实验1:大小端编码
+
+  演示如何使用'<'和'>'格式符进行小端和大端编码
+
+        ``` lua
+        I/user.小端编码: DDCCBBAA 8
+        I/user.大端编码: AABBCCDD 8
+        I/user.解包验证 - 小端: 0xAABBCCDD
+        I/user.解包验证 - 大端: 0xAABBCCDD
+         ```
+
+- 实验2:多种数据类型打包
+
+  演示如何同时打包short、int、float等多种数据类型
+
+        ``` lua
+        I/user.混合数据打包: 7B0055F80600C3F54840 20
+        I/user.解包混合数据: 123 456789 3.140000
+         ```
+
+
+- 实验3:字符串格式演示
+
+  演示'a'格式(带长度前缀)和'z'格式(以null结尾)的字符串打包和解包
+
+        ``` lua
+         I/user.'a'格式字符串: 060000004C7561744F53 20
+         I/user.'a'格式解包: LuatOS
+         I/user.'z'格式字符串: 4C7561744F5300 14
+         I/user.'z'格式解包: LuatOS
+         ```
+    
+- 实验4:An格式演示
+
+  演示An格式(如A2、A5)的打包行为,即打包前n个字符串参数
+
+        ``` lua
+        I/user.'A'格式打包: 68657A686F75 12
+        I/user.'A'格式结果: hezhou
+        I/user.'A5'格式打包: 68657A686F754C7561744F532121 28
+        I/user.'A5'格式结果: hezhouLuatOS!!
+         ```
+
+- 实验5:指定位置解包
+
+  演示如何从指定位置开始解包数据
+
+        ``` lua
+         I/user.多数据打包: 6400C80000002C01 16
+         I/user.分步解包结果: 100 200 300
+         ```
+
+- 实验6:复杂数据组合
+
+  演示如何打包和解包复杂的数据结构,包括整数、字符串和短整数
+
+        ``` lua
+         I/user.复杂数据打包: 12340000000454657374FFCE 24
+         I/user.复杂数据解包: 0x1234 Test -50
+         ```
+
+ - 实验7:边界情况
+
+    演示空数据打包和解包,以及数值边界测试
+
+        ``` lua
+         I/user.空格式打包:  0
+         I/user.空格式解包位置: 1
+         I/user.短整型边界 - 最大值: FF7F 4
+         I/user.短整型边界 - 最小值: 0080 4
+         I/user.边界值验证: 32767 -32768
+         ```
+
+## 注意事项
+
+本demo仅用于演示pack核心库的基本用法,更多高级用法请参考[pack 核心板文档](https://docs.openluat.com/osapi/core/pack/)。
+
+在实际使用中,请根据具体需求选择合适的数据类型和字节序。
+  

+ 59 - 93
module/Air8000/demo/string/main.lua

@@ -1,110 +1,76 @@
-
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "strtest"
-VERSION = "2.0.0"
-
 --[[
-本demo演示 string字符串的基本操作
-1. lua的字符串是带长度, 这意味着, 它不依赖0x00作为结束字符串, 可以包含任意数据
-2. lua的字符串是不可变的, 就不能直接修改字符串的一个字符, 修改字符会返回一个新的字符串
+@module  main
+@summary LuatOS字符串操作示例主入口,负责加载功能模块
+@version 1.0
+@date    2025.10.30
+@author  陈媛媛
+@usage
+本demo演示的核心功能为:
+1、字符串十六进制编码/解码
+2、字符串分割处理
+3、数值转换操作
+4、Base64/Base32编码解码
+5、URL编码处理
+6、字符串前后缀判断
+7、字符串裁剪处理
+
+更多说明参考本目录下的readme.md文件
 ]]
 
--- sys库是标配
-_G.sys = require("sys")
-
-sys.taskInit(function ()
-    sys.wait(1000) -- 免得看不到日志
-    local tmp
-
-    ----------------------------------------------
-    --================================================
-    -- 字符串的声明和生成
-    --================================================
-
-    -- 常量声明
-    local str = "123455" 
-    log.info("str", str)														--日志输出:123455
-
-    -- 合成式
-    str = string.char(0x31, 0x32, 0x33, 0x34)  --0x31为字符 1的ASCII码
-    log.info("str", str)           												--日志输出:1234                   
-    -- lua的字符串可以包含任意数据, 包括 0x00
-    str = string.char(0x12, 0x00, 0xF1, 0x3A)
-    log.info("str", str:toHex()) -- 注意, 这里用toHex(), 因为包含了不可见字符   --日志输出:1200F13A	8(其中8为输出字符串长度)
-    -- 使用转义字符
-    str = "\x00\x12ABC"			 -- 字符串中的\x表示十六进制转义序列								
-    log.info("str", str:toHex()) -- 注意, 这里用toHex(), 因为包含了不可见字符   --日志输出:0012414243	10 (其中41,42,43分别分字符 ABC的ASCII值的十六进制形式,10为输出字符串长度)
-    str = "ABC\r\n\t"
-    log.info("str", str:toHex()) -- 注意, 这里用toHex(), 因为包含了不可见字符   --日志输出:4142430D0A09	12(其中0D为\r回车键值的ASCII值的十六进制形式,
-	                                                                            --0A为\n换行键值的ASCII值的十六进制形式,\t 是一个转义字符,表示一个水平制表符(Tab))
-
 
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+PROJECT = "VOICE_CALL_DEMO"
+VERSION = "001.000.000"
 
-    -- 解析生成
-    str = string.fromHex("AABB00EE")											
-    log.info("str", str:toHex())												--日志输出:AABB00EE	8
-    str = string.fromHex("393837363433")       --将字符串转换为十六进制形式
-    log.info("str", #str, str)												    --日志输出:6	987643(其中6为输出字符长度,987643为输出字符串)
+-- 在日志中打印项目名和项目版本号
+log.info("main", PROJECT, VERSION)
 
-    -- 连接字符串, 操作符 ".."
-    str = "123" .. "," .. "ABC"  --将3段字符串连接起来
-    log.info("str", #str, str)												    --日志输出:7	123,ABC(其中7为输出字符长度,123,ABC为连接后的字符串)
 
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
 
-    -- 格式化生成
-    str = string.format("%s,%d,%f", "123", 45678, 1.5)		--格式化输出,	%s为字符串输出,%d为十进制输出,%f为浮点形式输出			
-    log.info("str", #str, str)													--日志输出:18	123,45678,1.500000
 
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
 
-    --================================================
-    -- 字符串的解析与处理
-    --================================================
-    -- 获取长度
-    str = "1234567"
-    log.info("str", #str)														--日志输出:7为字符串长度
-    -- 获取字符串的HEX字符串显示
-    log.info("str", str:toHex())												--日志输出:31323334353637	14(用字符格式输出十六进制)
 
-    -- 获取指定位置的值, 注意lua的下标是1开始的
-    str = "123ddss"
-    log.info("str[1]", str:byte(1))                                             --日志输出:49	 (字符1,对应十进制ASCII值)
-    log.info("str[4]", str:byte(4))												--日志输出: 100	 (字符d,对应十进制ASCII值)
-    log.info("str[1]", string.byte(str, 1))										--日志输出:49   (str位置1的字符,也是数字1)
-    log.info("str[4]", string.byte(str, 4))										--日志输出: 100	 (str位置4的字符,也是数字d)
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
 
-    -- 按字符串分割
-    str = "12,2,3,4,5"
-    tmp = str:split(",")
-    log.info("str.split", #tmp, tmp[1], tmp[3])									--日志输出:5	12	3
-    tmp = string.split(str, ",") -- 与前面的等价
-    log.info("str.split", #tmp, tmp[1], tmp[3])                                 --日志输出:5	12	3
-    str = "/tmp//def/1234/"
-    tmp = str:split("/")
-    log.info("str.split", #tmp, json.encode(tmp))								--日志输出:3	["tmp","def","1234"]
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
 
-    -- 2023.04.11新增的, 可以保留空的分割片段
-	--在 Lua 中,str:split("/", true) 语句表示将字符串 str 按照字符 "/" 进行分割,并且 true 参数通常用于表示保留空字符串(这取决于具体的 split 函数实现,因为 Lua 标准库中没有内置的 split 函数)。根据你的描述,输出结果是 6 ["","tmp","","def","1234",""]。这是因为:
-    --假设 str 是 "/tmp//def/1234/",在这种情况下,字符串以 "/" 开头和结尾,并且有连续的 "/"。
-    --split 函数将字符串分割成多个部分,每个 "/" 都会作为一个分割符。
-    --因为 true 参数表示保留空字符串,所以在分割过程中,连续的 "/" 和开头、结尾的 "/" 都会导致空字符串被保留。
 
-    tmp = str:split("/", true) 
-    log.info("str.split", #tmp, json.encode(tmp))								--日志输出:6	["","tmp","","def","1234",""]
+-- 仅加载必要的功能模块
+require "string_demo"  ---- 加载字符串操作演示模块
 
-end)
--- 这里演示4G模块上网后,会自动点亮网络灯,方便用户判断模块是否正常开机
-sys.taskInit(function()
-    while true do
-        sys.wait(6000)
-                if mobile.status() == 1 then
-                        gpio.set(27, 1)  
-                else
-                        gpio.set(27, 0) 
-                        mobile.reset()
-        end
-    end
-end)
 -- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
 sys.run()
--- sys.run()之后后面不要加任何语句!!!!!
+-- sys.run()之后不要加任何语句!!!!!

+ 160 - 0
module/Air8000/demo/string/readme.md

@@ -0,0 +1,160 @@
+# string_DEMO 项目说明
+
+## 项目概述
+
+本项目演示了LuatOS的string核心库的使用,string核心库提供了丰富的字符串处理功能,包括编码转换、字符串分割、格式处理等。
+## 功能说明
+
+本demo通过多个示例演示string核心库的主要功能:
+
+    十六进制编码/解码:演示字符串与十六进制格式的互相转换
+
+    字符串分割处理:演示使用不同分隔符进行字符串分割
+
+    数值转换操作:演示字符串到二进制数据的转换
+
+    Base64编码解码:演示Base64编码和解码功能
+
+    Base32编码解码:演示Base32编码和解码功能
+
+    字符串前后缀判断:演示字符串前缀和后缀判断功能
+
+    字符串裁剪处理:演示去除字符串前后空白字符的功能
+
+## 演示硬件环境
+
+1、Air8000开发板或者核心板
+
+![alt text](https://docs.openLuat.com/cdn/image/Air8000开发板1.jpg)
+ 
+![alt text]( https://docs.openLuat.com/cdn/image/Air8000核心板.png)
+
+
+2、TYPE-C USB数据线一根
+- Air8000开发板/核心板通过 TYPE-C USB 口供电;
+- TYPE-C USB 数据线直接插到核心板的 TYPE-C USB 座子,另外一端连接电脑 USB 口;
+
+
+## 演示软件环境
+1、Luatools下载调试工具 [https://docs.openluat.com/air780epm/common/Luatools/]
+
+2、Air8000 V2016版本固件。不同版本区别请见https://docs.openluat.com/air8000/luatos/firmware/
+
+3、lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;
+
+4、准备好软件环境之后,接下来查看[如何烧录项目文件到Air8000核心板中](https://docs.openluat.com/air8000/luatos/common/download/) 或者查看 [Air8000 产品手册](https://docs.openluat.com/air8000/product/shouce/)中“Air8000 整机开发板使用手册 -> 使用说明”,将本篇文章中演示使用的项目文件烧录到 Air8000 开发板中。
+
+## 相关软件资料
+string 核心库文档:https://docs.openluat.com/osapi/core/string/
+
+## 演示核心步骤
+1、搭建好硬件环境
+
+2、Luatools烧录内核固件和demo脚本代码
+
+3、烧录成功后,自动开机运行
+
+4、在日志中查看演示结果
+
+``` lua
+ I/user.string_demo 字符串操作演示模块初始化
+ I/user.string_demo 开始执行所有字符串操作演示
+```
+
+本demo包含6个主要功能,运行后会在日志中输出每一步的结果:
+
+- 十六进制转换示例
+
+  演示字符串与十六进制格式的互相转换
+
+  ``` lua
+  I/user.=== 十六进制转换示例 ===
+  I/user.toHex 原始字符串: 123abc HEX结果: 313233616263 长度: 12
+  I/user.toHex 带空格分隔: 31 32 33 61 62 63 
+  I/user.fromHex HEX字符串解码: 123abc
+  I/user.toHex 二进制数据转HEX: 0102030405
+         ```
+
+- 字符串分割示例
+
+  演示使用不同分隔符进行字符串分割
+
+  ``` lua
+  I/user.=== 字符串分割示例 ===
+  I/user.split CSV分割结果: 3 ["123","456","789"]
+  I/user.split IP地址分割: 1 ["192.168.1.1"]
+  I/user.split 多字符分隔符: 4 ["a","b","c","d"]
+  I/user.split 路径分割: 4 ["usr","local","bin","lua"]
+  ```
+
+
+- 实数值转换示例
+
+  演示字符串到二进制数据的转换
+  
+  ``` lua
+  I/user.=== 数值转换示例 ===
+  I/user.toValue 原始字符串: 123456 转换字符数: 6
+  I/user.toValue 二进制结果HEX: 010203040506 12
+  I/user.toValue 混合字符串转换: 123abc 字符数: 6
+  I/user.toValue 混合结果HEX: 0102030A0B0C 12
+  ```
+
+- Base64编码示例
+
+  演示Base64编码和解码功能    
+  ``` lua
+  I/user.=== Base64编码示例 ===
+  I/user.toBase64 原文: Hello LuaOS! 编码后: SGVsbG8gTHVhT1Mh
+  I/user.fromBase64 解码结果: Hello LuaOS!
+  I/user.toBase64 中文原文: 你好世界 编码后: 5L2g5aW95LiW55WM
+  I/user.fromBase64 中文解码: 你好世界
+  ```
+
+- Base32编码示例
+  演示Base32编码和解码功能
+  ``` lua
+  I/user.=== Base32编码解码示例 ===
+  I/user.toBase32 原文: Hello World 编码后: JBSWY3DPEBLW64TMMQ======
+  I/user.fromBase32 解码结果: Hello World
+  I/user.toBase32 短字符串编码: test => ORSXG5A=
+  I/user.fromBase32 短字符串解码: test
+  I/user.toBase32 中文原文: 你好世界 编码后: 4S62BZNFXUYQKIIUHU4Q====
+  I/user.fromBase32 中文解码: 你好世界
+  I/user.toBase32 二进制数据HEX: 0102030405 Base32: AEBAGBAFAYDQ====
+  I/user.toBase32 空字符串编码:'' => 
+  I/user.fromBase32 空字符串解码: ''
+  ```
+
+- 字符串判断示例
+
+  演示字符串前缀和后缀判断功能
+
+  ``` lua
+  I/user.=== 字符串判断示例 ===
+  I/user.startsWith 字符串: hello world
+  I/user.startsWith 以'hello'开头: true
+  I/user.startsWith 以'world'开头: false
+  I/user.endsWith 以'world'结尾: true
+  I/user.endsWith 以'hello'结尾: false
+  ```
+
+- 字符串裁剪示例
+
+  演示去除字符串前后空白字符的功能
+
+  ``` lua
+  I/user.=== 字符串裁剪示例 ===
+  I/user.trim 原始字符串长度: 23
+  I/user.trim 裁剪后字符串: 'hello world' 长度: 11
+  I/user.trim 用户输入清理: '   admin   ' => 'admin'
+  ```
+
+
+
+## 注意事项
+
+本demo仅用于演示string核心库的基本用法,更多高级用法请参考[string核心库](https://docs.openluat.com/osapi/core/string/)文档。
+
+在实际使用中,请根据具体需求选择合适的字符串处理函数,注意不同函数对输入数据的要求和边界情况处理。
+  

+ 206 - 0
module/Air8000/demo/string/string_demo.lua

@@ -0,0 +1,206 @@
+--[[
+@summary 字符串操作功能演示脚本
+@version 1.0
+@date 2025.07.16
+@author 陈媛媛
+@usage
+本demo通过多个示例演示string核心库的主要功能:
+1、十六进制编码/解码:演示字符串与十六进制格式的互相转换
+2、字符串分割处理:演示使用不同分隔符进行字符串分割
+3、数值转换操作:演示字符串到二进制数据的转换
+4、Base64编码解码:演示Base64编码和解码功能
+5、Base32编码解码:演示Base32编码和解码功能
+6、字符串前后缀判断:演示字符串前缀和后缀判断功能
+7、字符串裁剪处理:演示去除字符串前后空白字符的功能
+]]
+
+-- 初始化函数
+local function init()
+    log.info("string_demo", "字符串操作演示脚本初始化")
+end
+
+-- ====================== 十六进制转换示例 ======================
+local function hex_examples()
+    log.info("=== 十六进制转换示例 ===")
+    
+    -- 字符串转十六进制
+    local original_str = "123abc"
+    local hex_result, hex_length = string.toHex(original_str)
+    log.info("toHex", "原始字符串:", original_str, "HEX结果:", hex_result, "长度:", hex_length)
+    
+    -- 带分隔符的十六进制转换
+    local hex_with_space = string.toHex(original_str, " ")
+    log.info("toHex", "带空格分隔:", hex_with_space)
+    
+    -- 十六进制转字符串
+    local decoded_str = string.fromHex("313233616263")
+    log.info("fromHex", "HEX字符串解码:", decoded_str)
+    
+    -- 二进制数据转换
+    local binary_data = string.char(0x01, 0x02, 0x03, 0x04, 0x05)
+    local binary_hex = string.toHex(binary_data)
+    log.info("toHex", "二进制数据转HEX:", binary_hex)
+end
+
+-- ====================== 字符串分割示例 ======================
+local function split_examples()
+    log.info("=== 字符串分割示例 ===")
+    
+    -- 基本分割
+    local csv_str = "123,456,789"
+    local parts1 = string.split(csv_str, ",")
+    log.info("split", "CSV分割结果:", #parts1, json.encode(parts1))
+    
+    -- 使用小数点作为分隔符
+    local ip_str = "192.168.1.1"
+    local ip_parts = string.split(ip_str, "%.")
+    log.info("split", "IP地址分割:", #ip_parts, json.encode(ip_parts))
+    
+    -- 多字符分隔符
+    local multi_sep = "a||b||c||d"
+    local multi_parts = string.split(multi_sep, "||")
+    log.info("split", "多字符分隔符:", #multi_parts, json.encode(multi_parts))
+end
+
+-- ====================== 数值转换示例 ======================
+local function value_conversion_examples()
+    log.info("=== 数值转换示例 ===")
+    
+    -- 字符串转数值编码
+    local num_str = "123456"
+    local binary_result, converted_chars = string.toValue(num_str)
+    log.info("toValue", "原始字符串:", num_str, "转换字符数:", converted_chars)
+    log.info("toValue", "二进制结果HEX:", string.toHex(binary_result))
+    
+    -- 包含字母的转换
+    local mixed_str = "123abc"
+    local mixed_result, mixed_count = string.toValue(mixed_str)
+    log.info("toValue", "混合字符串转换:", mixed_str, "字符数:", mixed_count)
+    log.info("toValue", "混合结果HEX:", string.toHex(mixed_result))
+end
+
+-- ====================== Base64编码示例 ======================
+local function base64_examples()
+    log.info("=== Base64编码示例 ===")
+    
+    -- Base64编码
+    local plain_text = "Hello LuaOS!"
+    local encoded_b64 = string.toBase64(plain_text)
+    log.info("toBase64", "原文:", plain_text, "编码后:", encoded_b64)
+    
+    -- Base64解码
+    local decoded_b64 = string.fromBase64(encoded_b64)
+    log.info("fromBase64", "解码结果:", decoded_b64)
+    
+    -- 中文编码
+    local chinese_text = "你好世界"
+    local chinese_b64 = string.toBase64(chinese_text)
+    log.info("toBase64", "中文原文:", chinese_text, "编码后:", chinese_b64)
+end
+
+-- ====================== Base32编码解码示例 ======================
+local function base32_examples()
+    log.info("=== Base32编码解码示例 ===")
+    
+    -- 检查Base32功能是否可用
+    if string.toBase32 and string.fromBase32 then
+        -- 基本编码
+        local plain_text = "Hello World"
+        local encoded_b32 = string.toBase32(plain_text)
+        log.info("toBase32", "原文:", plain_text, "编码后:", encoded_b32)
+        
+        -- 解码验证
+        local decoded_b32 = string.fromBase32(encoded_b32)
+        log.info("fromBase32", "解码结果:", decoded_b32)
+        
+        -- 短字符串编码
+        local short_text = "test"
+        local short_b32 = string.toBase32(short_text)
+        log.info("toBase32", "短字符串编码:", short_text, "=>", short_b32)
+        log.info("fromBase32", "短字符串解码:", string.fromBase32(short_b32))
+        
+        -- 中文编码
+        local chinese_text = "你好世界"
+        local chinese_b32 = string.toBase32(chinese_text)
+        log.info("toBase32", "中文原文:", chinese_text, "编码后:", chinese_b32)
+        log.info("fromBase32", "中文解码:", string.fromBase32(chinese_b32))
+        
+        -- 二进制数据编码
+        local binary_data = string.char(0x01, 0x02, 0x03, 0x04, 0x05)
+        local binary_b32 = string.toBase32(binary_data)
+        log.info("toBase32", "二进制数据HEX:", string.toHex(binary_data), "Base32:", binary_b32)
+        
+        -- 空字符串处理
+        local empty_b32 = string.toBase32("")
+        log.info("toBase32", "空字符串编码:", "''", "=>", empty_b32)
+        log.info("fromBase32", "空字符串解码:", "'" .. string.fromBase32(empty_b32) .. "'")
+        
+    else
+        log.warn("Base32", "当前固件不支持Base32编码解码功能")
+        log.info("Base32", "请确保使用支持Base32的LuatOS固件版本")
+    end
+end
+
+-- ====================== 字符串判断示例 ======================
+local function string_check_examples()
+    log.info("=== 字符串判断示例 ===")
+    
+    local test_str = "hello world"
+    
+    -- 判断前缀
+    local starts_with_hello = string.startsWith(test_str, "hello")
+    local starts_with_world = string.startsWith(test_str, "world")
+    log.info("startsWith", "字符串:", test_str)
+    log.info("startsWith", "以'hello'开头:", starts_with_hello)
+    log.info("startsWith", "以'world'开头:", starts_with_world)
+    
+    -- 判断后缀
+    local ends_with_world = string.endsWith(test_str, "world")
+    local ends_with_hello = string.endsWith(test_str, "hello")
+    log.info("endsWith", "以'world'结尾:", ends_with_world)
+    log.info("endsWith", "以'hello'结尾:", ends_with_hello)
+end
+
+-- ====================== 字符串裁剪示例 ======================
+local function trim_examples()
+    log.info("=== 字符串裁剪示例 ===")
+    
+    -- 包含空白字符的字符串
+    local dirty_str = "  \r\n  hello world  \t\n  "
+    
+    -- 默认裁剪(前后都裁剪)
+    local trimmed = string.trim(dirty_str)
+    log.info("trim", "原始字符串长度:", #dirty_str)
+    log.info("trim", "裁剪后字符串:", "'" .. trimmed .. "'", "长度:", #trimmed)
+    
+    -- 用户输入清理示例
+    local user_input = "   admin   "
+    local clean_input = string.trim(user_input)
+    log.info("trim", "用户输入清理:", "'" .. user_input .. "'", "=>", "'" .. clean_input .. "'")
+end
+
+-- ====================== 主演示函数 ======================
+local function run_all_demos()
+    log.info("string_demo", "开始执行所有字符串操作演示")
+    
+    init()
+    hex_examples()
+    split_examples()
+    value_conversion_examples()
+    base64_examples()
+    base32_examples()
+    string_check_examples()
+    trim_examples()
+    
+    log.info("string_demo", "所有演示执行完成")
+end
+
+-- 主任务函数
+local function main()
+    log.info("string_demo", "开始运行字符串操作演示")
+    run_all_demos()
+    log.info("string_demo", "演示运行完毕")
+end
+
+-- 启动演示任务
+sys.taskInit(main)

+ 65 - 0
module/Air8000/demo/wdt/air153c_wdt.lua

@@ -0,0 +1,65 @@
+-- air153c_wdt.lua
+--[[
+@summary Air153C外部看门狗演示模块
+@version 1.0
+@date    2025.10.25
+@author  陈媛媛
+@usage
+本模块演示Air153C外部看门狗的正常和异常场景:
+1、正常场景:定期喂狗,系统正常运行
+2、异常场景:模拟故障导致无法喂狗,触发看门狗复位
+3、通过修改 DEMO_MODE 变量来选择演示模式:
+- "normal": 正常喂狗模式
+- "fault": 异常故障模式
+
+注意:在异常模式下,设备会在运行一段时间后重启
+]]
+
+-- 演示模式选择: "normal" 或 "fault"
+local DEMO_MODE = "normal"  -- 修改这个变量来切换演示模式
+
+-- 看门狗喂狗任务函数
+local function watchdogTask()
+    -- 检查air153C_wtd库是否存在
+    if air153C_wtd == nil then
+        log.error("air153C_wtd", "air153C_wtd库不存在")
+        return
+    end
+    
+    -- 初始化看门狗引脚28
+    air153C_wtd.init(28)
+    log.info("air153C_wtd", "外部看门狗已初始化,引脚28")
+
+    if DEMO_MODE == "normal" then
+        -- 正常模式:主循环中定期喂狗
+        while true do
+            -- 每10秒喂一次狗
+            air153C_wtd.feed_dog(28)
+            log.info("wdt", "Watchdog fed")
+            
+            -- 执行其他业务逻辑
+            sys.wait(10000)  -- 等待10秒
+        end
+    elseif DEMO_MODE == "fault" then
+        -- 异常模式:先正常喂狗一段时间,然后停止喂狗
+        local feed_count = 0
+        while true do
+            -- 每10秒喂一次狗
+            air153C_wtd.feed_dog(28)
+            feed_count = feed_count + 1
+            log.info("wdt", "Watchdog fed")
+            
+            -- 执行其他业务逻辑
+            sys.wait(10000)  -- 等待10秒
+            
+            -- 喂狗3次后(约30秒)停止喂狗,模拟故障
+            if feed_count >= 3 then
+                log.info("wdt", "Stopping watchdog feed to simulate fault")
+                break
+            end
+        end
+    end
+end
+
+-- 看门狗喂狗任务
+sys.taskInit(watchdogTask)

+ 71 - 0
module/Air8000/demo/wdt/internal_wdt.lua

@@ -0,0 +1,71 @@
+-- internal_wdt.lua
+--[[
+@summary 内部看门狗演示模块
+@version 1.0
+@date    2025.10.25
+@author  陈媛媛
+@usage
+本模块演示内部看门狗的正常和异常场景:
+1、正常场景:定期喂狗,系统正常运行
+2、异常场景:模拟故障导致无法喂狗,触发看门狗复位
+3、通过修改 DEMO_MODE 变量来选择演示模式:
+- "normal": 正常喂狗模式
+- "fault": 异常故障模式
+
+注意:在异常模式下,设备会在运行一段时间后重启
+]]
+
+-- 演示模式选择: "normal" 或 "fault"
+local DEMO_MODE = "fault"  -- 修改这个变量来切换演示模式
+
+-- 喂狗函数
+function feed_watchdog()
+    wdt.feed()
+    log.info("wdt", "喂狗完成")
+end
+
+-- 故障模拟函数
+function simulate_fault()
+    sys.wait(5000) -- 等待5秒,让系统先正常运行一会
+    
+    -- 在进入死循环前尝试喂狗一次,并检查返回值
+    local success = wdt.feed()
+    log.info("wdt", "故障前最后一次喂狗,成功 =", success)
+    
+    log.info("fault_task", "进入死循环模拟故障")
+    log.info("fault_task", "看门狗喂狗任务被阻塞,系统将在约20秒后重启")
+    
+    while true do
+        -- 模拟故障场景,真的进入死循环
+        -- 这将导致无法喂狗,最终触发系统重启
+    end
+end
+
+-- 内部看门狗演示函数
+function internal_wdt_demo()
+    -- 检查wdt库是否存在
+    if wdt == nil then
+        log.error("wdt", "wdt库不存在")
+        return
+    end
+    
+    log.info("wdt", "硬件看门狗已由底层固件启用")
+    
+    -- 检查开机原因
+    local reason1, reason2, reason3 = pm.lastReson()
+    log.info("reset_reason", "重启原因1:", reason1, "原因2:", reason2, "原因3:", reason3)
+    
+    -- 定期喂狗,防止系统重启
+    -- 设置喂狗间隔为3秒,确保在20秒超时前完成喂狗
+    sys.timerLoopStart(feed_watchdog, 3000) -- 每3秒喂一次狗
+end
+
+if DEMO_MODE == "fault" then
+    -- 创建一个新的任务来模拟故障场景
+    sys.taskInit(simulate_fault)
+end
+
+-- 启动演示
+sys.taskInit(internal_wdt_demo)
+
+return internal_wdt_demo

+ 62 - 0
module/Air8000/demo/wdt/main.lua

@@ -0,0 +1,62 @@
+--[[
+@module  main
+@summary LuatOS语音通话应用主入口,负责加载功能模块
+@version 1.0
+@date    2025.10.25
+@author  陈媛媛
+@usage
+本demo演示的核心功能为:
+1、内部看门狗正常和异常场景演示
+2、外部硬件看门狗Air153C正常和异常场景演示
+
+更多说明参考本目录下的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这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+PROJECT = "wdt_DEMO"
+VERSION = "001.000.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)
+
+
+-- 仅加载必要的功能模块,有选择的打开以下两个lua文件中的一个
+require "internal_wdt"  -- 内部看门狗演示模块
+--require "air153c_wdt"    -- 外部看门狗演示模块
+
+-- 用户代码已结束---------------------------------------------
+sys.run()
+-- sys.run()之后不要加任何语句!!!!!

+ 133 - 0
module/Air8000/demo/wdt/readme.md

@@ -0,0 +1,133 @@
+# wdt_DEMO 项目说明
+
+## 项目概述
+本项目是基于 Air8000核心板,演示了两种看门狗(WDT)功能的使用。
+
+- 内部看门狗 - 使用芯片内置的硬件看门狗
+
+- 外部看门狗 - 使用 Air153C 外置看门狗芯片
+
+## 功能说明
+
+内部看门狗演示
+
+ - 自动启用:硬件看门狗由底层固件自动启用,超时时间20秒
+
+ - 定期喂狗:每3秒执行一次喂狗操作,确保系统正常运行
+
+ - 故障模拟:可模拟系统死锁导致无法喂狗的场景
+
+ - 自动恢复:看门狗超时后自动重启系统
+
+外部看门狗演示 (Air153C)
+
+ - 引脚控制:通过GPIO引脚28控制外部看门狗芯片
+
+ - 定期喂狗:每10秒执行一次喂狗操作
+
+ - 故障模拟:可模拟程序异常停止喂狗的场景
+
+ - 硬件复位:外部看门狗超时后通过硬件复位系统
+
+## 演示硬件环境
+1、Air8000核心板
+ 
+![alt text]( https://docs.openLuat.com/cdn/image/Air8000%E6%A0%B8%E5%BF%83%E6%9D%BF.jpg)
+
+2、Air153C配件版(待补充图片和接线图)
+
+
+3、TYPE-C USB数据线一根
+- Air8000开发板/核心板通过 TYPE-C USB 口供电;
+- TYPE-C USB 数据线直接插到核心板的 TYPE-C USB 座子,另外一端连接电脑 USB 口;
+
+
+## 演示软件环境
+1、Luatools下载调试工具 [https://docs.openluat.com/air780epm/common/Luatools/]
+
+2、Air8000 V2016版本固件。不同版本区别请见https://docs.openluat.com/air8000/luatos/firmware/
+
+3、lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;
+
+4、准备好软件环境之后,接下来查看[如何烧录项目文件到 Air8000核心板中](https://docs.openluat.com/air780epm/common/Luatools/)。
+
+## 相关软件资料
+wdt 核心库文档:https://docs.openluat.com/osapi/core/wdt/
+
+air153C_wtd 扩展库文档:https://docs.openluat.com/osapi/ext/air153C_wtd/
+
+## 演示核心步骤
+1、搭建好硬件环境
+
+2、加载演示脚本文件:
+
+- 在main.lua中有选择的选择以下两个lua文件中的一个
+
+  - require "internal_wdt"  -- 内部看门狗演示模块
+
+  - require "air153c_wdt"    -- 外部看门狗演示模块
+
+- 在internal_wdt.lua或者air153c_wdt.Lua 两个演示脚本中,通过修改 DEMO_MODE 变量选择演示模式
+
+ - local DEMO_MODE = "normal"   -- 正常模式:持续喂狗
+
+ - local DEMO_MODE = "fault"    -- 故障模式:模拟系统故障
+
+3、Luatools烧录内核固件和修改后的demo脚本代码
+
+4、烧录成功后,自动开机运行
+
+5、内部看门狗演示
+
+- 正常模式演示
+
+  设置 DEMO_MODE = "normal"
+
+  烧录并运行脚本
+
+  程序运行后会显示以下典型日志:
+  ```lua
+  I/user.wdt 硬件看门狗已由底层固件启用
+  I/user.wdt 喂狗完成
+  I/user.wdt 喂狗完成
+   ```
+
+- 故障模式演示
+
+  设置 DEMO_MODE = "fault"
+
+  烧录并运行脚本
+
+  程序运行后会显示以下典型日志:
+  ```lua
+   [2025-11-04 15:31:38.907][000000000.263] I/user.main wdt_DEMO 001.000.000
+   [2025-11-04 15:31:38.913][000000000.271] I/user.wdt 硬件看门狗已由底层固件启用
+   [2025-11-04 15:31:41.459][000000003.272] I/user.wdt 喂狗完成
+   [2025-11-04 15:31:43.457][000000005.271] I/user.wdt 故障前最后一次喂狗,成功 = true
+   [2025-11-04 15:31:43.464][000000005.272] I/user.fault_task 进入死循环模拟故障
+   [2025-11-04 15:31:43.472][000000005.272] I/user.fault_task 看门狗喂狗任务被阻塞,系统将在约20秒后重启
+   [2025-11-04 15:32:08.710] 工具提示: 模组已经死机,请不要关闭程序,正在接收必要的信息用于分析
+   [2025-11-04 15:32:32.943] 工具提示: diag com USB 断开连接 COM4 CommError,[WinError 22] 设备不识别此命令。
+   [2025-11-04 15:32:32.985] 工具提示: 死机信息接收成功,如有需要请将死机信息文件交给FAE分析,文件保存在log\ramdump\2025-11-04_153209_LuatOS-SoC_V2016_Air780EGH_867920073503634_COM4_ramdump.bin
+   [2025-11-04 15:32:33.006] 工具提示: 同时把使用的soc固件包或者编译生成的.elf文件交给FAE
+   [2025-11-04 15:32:33.022] 工具提示: print com USB 断开连接 COM3 CommError,[WinError 22] 设备不识别此命令。
+   [2025-11-04 15:32:33.664] 工具提示: soc log port COM3打开成功
+   [2025-11-04 15:32:33.738] 工具提示: ap log port COM4打开成功
+   [2025-11-04 15:32:33.751] 工具提示: 用户虚拟串口 COM5
+   [2025-11-04 15:32:34.049][000000000.272] I/user.wdt 硬件看门狗已由底层固件启用
+   [2025-11-04 15:32:34.054][000000000.272] I/user.reset_reason 重启原因1: 0 原因2: 0 原因3: 8
+  ``` 
+ 6、关于重启时间的说明:
+
+   实际重启时间不是精确的20秒,主要原因包括:
+
+   硬件处理时间:从看门狗超时到实际硬件复位需要一定的处理时间
+
+   系统状态保存:在复位前系统需要保存必要的状态信息和日志便于分析
+
+
+ 7、关于重启原因值的验证:
+
+   根据[pm.lastReson()函数的返回值说明](https://docs.openluat.com/osapi/core/pm/#45-pmlastreson)确认重启的原因3: 8 是内部看门狗触发的重启。
+
+8、外部看门狗演示(待补充)

+ 0 - 33
module/Air8000/demo/wdt/示例一 程序正常运行/main.lua

@@ -1,33 +0,0 @@
-
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "wdtdemo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-sys.taskInit(function()
-    -- 这个demo要求有wdt库
-    -- wdt库的使用,基本上每个demo的头部都有演示
-    -- 模组/芯片的内部硬狗, 能解决绝大多数情况下的死机问题
-    -- 但如果有要求非常高的场景, 依然建议外挂硬件,然后通过gpio/i2c定时喂狗
-    if wdt == nil then
-        while 1 do
-            sys.wait(1000)
-            log.info("wdt", "this demo need wdt lib")
-        end
-    end
-    -- 注意, 大部分芯片/模块是 2 倍超时时间后才会重启
-    -- 以下是常规配置, 9秒超时, 3秒喂一次狗
-    -- 若软件崩溃,死循环,硬件死机,那么 最多 18 秒后,自动复位
-    -- 注意: 软件bug导致业务失败, 并不能通过wdt解决
-    wdt.init(9000)
-    sys.timerLoopStart(wdt.feed, 3000)
-end)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 42
module/Air8000/demo/wdt/示例二 添加死循环模拟故障场景/main.lua

@@ -1,42 +0,0 @@
-
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "wdtdemo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-sys.taskInit(function()
-    -- 这个demo要求有wdt库
-    -- wdt库的使用,基本上每个demo的头部都有演示
-    -- 模组/芯片的内部硬狗, 能解决绝大多数情况下的死机问题
-    -- 但如果有要求非常高的场景, 依然建议外挂硬件,然后通过gpio/i2c定时喂狗
-    if wdt == nil then
-        while 1 do
-            sys.wait(1000)
-            log.info("wdt", "this demo need wdt lib")
-        end
-    end
-    -- 注意, 大部分芯片/模块是 2 倍超时时间后才会重启
-    -- 以下是常规配置, 9秒超时, 3秒喂一次狗
-    -- 若软件崩溃,死循环,硬件死机,那么 最多 18 秒后,自动复位
-    -- 注意: 软件bug导致业务失败, 并不能通过wdt解决
-    wdt.init(9000)
-    sys.timerLoopStart(wdt.feed, 3000)
-end)
-
--- 创建一个新的任务来模拟故障场景
-sys.taskInit(function()
-    log.info("fault_task", "Entering infinite loop to simulate fault.")
-    while true do
-        -- 模拟故障场景,真的进入死循环
-    end
-end)
-
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!