---
title: "STM32 W5500 Http OTA"
url: "https://maker.wiznet.io/tonywang_/projects/stm32-w5500-http-ota/"
markdown_url: "https://maker.wiznet.io/tonywang_/projects/stm32-w5500-http-ota/md"
type: "UCC: User Created Content"
author: "tonywang_"
author_url: "https://maker.wiznet.io/tonywang_/"
original_author: "杨奉武"
original_url: "https://www.cnblogs.com/yangfengwu/p/15906937.html"
published: "2022-10-03"
language: "zh"
likes: 11
views: 2223
comments: 3
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# STM32 W5500 Http OTA

> STM32通过W5500使用http远程下载升级单片机程序

Original author: 杨奉武 (source: https://www.cnblogs.com/yangfengwu/p/15906937.html)

## Article

## **说明**

## **这节测试一下STM32通过W5500使用http远程下载升级单片机程序**

## **为应对小容量单片机问题,升级底层包也支持把备份程序写到外部flash.**

## **打开BootLoader程序,说明下flash支持情况**

## **1,当前程序(V3.0.0)支持外接W25Q80/16/32/64/128,后续将根据用户需求增加更多的flash支持**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917135828315-895206059.png)

### **使用内部flash和外部flash分配情况如下:**

### **使用外部flash以后,备份用户程序区放到了外部flash, 使得用户程序有了更大的空间**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917195436828-431306270.png)

## **2,当前开发板未板载外部flash,测试外部flash需要用户自己外接flash**

### **MCU flash芯片**

### **PA4 -- CS**

### **PA5 -- CLK**

### **PA6 -- MISO (SO)**

### **PA7 -- MOSI (SI)**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917134759895-1358201646.png)

## **3,flash选择**

### ** 如果用户使用内部flash备份程序, 则把FLASH_EXTERN_BACKUP_ENABLE 设置为0**

### ** 如果用户使用外部flash备份程序, 则把FLASH_EXTERN_BACKUP_ENABLE 设置为1**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917140844177-1241518997.png)

## **测试**

## **我已经把固件文件放在了自己的服务器上**

## **默认使用本人提供的下载路径测试**

## **文件路径: 网站根目录->ota->hardware->STM32W5500BK**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217221106124-20766047.png)

## **user_crc.bin: 是固件程序文件.**

### **该固件程序文件并不是直接可以运行的文件**

### **里面的数据每隔128字节后面增加2位CRC校验位**

### **单片机下载以后每隔130字节校验一下数据,然后把前128字节写入Flash.**

### **加入CRC校验让升级变的稳定可靠.**

## **info.txt文件内容:**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217221149663-2025560393.png)

### **version:0.0.1 云端固件程序版本**

### ** url:http://mnif.cn/ota/hardware/STM32W5500BK/user_crc.bin 固件程序下载地址**

### **"info":"1.解决了部分BUG 2.优化了部分程序" 使用APP控制升级时,APP的提示信息.**

## **升级过程:**

## **用户程序里面每隔一定时间控制网络模块使用http的GET指令获取云端info.txt文件**

## **然后从文件里面获取服务器里面的固件程序版本和固件程序下载地址等信息**

## **如果与自身版本号对比不一致,就把固件程序下载地址写入flash,然后设置更新标志,重启,**

## **重启执行BootLoader以后,BootLoader程序检测到更新标志,则提取固件下载的地址,**

## **然后使用http下载程序文件,把程序文件写入flash,完成升级.**

## **备份升级流程图**

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912100542488-212053345.png)

## **测试**

## **1.使用网线连接路由器或者交换机**

