IAP固件升级分几步?(Qt上位机、)

前言

这周一直想做一个IAP固件升级的上位机,然后把升级流程全都搞懂

有纰漏请指出,转载请说明。

学习交流请发邮件 1280253714@qq.com

IAP原理

IAP的原理我就不多赘述了,这里贴上几位大佬的文章

STM32CubeIDE IAP原理讲解,及UART双APP交替升级IAP实现-CSDN博客

STM32 IAP升级固件 + 上位机 例程 | 码农家园

IAR环境下STM32+IAP方案的实现

之前做过IAP,也讲解了一些存在的问题,参考之前我写的博客

单片机IAP升级的一些问题与经验_iap更新_TianYaKe-天涯客的博客-CSDN博客

Qt读取二进制文件

读取二进制文件,将内容放在binRawData里

void MainWindow::readFw()
{QFileDialog dlg(this);QString fileName = dlg.getOpenFileName(this, tr("Open"), "./", tr("Bin File(*.bin)"));if( fileName == "" ){return;}QFile file(fileName);QFileInfo fileInfo(fileName);fwFileLen = fileInfo.size();fwPackNum = fwFileLen/fwPackLength + 1;if(file.open(QIODevice::ReadOnly)){binRawData = file.readAll();ui->lineEdit_fwUpdateFile->setText(fileName);ui->textEdit_fwUpdateFile->append(binRawData.toHex());file.close();ui->pushButton_startFwUpdate->setEnabled(true);ui->pushButton_stopFwUpdate->setEnabled(false);}else{QMessageBox::warning(this, tr("Error"), tr("Fail to open file!"));}
}

将binRawData拆包,并调用串口发送

connect(fwUpdateTimer,&QTimer::timeout,[=](){if(fwUpdateState == 1){QByteArray fwSendBuff = binRawData.mid(fwPackIndex*fwPackLength+1,fwPackLength);fwPackIndex++;serialPort->write(fwSendBuff);if(fwPackIndex>fwPackNum){fwUpdateTimer->stop();fwUpdateState = 3;}}});

加上固件传输的协议

发送开始指令,发送固件包大小

void MainWindow::startFwUpdate()
{ui->pushButton_startFwUpdate->setEnabled(false);ui->pushButton_stopFwUpdate->setEnabled(true);fwUpdateState = fwStart;QByteArray startCmd;uchar startCmd1 = 0xAB;uchar startCmd2 = 0xf0;startCmd = loadTxMsg(startCmd1, startCmd2, &startCmd);serialPort->write(startCmd);delay_ms(1000);uchar cmd1 = 0xAB;uchar cmd2 = 0xf1;uchar uData[2];uint16_t u16FwPackNum = fwPackNum;*(uint16_t *)&uData[0] = *(uint16_t *)&u16FwPackNum;QByteArray  txFwData;txFwData.append(uData[0]);txFwData.append(uData[1]);txFwData = loadTxMsg(cmd1, cmd2, &txFwData);serialPort->write(txFwData);fwUpdateTimer->start(100);
}

通过定时器逐帧传输,传输结束后发送结束信号

connect(fwUpdateTimer,&QTimer::timeout,[=](){if(fwUpdateState == fwStart){QByteArray fwSendBuff = binRawData.mid(fwPackIndex*fwPackLength,fwPackLength);fwSendBuff.insert(0,fwSendBuff.length());QByteArray fwSendProtocolBuff = loadFwPackData(&fwSendBuff);serialPort->write(fwSendProtocolBuff);fwPackIndex++;QString fwDataString = ByteArrayToHexString(fwSendProtocolBuff).toLatin1();ui->textEdit_fwInfo->clear();ui->textEdit_fwInfo->setWordWrapMode(QTextOption::WordWrap);ui->textEdit_fwInfo->insertPlainText(QString("["));ui->textEdit_fwInfo->insertPlainText(QString::number(fwPackIndex));ui->textEdit_fwInfo->insertPlainText(QString("]  "));ui->textEdit_fwInfo->insertPlainText(fwDataString);if(fwPackIndex>=fwPackNum){fwUpdateState = fwComplete;fwUpdateTimer->stop();QByteArray stopCmd;uchar stopCmd1 = 0xAB;uchar stopCmd2 = 0xf3;stopCmd = loadTxMsg(stopCmd1, stopCmd2, &stopCmd);serialPort->write(stopCmd);}}});

STM32代码部分

iap.h

