Эх сурвалжийг харах

add:新增8101的xmodem的demo和xxtea的demo

liszt123 4 сар өмнө
parent
commit
4044aa497c

+ 1 - 1
module/Air780EHM_Air780EHV_Air780EGH/demo/xmodem/main.lua

@@ -66,7 +66,7 @@ end
 --     log.info("mem.sys", rtos.meminfo("sys"))
 -- end, 3000)
 
--- 加载网络环境检测看门狗功能模块
+-- 加载xmodem_demo模块
 require "xmodem_demo"
 
 -- 用户代码已结束---------------------------------------------

+ 1 - 1
module/Air780EPM/demo/xmodem/main.lua

@@ -66,7 +66,7 @@ end
 --     log.info("mem.sys", rtos.meminfo("sys"))
 -- end, 3000)
 
--- 加载网络环境检测看门狗功能模块
+-- 加载xmodem_demo模块
 require "xmodem_demo"
 
 -- 用户代码已结束---------------------------------------------

+ 1 - 1
module/Air8000/demo/xmodem/main.lua

@@ -66,7 +66,7 @@ end
 --     log.info("mem.sys", rtos.meminfo("sys"))
 -- end, 3000)
 
--- 加载网络环境检测看门狗功能模块
+-- 加载xmodem_demo模块
 require "xmodem_demo"
 
 -- 用户代码已结束---------------------------------------------

+ 78 - 0
module/Air8101/demo/xmodem/main.lua

@@ -0,0 +1,78 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.14
+@author  李源龙
+@usage
+本demo演示的核心功能为:
+用Air8101核心板利用xmodem协议,将模块内的文件从串口发送到对端
+主要提供了两种方式:
+1、文件存到脚本区里面,通过xmodem协议,把脚本区文件发给对端
+2、通过http下载文件到文件系统区,通过xmodem协议,把文件系统区文件发给对端
+
+更多说明参考本目录下的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 = "xmodem_demo"
+VERSION = "001.000.000"
+
+
+-- 在日志中打印项目名和项目版本号
+log.info("main", PROJECT, VERSION)
+
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+
+-- 如果内核固件支持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)
+
+-- 加载网络驱动设备功能模块
+require "netdrv_device"
+
+-- 加载xmodem模块
+require "xmodem_demo"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后不要加任何语句!!!!!因为添加的任何语句都不会被执行

+ 115 - 0
module/Air8101/demo/xmodem/netdrv/netdrv_4g.lua

