【STM32CUBE+IAR+IAP升级】

2023-11-18

STM32CUBE+IAR+IAP升级

案例应用:利用IAR+串口调试助手对STM32F411VET6进行简单的IAP实现,(代码分为两部分:BootLoader+APP翻转LED)

1.工具:

2.工程配置

2.1.1简要说下,本案例IAP,使用uart进行轮询方式接收数据(bin文件),没有任何校验,因此在后续接受过程中可能会出现丢包(丢失bin文件数据)的问题,建议串口波特率设置小些(本案例为9600

FLASH划分:STM32F411vet6片内FLASH512K,RAM128K,本案例将分配32KByte给BootLoader,480KByte给应用程序(本案例为LED_APP,功能0.5s翻转电平一次),如下图所示
在这里插入图片描述
2.1.2 LED_APP

​ ——>STM32CUBEMX中 RCC,SYS,GPIO(PD12),UART,时钟树配置如下,LED应用程序挺简单的
在这里插入图片描述
对printf()函数的重定义具体见:【STM32】STM32CUBEMX+UART串口调试,循环接受发送数据

——>main.c

#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"

void SystemClock_Config(void);
#define APPLICATION_ADDRESS  (uint32_t)0x08008000//LED_APP起始位置

int main(void)
{
  __enable_irq();//开中断
  SCB->VTOR = APPLICATION_ADDRESS;//设置程序烧写起始位置

  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();
  MX_USART2_UART_Init();

  printf("LED_APP TEST, This is IAP Application\r\n");
  while (1)
  {
      printf("This is IAP Application running\r\n");
      HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
      HAL_Delay(500);
  }

}

——>IAR设置程序起始位置,(对应用程序调试时,不用修改起始位置,调试无误后再修改向量表起始地址和其ROM,RAM,并生成bin文件)

​ 1.在第2步中.cif文件要选选stm32f411xe_flash.icf,因为我们这里是将程序烧写进flash,如果是烧写到sarm,那就选sarm.icf

​ 2.第3步中设置向量表起始地址这里是0x08008000(可以相应修改自定义的,根据你分配区域的大小设置)

​ 3.第4步中Memory Regions中ROM: 0x08008000~0x0807FFFF(总共480KB),RAM:栈是在RAM上分配 的,大小0x2000 0000 ~ 0x2001 FFFF(对应F411ve 128K),一般起始地址为0x2000 0000 ,这里设置为0x2000 00c0,留给参数变量c0大小的区域,也可不用修改
在这里插入图片描述
——>IAR生成bin文件设置,设置完后保存,编译之后会在你的工程exe文件中生成BIN文件,注意bin文件的大小要在设置的范围内
在这里插入图片描述
2.1.3 BootLoader

​ ——>STM32CUBEMX配置和LED_APP配置一样,UART串口波特率设置成9600,

​ ——>同样需要对printf()函数进行重定义,具体见:【STM32】STM32CUBEMX+UART串口调试,循环接受发送数据

main.c

#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include <string.h>
#include "flash_if.h"

typedef  void (*pFunction)(void);

#define	UART_BUF_SIZE		256

uint32_t JumpAddress;
pFunction JumpToApplication;
uint8_t uart_buf[UART_BUF_SIZE] = {0};

void SystemClock_Config(void);

int main(void)
{
   uint8_t key = 0;
   uint32_t temp = 0;
   uint32_t timeout = 0;
   uint32_t userapplen = 0;

  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART2_UART_Init();

  printf("\r\n This is Bootloader\r\n");
 
  while (1)
  {

      printf("\r\n=================== Main Menu ============================\r\n\n");
	  printf("  Download user application to the internal Flash ------ 1\r\n\n");
	  printf("  Execute the loaded application ----------------------- 2\r\n\n");


           /* Clean the input path */
	  __HAL_UART_FLUSH_DRREGISTER(&huart2);
	  /* Receive key */
	  HAL_UART_Receive(&huart2, &key, 1, HAL_MAX_DELAY);
            switch(key)
	  {
	  case '1':
		  /* Download user application in the Flash */
		  /* 1. erase user application area */
		  printf("Wait for the internal Flash erase to complete\r\n");
		  if(FLASH_If_Erase(APPLICATION_ADDRESS, 6) == 1)
		  {
			  printf("Erase the internal Flash is fail\r\n");
			  Error_Handler();
		  }
		  printf("Erase the internal Flash is complete\r\n");

		  /* 2. download a file via serial port */
		  printf("Waiting for the file to be sent ... \r\n");
		  userapplen = 0;
		  timeout = HAL_MAX_DELAY;
		  /* Clean the input path */
		  __HAL_UART_FLUSH_DRREGISTER(&huart2);
		  while(1)
		  {
			  if(HAL_UART_Receive(&huart2, uart_buf, UART_BUF_SIZE, timeout) != HAL_OK)
			  {
				  temp = UART_BUF_SIZE - (huart2.RxXferCount + 1);
				  if(FLASH_If_Write(APPLICATION_ADDRESS + userapplen, (uint32_t*)uart_buf, temp / 4) != FLASHIF_OK)
				  {
					  printf("Write the internal Flash is fail\r\n");
					  Error_Handler();
				  }
				  userapplen = userapplen + temp;
				  break;
			  }
			  timeout = 1000;//等待接收完成
			  if(FLASH_If_Write(APPLICATION_ADDRESS + userapplen, (uint32_t*)uart_buf, UART_BUF_SIZE / 4))//4字节对齐
			  {
				  printf("Write the internal Flash is fail\r\n");
				  Error_Handler();
			  }
			  userapplen = userapplen + UART_BUF_SIZE;
		  }
		  printf("Programming Completed Successfully! %ldBtye\r\n", userapplen);
		  break;

	  case '2':
		  printf("Start program execution......\r\n\n");
		  /*
		   * 关闭或反初始化前面用到的外设和中断
		   * 1、反初始化UART
		   * 2、关闭系统滴答定时器中断
		   * */
		 HAL_UART_DeInit(&huart2);
		// HAL_SuspendTick();
       //  __disable_irq();
 	    /* execute the new program */
	      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
         /* Jump to user application */
	      JumpToApplication = (pFunction) JumpAddress;
	     /* Initialize user application's Stack Pointer */
	      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
	      JumpToApplication();
		  break;

	  default:
		  printf("Invalid Number ! ==> The number should be either 1 or 2\r");
		  break;
	  }
  }
}

编译调试无误后就可以开始了,生成bin文件注意大小,在32K之内,不需要修改起始地址。

1、上电后打印功能菜单。

2、发送‘1’就会进入IAP模式;首先会擦除APP空间,然后等待用串口助手发送LED_APP的bin文件写入flash,直至完成。

3、发送‘2’就会直接跳转到LED_APP运行,结果如下。
在这里插入图片描述
——>BootLoader程序简单说下(个人看法,如有不同见解,欢迎留言讨论)

  • FLASH_If_Erase(APPLICATION_ADDRESS, 6)函数,第一个参数擦除的sector的起始地址,第二个参数根据自己的flash中sector数进行相应设置(判断下有没有擦除成功)

  • FLASH_If_Write(APPLICATION_ADDRESS + userapplen, (uint32_t * )uart_buf, temp / 4)写flash函数,第一个参数起始地址,第二个要写的数据的缓存地址,第三个要写的数据长度。在该函数之前uart_buf类型为uint8_t,(1个字节)用于接收BIN文件数据,所以轮询方式的HAL_UART_Receive()接收了几十次,FLASH_If_Write()也写了几十次,不过FLASH_If_Write()是以4字节对齐的方式写入,对应于(uint32_t * )uart_buf,

  • case ‘1’:中while()循环:当通过串口助手发送bin文件之后,执行HAL_UART_Receive()后(有可能满buffer有可能没有)—>执行1次FLASH_If_Write(),写完之后更新下次要写的flash起始位置—>HAL_UART_Receive()—>执行1次FLASH_If_Write()…,最后一次进入if(HAL_UART_Receive()!= HAL_OK),写完剩余数据,跳出循环,那么问题来了HAL_UART_Receive()接收数据和FLASH_If_Write()会存在快慢的问题,如果本次接收到的数据还没有写完flash,下一次又来数据又去写那么会存在丢包的问题,为避免该问题,这里将波特率设置的很小9600,可以尝试看看115200时的现象。

  • case ‘2’:在跳转到新的LED_APP之前关掉前面用到的外设和中断,然后在新的应用程序重新开启中断,避免干扰

具体代码见:STM32CUBEMX+IAR+IAP应用程序升级(STM32F411VET6)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【STM32CUBE+IAR+IAP升级】 的相关文章

随机推荐

  • 从物业管理到IT互联网精英,月薪11k的她几经辗转,终得偿所愿!

    所谓 男怕入错行 其实对女生来说也是一样 不同行业对人生的改变太大 想要找到满意的工作 就要不断去尝试 西安的学员小文 大学毕业后从事的本专业 物业管理 工作 但不是很喜欢 薪资也偏低 后面转到建筑行业做人力资源管理 需要跟着项目走 考虑到
  • MyBatis课后练习题——(狂神说系列)

    MyBatis课后练习题 1 导入数据库 及配置文件 1 1 导入数据库 1 1 1 smbms address CREATE TABLE smbms address id bigint 20 NOT NULL AUTO INCREMENT
  • 云服务器我的数据保存在哪个文件夹,云服务器存储在哪里

    云服务器存储在哪里 内容精选 换一换 整机镜像是包含云服务器操作系统 应用软件和业务数据的镜像 一般适用于云服务器数据整体搬迁 例如 将云服务器共享给其他租户将 华北 北京一 的云服务器迁移至 华南 广州 区域将老旧云服务器上的数据迁移至新
  • java: framework from BLL、DAL、IDAL、MODEL、Factory, using Ms SQL server

    sql create database geovindu go use geovindu go 基础数据设置BasicDataSet 书分类目录kind BookKindForm IF EXISTS select from sysobjec
  • VMware 15 安装ubuntu 18.04的总结

    换了新电脑 想安装了VMware12 0版本的 结果发现安装包和我现在的电脑并不匹配 所以下载了较新版本的vmware 15 5 网上找到对应版本的序列号注册 在安装完成后激活即可 emsp 从Linux公社的文章 Ubuntu 18 04
  • 一个开源项目维护者的笔记:为什么我关闭 PR

    原文出处 jeffgeerling 译文出处 oschina 局长 我在 GitHub 上和其他地方维护着许多的开源项目 截止本文写作时超过 160 个 在过去几年里 我已经合并 以及 或者 关闭了上千个 Pull Requests PRs
  • Linux 下面编译内核模块的 方法

    1 选择好你的内核版本 内核模块经常是和内核版本紧密相关的 建议尽量选择高内核的版本 否则有可能会遇到很大的问题 2 下载内核代码到 usr src kernel 目录 如果有了 则不用下载 3 mkdir p lib modules 3
  • [FPGA系列] 扩展知识 --- 时钟小结

    一 基本概念 时钟域 由同一个时钟信号控制的区域 时钟抖动 Jitter 相对于理想时钟信号 实际时钟信号存在时而超前 时而之后的偏移 时钟偏斜 Skew 时钟信号到达数字电路各个部分所用时间的差异 时钟漂移 Wander 工程上解释 抖动
  • Day【10】相交链表

    原题链接 思路 代码 public class Solution public ListNode getIntersectionNode ListNode headA ListNode headB if headA null headB n
  • Typora的安装与配置

    Markdown对于码农来讲有多重要就不多说了吧 那么Typora作为一款极好用的生产工具 它的重要性也不言而喻了吧 Typora简介 Typora 是一款支持实时预览的 Markdown 文本编辑器 风格极简 多种主题 支持 macOS
  • Linux操作系统

    一 Linux系统概述 1 1Linux操作系统的组成 Linux操作系统是由Linux系统内核和系统级应用程序两部分组成的 1 内核提供系统核心的功能 如调度CPU 调度内存 调度系统文件 调度网路通讯 调度IO 2 系统级应用程序可以理
  • 【PythonCode】这些题,不会做就选D

    PythonCode 这些题 不会做就选D 前言 在很多高大上的项目中 一个花费很长时间 消耗大量人力物力才查出来的BUG 经常是一个符号错误 一个值传错 一个基本函数的用法没有考虑周到等基本问题 所以基础不牢 地动山摇 真的不是开玩笑 2
  • Qt信号槽自动关联的用法

    Qt除使用connect方法显式的关联信号与槽 还可以通过自动关联机制实现信号与槽函数的连接 自动关联的槽函数命名规则 void on lt 窗口部件名称 gt lt 信号名称 gt lt 信号参数 gt 实现信号与槽函数关联的步骤 1 在
  • Android 安全机制(1)uid 、 gid 与 pid

    1 概述 Android 安全机制来源于Linux 并且以Linux权限管理为基础 要了解Android的安全机制 需要从linux中的安全机制了解开始 而用户的权限管理又是linux安全机制的最基本的一个组成 Android的创新之处是在
  • KVM网卡模式(初探KVM)

    最近在看 KVM虚拟化技术实战与原理解析 这本书 略读了前四章后 开始动手创建并安装一个虚拟机 然后发现一个很严重的问题 就是我没有办法通过ssh连接到虚拟机 linux 也没有办法通过mstsc连到到虚拟机 windows 因为我在创建虚
  • oracle索引监控

    oracle索引是加快查询速度 减少i o操作的 但是如果索引无用的话那他就是浪费资源的 尤其是在做DML操作时 这是 就需要我们查看那些索引是无用的 相关视图 user indexesuser ind columnsv object us
  • java学习03-程序执行三大结构

    一 顺序执行语句 程序运行时 按顺序从上往下执行 二 分支语句 分支运算 if else if 条件 if 条件 else 虽然多个语句块 但是只有一个执行 if 条件 else if 条件 else switch case 不能嵌套 sw
  • 报错Attribute "path" is required and must be specified for element type

    Attribute path is required and must be specified for element type 最近搞一个项目总遇到这个或者类似的问题 其实问题很简单 其实就是batis和MyBatis之间有区别 就是在
  • java8 stream findfirst().get()空指针

    java8 stream findfirst get 空指针 List
  • 【STM32CUBE+IAR+IAP升级】

    STM32CUBE IAR IAP升级 案例应用 利用IAR 串口调试助手对STM32F411VET6进行简单的IAP实现 代码分为两部分 BootLoader APP翻转LED 1 工具 IAR STM32CUBEMX 串口调试助手 IA