IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 将STM32 内部Flash虚拟成优盘,进行IAP升级 -> 正文阅读

[嵌入式]将STM32 内部Flash虚拟成优盘,进行IAP升级

????????书接上回,上篇文章已经成功的将 STM32 内部FLASH虚拟成优盘进行文件存储了。

【将 STM32 内部Flash虚拟成优盘】icon-default.png?t=M85Bhttps://blog.csdn.net/qq_44810226/article/details/127508789

? ? ? ? 然后我们开始固件升级流程:

? ? ? ?

?从上图可以看出,固件存储的位置是不知道的,不确定的,但是一定在U盘存储的区域内。

????????我们可以通过给bin文件加上一些标志,来在Flash中判断是否有固件存在。如下图所示,给bin文件开头添加 固件名称、软件版本、硬件版本、起始地址、校验位、长度等数据。

?

因为FAT系统存储的特性,每个文件都会在扇区的开头存储,我们设置的扇区大小为0x200,所以我们可以在U盘开始的地址来遍历,搜索每个地址的前几个字符是否为我们想要固件的名称。

/*************************************************************
** Function name:       FindBinFileAddr
** Descriptions:        在指定地址查找是否有固件存在
** Input parameters:    None
** Output parameters:   None
** Returned value:      固件地址 或者 0(没有找到)
** Remarks:             None
*************************************************************/
uint32_t FindBinFileAddr(void){
	unsigned char tempBuff[14] = {0};
	for(uint16_t i=40;i<BLOCKNUM;i++){
  		memcpy(tempBuff, (char *)(MASS_STORAGE_CLASS_START_ADDR+(i*STORAGE_BLK_SIZ)), sizeof(tempBuff)-1);
		if (strcmp(tempBuff, BIN_START_FLAG) == 0){
			SEGGER_RTT_printf(0,"Find Fw StartName in[%x]	USB-Device Sector %d->   %s\r\n",(MASS_STORAGE_CLASS_START_ADDR+(i*STORAGE_BLK_SIZ)),i,tempBuff);
			return (MASS_STORAGE_CLASS_START_ADDR+(i*STORAGE_BLK_SIZ));
		} 
	}
	SEGGER_RTT_printf(0,"Not Find Fw !!!\r\n");
	return 0;
}

这里还可以先判断一下固件的其他描述参数,判断固件是否有效,也可以在后面判断。

找到固件之后就可以进行正常升级了。

找到合适的固件之后,判断固件是否有效:通过名称、CRC、版本号等

这里我将升级用到的参数都做到了一个 结构体中,方便后面写代码。PUpdateFw_Struct 是这个结构体的指针。


UPDATE_Frameware_INIT(gFWUpdate,0x08050600,0x08019000,50,STMFLASH_ReadByte,STMFLASH_Write,2048);

.c文件?

/*************************************************************
** Function name:       FWInit
** Descriptions:        固件升级 初始化
** Input parameters:    None
** Output parameters:   None
** Returned value:      None
** Remarks:             None
*************************************************************/
uint8_t FWUpdateInit(PUpdateFw_Struct fw){

    uint16_t checkCRC = 0;
    memcpy(fw->info_fwName,(uint8_t *)(fw->fwAddr),FW_NAME_LENGTH);
    memcpy(fw->info_fwVersion,(uint8_t *)(fw->fwAddr+FW_NAME_LENGTH),FW_VERSION_LENGTH);
    memcpy(&fw->info_fwLength,(uint32_t *)(fw->fwAddr+FW_NAME_LENGTH+FW_VERSION_LENGTH),4);
    memcpy(fw->info_boardVersion,(uint8_t *)(fw->fwAddr+FW_NAME_LENGTH+FW_VERSION_LENGTH+4),FW_VERSION_LENGTH);
    memcpy(&fw->info_crc,(uint8_t *)(fw->fwAddr+FW_NAME_LENGTH+2*FW_VERSION_LENGTH+4+4),sizeof(uint16_t));
    memcpy(fw->info_binEndFlag,(uint8_t *)(fw->fwAddr+48+fw->info_fwLength),BIN_END_FLAG_LENGTH);

    checkCRC = usMBCRC16((unsigned char *)(fw->fwAddr+48),fw->info_fwLength);

    if (strcmp(fw->info_fwName, BIN_START_FLAG) != 0){
        SEGGER_RTT_printf(0,"fw name is err ! not a effective firmware ... \r\n");
        return 0;
    }
    if (strcmp(fw->info_binEndFlag, BIN_END_FLAG) != 0){
        SEGGER_RTT_printf(0,"fw end name is err ! not a effective firmware ... \r\n");
        return 0;
    }
    if (checkCRC != fw->info_crc){
        SEGGER_RTT_printf(0,"crc check is err ! not a effective firmware ... \r\n");
        return 0;
    }

    SEGGER_RTT_printf(0,"   Firmware effective  : name-> %s  \r\n",fw->info_fwName);

    SEGGER_RTT_printf(0,"   Version-> %d.%d.%d.%d\r\n",fw->info_fwVersion[0],fw->info_fwVersion[2],fw->info_fwVersion[4],fw->info_fwVersion[6]);
    SEGGER_RTT_printf(0,"   FileLength-> %x\r\n",fw->info_fwLength);
    SEGGER_RTT_printf(0,"   BoardVersion-> %d.%d.%d.%d\r\n",fw->info_boardVersion[0],fw->info_boardVersion[2],fw->info_boardVersion[4],fw->info_boardVersion[6]);
    // crc 检测
    SEGGER_RTT_printf(0,"   FileCRC-> %x\r\n",fw->info_crc);
    SEGGER_RTT_printf(0,"   CheckCRC-> %x \r\n",checkCRC);

    SEGGER_RTT_printf(0,"   FileEndName-> [%p] %s\r\n",(uint8_t *)(fw->fwAddr+48+fw->info_fwLength),fw->info_binEndFlag);

    // 返回是否init成功 如果失败则代表不是一个正常的固件 不可以进行升级
    return 1;
}