@@ -0,0 +1,115 @@
+--[[
+@module  netdrv_4g
+@summary “通过SPI接口外挂4G模组(Air780EHM/Air780EHV/Air780EGH/Air780EPM)的4G网卡”驱动模块 
+@version 1.0
+@date    2025.07.27
+@author  朱天华
+@usage
+本文件为 “通过SPI接口外挂4G模组(Air780EHM/Air780EHV/Air780EGH/Air780EPM)的4G网卡”驱动模块,核心业务逻辑为:
+1、初始化和外部4G网卡的配置(初始化AirLINK、配置桥接网络、配置SPI、静态配置IP地址/子网掩码/网关);
+2、4G网卡的连接状态发生变化时,在日志中进行打印;
+
+
+硬件环境使用以下两种环境中的一种即可:
+1、Air8101核心板+Air780EHM/Air780EHV/Air780EGH/Air780EPM核心板
+2、Air8101核心板+Air780EHM/Air780EHV/Air780EGH/Air780EPM开发板
+
+一、当使用第1种硬件环境时,Air8101核心板和Air780EHM/Air780EHV/Air780EGH/Air780EPM核心板的硬件接线方式为:
+
+1、Air8101核心板:
+- 核心板通过TYPE-C USB口供电(核心板背面的功耗测试开关拨到OFF一端);
+- 如果测试发现软件重启,并且日志中出现  poweron reason 0,表示供电不足,此时再通过直流稳压电源对核心板的VIN管脚进行5V供电;
+
+2、Air780EHM/Air780EHV/Air780EGH/Air780EPM核心板:
+- 核心板通过TYPE-C USB口供电(TYPE-C USB口旁边的ON/OFF拨动开关拨到ON一端);
+- 如果测试发现软件重启,并且日志中出现  poweron reason 0,表示供电不足,此时再通过直流稳压电源对核心板的5V管脚进行5V供电;
+
+3、
+| Air8101核心板 | Air780EHM/Air780EHV/Air780EGH/Air780EPM核心板  |
+| ------------ | ---------------------------------------------- |
+|     gnd      |                     GND                        |
+|  54/DISP     |                     83/SPI0CS                  |
+|  55/HSYN     |                     84/SPI0MISO                |
+|    57/DE     |                     85/SPI0MOSI                |
+|  28/DCLK     |                     86/SPI0CLK                 |
+|    43/R2     |                     19/GPIO22                  |
+|  75/GPIO28   |                     22/GPIO1                   |
+
+二、当使用第2种硬件环境时,Air8101核心板和Air780EHM/Air780EHV/Air780EGH/Air780EPM开发板的硬件接线方式为:
+
+1、Air8101核心板:
+- 核心板通过TYPE-C USB口供电(核心板背面的功耗测试开关拨到OFF一端);
+- 如果测试发现软件重启,并且日志中出现  poweron reason 0,表示供电不足,此时再通过直流稳压电源对核心板的VIN管脚进行5V供电;
+
+2、Air780EHM/Air780EHV/Air780EGH/Air780EPM开发板:
+- 核心板通过TYPE-C USB口供电(外部供电/USB供电拨动开关拨到USB供电一端);
+- 如果测试发现软件重启,并且日志中出现  poweron reason 0,表示供电不足,此时再通过直流稳压电源对开发板的4V管脚进行4V供电;
+
+3、
+| Air8101核心板 | Air780EHM/Air780EHV/Air780EGH/Air780EPM开发板  |
+| ------------ | ---------------------------------------------- |
+|     gnd      |                     GND                        |
+|  54/DISP     |                     SPI_CS                     |
+|  55/HSYN     |                     SPI_MISO                   |
+|    57/DE     |                     SPI_MOSI                   |
+|  28/DCLK     |                     SPI_CLK                    |
+|    43/R2     |                     GPIO22                     |
+|  75/GPIO28   |                     GPIO1                      |
+
+三、以上两种硬件环境,Air8101使用的SPI0默认的一组引脚,也可以使用SPI1;使用SPI1时,硬件连接说明的更多资料参考:
+https://docs.openluat.com/air8101/luatos/hardware/design/4gnet/
+软件代码需要做以下配置:
+airlink.config(airlink.CONF_SPI_ID, 1)
+airlink.config(airlink.CONF_SPI_CS, 10)
+
+四、测试本功能模块时,Air780EHM/Air780EHV/Air780EGH/Air780EPM需要烧录以下软件:
+1、最新版本的内核固件
+2、脚本:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8101/demo/multi_network/WIFI_4G_ETH/Air8101_Air780EPM/Air780EPM_master
+
+本文件没有对外接口,直接在其他功能模块中require "netdrv_4g"就可以加载运行;
+]]
+
+local function ip_ready_func()
+    log.info("netdrv_4g.ip_ready_func", "IP_READY", socket.localIP(socket.LWIP_USER0))
+end
+
+local function ip_lose_func()
+    log.warn("netdrv_4g.ip_lose_func", "IP_LOSE")
+end
+
+
+
+--此处订阅"IP_READY"和"IP_LOSE"两种消息
+--在消息的处理函数中,仅仅打印了一些信息,便于实时观察“通过SPI接口外挂4G模组(Air780EHM/Air780EHV/Air780EGH/Air780EPM)的4G网卡”的连接状态
+--也可以根据自己的项目需求,在消息处理函数中增加自己的业务逻辑控制,例如可以在连网状态发生改变时更新网络图标
+sys.subscribe("IP_READY", ip_ready_func)
+sys.subscribe("IP_LOSE", ip_lose_func)
+
+
+-- 设置默认网卡为socket.LWIP_USER0
+socket.dft(socket.LWIP_USER0)
+
+
+-- 初始化airlink,Air8101和4G网卡之间,在spi之上,基于airlink协议通信
+airlink.init()
+-- 创建桥接网络设备
+-- 此处第一个参数必须是socket.LWIP_USER0,是因为Air780EHM/Air780EHV/Air780EGH/Air780EPM使用的也是socket.LWIP_USER0,双方是点对点通讯的对等网络
+-- 此处第二个参数必须是netdrv.WHALE,表示虚拟网卡的实现方式
+netdrv.setup(socket.LWIP_USER0, netdrv.WHALE)
+-- 启动airlink,配置Air8101作为SPI从机模式。
+airlink.start(airlink.MODE_SPI_SLAVE)
+
+-- 静态配置IPv4地址
+-- 本地ip地址为"192.168.111.1",网关ip地址为"192.168.111.2",子网掩码为"255.255.255.0"
+-- 此处设置的本地ip地址要和Air780EHM/Air780EHV/Air780EGH/Air780EPM中设置的网关ip地址完全一样
+-- 此处设置的网关ip地址要和Air780EHM/Air780EHV/Air780EGH/Air780EPM中设置的本地ip地址完全一样
+-- 此处设置的子网掩码要和Air780EHM/Air780EHV/Air780EGH/Air780EPM中设置的子网掩码完全一样
+netdrv.ipv4(socket.LWIP_USER0, "192.168.111.1", "255.255.255.0", "192.168.111.2")
+
+--4G联网成功后,内核固件会产生一个"IP_READY"消息
+--各个功能模块可以订阅"IP_READY"消息实时处理4G联网成功的事件
+--也可以在任何时刻调用socket.adapter(socket.LWIP_USER0)来获取4G网络是否连接成功
+
+--4G断网后,内核固件会产生一个"IP_LOSE"消息
+--各个功能模块可以订阅"IP_LOSE"消息实时处理4G网络断网的事件
+--也可以在任何时刻调用socket.adapter(socket.LWIP_USER0)来获取4G网络是否连接成功

+ 75 - 0
module/Air8101/demo/xmodem/netdrv/netdrv_eth_rmii.lua

