您的位置:首页   >  关于我们  >  新闻动态

大彩串口屏M系列OTA升级

发布人:大彩科技发布日期:2021-01-12

串口升级ota.bin演示(升级后,屏幕显示彩色圆圈)


一、适用范围


本文档适合大彩医用级的串口屏产品使用。




二、开发环境版本


1. VisualTFT软件版本:V3.0.1.1137及以上的版本。

版本查看:

1) 打开VisualTFT软件启动页面如图2-1软件版本,右上角会显示的软件版本号;

图片

图2-1软件版本


2) 打开VisualTFT,在软件右下角可以查看软件版本图2-2软件版本,最新版本可登录http://www.gz-dc.com/进行下载。

图片

2-2软件版本


2. 串口屏硬件版本: M系列固件 >= V6.3.319.00。

版本查看:

1) 查看屏幕背面版本号贴纸;

2) VisualTFT与屏幕联机成功后,右下角显示的版本号。




、概述


本文介绍VisualTFT PC软件编译生成的‘ota.bin’工程文件,用户通过MCU用串口对屏幕升级的说明。相比之前的 对‘private’ 文件升级,区别如下所示:
文件数量:private’是一个文件夹,里面含有多个文件;‘ota.bin’是一个文件
升级协议:private’升级的协议是固定,可参考http://www.gz-dc.com/uploads/file/; ‘ota.bin’升级协议不限制,可自定义帧内容。

数据交互:private’指令交互由固件处理;‘ota.bin’由lua脚本处理。




、参考资料


1



《LUA 脚本API V1.4》可通过以下链接下载物联型开发包获取:

http:/www.gz-dc.com/index.php?s=/List/index/cid/19.html

2



《LUA基础学习》可通过以下链接下载物联型开发包获取:

http:/www.gz-dc.com/index.php?s=/List/index/cid/19.html

3



LUA脚本初学者可以通过下面链接进行学习。

http://www.runoob.com/lua/lua-arrays.html

4



AT指令,可以通过下面链接了解

http://www.openluat.com/




五、教程实现


本例程通过大彩协议自定义指令和用户主板通讯,指令格式为 EE B6 … FF FC FF FF,且将OTA升级部分代码封装成‘ota.lua’文件。若用户采用的是自由串口协议,可参考本例程的方法实现。







5.1 创建虚拟串口

在实现例程前需要作以下3个准备:

1. 硬件平台;

2. 软件平台;

3. UI素材。

该例程使用大彩物联型7寸串口屏DC80480M070_1111_0C为验证开发平台。如图5-1所示;

图片

5-1  M系列7寸串口屏

其他尺寸M型的串口屏均可借鉴此教程。

 

5.1.1 软件平台

使用大彩自主研发的上位机软件VisualTFT配置工程,登录http://www.gz-dc.com/下载。如图5-2所示;

图片

图5-2  下载软件







5.2 配置串口屏工程

工程配置主要介绍以下6点:

(1) OTA文件生成

(2) 画面配置

(3) LUA API介绍

(4) 串口升级OTA流程图

(5) LUA 串口升级源码

(6) LUA SD卡升级源码

 

5.2.1 OTA文件生成

在 VisualTFT软件菜单栏点击图片 ,将弹出【量产下载】弹窗界面,如图5-3所示:

图片

图5-3  量产下载

 

点击【OTA升级包…】,打包生产ota.bin文件,如图5-4所示

图片

图5-4  OTA文件生成

注意:

OTA文件可以指定或全部文件打包升级,相关下载项说明如下所示:


  • 图片资源:gif、iocn、图片等。增加、修改、删除图片 UI,应勾选此项。
  • 触碰配置:控件、lua、工程相设置参数。增加控件(非图片)、修改、删除等,应勾选该项。
  • 下载字库资源:增加、删除、修改字库样式或增加一个字体大小等,应勾选该项。
  • 下载音频文件:增加、删除、修改音频文件等,应该勾选此项。
  • 下载音频文件:增加、删除、修改视频文件等,应该勾选此项。
  • 下载音频文件:增加、删除、修改系统键盘等,应该勾选此项。


即用户修改对应下载项后,打包内容可选择为“指定文件”。

 

5.2.2 画面配置

