加入星計劃,您可以享受以下權益:

  • 創(chuàng)作內容快速變現
  • 行業(yè)影響力擴散
  • 作品版權保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關推薦
  • 電子產業(yè)圖譜
申請入駐 產業(yè)圖譜

RT-thread應用講解——通過U盤升級程序固件

04/03 13:11
3603
閱讀需 15 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

我前面介紹過RT-thread的一種OTA方案,可以通過串口或者網絡進行遠程升級,那今天在原來的這套方案的基礎上做一些修改,實現U盤升級。

相比于串口和網絡,U盤升級在某些方面有很大的優(yōu)勢,首先它不需要網絡,對于那些不具備上網功能的設備來說很方便,其次它不需要連接數據線,在距離上有優(yōu)勢,說到這,可能有人會說,u盤要插到設備上才能用,距離怎么就有優(yōu)勢了呢?

是的,U盤升級確實需要有人到設備這邊手動操作,但是因為U盤是很通用的設備,即使是非研發(fā)人員也可以操作,不需要燒錄器,也不需要安裝一些驅動和軟件,只需要找一個U盤把升級固件放進去,然后插到設備上升級即可。

比如有個客戶安裝了我們的設備,但是后來軟件要進行升級優(yōu)化,如果這個設備是支持U盤升級的那么我就可以把升級的固件發(fā)給客戶,讓他自己用一個U盤來升級設備,這樣一來,我們就不需要跑到現場去燒錄固件了。

好了,廢話不多說,馬上開整。

一、掛載U盤

使用U盤升級,第一步要先把U盤的讀寫調試好,關于U盤的使用,可以看下我之前的博客,有很詳細的介紹,這里就不多說了。

RT-thread應用講解——U盤(usb host)

二、使能OTA

要想遠程升級,那肯定先得有OTA的功能,關于OTA的使用我在前面的博客里面也詳細介紹過了,不知道的同學可以先去看下。

RT-thread應用講解——OTA

OTA部分只要要完成bootloader的制作和app的制作即可。這兩部分都調試好了之后就可以加入U盤升級的代碼。

三、U盤升級代碼

前面把U盤的掛載和OTA都調試好了之后就可以使用U盤來進行OTA了。

示例代碼如下:

#include <rtthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <finsh.h>
#include <fal.h>
#include <dfs_posix.h>

#define DBG_SECTION_NAME          "ota_usb"

#define DBG_LEVEL                 DBG_LOG

#define DBG_COLOR
#include <rtdbg.h>

/* 固件版本號 */
#define APP_VERSION               "1.0.0"

/* 固件名稱 */
#define USBH_UPDATE_FN            "/rtthread.rbl"

/* 固件下載分區(qū)名稱 */
#define DEFAULT_DOWNLOAD_PART     "download"

static char* recv_partition = DEFAULT_DOWNLOAD_PART;

rt_sem_t ota_sem = RT_NULL;

static void print_progress(size_t cur_size, size_t total_size)
{
    static unsigned char progress_sign[100 + 1];
    uint8_t i, per = cur_size * 100 / total_size;

    if (per > 100)
    {
        per = 100;
    }

    for (i = 0; i < 100; i++)
    {
        if (i < per)
        {
            progress_sign[i] = '=';
        }
        else if (per == i)
        {
            progress_sign[i] = '>';
        }
        else
        {
            progress_sign[i] = ' ';
        }
    }

    progress_sign[sizeof(progress_sign) - 1] = '?';

    LOG_I("?33[2A");
    LOG_I("Download: [%s] %d%%", progress_sign, per);
}