@@ -0,0 +1,75 @@
+--[[
+@module  netdrv_eth_rmii
+@summary “通过MAC层的rmii接口外挂PHY芯片(LAN8720Ai)的以太网卡”驱动模块 
+@version 1.0
+@date    2025.07.24
+@author  朱天华
+@usage
+本文件为“通过MAC层的rmii接口外挂PHY芯片(LAN8720Ai)的以太网卡”驱动模块 ,核心业务逻辑为:
+1、打开PHY芯片供电开关;
+2、初始化以太网卡,并且在以太网卡上开启DHCP(动态主机配置协议);
+3、以太网卡的连接状态发生变化时,在日志中进行打印;
+
+Air8101核心板和AirPHY_1000配件板的硬件接线方式为:
+Air8101核心板通过TYPE-C USB口供电(核心板背面的功耗测试开关拨到OFF一端);
+如果测试发现软件重启,并且日志中出现  poweron reason 0,表示供电不足,此时再通过直流稳压电源对核心板的VIN管脚进行5V供电;
+| Air8101核心板 | AirPHY_1000配件板  |
+| ------------ | ------------------ |
+|    59/3V3    |         3.3v       |
+|     gnd      |         gnd        |
+|     5/D2     |         RX1        |
+|    72/D1     |         RX0        |
+|    71/D3     |         CRS        |
+|     4/D0     |         MDIO       |
+|     6/D4     |         TX0        |
+|    74/PCK    |         MDC        |
+|    70/D5     |         TX1        |
+|     7/D6     |         TXEN       |
+|     不接     |          NC        |
+|    69/D7     |         CLK        |
+
+本文件没有对外接口,直接在其他功能模块中require "netdrv_eth_rmii"就可以加载运行;
+]]
+
+local function ip_ready_func()
+    log.info("netdrv_eth_rmii.ip_ready_func", "IP_READY", socket.localIP(socket.LWIP_ETH))
+end
+
+local function ip_lose_func()
+    log.warn("netdrv_eth_rmii.ip_lose_func", "IP_LOSE")
+end
+
+
+
+--此处订阅"IP_READY"和"IP_LOSE"两种消息
+--在消息的处理函数中,仅仅打印了一些信息,便于实时观察“通过MAC层的rmii接口外挂PHY芯片(LAN8720Ai)的以太网卡”的连接状态
+--也可以根据自己的项目需求,在消息处理函数中增加自己的业务逻辑控制,例如可以在连网状态发生改变时更新网络图标
+sys.subscribe("IP_READY", ip_ready_func)
+sys.subscribe("IP_LOSE", ip_lose_func)
+
+
+-- 设置默认网卡为socket.LWIP_ETH
+socket.dft(socket.LWIP_ETH)
+
+
+--本demo测试使用的是核心板的VDD 3V3引脚对AirPHY_1000配件板进行供电
+--VDD 3V3引脚是Air8101内部的LDO输出引脚,最大输出电流300mA
+--GPIO13在Air8101内部使能控制这个LDO的输出
+--所以在此处GPIO13输出高电平打开这个LDO
+gpio.setup(13, 1, gpio.PULLUP) 
+
+
+
+--初始化以太网卡
+
+--以太网联网成功(成功连接路由器,并且获取到了IP地址)后,内核固件会产生一个"IP_READY"消息
+--各个功能模块可以订阅"IP_READY"消息实时处理以太网联网成功的事件
+--也可以在任何时刻调用socket.adapter(socket.LWIP_ETH)来获取以太网是否连接成功
+
+--以太网断网后,内核固件会产生一个"IP_LOSE"消息
+--各个功能模块可以订阅"IP_LOSE"消息实时处理以太网断网的事件
+--也可以在任何时刻调用socket.adapter(socket.LWIP_ETH)来获取以太网是否连接成功
+netdrv.setup(socket.LWIP_ETH)
+
+--在以太网卡上开启动态主机配置协议
+netdrv.dhcp(socket.LWIP_ETH, true)

+ 99 - 0
module/Air8101/demo/xmodem/netdrv/netdrv_eth_spi.lua

