소스 검색

add: 添加从uart读取数据进行fota的demo

https://gitee.com/openLuat/LuatOS/issues/I8B6HO
Wendal Chen 2 년 전
부모
커밋
049a0536bf
4개의 변경된 파일172개의 추가작업 그리고 1개의 파일을 삭제
  1. BIN
      demo/fota_uart/fota_uart.bin
  2. 135 0
      demo/fota_uart/main.lua
  3. 34 0
      demo/fota_uart/main.py
  4. 3 1
      luat/modules/luat_lib_fota.c

BIN
demo/fota_uart/fota_uart.bin


+ 135 - 0
demo/fota_uart/main.lua

@@ -0,0 +1,135 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "fotademo"
+VERSION = "1.0.0"
+
+--[[
+演示用uart进行固件升级
+
+本demo 适用于 Air780E/Air780EG/Air600E
+1. 需要 V1107及以上的固件
+2. 需要 LuaTools 2.1.89 及以上的升级文件生成
+
+目录内文件的说明
+1. main.lua 本文件, 是下载到模块的唯一文件
+2. fota_uart.bin 演示用的脚本升级文件,不需要下载到模块
+3. main.py 上位机发送升级包的程序, 不需要下载到模块
+
+fota_uart.bin 使用 LuaTools 的 "量产文件" 按钮进行生成, .bin后缀的就是脚本OTA文件
+
+用法:
+1. 先把脚本和固件烧录到模块里, 并确认开机
+2. 进入命令行程序, 执行 python main.py 升级
+3. 观察luatools的输出和main.py的输出
+4. 模块接收正确的升级数据后,会提示1秒后重启
+5. 本demo自带的脚本升级包,升级后是GPIO闪灯的demo
+
+注意: 本demo默认是走虚拟串口进行交互, 如需改成物理串口, 修改uart_id和main.py
+]]
+
+_G.sys = require "sys"
+
+-- 定义所需要的UART编号
+-- uart_id = 1    -- 物理UART1, 通常也是MAIN_UART
+uart_id = uart.VUART_0 -- 虚拟USB串口
+
+-- 循环打印当前版本, 从而直观表示是否升级成功
+-- sys.taskInit(function()
+--     while 1 do
+--         sys.wait(3000)
+--         log.info("fota", "version", VERSION)
+--     end
+-- end)
+
+-- 开始初始化uart
+uart_zbuff = zbuff.create(1024)
+uart.setup(uart_id, 115200)
+
+-- 几个状态变量, 调试用
+local uart_fota_state = 0
+local uart_rx_counter = 0
+local uart_fota_writed = 0
+uart.on(uart_id, "receive", function(id, len)
+    -- 防御缓冲区超标的情况
+    if uart_zbuff:used() > 8192 then
+        log.warn("fota", "uart_zbuff待处理的数据太多了,强制清空")
+        uart_zbuff:del()
+    end
+    while 1 do
+        local len = uart.rx(id, uart_zbuff)
+        if len <= 0 then
+            break
+        end
+        -- if #s > 0 then -- #s 是取字符串的长度
+        uart_rx_counter = uart_rx_counter + len
+        log.info("uart", "收到数据", len, "累计", uart_rx_counter)
+        if uart_fota_state == 0 then
+            sys.publish("UART_FOTA")
+        end
+    end
+end)
+
+sys.taskInit(function()
+    local fota_state = 0 -- 0还没开始, 1进行中
+    while 1 do
+        -- 等待升级数据到来
+        sys.waitUntil("UART_FOTA", 1000)
+        local used = uart_zbuff:used()
+        if used > 0 then
+            if fota_state == 0 then
+                -- 等待FOTA的状态
+                if used > 5 then
+                    local data = uart_zbuff:query()
+                    uart_zbuff:del()
+                    -- 如果接受到 #FOTA\n 代表数据要来了
+                    if data:startsWith("#FOTA") and data:endsWith("\n") then
+                        fota_state = 1
+                        log.info("fota", "检测到fota起始标记,进入FOTA状态", data)
+                        fota.init()
+                        -- 固件数据发送端应该在收到#FOTA RDY\n之后才开始发送数据
+                        uart.write(uart_id, "#FOTA RDY\n")
+                    end
+                end
+            else
+                uart_fota_writed = uart_fota_writed + used
+                log.info("准备写入fota包", used, "累计写入", uart_fota_writed)
+                local result, isDone, cache = fota.run(uart_zbuff)
+                log.debug("fota.run", result, isDone, cache)
+                uart_zbuff:del() -- 清空缓冲区
+                if not result then
+                    fota_state = 0
+                    fota.isDone()
+                    uart.write(uart_id, "#FOTA ERR\n")
+                    log.info("fota", "出错了", result, isDone, cache)
+                elseif isDone then
+                    while true do
+                        sys.wait(100)
+                        local succ, fotaDone = fota.isDone()
+                        if not succ then
+                            fota_state = 0
+                            uart.write(uart_id, "#FOTA ERR\n")
+                            log.info("fota", "出错了")
+                            break
+                        end
+                        if fotaDone then
+                            uart_fota_state = 1
+                            log.info("fota", "已完成,1s后重启")
+                            -- 反馈给上位机
+                            uart.write(uart_id, "#FOTA OK\n")
+                            sys.wait(1000)
+                            rtos.reboot()
+                        end
+                        sys.wait(100)
+                    end
+                else
+                    log.info("fota", "单包写入完成", used, "等待下一个包")
+                    uart.write(uart_id, "#FOTA NEXT\n")
+                end
+            end
+        end
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 34 - 0
demo/fota_uart/main.py

@@ -0,0 +1,34 @@
+#!/usr/bin/python3
+# -*- coding: UTF-8 -*-
+
+import os, sys, serial.tools.list_ports, time
+
+
+for item in serial.tools.list_ports.comports():
+    if not item.pid or not item.location :
+        continue
+    if item.vid == 0x19d1 and item.pid == 0x0001 and "x.6" in item.location :
+        print(dir(item))
+        print(item.name)
+        with serial.Serial(item.name, 115200, timeout=1) as ser:
+            while 1:
+                ser.write(b"#FOTA\n")
+                data = ser.read(128)
+                if data and data.startswith(b"#FOTA") :
+                    print("设备响应", data)
+                    with open("fota_uart.bin", "rb") as f :
+                        while 1 :
+                            fdata = f.read(256)
+                            if not fdata :
+                                print("发送完毕,退出")
+                                sys.exit(0)
+                            print("发送升级包数据", len(fdata))
+                            ser.write(fdata)
+                            data = ser.read(128)
+                            if data :
+                                print("设备响应", data)
+                else :
+                    print("设备没响应", data)
+                break
+
+

+ 3 - 1
luat/modules/luat_lib_fota.c

@@ -110,12 +110,14 @@ static int l_fota_wait(lua_State* L)
 /**
 写入fota数据
 @api fota.run(buff)
-@zbuff/string fota数据,尽量用zbuff,如果传入的是zbuff,写入成功后,自动清空zbuff内的数据
+@zbuff/string fota数据,尽量用zbuff
 @return boolean 有异常返回false,无异常返回true
 @return boolean 接收到最后一块返回true
 @return int 还未写入的数据量,超过64K必须做等待
 @usage
 local result, isDone, cache = fota.run(buf) -- 写入fota流程
+
+-- 提示: ,如果传入的是zbuff,写入成功后,请自行清空zbuff内的数据
 */
 static int l_fota_write(lua_State* L)
 {