如何通过SD卡和ymodem串口升级固件

描述

1.文件系统简介

1.1 DFS 简介

DFS( Device File System)是一种抽象的文件机制,RT-Thread中对文件系统的相关操作实际上都是通过操作DFS实现,也就是说DFS是对各种文件系统的抽象。DFS使的其他部分无须关心不同文件系统之间的差异,使得RT-Thread可以支持多种类型的文件系统。

1.2 DFS 框架

RT-Thread DFS 组件的主要功能特点有:

为应用程序提供统一的 POSIX 文件和目录操作接口:read、write、poll/select 等。

支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。

支持多种类型的存储设备,如 SD Card、SPI Flash、Nand Flash 等。

DFS 的层次架构如下图所示,主要分为 POSIX 接口层、虚拟文件系统层和设备抽象层。

SD卡

1.3 elm-FAT文件系统简介

FatFs 是一个通用的文件系统(FAT/exFAT)模块,用于在小型嵌入式系统中实现FAT文件系统。

1.4 使用流程

初始化 DFS 组件。

初始化具体类型的文件系统。

在存储器上创建块设备。

格式化块设备。

挂载块设备到 DFS 目录中。

当文件系统不再使用,可以将它卸载

1.5 注册elm-FAT文件系统

elm-FAT文件系统注册过程如下图所示:

SD卡

1.6 挂载elm-FAT文件系统

1void sd_mount(void *parameter) 2{ 3    while (1) 4    { 5        rt_thread_mdelay(500); 6        if(rt_device_find("sd0") != RT_NULL) 7        { 8            if (dfs_mount("sd0", "/fatfs", "elm", 0, 0) == RT_EOK) 9            { 10                LOG_I("sd card mount to '/fatfs'"); 11                break; 12            } 13            else 14            { 15                LOG_W("sd card mount to '/fatfs' failed!"); 16            } 17        } 18    } 19} 20 21int stm32_sdcard_mount(void) 22{ 23    rt_thread_t tid; 24 25    tid = rt_thread_create("sd_mount", sd_mount, RT_NULL, 26                           1024, RT_THREAD_PRIORITY_MAX - 2, 20); 27    if (tid != RT_NULL) 28    { 29        rt_thread_startup(tid); 30    } 31    else 32    { 33        LOG_E("create sd_mount thread err!"); 34    } 35    return RT_EOK; 36} 37INIT_APP_EXPORT(stm32_sdcard_mount);

在文件系统操作表中找出elm文件系统

检查"/fatfs"路径是否存在

检查elm文件系统是否已经挂载在文件系统表中

检查文件系统表是否有空余,如果有,把空余地址指向elm文件系统

注册文件系统

调用elm文件系统的挂载接口

1.7 测试elm-FAT文件系统

在根目录下使用ls命令,可以查看目录:

SD卡

2.设计界面

使用TouchGFX 4.14.0 Designer添加设置界面。增加进度条,和两个按钮,以及固件版本和更新时间的记录(记录环境变量使用的是easyflash软件包)。我这个界面设计的比较简陋,重在实现功能,审美好的人,欢迎重新设计这个界面。


依然利用TouchGFX的MVP架构,将UI命令传递到后台。
参考前边的文章:【DIY数字仪表】使用TouchGFX的MVP架构来实现GUI和硬件的双向交互(2)

3.添加sd卡或者spi flash拷贝到SDRAM的代码

1bool TouchGFXHAL::blockCopy(void* RESTRICT dest, const void* RESTRICT src, uint32_t numBytes) 2{ 3    uint32_t dataOffset = (uint32_t)src; 4    if (dataOffset >= 0x90000000 && dataOffset < 0x92000000) 5    { 6        char *updata_pciture; 7 8        /* get the updata pciture location from Env */ 9        updata_pciture = ef_get_env("updata_pciture");   10 11        if(0 == strcmp(updata_pciture, "spi_flash")) 12        { 13            const struct fal_partition *part; 14            part = fal_partition_find("tgfx"); 15 16            dataOffset =  dataOffset - 0x90000000; 17            // for copying data from there. 18            if (part != RT_NULL) 19            { 20                fal_partition_read(part, dataOffset, (uint8_t *)dest, numBytes); 21            } 22            return true; 23        } 24        else 25        { 26            int fd; 27            struct statfs buffer; 28            if(rt_device_find("sd0") != RT_NULL) 29            { 30                if ((dfs_statfs("/",&buffer) == RT_EOK)|(dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK)) 31                { 32                    fd = open("/ER_EROM1", O_RDONLY, 0);                         33                    if (fd < 0) 34                    { 35                        rt_kprintf("open file for read failed "); 36                        return false; 37                    } 38                    dataOffset =  dataOffset - 0x90000000; 39                    lseek(fd, dataOffset, SEEK_SET); 40                    // for copying data from there. 41                    read(fd, (uint8_t *)dest, numBytes); 42                    close(fd); 43                } 44                return true;     45            } 46            else 47            { 48                return false; 49            } 50        } 51    }    52    else 53    { 54        // For all other addresses, just use the default implementation. 55        // This is important, as blockCopy is also used for other things in the core framework. 56        return HAL::blockCopy(dest, src, numBytes); 57    }    58}

此代码用来根据设置的环境变量选择从sd卡还是spi flash拷贝图片。

4.添加msh命令

1#ifdef RT_USING_FINSH 2#include  3/* export to finsh */ 4FINSH_FUNCTION_EXPORT(ReadUpdataToSpiflash, Read data To Spiflash test); 5 6#ifdef FINSH_USING_MSH 7static void cmd_updata(int argc, char *argv[]) 8{ 9    char* filename; 10 11    if(argc == 2) 12    { 13        filename = argv[1]; 14    } 15    else 16    { 17        filename = DEFAULT_FILENAME; 18        recv_partition = DEFAULT_DOWNLOAD_PART; 19        LOG_I("Default save firmware on download partition. "); 20    } 21    ReadUpdataToSpiflash(filename); 22} 23FINSH_FUNCTION_EXPORT_ALIAS(cmd_updata, __cmd_updata, Read data To Spiflash test); 24#endif /* FINSH_USING_MSH */ 25#endif /* RT_USING_FINSH */

添加msh命令,使通过msh命令也能升级固件,将SD的图片资源拷贝到spi flash的功能

SD卡


updata命令默认将从sd卡中读取ER_IROM1.rbl固件,将固件下载到download分区。

SD卡


通过updata  /ER_EROM1命令,可以将sd中的图片资源拷贝到tgfx分区(spi flash中图片所在的位置)中

SD卡

5.生成bin文件

在keil中添加以下命令,然后便会在binary目录下,生成外部flash和内部flash的bin文件:

SD卡


利用rt_ota_packaging_tool工具,对内部flash烧录bin文件进行加密和压缩,然后将生成的ER_IROM1.rbl文件和ER_EROM1文件拷贝到SD卡中:

SD卡

6.制作BootLoader

参考以下文章:STM32通用Bootloader——FOTA
rt_fota集成了ymodem的协议,在没有app的情况下,也可以通过rt_fota的ymodem命令给固件和图片资源升级。
ymodem_ota命令,默认将固件下载到download分区:

SD卡


ymodem_ota -p tgfx命令,可以将sd中的图片资源拷贝到tgfx分区中:

SD卡

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分