@@ -0,0 +1,99 @@
+--[[
+@module  netdrv_eth_spi
+@summary “通过SPI外挂CH390H芯片的以太网卡”驱动模块 
+@version 1.0
+@date    2025.07.24
+@author  朱天华
+@usage
+本文件为“通过SPI外挂CH390H芯片的以太网卡”驱动模块 ,核心业务逻辑为:
+1、打开AirETH_1000配件板供电开关;
+2、初始化spi0,初始化以太网卡,并且在以太网卡上开启DHCP(动态主机配置协议);
+3、以太网卡的连接状态发生变化时,在日志中进行打印;
+
+Air8101核心板和AirETH_1000配件板的硬件接线方式为:
+Air8101核心板通过TYPE-C USB口供电(核心板背面的功耗测试开关拨到OFF一端);
+如果测试发现软件重启,并且日志中出现  poweron reason 0,表示供电不足,此时再通过直流稳压电源对核心板的VIN管脚进行5V供电;
+| Air8101核心板   |  AirETH_1000配件板 |
+| --------------- | ----------------- |
+| 59/3V3          | 3.3v              |
+| gnd             | gnd               |
+| 28/DCLK         | SCK               |
+| 54/DISP         | CSS               |
+| 55/HSYN         | SDO               |
+| 57/DE           | SDI               |
+| 14/GPIO8        | INT               |
+
+本文件没有对外接口,直接在其他功能模块中require "netdrv_eth_spi"就可以加载运行;
+]]
+
+local function ip_ready_func()
+    log.info("netdrv_eth_spi.ip_ready_func", "IP_READY", socket.localIP(socket.LWIP_USER1))
+end
+
+local function ip_lose_func()
+    log.warn("netdrv_eth_spi.ip_lose_func", "IP_LOSE")
+end
+
+
+
+--此处订阅"IP_READY"和"IP_LOSE"两种消息
+--在消息的处理函数中,仅仅打印了一些信息,便于实时观察“通过SPI外挂CH390H芯片的以太网卡”的连接状态
+--也可以根据自己的项目需求,在消息处理函数中增加自己的业务逻辑控制,例如可以在连网状态发生改变时更新网络图标
+sys.subscribe("IP_READY", ip_ready_func)
+sys.subscribe("IP_LOSE", ip_lose_func)
+
+
+-- 设置默认网卡为socket.LWIP_USER1
+socket.dft(socket.LWIP_USER1)
+
+
+--本demo测试使用的是核心板的VDD 3V3引脚对AirETH_1000配件板进行供电
+--VDD 3V3引脚是Air8101内部的LDO输出引脚,最大输出电流300mA
+--GPIO13在Air8101内部使能控制这个LDO的输出
+--所以在此处GPIO13输出高电平打开这个LDO
+gpio.setup(13, 1, gpio.PULLUP) 
+
+
+--这个task的核心业务逻辑是:初始化SPI,初始化以太网卡,并在以太网卡上开启动态主机配置协议
+local function netdrv_eth_spi_task_func()
+    -- 初始化SPI0
+    local result = spi.setup(
+        0,--spi_id
+        nil,
+        0,--CPHA
+        0,--CPOL
+        8,--数据宽度
+        25600000--,--频率
+        -- spi.MSB,--高低位顺序    可选,默认高位在前
+        -- spi.master,--主模式     可选,默认主
+        -- spi.full--全双工       可选,默认全双工
+    )
+    log.info("netdrv_eth_spi", "spi open result", result)
+    --返回值为0,表示打开成功
+    if result ~= 0 then
+        log.error("netdrv_eth_spi", "spi open error",result)
+        return
+    end
+
+    --初始化以太网卡
+
+    --以太网联网成功(成功连接路由器,并且获取到了IP地址)后,内核固件会产生一个"IP_READY"消息
+    --各个功能模块可以订阅"IP_READY"消息实时处理以太网联网成功的事件
+    --也可以在任何时刻调用socket.adapter(socket.LWIP_USER1)来获取以太网是否连接成功
+
+    --以太网断网后,内核固件会产生一个"IP_LOSE"消息
+    --各个功能模块可以订阅"IP_LOSE"消息实时处理以太网断网的事件
+    --也可以在任何时刻调用socket.adapter(socket.LWIP_USER1)来获取以太网是否连接成功
+
+    -- socket.LWIP_USER1 指定网络适配器编号
+    -- netdrv.CH390外挂CH390
+    -- SPI ID 0, 片选 GPIO15
+    netdrv.setup(socket.LWIP_USER1, netdrv.CH390, {spi=0, cs=15})
+
+    --在以太上开启动态主机配置协议
+    netdrv.dhcp(socket.LWIP_USER1, true)
+end
+
+--创建并且启动一个task
+--task的处理函数为netdrv_eth_spi_task_func
+sys.taskInit(netdrv_eth_spi_task_func)

+ 147 - 0
module/Air8101/demo/xmodem/netdrv/netdrv_multiple.lua