#ifndef __IAP_H
#define __IAP_H#include "includes.h"#define __APP_START_ADDR	0x08010000U
#define __APP_SIZE			0x10000Utypedef enum 
{IAP_START,IAP_TRANFER,IAP_COMPLETE,
} IAP_Status;typedef struct
{u8	u8Length;		// 当前接受到数据帧的帧长u8	u8Data[64];		// 当前接受到的数据
} RcvFrame_S;typedef struct 
{IAP_Status state;		// ipa升级当前状态RcvFrame_S stRcvFrame;	// 接受到的数据u16	u16FwFrameNum;		// 固件数据帧总量u16 u16FwFrameIndex;	// 固件数据帧偏移u32 u32WriteAddrIndex;	// 写地址偏移
} IAP_S;extern IAP_S stIap;
void IapRcvDataProc(u8 *MsgData);
typedef void (*Application)(void);
void JumpToApplication(void);
#endif //__IAP_H

iap.c

#include "includes.h"IAP_S stIap;void IapRcvDataProc(u8 *MsgData)
{u8 cmd = MsgData[3];u8 i = 0;switch(cmd){case 0xF1:EraseFwSpace(__APP_START_ADDR,__APP_SIZE/__FLASH_PAGE_SIZE);memcpy(&stIap.u16FwFrameNum, &MsgData[4], 2);break;case 0xF2:stIap.u16FwFrameIndex++;stIap.stRcvFrame.u8Length = MsgData[6];	memcpy(&stIap.stRcvFrame.u8Data, &MsgData[7], stIap.stRcvFrame.u8Length);for(i = 0; i < stIap.stRcvFrame.u8Length; i += 4)  //一次写入是4个字节{FlashWriteWord(__APP_START_ADDR+stIap.u32WriteAddrIndex, *(u32 *)&stIap.stRcvFrame.u8Data[i]);stIap.u32WriteAddrIndex += 4; //写入的地址加4}			break;case 0xF3:JumpToApplication();}}void JumpToApplication(void)
{	Application application;__set_FAULTMASK (1);application = (Application)(*(__IO u32*)(__APP_START_ADDR+4));__set_MSP(*(__IO u32*)(__APP_START_ADDR));SCB->VTOR = __APP_START_ADDR;application();	
}

视频演示

IAP固件升级(Qt上位机)最初版0923_哔哩哔哩_bilibili

IAP固件升级(Qt上位机)最初版0923

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/139645.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学会使用Git 和 GitHub

Git 和 GitHub 都是程序员每天都要用到的东西 —— 前者是目前最先进的 版本控制工具&#xff0c;拥有最多的用户&#xff0c;且管理着地球上最庞大的代码仓库&#xff1b;而后者是全球最大 同性交友 代码托管平台、开源社区。 在没有这两个工具时&#xff0c;编程可能是这样的…

驱动代码整理

一&#xff0c;控制LED灯控制实验 头文件 #ifndef __HEAD_H__ #define __HEAD_H__#define LED1_MODER 0X50006000 #define LED1_ODR 0X50006014 #define LED1_RCC 0X50000A28#endif 驱动 #include <linux/init.h> #include <linux/module.h> #include &l…

洛谷刷题入门篇:分支结构

今天又来了&#xff0c;刷题刷题&#xff0c;我爱刷题&#xff0c;题单链接如下&#xff1a; https://www.luogu.com.cn/training/101#problems 一、【深基1-2】小学数学 N 合一 题目如下&#xff1a;https://www.luogu.com.cn/problem/P2433 题目描述 问题 1 请输出 I lov…

【C语言】指针经典笔试题(上)

C语言的一大重头戏就是指针。 对于指针有一些认识&#xff1a; 1.指针是存放变量的地址&#xff0c;一般说的指针和指针变量是一个概念。 2.地址的单位是字节&#xff0c;大小在不同编译器环境下有所不同&#xff0c;32位机器是4个字节&#xff0c;64位机器是8个字节。 3.数组名…

C# ref 学习1

ref 关键字用在四种不同的上下文中&#xff1b; 1.在方法签名和方法调用中&#xff0c;按引用将参数传递给方法。 2.在方法签名中&#xff0c;按引用将值返回给调用方。 3.在成员正文中&#xff0c;指示引用返回值是否作为调用方欲修改的引用被存储在本地&#xff0c;或在一般…

大厂面试-16道面试题

1 java集合类有哪些&#xff1f; List是有序的Collection&#xff0c;使用此接口能够精确的控制每个元素的插入位置&#xff0c;用户能根据索引访问List中元素。常用的实现List的类有LinkedList&#xff0c;ArrayList&#xff0c;Vector&#xff0c;Stack。 ArrayList是容量…

C语言内存函数的使用、剖析及模拟实现

目录 一、内存拷贝函数——memcpy 1.函数声明&#xff1a; 注意&#xff1a; 2.函数使用用例&#xff1a; 3.memcpy函数的模拟实现&#xff1a; 二、内存拷贝函数2——memmove 1.函数声明&#xff1a; 2.memmove函数的模拟实现 三、内存比较函数——memcmp 1.函数声明…

卸载Visual Studio 2010学习版 —— 卸载VCExpress

目录 最初安装Visual Studio 2010学习版是因为计算机二级 C语言考试而装&#xff0c;现如今考完试后便可卸载掉了&#xff0c;安装简便而卸载却没有uninstall.exe文件。故本文提供卸载方式。 进入到程序目录&#xff0c;找到setup.exe文件&#xff0c;也可以在程序目录搜索set…

【lesson10】进程状态

文章目录 认识进程状态新建运行阻塞挂起 Linux具体的进程状态RSDtTXZ是什么为什么 认识进程状态 上面就是各种进程状态&#xff0c;上面都是理论进程状态理论进程状态放在哪个操作系统中都是正确的&#xff0c;但是具体的操作系统实现可能又会有所不同。 下面我们来理解进程状态…

springBoot对接多个mq并且实现延迟队列---未完待续

mq调用流程 创建消息转换器 package com.wd.config;import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.context.annotation.Bean; import o…

Vue的详细教程--Vue路由与nodejs

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Vue的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Vue路由是什么 二.使用Vue路由的步骤 1、…

小程序中如何划分会员级别以及不同级别不同积分累计、折扣、返佣、升级条件等

以下是一些关键步骤和注意事项&#xff0c;帮助商家在小程序中有效设置会员卡等级和相关规则。 1. 设定会员卡等级。在管理员后台->会员管理处&#xff0c;点击“等级...”。会出现级别设置界面。 可以创建会员卡等级&#xff0c;并为每个等级设定名称和对应的规则。一般会员…

MyBatis 日志模块

文章目录 前言LogLogFactory日志应用JDBC 日志BaseJdbcLoggerConnectionLogger应用实现 总结 前言 日志在我们开发过程中占据了一个非常重要的地位&#xff0c;是开发和运维管理之间的桥梁&#xff0c;在Java中的日志框架也非常多&#xff0c;Log4j、Log4j2、slf4j等&#xff…

创建表

MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 创建表 语法格式: create table 表名(列名1 数据类型,列名2 数据类型,... ,列名n, 数据类型 ); 练习:在czwbkl库中,创建一格test01表 跟大家说…

开发高性能知识付费平台:关键技术策略

引言 在构建知识付费平台时&#xff0c;高性能是确保用户满意度和平台成功的关键因素之一。本文将探讨一些关键的技术策略&#xff0c;帮助开发者打造高性能的知识付费平台。 1. 前端性能优化 使用CDN加速资源加载 使用内容分发网络&#xff08;CDN&#xff09;来托管和加…

Flask数据库之SQLAlchemy--介绍--链接数据库

目录 SQLAlchemy介绍 SQLAlchemy连接数据库 SQLAlchemy介绍 数据库是一个网站的基础&#xff01;&#xff01;&#xff01; 比如MySQL、MongoDB、SQLite、PostgreSQL等&#xff0c;这里我们以MySQL为例进行讲解。 SQLAlchemy是一个ORM框架 对象关系映射&#xff08;英语&…

第一个 Go 程序“hello,world“ 与 main 函数

第一个 Go 程序"hello&#xff0c;world" 与 main 函数 文章目录 第一个 Go 程序"hello&#xff0c;world" 与 main 函数一.创建“hello&#xff0c;world”示例程序二. “hello&#xff0c;world” 程序结构拆解三、main 函数四、Go 语言中程序是怎么编译…

Xpath使用

有如下网页&#xff1a; 需要选中“若出现" 操作如下&#xff1a; 打开Xpath Helper 选中"若出现",右击检查 复制对应的Xpath 在QUERY栏插入即可

[杂谈]-快速了解半波和全波整流

快速了解半波和全波整流 文章目录 快速了解半波和全波整流1、滤波2、半波整流器3、全波整流器4、常见问题 整流器是一种将交流信号转换为脉动直流信号以及将交流电转换为直流电的电子电路。 我们日常生活中几乎所有的电子项目都会用到它。 根据周期传导&#xff0c;本文我们介绍…

VisualBox QA

出现提示注册表错误&#xff0c;或者之前正常&#xff0c;重启VisualBox后&#xff0c;VM运行失败时&#xff0c;可通过正确卸载VisualBox&#xff0c;然后使用注册表清理软件(CCleaner)清理注册表后&#xff0c;重装VisualBox&#xff0c;即会正常。&#xff08;一般用这个能解…