static int ota_usb_download_entry(void* parameter)
{
    DIR *dirp;
    static size_t update_file_total_size, update_file_cur_size;
    static const struct fal_partition * dl_part = RT_NULL;
    static int fd;
    static rt_uint8_t buf[1024];
    static rt_err_t result;
    struct stat file;

    rt_kprintf("The current version of APP firmware is %sn", APP_VERSION);	

    while(1)
    {
        result = rt_sem_take(ota_sem, RT_WAITING_FOREVER);
        if(result == RT_EOK)
        {
            rt_kprintf("Default save firmware on download partition.n");

            rt_kprintf("Warning: usb has started! This operator will not recovery.n");

            /* 查詢固件大小 */
            result = stat(USBH_UPDATE_FN, &file);
            if(result == RT_EOK)
            {
                LOG_D(""USBH_UPDATE_FN" file size is : %dn", file.st_size);
            }
            else
            {
                LOG_E(""USBH_UPDATE_FN" file not fonud.");
                goto __exit;
            }
            if(file.st_size <= 0)
            {
                LOG_E(""USBH_UPDATE_FN" file is empty.");
                goto __exit;
            }
                
            /* 獲取"download"分區(qū)信息并清除分區(qū)數據 */
            if ((dl_part = fal_partition_find(recv_partition)) == RT_NULL)
            {
                LOG_E("Firmware download failed! Partition (%s) find error!", recv_partition);
                goto __exit;
            }
            if (file.st_size > dl_part->len)
            {
                LOG_E("Firmware is too large! File size (%d), '%s' partition size (%d)", file.st_size, recv_partition, dl_part->len);
            }
            if (fal_partition_erase(dl_part, 0, file.st_size) < 0)
            {
                LOG_E("Firmware download failed! Partition (%s) erase error!", dl_part->name);
            }

            /* 以只讀模式打開固件 */
            fd = open(USBH_UPDATE_FN, O_RDONLY);
            if (fd >= 0)
            {
                do
                {
                    /* 讀取u盤的固件,一次讀1024字節(jié) */
                    update_file_cur_size = read(fd, buf, sizeof(buf));

                    /* 把固件寫入片外flash的download分區(qū)  */
                    if (fal_partition_write(dl_part, update_file_total_size, buf, update_file_cur_size) < 0)
                    {
                        LOG_E("Firmware download failed! Partition (%s) write data error!", dl_part->name);
                        close(fd);
                        goto __exit;
                    }

                    update_file_total_size += update_file_cur_size;

                    print_progress(update_file_total_size, file.st_size);
                } 
                while (update_file_total_size != file.st_size);
                
                close(fd);
            }
            else
            {
                LOG_E("check: open file for read failedn");
                goto __exit;
            }

            rt_kprintf("Download firmware to flash success.n");
            rt_kprintf("System now will restart...rn");

            /* wait some time for terminal response finish */
            rt_thread_delay(rt_tick_from_millisecond(200));

            /* Reset the device, Start new firmware */
            extern void rt_hw_cpu_reset(void);
            rt_hw_cpu_reset();
            /* wait some time for terminal response finish */
            rt_thread_delay(rt_tick_from_millisecond(200));

        __exit:
            LOG_E("download rtthread.rbl file failed");
        }
    }
}

void ota_usb_init(void)
{
    fal_init();

    ota_sem = rt_sem_create("otasem", 0, RT_IPC_FLAG_FIFO);
    
    rt_thread_t thread1 = rt_thread_create("ota_usb", ota_usb_download_entry, RT_NULL, 4096, 26, 10);
    if (thread1 != RT_NULL)
    {
        rt_thread_startup(thread1);
    }
}
INIT_APP_EXPORT(ota_usb_init);

static rt_uint8_t ota_usb_start(void)
{
    rt_sem_release(ota_sem);

    return RT_EOK;
}
MSH_CMD_EXPORT(ota_usb_start, OTA start);

四、運行測試

先做好一個要升級的固件(rtthread.rbl)放到U盤里,插入U盤之后,查看U盤是否有該文件。

在這里插入圖片描述

通過調用命令開始升級。

提示:用命令只是為了方便調試,實際使用可以通過實體按鍵或屏幕按鍵來觸發(fā)升級。

在這里插入圖片描述

至此,整個升級的流程就走完了。

五、結束語

好了,關于U盤升級的介紹就到這里,整個流程看著挺復雜,但是知道原理之后回頭再看,其實結構還是很清晰的,如果還有什么問題,歡迎在評論區(qū)留言。如果這篇文章能夠幫到你,就給我點個贊吧,如果想了解更多RT-thread和單片機的內容,可以關注一下博主,后續(xù)我還會繼續(xù)分享更多的經驗給大家。

教程相關源碼:https://download.csdn.net/download/ShenZhen_zixian/12880749

RT-thread相關教程匯總:https://blog.csdn.net/ShenZhen_zixian/article/details/120563891

推薦器件

更多器件
器件型號 數量 器件廠商 器件描述 數據手冊 ECAD模型 風險等級 參考價格 更多信息
TJA1055T/3/1J 1 NXP Semiconductors TJA1055 - Enhanced fault-tolerant CAN transceiver SOIC 14-Pin

ECAD模型

下載ECAD模型
$1.06 查看
LFSPXO019170REEL 1 IQD Frequency Products HCMOS Output Clock Oscillator, 25MHz Nom
$11.83 查看
HFBR-2528 1 Hewlett Packard Co Receiver, 5Mbps, DIP, Through Hole Mount
暫無數據 查看

相關推薦

電子產業(yè)圖譜