@@ -0,0 +1,147 @@
+--[[
+@module  netdrv_multiple
+@summary 多网卡(WIFI STA网卡、通过MAC层的rmii接口外挂PHY芯片(LAN8720Ai)的以太网卡、通过SPI外挂CH390H芯片的以太网卡、通过SPI外挂4G模组的4G网卡)驱动模块 
+@version 1.0
+@date    2025.07.24
+@author  朱天华
+@usage
+本文件为多网卡驱动模块 ,核心业务逻辑为:
+1、调用exnetif.set_priority_order配置多网卡的控制参数以及优先级;
+
+
+通过MAC层的rmii接口外挂PHY芯片(LAN8720Ai)的以太网卡:
+Air8101核心板和AirPHY_1000配件板的硬件接线方式为:
+Air8101核心板通过TYPE-C USB口供电(核心板背面的功耗测试开关拨到OFF一端);
+如果测试发现软件重启,并且日志中出现  poweron reason 0,表示供电不足,此时再通过直流稳压电源对核心板的VIN管脚进行5V供电;
+| Air8101核心板 | AirPHY_1000配件板  |
+| ------------ | ------------------ |
+|    59/3V3    |         3.3v       |
+|     gnd      |         gnd        |
+|     5/D2     |         RX1        |
+|    72/D1     |         RX0        |
+|    71/D3     |         CRS        |
+|     4/D0     |         MDIO       |
+|     6/D4     |         TX0        |
+|    74/PCK    |         MDC        |
+|    70/D5     |         TX1        |
+|     7/D6     |         TXEN       |
+|     不接     |          NC        |
+|    69/D7     |         CLK        |
+
+
+通过SPI外挂CH390H芯片的以太网卡(此网卡和4G网卡硬件连接有冲突,如果使用以太网,可以优先使用rmii接口的以太网卡,如果必须使用spi以太网卡,注意更换以太网或者4G网卡使用的spi,不要冲突):
+Air8101核心板和AirETH_1000配件板的硬件接线方式为:
+Air8101核心板通过TYPE-C USB口供电(核心板背面的功耗测试开关拨到OFF一端);
+如果测试发现软件重启,并且日志中出现  poweron reason 0,表示供电不足,此时再通过直流稳压电源对核心板的VIN管脚进行5V供电;
+| Air8101核心板   |  AirETH_1000配件板 |
+| --------------- | ----------------- |
+| 59/3V3          | 3.3v              |
+| gnd             | gnd               |
+| 28/DCLK         | SCK               |
+| 54/DISP         | CSS               |
+| 55/HSYN         | SDO               |
+| 57/DE           | SDI               |
+| 14/GPIO8        | INT               |
+
+
+通过SPI接口外挂4G模组(Air780EHM/Air780EHV/Air780EGH/Air780EPM)的4G网卡:
+Air8101核心板和Air780EHM/Air780EHV/Air780EGH/Air780EPM核心板或者开发板的硬件接线方式,参考netdrv_4g.lua的文件头注释;
+
+
+
+本文件没有对外接口,直接在其他功能模块中require "netdrv_multiple"就可以加载运行;
+]]
+
+
+local exnetif = require "exnetif"
+
+-- 网卡状态变化通知回调函数
+-- 当exnetif中检测到网卡切换或者所有网卡都断网时,会触发调用此回调函数
+-- 当网卡切换切换时:
+--     net_type:string类型,表示当前使用的网卡字符串
+--     adapter:number类型,表示当前使用的网卡id
+-- 当所有网卡断网时:
+--     net_type:为nil
+--     adapter:number类型,为-1
+local function netdrv_multiple_notify_cbfunc(net_type,adapter)
+    if type(net_type)=="string" then
+        log.info("netdrv_multiple_notify_cbfunc", "use new adapter", net_type, adapter)
+    elseif type(net_type)=="nil" then
+        log.warn("netdrv_multiple_notify_cbfunc", "no available adapter", net_type, adapter)
+    else
+        log.warn("netdrv_multiple_notify_cbfunc", "unknown status", net_type, adapter)
+    end
+end
+
+
+
+local function netdrv_multiple_task_func()
+    --设置网卡优先级
+    exnetif.set_priority_order(
+        {
+            -- “通过MAC层的rmii接口外挂PHY芯片(LAN8720Ai)”的以太网卡,可以使用Air8101核心板+AirPHY_1000配件板验证
+            {
+                ETHERNET = {
+                    -- 供电使能GPIO,此demo使用的59脚3V3供电,受GPIO13控制
+                    pwrpin = 13,
+                    -- 设置的多个“已经IP READY,但是还没有ping通”网卡,循环执行ping动作的间隔(单位毫秒,可选)
+                    -- 如果没有传入此参数,exnetif会使用默认值10秒
+                    ping_time = 3000,
+
+                    -- 连通性检测ip(选填参数);
+                    -- 如果没有传入ip地址,exnetif中会默认使用httpdns能否成功获取baidu.com的ip作为是否连通的判断条件;
+                    -- 如果传入,一定要传入可靠的并且可以ping通的ip地址;
+                    -- ping_ip = "填入可靠的并且可以ping通的ip地址",                   
+                }
+            },
+
+            -- “通过SPI外挂CH390H芯片”的以太网卡,可以使用Air8101核心板+AirETH_1000配件板验证
+            -- {
+            --     ETHUSER1 = {
+            --         -- 供电使能GPIO,此demo使用的59脚3V3供电,受GPIO13控制
+            --         pwrpin = 13,
+            --         -- 设置的多个“已经IP READY,但是还没有ping通”网卡,循环执行ping动作的间隔(单位毫秒,可选)
+            --         -- 如果没有传入此参数,exnetif会使用默认值10秒
+            --         ping_time = 3000, 
+
+            --         -- 连通性检测ip(选填参数);
+            --         -- 如果没有传入ip地址,exnetif中会默认使用httpdns能否成功获取baidu.com的ip作为是否连通的判断条件;
+            --         -- 如果传入,一定要传入可靠的并且可以ping通的ip地址;
+            --         -- ping_ip = "填入可靠的并且可以ping通的ip地址",
+
+            --         -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
+            --         tp = netdrv.CH390, 
+            --         opts = {spi=0, cs=15}
+            --     }
+            -- },
+
+            -- WIFI STA网卡
+            {
+                WIFI = {
+                    -- 要连接的WIFI路由器名称
+                    ssid = "茶室-降功耗,找合宙!",
+                    -- 要连接的WIFI路由器密码
+                    password = "Air123456", 
+
+                    -- 连通性检测ip(选填参数);
+                    -- 如果没有传入ip地址,exnetif中会默认使用httpdns能否成功获取baidu.com的ip作为是否连通的判断条件;
+                    -- 如果传入,一定要传入可靠的并且可以ping通的ip地址;
+                    -- ping_ip = "填入可靠的并且可以ping通的ip地址",
+                }
+            }
+        }
+    )    
+end
+
+-- 设置网卡状态变化通知回调函数netdrv_multiple_notify_cbfunc
+exnetif.notify_status(netdrv_multiple_notify_cbfunc)
+
+-- 如果存在udp网络应用,并且udp网络应用中,根据应用层的心跳能够判断出来udp数据通信出现了异常;
+-- 可以在判断出现异常的位置,调用一次exnetif.check_network_status()接口,强制对当前正式使用的网卡进行一次连通性检测;
+-- 如果存在tcp网络应用,不需要用户调用exnetif.check_network_status()接口去控制,exnetif会在tcp网络应用通信异常时自动对当前使用的网卡进行连通性检测。
+
+
+-- 启动一个task,task的处理函数为netdrv_multiple_task_func
+-- 在处理函数中调用exnetif.set_priority_order设置网卡优先级
+-- 因为exnetif.set_priority_order要求必须在task中被调用,所以此处启动一个task
+sys.taskInit(netdrv_multiple_task_func)

