STM32单片机实现串口IAP升级

一.概述

1.要实现串口IAP升级,首先要编写一个bootloader程序,然后再写支持IAP的app程序;

2.keil下bootloader的程序rom和ram设置

3.app程序要用bin文件

注:本文以STM32H743举例,其他stm32单片机IAP升级原理类似。

二.实现

1.bootloder程序实现

(1)基本知识

     stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯片实际的flash大小,不同的芯片flash大小不同。

     RAM起始地址是0x2000 0000,结束地址是0x2000 0000加上芯片的RAM大小。不同的芯片RAM也不同。

(2)STM32H743 bootloader设置

说明:由于 STM32H7 的扇区大小固定为 128KB 一个,最小擦除单位也是以扇区为单位的,因此,至少分配一个扇区给 Bootloader,否则后续擦写 APP 的时候,可能把 Bootloader 也给擦了!所以,我们使用 128K(0X20000)字节来存放 Bootloader。

(3)代码实现

int main(void)

{

u8 t;

u16 wait_s = 0;

u8 key;

u32 applenth=0;         //接收到的app代码长度

u8 clearflag=0;  

u32 Buffer[4];

Cache_Enable();               //打开L1-Cache

HAL_Init();          //初始化HAL库

Stm32_Clock_Init(160,5,2,4);       //设置时钟,400Mhz

delay_init(400); //延时初始化

uart_init(115200); //串口初始化

LED_Init(); //初始化LED

KEY_Init(); //初始化按键

SDRAM_Init();             //初始化SDRAM

while(1)

{

  if(USART_RX_STA&0x8000)

{

        USART_RX_STA=0;     //清空   

applenth=USART_RX_CNT;    //  applenth

USART_RX_CNT=0;

printf("用户程序接收完成!\r\n");

printf("代码长度:%dBytes\r\n",applenth);

}

else

{

  if(wait_s >= 500)

{

  wait_s = 0;

  printf("等待用法发送程序...  \r\n");

}

}

t++;

wait_s ++;

delay_ms(10);

if(t==30)

{

LED0_Toggle;

t=0;

if(clearflag)

{

clearflag--;

}

}     

key=KEY_Scan(0);

if(key==WKUP_PRES) //WK_UP按键按下

{

if(applenth)

{

printf("开始更新固件...\r\n");

  if(((*(vu32*)(0x24001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.

{  

iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//更新FLASH代码   #define FLASH_APP1_ADDR 0x08020000

printf("固件更新完成!\r\n");

}else

{

printf("非FLASH应用程序!\r\n");

}

  }else

{

printf("没有可以更新的固件!\r\n");

}

clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示  

}

if(key==KEY1_PRES) //KEY1按下

{

if(applenth)

{  

printf("固件清除完成!\r\n");    

applenth=0;

}else  

{

printf("没有可以清除的固件!\r\n");

}

clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示  

}

if(key==KEY2_PRES) //KEY2按下

{

printf("开始执行FLASH用户代码!!\r\n");

if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.

{  

iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码  

}else

{

printf("非FLASH应用程序,无法执行!\r\n");   

}  

clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示   

}

}      

}

(4)代码功能逻辑:

需要先按下 KEY_UP 按键,将串口接收到的 APP 程序存放到 STM32 的内部 FLASH;

再按 KEY2 既可以执行这个 FLASH APP 程序。

通过 KEY1 按键,可以手动清除串口接收到的APP 程序。

DS0 用于指示程序运行状态。

2.app程序及逻辑

(1)IAP流程逻辑

(2)keil设置

(3)代码实现

int main(void)

{

  SCB->VTOR = FLASH_BASE|0x20000;//设置偏移量  FLASH_BASE :  (uint32_t)0x08000000

RTC_TimeTypeDef RTC_TimeStruct;

  RTC_DateTypeDef RTC_DateStruct;

  u8 tbuf[40];

u8 t=0;

HAL_Init();          //初始化HAL库

Stm32_Clock_Init(160,5,2,4);       //设置时钟,400Mhz

delay_init(400);     //延时初始化

uart_init(115200); //串口初始化

usmart_dev.init(200);      //初始化USMART

    printf("RTC APP running\r\n");

LED_Init(); //初始化LED

KEY_Init(); //初始化按键

SDRAM_Init();                    //初始化SDRAM

    RTC_Init();                     //初始化RTC

    RTC_Set_WakeUp(RTC_WAKEUPCLOCK_CK_SPRE_16BITS,0); //配置WAKE UP中断,1秒钟中断一次  

    while(1)

    {

t++;

if((t%100)==0) //每100ms更新一次显示数据

{

            HAL_RTC_GetTime(&RTC_Handler,&RTC_TimeStruct,RTC_FORMAT_BIN);

sprintf((char*)tbuf,"Time:%02d:%02d:%02d",RTC_TimeStruct.Hours,RTC_TimeStruct.Minutes,RTC_TimeStruct.Seconds);

      printf("RTC time=%s\r\n",tbuf);

            HAL_RTC_GetDate(&RTC_Handler,&RTC_DateStruct,RTC_FORMAT_BIN);

sprintf((char*)tbuf,"Date:20%02d-%02d-%02d",RTC_DateStruct.Year,RTC_DateStruct.Month,RTC_DateStruct.Date);

printf("RTC date=%s\r\n",tbuf);

sprintf((char*)tbuf,"Week:%d",RTC_DateStruct.WeekDay);

printf("RTC week=%s\r\n",tbuf);

}

if((t%20)==0)LED0_Toggle; //每200ms,翻转一次LED0

        delay_ms(10);

}  

}

说明:重点是程序开始要有语句:SCB->VTOR = FLASH_BASE|0x20000;后面代码和普通app程序无区别

3.app生成bin文件

通过在 User 选项卡,设置编译后调用 fromelf.exe,根据.axf 文件生成.bin 文件,用于

IAP 更新。 

具体见之前文章:

STM32多种开发环境及生成hex及bin文件介绍_stm32 cubeide fromelf-CSDN博客文章浏览阅读758次,点赞29次,收藏23次。STM32多种开发环境及生成hex及bin文件介绍keil5 STM32CubeIDE EWARM如果不考虑商业应用keil的比较好,如果考虑商业付费用STM32CubeIDE更好一些,毕竟是免费的。_stm32 cubeide fromelfhttps://blog.csdn.net/xieliru/article/details/139849283?spm=1001.2014.3001.5501

4.串口升级app

(1)首先用keil把bootloader程序用烧写器烧写到单片机中

(2)通过串口IAP升级app程序

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

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

相关文章

达梦数据库的系统视图v$database

达梦数据库的系统视图v$database 基础信息 OS版本: Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本: DM Database Server 64 V8 DB Version: 0x7000c 03134284132-20240115-215128-20081在达梦数据库(Dameng Database&#xf…

Java——Lambda表达式

1. 背景 Lambda表达式是JavaSE 8中一个重要的新特性。Lambda表达式允许你通过表达式来代替功能接口。 Lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。 Lambda 表达式(…

C# YoloV8 模型效果验证工具(OnnxRuntime+ByteTrack推理)

C# YoloV8 模型效果验证工具(OnnxRuntimeByteTrack推理) 目录 效果 项目 代码 下载 效果 模型效果验证工具 项目 代码 using ByteTrack; using OpenCvSharp; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using Sys…

远程服务器配置(堡垒机samba/ssh等)

分配了新的服务器后,要下载代码首先要配置ssh。有以下两种方式: 拷贝原本服务器的在本地的重新生成ssh,再跟服务器密钥配对(如未备份.gitconfig,还需重新配置git账号邮箱。) ssh配置 如果是拷贝过来的.ss…

【win11】Mouse without Borders安装问题以管理员权限安装msi文件

【win11】Mouse without Borders安装问题&以管理员权限安装msi文件 Mouse without Borders安装问题解决&以管理员权限安装msi文件启动Windows Installer服务以管理员权限安装msi文件 参考文献 Mouse without Borders安装问题 在win11下我双击MouseWithoutBorders2.2.1…

nodejs使用mysql模块自动断开

背景 第二天早上来的时候,发现接口返回异常Cannot enqueue Query after fatal error 从日志看上去,接口是正常运行的,搜索一下之后发现是数据库的问题,连接断开了 原因 MySQL中有一个名叫wait_timeout的变量,表示操…

由监官要求下架docker hub镜像导致无法正常拉取镜像

问题:下载docker镜像超时 error pulling image configuration: download failed after attempts6: dial tcp 202.160.128.205:443: i/o timeout解决办法:配置daemon.json [rootbogon aihuidi]# cat /etc/docker/daemon.json {"registry-mirrors&qu…

java springboot过滤器

在Spring Boot应用中添加自定义过滤器,可以通过实现Filter接口或继承OncePerRequestFilter类来创建过滤器,并使用FilterRegistrationBean将其注册到Spring容器中。 以下是一个简单的示例: 1. 创建过滤器类 首先,创建一个实现Fil…

C++基础语法:类构造函数

前言 "打牢基础,万事不愁" .C的基础语法的学习 引入 类是实现面向对象思想的主要方法.前面提到:类是函数的变种,类可以通过调用静态方法或者成员函数来实现逻辑.多数情况下使用成员函数.构造函数是生成类对象成员的必须条件,对此做一些构造函数的归纳 构造函数的目…

【日志消息类的编写】

日志消息类编写 由于上篇的代码比较简单,今天就多写两段代码顺便把日志消息类编写完成。 这个类的实现就是:什么时间,哪个线程,哪个文件的哪一行,发生了什么等级的日志,日志机器名字是什么,日…

20240628 每日AI必读资讯

📚 Hugging Face 推出新版开源大模型排行榜,中国模型 Qwen-72B 夺冠 - 阿里Qwen-2-72B指令微调版本问鼎全球开源大模型排行榜榜首 - Llama-3-70B 微调版本排名第二,而 Mixtral-8x22B 微调版本位居第四。 - 另外,微软的 Phi-3-M…

三种分布式锁实现方式

目录 1、数据库自增 2、Redis自增 3、Zookeeper 4、其他 4.1、雪花算法 4.2、Tinyid 4.3、Leaf 4.4、数据库号段 1、数据库自增 利用数据库表的自增特性,或主键唯一性,实现分布式ID REPLACE INTO id_table (stub) values (’a‘) ; SELECT LA…

社交App广告优化新篇章:Xinstall引领用户体验升级,助力买量效果提升

随着移动互联网的快速发展,社交App已经成为人们生活中不可或缺的一部分。然而,在竞争激烈的市场环境下,如何有效地进行广告投放,吸引并留住用户,成为了每个社交App运营者面临的重大挑战。今天,我们就来谈谈…

自费5K,测评安德迈、小米、希喂三款宠物空气净化器谁才是高性价比之王

最近,家里的猫咪掉毛严重,简直成了一个活生生的蒲公英,家中、空气中各处都弥漫着猫浮毛甚至所有衣物都覆盖着一层厚厚的猫毛。令人难以置信的是,有时我甚至在抠出的眼屎中都能发现夹杂着几根猫毛。真的超级困扰了。但其实最空气中…

Packer-Fuzzer一款好用的前端高效安全扫描工具

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与学习之用,读者将信息做其他用途,由Ta承担全部法律及连带责任,文章作者不承担任何法律及连带责任。 1、Packer Fuzzer介绍 Packer Fuzzer是一款针对Webpack…

4.if 条件判断

1.if-else语句 if #判断条件 :pass else:pass2.if - elif- else if #判断条件 :pass elif #判断条件:pass else:pass3.if语句可以嵌套 if #判断条件 :passif #判断条件 :pass 4.逻辑运算符 and 两个都为真,才是真 or 一个为真 即是真 not 取反 and从左到右,所有值为真,返回…

麒麟系统安装MySQL

搞了一整天,终于搞定了,记录一下。 一、背景 项目的原因,基于JeecgBoot开发的系统需要国产化支持,这就需要在电脑上安装MySQL等支撑软件。 国产化项目的操作系统多是麒麟系统,我的系统如下: arm64架构。…

C#快速开发OPCUA服务器

为方便演示,此时创建一个控制台应用程序。第三方dll(C编写的库opcsrv.dll,他人实现)。 拷贝dll到运行目录下: 拷贝二次封装后的文件到项目目录下: 第一步:创建OpcUa服务器 //第一步:创建OpcUa服务器 OPCSr…

java.util.Optional类介绍

java.util.Optional 是 Java 8 引入的一个容器类,用于表示可能包含或不包含非空值的对象。它的设计初衷是为了减少程序中的空指针异常(NullPointerException),并使代码更加简洁和易读。 Optional 类的介绍 1. 特点 避免显式的 null 检查:使用 Optional 可以避免显式的 n…

基于ssh框架的个人博客源码

基于ssh的个人博客源码,页面清爽简洁,原先有部分bug,运行不了,现已修复 1.博客首页 (本地访问地址 :localhost:8080/Blog/index/index) 2.关于我 3.慢生活 4.留言板 5.我的相册 微信扫码下载源码