本例程,只配置下载部分的画面及控件,在主页面(画面ID0)中,添加以下控件:


  • 控件ID88 :文本控件,显示下载信息。本例程中显示下载进度、解压进度。
  • 控件ID188:进度条控件,显示下载信息。本例程中显示下载进度、解压进度。


本例程中,屏幕初上电始化后,在LUA脚本设置文本控件、进度条控件隐藏。当用户单片机发送开始升级指令时,显示出控件ID88、ID188。如图5-5所示:

图片

图5-5  画面配置

 

5.2.3 LUA API介绍

本例程中,OTA升级相关API如下:

1. ota_init(md5, filesize, addr)

设置OTA写入参数


  • md5:字符串,固定为‘0123456789abcdef’
  • filesize:ota.bin文件的大小,单位:byte
  • addr:固定为0x800000(16进制)


如ota.bin文件大小为17542byte,则ota_init(‘0123456789abcdef’, 17542, 0x800000)。

 

2. ota_write(writeTb)

OTA写入,用户调用ota_write(writeTb),将writeTb数据写入到0x800000地址。


  • writeTb:写入字节数据,写入大小为2048 byte,不足2048byte补零。写入该地址的数据掉电后不清除。


 

3. ota_check_upgrade(state)

ota.bin文件校验、解压。当用户将ota.bin文件传输完毕后,调用ota_check_upgrade(state)对ota.bin进行先校验在解压,解压成功后即已经升级完成,屏幕自动重启。

  • state:1,进入升级状态。

 

4. ota_destroy()

清除OTA数据:对0x800000地址写入的数据清除。

 

5. on_ota_progress(status,value)

OTA校验、解压回调。当用户ota_check_upgrade(state)函数后,会自动回到该API。


  • status:状态。1-校验过程,2-校验结果,3-解压过程,4解压结果
  • value:处理结果。


当state = 1,value 固定为0
当state = 2,0-校验失败,1-校验成功
当state = 3,0-~100,解压进度
当state = 4,0-解压失败,1-解压成功

 

5.2.4 串口升级OTA流程图

M系列串口屏需要使用 ota.bin 文件进行升级,ota.bin 生成方式参考OTA文件生成章节。详细指令可参考附录A。升级流程如图5-6所示:

图片

图5-6  OTA流程


5.2.5 LUA 串口升级源码

1. 初始化加载

本例程中,采用大彩协议自定义指令实现(EE B6 … FF FC FF FF),且OTA实现已封装在‘ota.lua’中。用户需要在‘main.lua’处理以下关键点:


  • 全局变量:修改升级页面对应的画面ID


 注意:ota.lua文件里面也需要更改画面ID以及控件ID


  • 初始化:加载ota.lua文件
  • 初始化:初始化隐藏ota 升级的进度
  • 串口回调:判断是否是B6指令


 

代码如程序清单 1所示。

程序清单 1  main.lua初始化

--------------------------------------------------------------------------
-------------------------screen id define strat----------------------------
--------------------------------------------------------------------------
--screen id variant: define rule 'sc_' + name

sc_Lock = 0                   --升级画面的ID
--------------------------------------------------------------------------
--------------------------- screen id define end ---------------------------
--------------------------------------------------------------------------

function on_init()
    
    dofile('ota.lua')  --加载ota.lua文件
    my_assecc_ota(0)   --隐藏ota升级进度
end

function on_uart_recv_data(packet)
    
    collectgarbage("collect")
    local isOTA = packet[1]
    
    print('> funcode = '..string.format('%02X', packet[2])) 
    
    if isOTA == 0xB6
    then
        ota_operating(packet)  --ota处理流程
    end
end

▲下滑查看



2.开始下载

当屏幕接收到用户主板发送开始下载指令(EE B6 Len 88 11 baudrate filesize down_name FF FC FF FF),先判断文件大小和文件名称是否合法,在显示下载进度部分的控件→响应主板→OTA_INIT(先清除备份区,在初始化) →提升波特率。代码如程序清单 1所示。

程序清单 2  开始下载