+ 52 - 0
module/Air8101/demo/xmodem/netdrv/netdrv_wifi.lua

@@ -0,0 +1,52 @@
+--[[
+@module  netdrv_wifi
+@summary “WIFI STA网卡”驱动模块 
+@version 1.0
+@date    2025.07.01
+@author  朱天华
+@usage
+本文件为WIFI STA网卡驱动模块,核心业务逻辑为:
+1、初始化WIFI网络;
+2、连接WIFI路由器;
+3、和WIFI路由器之间的连接状态发生变化时,在日志中进行打印;
+
+本文件没有对外接口,直接在其他功能模块中require "netdrv_wifi"就可以加载运行;
+]]
+
+local function ip_ready_func()
+    log.info("netdrv_wifi.ip_ready_func", "IP_READY", json.encode(wlan.getInfo()))
+end
+
+local function ip_lose_func()
+    log.warn("netdrv_wifi.ip_lose_func", "IP_LOSE")
+end
+
+
+
+--此处订阅"IP_READY"和"IP_LOSE"两种消息
+--在消息的处理函数中,仅仅打印了一些信息,便于实时观察WIFI的连接状态
+--也可以根据自己的项目需求,在消息处理函数中增加自己的业务逻辑控制,例如可以在连网状态发生改变时更新网络图标
+sys.subscribe("IP_READY", ip_ready_func)
+sys.subscribe("IP_LOSE", ip_lose_func)
+
+
+-- 设置默认网卡为socket.LWIP_STA
+-- 在Air8101上,内核固件运行起来之后,默认网卡就是socket.LWIP_STA
+-- 在单socket.LWIP_STA网卡使用场景下,下面这一行代码加不加都没有影响,为了和其他网卡驱动模块的代码风格保持一致,所以加上了
+socket.dft(socket.LWIP_STA)
+
+
+wlan.init()
+--连接WIFI热点,连接结果会通过"IP_READY"或者"IP_LOSE"消息通知
+--Air8101仅支持2.4G的WIFI,不支持5G的WIFI
+--此处前两个参数表示WIFI热点名称以及密码,更换为自己测试时的真实参数即可
+--第三个参数1表示WIFI连接异常时,内核固件会自动重连
+wlan.connect("602", "gkfcish1314", 1)
+
+--WIFI联网成功(做为STATION成功连接AP,并且获取到了IP地址)后,内核固件会产生一个"IP_READY"消息
+--各个功能模块可以订阅"IP_READY"消息实时处理WIFI联网成功的事件
+--也可以在任何时刻调用socket.adapter(socket.LWIP_STA)来获取WIFI网络是否连接成功
+
+--WIFI断网后,内核固件会产生一个"IP_LOSE"消息
+--各个功能模块可以订阅"IP_LOSE"消息实时处理WIFI断网的事件
+--也可以在任何时刻调用socket.adapter(socket.LWIP_STA)来获取WIFI网络是否连接成功

+ 37 - 0
module/Air8101/demo/xmodem/netdrv_device.lua