void (*JumpToApplication)(void);
uint32_t gJumpAddress;
typedef  void (*pFunction)(void);

/*************************************************************
** Function name:       FWStartUpdate
** Descriptions:        开始升级
** Input parameters:    None
** Output parameters:   None
** Returned value:      None
** Remarks:             None
*************************************************************/
void FWStartUpdate(PUpdateFw_Struct fw){
    fw->WriteByte(fw->appAddr,(uint32_t *)(fw->fwAddr+48),fw->info_fwLength/8);
    SEGGER_RTT_printf(0,"Write FW ok \r\n");

    uint32_t erase[2] = {0};

    // 破坏APP2 固件存储的地址 
    fw->WriteByte(fw->fwAddr,erase,1);
    SEGGER_RTT_printf(0,"Eares app2 fw ok \r\n");
    // 破坏fat结构 上电重新初始化
    // fw->WriteByte(MASS_STORAGE_CLASS_START_ADDR,erase,1);

    // 跳转到APP
    /* Test if user code is programmed starting from address 0x0800C000 */
    // 检查栈顶是否合法,确保栈顶落在0x2000 0000 - 0x2001 0000 之间,刚好在stm32f1的RAM范围内
    if (((*(__IO uint32_t *)fw->appAddr) & 0x2FFE0000) == 0x20000000)
    {
        SEGGER_RTT_printf(0,"Check ok %x  %x  %x \r\n",fw->appAddr,(*(__IO uint32_t *)fw->appAddr),((*(__IO uint32_t *)fw->appAddr) & 0x2FFE0000));
    // 检查reset入口是否正确
    // if (((*(uint32_t*)(STM32_APP_BASE + 4)) & 0x0fff0000 ) == 0x08020000 ) 

      /* Jump to user application */
      gJumpAddress = *(__IO uint32_t *)(fw->appAddr + 4);
      JumpToApplication = (pFunction)gJumpAddress;

      /* Reset of all peripherals */
      HAL_DeInit();

      /* Set interrupt vector to app code */
      SCB->VTOR = fw->appAddr;

      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t *)fw->appAddr);
        __disable_irq();
      JumpToApplication();
    }else{
        SEGGER_RTT_printf(0,"Check err %x  %x  %x \r\n",fw->appAddr,(*(__IO uint32_t *)fw->appAddr),((*(__IO uint32_t *)fw->appAddr) & 0x2FFE0000));

    }

}

?.h文件

// 写入前先检查 是不是所有位置都可以写入:即是不是0xff  如果不是则擦除所在位置

struct SUpdateFw_Struct {
    // 固件存放地址
    uint32_t fwAddr;
    // 写入地址:APP1地址
    uint32_t appAddr;
    // APP1所在区块
    uint16_t appSector;

    // 读取函数
    uint8_t (*ReadOneByte)(uint32_t addr);
    // 写入函数
    void (*WriteByte)(uint32_t addr,uint32_t *data, uint32_t num);
    // Flash Sector 大小
    uint16_t sectorSize;

    // 固件Info
    char info_fwName[FW_NAME_LENGTH+1];
    // 固件版本信息
    char info_fwVersion[FW_VERSION_LENGTH+1];
    // 固件长度
    uint32_t info_fwLength;
    char info_boardVersion[FW_VERSION_LENGTH+1];
    // info中的起始地址
    uint32_t info_startAddr;
    // 固件Info
    uint16_t info_crc;
    char info_binEndFlag[BIN_END_FLAG_LENGTH+1];
};
typedef struct SUpdateFw_Struct UpdateFw_Struct;
typedef UpdateFw_Struct *PUpdateFw_Struct;

//                              固件存放地址、写入地址:APP1地址、 APP1所在区块、 读取函数、 写入函数、  Flash Sector 大小
#define UPDATE_Frameware_INIT(xname,xfwAddr,xappAddr,xappSector,xReadOneByte,xWriteByte,xsectorSize)     \
UpdateFw_Struct xname = {                                                 \
    .fwAddr = xfwAddr,                                  \
    .appAddr = xappAddr,                                \
    .appSector = xappSector,                            \
    .ReadOneByte = xReadOneByte,                        \
    .WriteByte = xWriteByte,                            \
    .sectorSize = xsectorSize,                          \
    .info_fwName = {0},                                 \
    .info_fwVersion = {0},                              \
    .info_fwLength = 0,                                 \
    .info_boardVersion = {0},                           \
    .info_startAddr = 0,                                \
    .info_crc = 0,                                      \
    .info_binEndFlag = {0},                             \
};

?

?这里程序参考意义不大,可能指针会有点难看。我将整个代码放在csdn中,需要的同学可以下载学习。

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:14:20  更:2022-10-31 12:17:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 13:18:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码