![](https://img2022.cnblogs.com/blog/819239/202201/819239-20220121110408260-1076841797.png)

![](https://img2018.cnblogs.com/blog/819239/201908/819239-20190805054715733-1856936083.png)

## **2.打开串口调试助手打印串口日志**

![](https://img2020.cnblogs.com/blog/819239/202110/819239-20211025101219878-93763800.png)

## **3.使用下载器下载BootLoader程序**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217221456535-1384891182.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217221533075-2079805411.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217221639680-708505918.png)

## **8.下载用户程序到开发板**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217221652346-1695308600.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217221751763-485755617.png)

## **9.观察日志,说明执行流程**

### **开始运行用户程序,默认提供的用户程序设置的程序版本是0.0.0**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217222605392-1389046772.png)

### **用户程序控制模组连接服务器,使用get指令获取获取服务器上的固件信息文件 info.txt**

### **检测到版本不一致以后,把获取的url存储到flash,设置更新标志,重启.**

### **重启之后BootLoader提取url**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217222747598-1208813042.png)

### **BootLoader发送get指令获取程序固件**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217222927210-502357282.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223004453-696059171.png)

### **升级完成以后,运行新下载的程序.**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223049184-422930040.png)

### **用户程序每隔一段时间控制模组连接服务器,使用get指令获取获取服务器上的固件信息文件 info.txt**

### **现在程序版本和上面的是一致的,所以不需要更新**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223112837-889993596.png)

## **应用到自己的服务器**

## **1,首先确定好程序文件在服务器的路径**

### **关于本人服务器文件夹解释:(自己随意就好,最后的文件夹命名建议使用产品的型号)**

### **html:网站根目录**

### **ota: ota升级**

### **hardware : 硬件程序**

### **STM32W5500BK: 作为产品的型号(根据自己的产品型号修改)**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223148150-1519567985.png)

### **我把固件放到了里面那么固件程序下载地址为:**

### **http://服务器IP地址/ota/hardware/STM32W5500BK/user_crc.bin**

### **那么固件信息的下载地址为:**

### **http://服务器IP地址/ota/hardware/STM32W5500BK/info.txt**

## **2.修改 用户程序 的IAP.C文件**

### **提示:我把它们存储在程序bin文件的1024字节倍数的位置是为了BootLoader下载的时候便于提取这些数据;**

### **1.产品型号(我设置的为STM32W5500BK)**

### **2.修改固件程序版本(可随意指定,我设置的为0.0.2)**

### **3.修改记录云端固件信息文件下载地址(我的为:http://mnif.cn/ota/hardware/STM32W5500BK/info.txt)**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223417605-1916033907.png)

## **5.修改BootLoader程序 的 IAP.c (设置下产品型号和默认的固件程序下载地址)**

### **注意:BootLoader里面的产品型号要和用户里面的一样!!!!**

### **BootLoader程序下载的时候会判断这个型号一不一致**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223521620-1931715272.png)

## **6.编译用户程序**

### **会在工程目录的bin文件夹生成 user.bin文件**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223549729-46769354.png)

## **7.打开OTA Tools上位机软件**

![](https://img2020.cnblogs.com/blog/819239/202110/819239-20211027142820786-1174763134.png)

## **8.按照红框选择配置**

![](https://img2020.cnblogs.com/blog/819239/202008/819239-20200817115059813-40171645.png)

## **9.选择用户程序生成的 bin文件**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223642534-1452177509.png)

## **10.点击 生成固件**

![](https://img2020.cnblogs.com/blog/819239/202103/819239-20210324110517071-2135958912.png)

## **11.将在user.bin目录生成user_crc.bin文件**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223659428-236854084.png)

### **两个bin文件的区别:**

### **1.user_crc.bin文件是在user.bin的基础上增加了CRC校验位**

![](https://img2020.cnblogs.com/blog/819239/202007/819239-20200711104439209-894729265.png)

### **2.改写size,把真实的文件大小填写到bin文件**

![](https://img2020.cnblogs.com/blog/819239/202105/819239-20210518061004508-1707218274.png)

## **12.把生成的user_crc.bin文件拷贝到服务器**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223751597-1938284036.png)

## **13.还差一个info.txt文件**

### **我准备了一个模板**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223816317-1181566612.png)

## **14.修改版本号(和用户程序里面设置的一样)**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223852408-1794193131.png)

## **16.修改固件程序下载地址(和服务器上面的保持一致)**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217223950451-1028541129.png)

## **17.最后的提示信息不需要更改,当前用不到**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217224017396-2078159008.png)

## **18.把info.txt文件也拷贝到服务器,然后按照一开始的步骤测试即可**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217224037935-616683564.png)

## **小总结**

## **远程升级单片机程序其实就是使用模组以TCP方式连接Web服务器,**

## **然后给TCP服务器发数据,数据格式是GET指令.**

## **服务器接收到指令以后会下发文件给模组,模组通过串口把数据发给单片机,**

## **单片机接收到数据以后写到flash,最后加载运行.**

## **关于Flash分配调整**

## **1.打开BootLoader 或者 用户程序(mcu_project)里面的iap_interface.h 文件**

### **--------------------------------------------------------内部flash--------------------------------------------------------**

### **如果是使用内部flash备份程序,flash的开头存储的BootLoader程序, 结尾存储更新相关数据, 预留一些空间让用户存储其它数据**

### **最后剩下的平半分, 一部分存储用户程序, 另一部分用来备份用户程序**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917200435320-1553836933.png)

### **--------------------------------------------------------外部flash--------------------------------------------------------**

### **如果是使用外部flash备份程序, flash的最一开始存储的BootLoader程序, **

### **然后是存储用户程序, 然后是存储更新相关数据, 最后预留一些空间让用户存储其它数据**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917160757562-1141844102.png)

## **2,用户可以根据自己的需求调整Flash分配大小, 注意:BootLoader程序和用户程序的Flash分配要保证一样.**

### **--------------------------------------------------------内部flash--------------------------------------------------------**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917200806930-1840940117.png)

### **调整完成以后,下载BootLoader程序, 串口会打印flash具体分配**

![](https://img2022.cnblogs.com/blog/819239/202203/819239-20220317102518870-2096322842.png)

### **--------------------------------------------------------外部flash--------------------------------------------------------**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917201016580-82110143.png)

### **调整完成以后,下载BootLoader程序, 串口会打印flash具体分配**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917163103602-529962299.png)

## **3,无论是否使用外部flash,用户在项目中如果需要使用内部flash存储数据, 可以根据自己存储的数据量调整**

### **数据存储的起始地址是: FLASH_USERDATE_ADDR**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917162507286-1089657455.png)

## **4,如果使用外部flash备份数据, 如果用户也需要使用外部flash存储数据,**

### **为了不影响备份区,我给用户提供了数据存储的起始地址: FLASH_EXTERN_USERDATE_ADDR**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917162600105-126084934.png)

## **5.调整完flash以后,用户需要根据BootLoader打印的信息, 来设置用户程序(mcu_project)运行地址和占用空间**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917163103602-529962299.png)

### **这个要根据自己打印的设置**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917163159327-326204587.png)

## **关于升级底层包**

## **1.升级底层包分为iap, flash_extern, iap_interface文件**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917163251278-259920434.png)

## **1,flash_extern文件是配置和外部flash通信的文件**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917163512011-1904024303.png)

## **2. iap文件主要是控制着升级流程的文件**

### **可以在BootLoader程序里面设置升级过程中需要如何去下载,设置多大的缓存区**

![](https://img2022.cnblogs.com/blog/819239/202203/819239-20220317102651475-35224388.png)

## **3. iap_interface是接口文件**

### **根据移植的单片机实现内部的接口,只要完成里面的接口就完成了升级程序框架**

![](https://img2022.cnblogs.com/blog/819239/202209/819239-20220917163555702-1155761566.png)

![](https://img2020.cnblogs.com/blog/819239/202110/819239-20211027151933878-1356417389.png)

## **用户程序说明**

## **1.解析下info.txt下载路径(服务器上记录固件信息的文件)**

### **做这个程序是为省去用户解析的繁琐.**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217230631699-665443617.png)

![](https://img2020.cnblogs.com/blog/819239/202110/819239-20211027152317391-277910802.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217230710986-1638684876.png)

### **执行解析之后:**

### **IAPStructValue.IP = mnif.cn;**

### **IAPStructValue.Port = 80;**

### **IAPStructValue.Path = /ota/hardware/STM32W5500BK/info.txt**

## **4.处理更新(这个程序需要在认为用户程序没有问题的时候在用户程序里面执行一下)**

### **解释:**

### **BootLoader更新程序的时候会设置一些更新状态;用户程序需要调用一下这个函数清除更新状态.**

### **如果用户程序不清除更新状态,那么一旦程序重启以后BootLoader检查到更新状态以后会自行回滚程序.**

### **![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217230752223-1068753943.png)**

![](https://img2020.cnblogs.com/blog/819239/202108/819239-20210826190554264-1311732887.png)

## **5.控制模组发送get指令获取服务器上记录固件信息的文件**

![](https://img2020.cnblogs.com/blog/819239/202108/819239-20210826190642548-202360177.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231030659-607029810.png)

## **6.解析info.txt文件内容**

### **如果版本号不一样,提取和存储url然后设置升级标志,重启.**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231052904-1603922898.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231204240-212485256.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231240327-1570137132.png)

## **7,补充:如果编译用户程序出现下面的警告**

![](https://img2020.cnblogs.com/blog/819239/202103/819239-20210307151229250-666450244.png)

### **其实是这个地方导致的**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231311802-1789419156.png)

### **为了便于BootLoader程序提取用户程序bin文件里面的型号,把型号存储在了偏移1024字节的位置.**

### **设置的这个字符串存储的位置影响到了芯片本身默认分配一些数组的位置.就会报上面的警告.**

### **貌似不影响什么...**

## **BootLoader程序详细说明**

## **1.查看IAPInit函数**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231347881-2048502611.png)

## **2.获取存储的固件下载的url,并解析下url**

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912123746092-762844728.png)

## **3.如果有更新标志,则备份下用户程序**

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912123840568-1485774067.png)

## **4.如果没有更新标志,则查看下更新状态**

### **如果状态是更新有错误,则执行回滚,如果检测到没有备份的程序,就重新执行升级**

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912123946499-1348425575.png)

## **5.如果更新状态是0x01,就设置更新状态为0xFE**

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912124016370-1624851761.png)

## **7.控制模组连接TCP服务器(Web服务器)**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231559265-150490905.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231620276-2130932546.png)

### **IAP框架获取连接状态**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231706572-945352105.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231959979-309926459.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217232016014-1784748236.png)

## **8.发送get指令获取程序文件**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217231706572-945352105.png)

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912124218006-994291326.png)

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912124338750-1633149905.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217232203188-1694341071.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217232217330-784482743.png)

## **8.在TCP接收数据函数里面把固件数据写入缓存**

### **单片机是通过串口和模组通信,所以在串口中断里面接收**

### **底层解析什么的都做好了,自动解析以后存储到缓存里面**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217232257634-1452439258.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217232316964-2140794480.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217232339167-1914216038.png)

## **9.从缓存取数据,并写入flash**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217232408194-2053280867.png)

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912124658038-715490419.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217233231168-18345507.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217233338594-46439568.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217233615121-1057094695.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217233721117-144156898.png)

## **11,如果接收到相应的文件个数**

## **设置 IAPStructValue.ReadDataEndFlag = 1;认为接收完成**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217233822987-73654514.png)

## **12,判断接收完成之后做各种判断**

### **如果确实接收完了,则写入0x01状态,重启.**

### **如果有错误,则尝试重新下载.**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217234022724-126553671.png)

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217234206807-377951757.png)

## **13,如果是程序文件下载完成以后重启,重启以后检查到更新状态是0x01会设置更新状态为0XFE**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217234246262-383998991.png)

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912125310928-412761597.png)

## **14,然后加载运行用户程序**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217234310289-672002152.png)

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912125340143-69169033.png)

![](https://img2020.cnblogs.com/blog/819239/202110/819239-20211027153139169-389052858.png)

## **15,超过一段时间没有接收到数据了也设置为接收完了数据**

![](https://img2022.cnblogs.com/blog/819239/202202/819239-20220217234425863-1240357183.png)

![](https://img2020.cnblogs.com/blog/819239/202110/819239-20211027153256482-123112723.png)

## **16,客户可以在IAP.h修改默认的超时时间**

### **整体运行超时是BootLoader一运行就一直累加的的定时,超过时间就会控制程序重启**

![](https://img2020.cnblogs.com/blog/819239/202109/819239-20210912125529460-1312604389.png)

---

Source: https://maker.wiznet.io/tonywang_/projects/stm32-w5500-http-ota/