@@ -0,0 +1,37 @@
+--[[
+@module  netdrv_device
+@summary 网络驱动设备功能模块 
+@version 1.0
+@date    2025.07.24
+@author  朱天华
+@usage
+本文件为网络驱动设备功能模块,核心业务逻辑为:根据项目需求,选择并且配置合适的网卡(网络适配器)
+1、netdrv_wifi:socket.LWIP_STA,WIFI STA网卡;
+2、netdrv_ethernet_rmii:socket.LWIP_ETH,通过MAC层的rmii接口外挂PHY芯片(LAN8720Ai)的以太网卡;
+3、netdrv_ethernet_spi:socket.LWIP_USER1,通过SPI外挂CH390H芯片的以太网卡;
+4、netdrv_4g:socket.LWIP_USER0,通过SPI外挂4G模组的4G网卡;
+5、netdrv_multi_network:可以配置多种网卡的优先级,按照优先级配置,使用其中一种网卡连接外网;
+
+根据自己的项目需求,只需要require以上五种中的一种即可;
+
+
+本文件没有对外接口,直接在main.lua中require "netdrv_device"就可以加载运行;
+]]
+
+
+-- 根据自己的项目需求,只需要require以下五种中的一种即可;
+
+-- 加载“WIFI STA网卡”驱动模块
+require "netdrv_wifi"
+
+-- 加载“通过MAC层的rmii接口外挂PHY芯片(LAN8720Ai)的以太网卡”驱动模块
+-- require "netdrv_eth_rmii"
+
+-- 加载“通过SPI外挂CH390H芯片的以太网卡”驱动模块
+-- require "netdrv_eth_spi"
+
+-- 加载“通过SPI外挂4G模组的4G网卡”驱动模块
+-- require "netdrv_4g"
+
+-- 加载“可以配置优先级的多种网卡”驱动模块
+-- require "netdrv_multiple"

+ 86 - 0
module/Air8101/demo/xmodem/readme.md