--uart ota transmission operation
function ota_operating(packet)

    local datalen = (packet[2] << 8) | packet[3]
    local funcode = packet[4] 
    local cur_screen = get_current_screen()
    
    if funcode == ota_code
    then
        local child_code = packet[5]
        local down_name  = ''
            
        if child_code == _start_down
        then
            baudrate = uart_get_baudrate()
            
            local baudrateTemp = 115200
            
            baudrateTemp = (packet[6] << 24) | 
                              (packet[7] << 16) | 
                              (packet[8] <<  8) |
                              (packet[9] <<  0)

            filesize = (packet[10] << 24) | 
                         (packet[11] << 16) | 
                         (packet[12] <<  8) |
                         (packet[13] <<  0)
                    
            for i = 14, (#(packet) - 4)
            do
                down_name = down_name..string.char(packet[i])
            end
          
            if down_name == filename and filesize > 0
            then
                my_assecc_ota(1)
                down_state = 1
                change_screen(sc_Lock)
                
                my_uartsend_ota(child_code, ota_suc)
                
                if en_ota_SD == 1
                then
                    ......
                else
                    pre_sn         = -1
                    ota_cnt        = 0
                    ota_writeTb    = {}
                    ota_writeByte  = 0
                    TransferSize   = 0
                    set_value(sc_Lock,  88, 0)
                            set_text(sc_Lock,
                                       188,
                                       'Downloading : 0 %   
                                       [ '..math.ceil(TransferSize)..' byte / '..
                                        math.ceil(filesize)..' byte ]')
                    ota_destroy() 
                    ota_addr = ota_init('0123456789abcdef', filesize, 0x800000)
                end        
                uart_set_baudrate(baudrateTemp)
            else
                my_uartsend_ota(child_code, ota_nodown)
            end
        ......
        end
    end
end

▲下滑查看


3. 数据包

当屏幕接收到用户主板发送的数据指令(EE B6 Len 88 22 sn packet checksum FF FC FF FF),先判断数据包长度和大小、sn、校验码等是否合法。在传输累计2048字节后(传输4次,每次512字节)则调用ota_write(ota_writeTb)写到0x800000地址。若最后一次写入的数据累计后不足2048字节,屏幕自动补零写入。代码如程序清单 3所示。

程序清单 3  ota写入

--uart ota transmission operation
function ota_operating(packet)

    local datalen = (packet[2] << 8) | packet[3]
    local funcode = packet[4] 
    local cur_screen = get_current_screen()
    
    if funcode == ota_code
    then
    --EE B6 LEN(2BYTE) 88 11 FILESIZE(4byte) FILENAME FF FC FF FF
        local child_code = packet[5]
        local down_name  = ''

        if child_code == _start_down
        then
           ......
      
        elseif child_code == _dwoning
        then
        --EE B6 LEN(2BYTE) 88 22 01 00 00 11 11 check_H check_L FF FC FF FF
            local sn = packet[6]
            if pre_sn == 255
            then
                pre_sn = -1
            end
            print(' > pre_sn = '..pre_sn..' / sn = '..sn)

            if pre_sn + 1 == sn
            then
                local packsize = #(packet) - 13 + 1
                if packsize > 0 and packsize <= otaUartPacketSize
                then
                    if ((packsize + 13) == (#(packet) + 1)) and 
                        (((#(packet) + 1) - 13) > 0)
                    then
                        local isCheckTure = my_checkSum(packet)
                        if isCheckTure == 1
                        then
                            TransferSize = packsize + TransferSize
                            local prg = string.format ('%.1f', ((TransferSize *
                                          100) / filesize))
                            set_value(sc_Lock,  88, math.ceil((TransferSize *
                                          1000) / filesize))
                            set_text(sc_Lock, 188, 'Downloading : '..prg..' %
   [ '..math.ceil(TransferSize)..' byte / '..math.ceil(filesize)..' byte ]')
                            
                            for i = 7, (#(packet) - 6)
                            do
                                ota_writeTb[ota_writeByte] = packet[i]
                                ota_writeByte = ota_writeByte + 1
                            end
                            
                            if #(ota_writeTb) >= 0
                            then 
                            
                                local isOtaWrite = 0
                                
                                ota_cnt = ota_cnt + 1
                                if ota_cnt == 4 
                                then
                                    isOtaWrite = 1
                                    
                                elseif ota_cnt < 4 and TransferSize == filesize
                                then
                                    isOtaWrite = 1
                                end
                                
                                if isOtaWrite == 1
                                then
                                    
                                    if #(ota_writeTb) <= 2047
                                    then
                                        for i = (#(ota_writeTb) + 1), 2047
                                        do
                                            ota_writeTb[ota_writeByte] = 0x00
                                            ota_writeByte = ota_writeByte + 1
                                        end
                                    end
                                    ......
                                    local _write =  ota_write(ota_writeTb)
                                    
                                    ota_cnt = 0
                                    ota_writeByte = 0 
                                    ota_writeTb   = {}
                                end
                                
                                pre_sn = sn
                                my_uartsend_ota(child_code, ota_suc, pre_sn)
                            end   
                        end
                    else
                        --check sum error
                        my_uartsend_ota(child_code, 
                                           ota_packet_checkfail, (pre_sn + 1))
                    end
                else
                    --size > 512byte error
                    print(' > packet size > '..otaUartPacketSize..' ERROR !')
                end
            else
                --sn error
                my_uartsend_ota(child_code, ota_snfail, (pre_sn + 1))
            end     
            ......
        end
    end
end

▲下滑查看



4. 下载完成

当屏幕接收到用户主板确认升级的指令(EE B6 Len 88 33 01 FF FC FF FF),则调用ota_check_upgrade(1)开始进入校验解压过程。代码如程序清单 4所示。

程序清单 4  开始升级

--uart ota transmission operation
function ota_operating(packet)

    local datalen = (packet[2] << 8) | packet[3]
    local funcode = packet[4] 
    local cur_screen = get_current_screen()
    
    if funcode == ota_code
    then
        --EE B6 LEN(2BYTE) 88 11 FILESIZE(4byte) FILENAME FF FC FF FF
        local child_code = packet[5]
        local down_name  = ''
        
        if child_code == _start_down
        then
            ......

        elseif child_code == _dwoning
        then
            ......
        elseif child_code == _end_down and down_state == 1
        then
            local isUpdata = packet[6]
            if isUpdata == 0x01
            then
                my_uartsend_ota(child_code, ota_suc)
                
                ......
                ota_check_upgrade(1) 
                
            end
        ......
        end
    end
end

▲下滑查看


5. 校验解压


当屏幕进入升级过程,会自动调用on_ota_progress(status,value)进入校验、解压过程,校验中→校验结果→解压中→解压结果→恢复波特率→重启,代码程序清单 5所示。

程序清单 5  校验解压

function on_ota_progress(status,value)
    
    --Checking
    if status == 1 and value == 0
    then
        set_value(sc_Lock, 88, value)
        set_text(sc_Lock, 188, '')
        refresh_screen()
    
    --Check result
    elseif status == 2
    then
        my_uartsend_ota(_file_check, value)
    
    --Unpacking
    elseif status == 3
    then
        set_value(sc_Lock, 88, value*10)
        set_text(sc_Lock, 188, 'flash_updatesects : '..value..' %')
        refresh_screen()
        
    --Unpacking result    
    elseif status == 4
    then
        
        my_uartsend_ota(_unzip, value)
        print('> baudrate = '..baudrate)
        uart_set_baudrate(baudrate)    
        delay_ms(100)
    end
end

▲下滑查看


5.2.6 LUA SD升级源码

本例程中,用户还可以将ota.bin文件放在SD卡中进行升级,本例程中已将sd升级功能封装在‘ota.lua’中,用户只需要在sd插入回调函数里调用my_sd_updata

OTA()即可。代码程序清单 5所示。

程序清单 6  SD卡升级源码

--main.lua
function on_sd_inserted(dir)
    my_sd_updataOTA()
end


--ota.lua
--sd update ota 
function my_sd_updataOTA()
    
    local finish = 0
    
    if file_open(sd_path, 1) == true 
    then
        size = file_size()
        ota_destroy()
        
        local sdota_addr = ota_init('0123456789abcdef', size, 0x800000)

        --ota resume
        if sdota_addr > 0 
        then
            file_seek(sdota_addr)
        end
        
        while(true) 
        do
            local rddata = file_read(2048)
            if #(rddata) < 2047
            then
                for i = (#(rddata) + 1), 2047
                do
                    rddata[i] = 0x00

                end
                finish=1
            end

            ota_write(rddata)      
            print('> finish = '..finish)
            if finish == 1 then
                break
            end
        end

        file_close()
        my_assecc_ota(1)
        ota_check_upgrade(1)
    end
end

▲下滑查看





附录A


MCU 发送给屏幕的指令如下所示:

图片

 

屏幕应答或通知MCU屏幕的指令如下所示:

图片




附录B


DEMO下载链接:

http://www.gz-dc.com/uploads/file/20210111/M%20OTA.zip