@@ -0,0 +1,86 @@
+
+## 演示功能概述
+本demo演示的核心功能为:
+使用Air8101核心板的UART1连接PC端的串口工具,通过xmodem协议接收文件。
+
+## 演示硬件环境
+
+1、Air8101核心板一块
+
+2、TYPE-C USB数据线一根
+
+3、USB转串口线数据线一根
+
+4、Air8101核心板和数据线的硬件接线方式为
+
+- Air8101核心板通过TYPE-C USB口供电;(核心板背面的功耗测试开关拨到OFF一端)
+
+- 如果测试发现软件频繁重启,重启原因值为:poweron reason 0,可能是供电不足,此时再通过直流稳压电源对核心板的vbat管脚进行4V供电,或者VIN管脚进行5V供电;
+
+- TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+- USB转串口数据线,一般来说,白线连接核心板的12/U1TX,绿线连接核心板的11/U1RX,黑线连接核心板的gnd,另外一端连接电脑USB口;
+
+| Air8101核心板 | USB转串口数据线 |
+| -------------- | -------------- |
+| U1TX           | UART_RX        |
+| U1RX           | UART_TX        |
+| GND            | GND            |
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air8101最新版本固件](https://docs.openluat.com/air8101/luatos/firmware/)
+
+3、PC端的串口工具,例如SSCOM、LLCOM等都可以;
+
+
+## 演示核心步骤
+
+1、搭建好演示硬件环境
+
+2、不需要修改demo脚本代码
+
+3、Luatools烧录内核固件和demo脚本代码
+
+4、烧录成功后,自动开机运行
+
+5、打开串口工具,连接上Air8101 UATR1端口,Air8101等待接收到工具发送过来的字符'C',然后8101开始发送数据,工具端接收到数据返回0x06,0x06为xmodem协议的ack值表示正确接收,然后模块返回0x04,0x04为xmodem协议的​EOT​值,表示传输结束,然后对端发送0x06表示确认结束,Luatools的运行日志输出:
+
+发送脚本区的文件,日志内容如下:
+``` lua
+[2025-10-27 16:06:33.386] luat:U(11530):I/user.xmodem uart读取到数据: 43 2
+[2025-10-27 16:06:33.386] luat:U(11531):I/user.xmodem 发送第 1 包
+[2025-10-27 16:06:38.133] luat:U(16281):I/user.xmodem uart读取到数据: 06 2
+[2025-10-27 16:06:38.149] luat:U(16282):I/user.xmodem 文件到头了
+[2025-10-27 16:06:38.149] luat:U(16282):I/user.Xmodem start
+[2025-10-27 16:06:38.149] luat:U(16282):I/user.Xmodem send result true
+[2025-10-27 16:06:38.149] luat:U(16283):I/user.Xmodem send success
+
+
+```
+
+HTTP下载到文件系统区的,再通过xmodem协议发送日志如下:
+``` lua
+[2025-10-27 15:57:19.006] luat:U(6415):I/user.netdrv_wifi.ip_ready_func IP_READY {"gw":"192.168.2.1","rssi":-23,"bssid":"34CA81D40F19"}
+[2025-10-27 15:57:19.006] luat:D(6417):DNS:airtest.openluat.com state 0 id 1 ipv6 0 use dns server0, try 0
+[2025-10-27 15:57:19.006] luat:D(6417):net:adatper 2 dns server 192.168.2.1
+[2025-10-27 15:57:19.006] luat:D(6417):net:dns udp sendto 192.168.2.1:53 from 192.168.2.20
+[2025-10-27 15:57:19.006] luat:D(6419):wlan:event_module 2 event_id 0
+[2025-10-27 15:57:19.006] luat:I(6429):DNS:dns all done ,now stop
+[2025-10-27 15:57:19.006] luat:D(6429):net:connect 47.96.229.157:2900 TCP
+[2025-10-27 15:57:19.087] luat:U(6530):I/user.http success 200
+[2025-10-27 15:57:19.087] luat:U(6531):I/user.HTTP receive ok 29
+[2025-10-27 15:57:19.087] luat:U(6532):I/user.文件读取 路径:/send.bin 内容:AA BB CC DD 01 02 03 04 05 06
+[2025-10-27 15:57:23.387] luat:U(10839):I/user.xmodem uart读取到数据: 430D0A 6
+[2025-10-27 15:57:23.387] luat:U(10840):I/user.xmodem 发送第 1 包
+[2025-10-27 15:57:27.857] luat:U(15292):I/user.xmodem uart读取到数据: 06 2
+[2025-10-27 15:57:27.857] luat:U(15293):I/user.xmodem 文件到头了
+[2025-10-27 15:57:27.857] luat:U(15294):I/user.Xmodem start
+[2025-10-27 15:57:27.857] luat:U(15294):I/user.Xmodem send result true
+[2025-10-27 15:57:27.857] luat:U(15294):I/user.Xmodem send success
+
+
+
+```

+ 1 - 0
module/Air8101/demo/xmodem/send.bin

@@ -0,0 +1 @@
+AA BB CC DD 01 02 03 04 05 06

+ 93 - 0
module/Air8101/demo/xmodem/xmodem_demo.lua

@@ -0,0 +1,93 @@
+--[[
+@module  main
+@summary xmodem 发送文件应用功能模块 
+@version 1.0
+@date    2025.07.01
+@author  李源龙
+@usage
+本文件为Air8101核心板演示xmodem功能的代码示例,本文档主要提供了两种方案:
+1、把模块脚本区的文件利用xmodem协议通过uart发送到过去
+
+2、进行http下载文件,利用xmodem协议通过uart发送到过去
+]]
+
+--加载xmodem模块
+xmodem=require ("xmodem")
+
+--设置默认filepath为脚本区的send.bin文件
+local filepath="/luadb/send.bin"
+
+local taskName = "xmodem_run"
+
+
+local uart_id = 1    --串口号
+
+local baudrate = 115200  --波特率
+
+local file_path=filepath --文件路径
+
+local send_type=true  --true表示单次发送128字节,false表示单次发送1024字节
+
+local inform_data="wait C"    --发送前提示信息,告知对方要发送C字符来接收文件
+
+-- 处理未识别的消息
+local function xmodem_run_cb(msg)
+	log.info("xmodem_run_cb", msg[1], msg[2], msg[3], msg[4])
+end
+
+--http获取文件函数
+local  function http_recived_cb()
+    while not socket.adapter(socket.dft()) do
+        log.warn("httpplus_app_task_func", "wait IP_READY", socket.dft())
+        -- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"
+        -- 或者等待1秒超时退出阻塞等待状态;
+        -- 注意:此处的1000毫秒超时不要修改的更长;
+        -- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡
+        -- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配
+        -- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())
+        sys.waitUntil("IP_READY", 1000)
+    end
+    local path = "/send.bin"
+    -- 以下链接仅用于测试,禁止用于生产环境
+    local code, headers, body_size = http.request("GET", "http://airtest.openluat.com:2900/download/send.bin", nil, nil, {dst=path}).wait()
+    log.info("http", code==200 and "success" or "error", code)
+    if code==200 then
+       log.info("HTTP receive ok",body_size)
+       file = io.open(path, "rb")
+        if file then
+            content = file:read("*a")
+            log.info("文件读取", "路径:" .. path, "内容:" .. content)
+            file:close()
+        else
+            log.error("文件操作", "无法打开文件读取内容", "路径:" .. path)
+        end
+        file_path=path
+    end
+    
+end
+
+--  定义一个xmodem_run函数,用于用xmodem发送文件
+local function xmodem_run() 
+    --如果需要http下载文件,然后发送下载的文件,可以打开下面的http_recived_cb()函数
+    -- http_recived_cb()
+    
+    --启动xmodem发送
+    local result=xmodem.send(uart_id,baudrate,file_path,send_type)
+    --等待时间12秒,等待接收方发送C字符启动发送,发送结束后接收端发送ACK:0x06表示接收完成,文件全部传输完成之后模块发送EOT​:0x04表示传输结束,接收端返回0x06表示确认结束
+    log.info("Xmodem", "start")
+
+    log.info("Xmodem", "send result", result)
+    --判断是否传输成功,传输是否成功,都需要关闭xmodem
+    if result then
+        log.info("Xmodem", "send success")
+        xmodem.close(uart_id)
+    else
+        log.info("Xmodem", "send failed")
+        xmodem.close(uart_id)
+    end
+
+end
+
+--创建并且启动一个task
+--运行这个task的主函数xmodem_run
+sys.taskInit(xmodem_run, taskName,xmodem_run_cb)