STM32CbueMX之 USB下载更新固件Download Firmware Update(DFU)之一BootLoader程序编写

本文主要是介绍STM32CbueMX之 USB下载更新固件Download Firmware Update(DFU)之一BootLoader程序编写,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

声明:

STM32CbueMX之 USB下载更新固件Download Firmware Update(DFU)之一BootLoader程序编写https://blog.csdn.net/sudaroot/article/details/102549606
STM32CbueMX之 USB下载更新固件Download Firmware Update(DFU)之二APP编写及烧录升级https://blog.csdn.net/sudaroot/article/details/102743141
STM32CbueMX之 USB下载更新固件Download Firmware Update(DFU)之三Leave DFU mode会卡死https://blog.csdn.net/sudaroot/article/details/102746505
STM32CbueMX之 USB下载更新固件Download Firmware Update(DFU)之四FreeRTOS跳转运行失败https://blog.csdn.net/sudaroot/article/details/102800541

以下内容参考:

C:\Users\admin\STM32Cube\Repository\STM32Cube_FW_F4_V1.24.1\Projects\STM324xG_EVAL\Applications\USB_Device\DFU_Standalone

背景:

如果产品有USB电路且接口外露都适用,连上USB,打开DfuSe_Demo烧录固件,即可完成固件更新。

固件就是烧录在单片机的软件。

如果你使用的是F4以上的系列,boot0接高,boot1接地,进入系统启动模式,接上usb线PC,即可看到DFU模式。

F4系列默认系统BootLoader自带DFU程序。

需求:

1、做一个平时上电就运行固件,做一个LED闪烁。

2、当我们按住板子某个按键    上电就运行UFD模式,等待固件更新,此时LED灯常亮;

      更新完成后断电重启,即可看到新固件的现象。

硬件:

原理:

和IAP原理大同小异。

需要了解ST单片机的启动流程。

我把内部flash分成两个区域,

1、是BootLoader区域,就是带有DFU和启动(固件称为APP)的功能。起始地址:0x8000000,大小:64K。

2、是APP区域,放置项目功能代码。起始地址:0x8010000,大小:960K。

故我们需要写两个程序,一个是BootLoader程序,一个是APP程序。

简单讲一下:

上电 ST从flash 地址 0x8000000 处取代码执行。即执行BootLoader区域的程序。再判断按键是否按下,

1、没有按下则通过函数指针跳转到APP区域执行项目功能代码(跳转前需做准备工作);

2、有按下则初始化USB DFU函数,等待更新APP区域的固件,更新完成后断电重启。

安装DFU烧录软件:DfuSe_Demo

官网下载链接:

STSW-STM32080 - DfuSe USB device firmware upgrade (UM0412) (replaced by STM32CubeProgrammer) - STMicroelectronics

默认安装即可。

安装成功后得到两个软件。

Dfu file manager是把bin文件或者hex文件生成  .dfu后缀的文件,  .dfu后缀的文件就是我们的固件。

DfuSe_Demo是烧录 文件后缀   .duf  软件。

编写BootLoader程序的STM32CubeMX:

1、选择外部晶振25MHz

系统最大时钟配置为168MHz,USB时钟一定为48MHz。

2、选择USB_FS(全速)模式,选择从机模式。

2、选择DFU类;

USBD_DFU_APP_DEFAULT_ADD (Base Address 0x):0x08010000。

指你打算把固件放在哪里,以你使用的芯片flash最小页单位对齐(flash最小擦除单位是页)。这里我打算把APP放在从内部flash  64K 处起,前面放置BootLoader程序。

USBD_DFU_MEDIA Interface:@Internal Flash   /0x08000000/04*016Ka,01*064Kg,07*128Kg。

@Internal Flash   /0x08000000/04*016Ka,01*064Kg,07*128Kg。即:内部flash从0x08000000地址起,连续分配,前04*016K只读存放BootLoader程序,后面01*064K和07*128K可读可写。更详细的说明靠下面详细说明。

注意:由于芯片不同,芯片的内部flash分布情况也不一定相同,故请参考使用的芯片参考手册。

闪存的描述(由PC工具DFuSe使用)每个备用设置字符串描述符都必须遵循此内存映射,

以便PC主机软件可以解码所选设备的正确映射:

●@:检测到这是一个特殊的映射描述符(避免解码标准描述符)

●/:用于区域之间的分隔符

●每个地址以“ 0x”开头的最大8位数字

●/:用于区域之间的分隔符

●扇区数的最大2位数字

●* :用于扇区数和扇区大小之间的分隔符

●扇区大小在0到999之间的最大3位

●扇区大小乘数的1位数字。有效条目为:B(字节),K(千),M(兆)

●扇区类型的1位数字,如下所示:

        – a(0x41):可读

        – b(0x42):可擦除

        – c(0x43):可读和可擦除

              (0x44):可写

         – e(0x45):可读写

           –f(0x46):可擦除和可写

          –g(0x47):可读写,可写

注意:如果目标内存不连续,则用户可以添加斜线“ /”之后要解码的新扇区,

如以下示例所示:“ @ Flash / 0xF000 / 1 * 4Ka / 0xE000 / 1 * 4Kg / 0x8000 / 2 * 24Kg”

USB的抢占中断级别设置成15;最低的抢占中断。

原因:DfuSeDemo烧录完固件后,点击Leave DFU mode会卡死,并不会跳转到APP运行。

源码:函数 static void DFU_Leave(USBD_HandleTypeDef *pdev)逐级调用到了HAL_StatusTypeDef  USB_DevDisconnect(USB_OTG_GlobalTypeDef *USBx)会卡死在HAL_Delay(3U);,,后来仿真发现系统时钟中断没发生,准确地说是中断发生了,而由于USB中断和系统时钟中断默认都是抢占优先级最高的0,就会发生系统时钟中断不能抢到中断执行。导致节拍数一直没变,  while((HAL_GetTick() - tickstart) < wait)循环卡死。

/*** @brief  USB_DevDisconnect : Disconnect the USB device by disabling the pull-up/pull-down* @param  USBx  Selected device* @retval HAL status*/
HAL_StatusTypeDef  USB_DevDisconnect(USB_OTG_GlobalTypeDef *USBx)
{uint32_t USBx_BASE = (uint32_t)USBx;USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS;HAL_Delay(3U);   return HAL_OK;
}

USBD_DFU_XFER_SIZE:USB数据pack大小,越大配置速度越快。默认配置1024Bytes.  1024Bytes使用的是堆空间,故堆空间要大于1024Bytes.  原因:代码如下。

#define USBD_malloc         malloc

 /* Allocate Audio structure */
  pdev->pClassData = USBD_malloc(sizeof (USBD_DFU_HandleTypeDef));

个人使用习惯是 堆 空间比1024B 大 512B 即0x600.

个人觉得这个项目的main函数生成的不适合用于这个DFU,原因是调用关系。如,我没按下按键不需要初始化USB,生成的确调用了初始化。故不生成main函数,自己写。

我的板子上PA0是按键输入,PB0是一个LED灯。(根据情况定)

最后生成代码。

生成的USB功能相关文件:

usb_device.c                初始化
usbd_conf.c                  常规低层驱动程序配置
usbd_desc.c                 USB设备描述符
usbd_dfu_if.c                内部闪存管理

usb_device.h                初始化
usbd_conf.h                 USB设备驱动程序配置文件
usbd_desc.h                USB设备描述符头文件
usbd_dfu_if.h               内部闪存管理头文件

编程

1、打开usbd_dfu_if.h添加下面F429IG内部flash分区定义

项目添加/* USER CODE BEGIN EXPORTED_DEFINES */ ~ /* USER CODE END EXPORTED_DEFINES */代码

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : usbd_dfu_if.h* @brief          : Header for usbd_dfu_if.c file.******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under Ultimate Liberty license* SLA0044, the "License"; You may not use this file except in compliance with* the License. You may obtain a copy of the License at:*                             www.st.com/SLA0044********************************************************************************/
/* USER CODE END Header *//* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DFU_IF_H__
#define __USBD_DFU_IF_H__#ifdef __cplusplusextern "C" {
#endif/* Includes ------------------------------------------------------------------*/
#include "usbd_dfu.h"/* USER CODE BEGIN INCLUDE *//* USER CODE END INCLUDE *//** @addtogroup STM32_USB_DEVICE_LIBRARY* @brief For Usb device.* @{*//** @defgroup USBD_MEDIA USBD_MEDIA* @brief Header file for the usbd_dfu_if.c file.* @{*//** @defgroup USBD_MEDIA_Exported_Defines USBD_MEDIA_Exported_Defines* @brief Defines.* @{*//* USER CODE BEGIN EXPORTED_DEFINES *//* Base address of the Flash sectors *//* Bank 1 */#define ADDR_FLASH_SECTOR_0     ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */#define ADDR_FLASH_SECTOR_1     ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */#define ADDR_FLASH_SECTOR_2     ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */#define ADDR_FLASH_SECTOR_3     ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */#define ADDR_FLASH_SECTOR_4     ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */#define ADDR_FLASH_SECTOR_5     ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */#define ADDR_FLASH_SECTOR_6     ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */#define ADDR_FLASH_SECTOR_7     ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */#define ADDR_FLASH_SECTOR_8     ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */#define ADDR_FLASH_SECTOR_9     ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */#define ADDR_FLASH_SECTOR_10    ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */#define ADDR_FLASH_SECTOR_11    ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes *//* Bank 2 */#define ADDR_FLASH_SECTOR_12    ((uint32_t)0x08100000) /* Base @ of Sector 12, 16 Kbytes */#define ADDR_FLASH_SECTOR_13    ((uint32_t)0x08104000) /* Base @ of Sector 13, 16 Kbytes */#define ADDR_FLASH_SECTOR_14    ((uint32_t)0x08108000) /* Base @ of Sector 14, 16 Kbytes */#define ADDR_FLASH_SECTOR_15    ((uint32_t)0x0810C000) /* Base @ of Sector 15, 16 Kbytes */#define ADDR_FLASH_SECTOR_16    ((uint32_t)0x08110000) /* Base @ of Sector 16, 64 Kbytes */#define ADDR_FLASH_SECTOR_17    ((uint32_t)0x08120000) /* Base @ of Sector 17, 128 Kbytes */#define ADDR_FLASH_SECTOR_18    ((uint32_t)0x08140000) /* Base @ of Sector 18, 128 Kbytes */#define ADDR_FLASH_SECTOR_19    ((uint32_t)0x08160000) /* Base @ of Sector 19, 128 Kbytes */#define ADDR_FLASH_SECTOR_20    ((uint32_t)0x08180000) /* Base @ of Sector 20, 128 Kbytes */#define ADDR_FLASH_SECTOR_21    ((uint32_t)0x081A0000) /* Base @ of Sector 21, 128 Kbytes */#define ADDR_FLASH_SECTOR_22    ((uint32_t)0x081C0000) /* Base @ of Sector 22, 128 Kbytes */#define ADDR_FLASH_SECTOR_23    ((uint32_t)0x081E0000) /* Base @ of Sector 23, 128 Kbytes */
/* USER CODE END EXPORTED_DEFINES *//*** @}*//** @defgroup USBD_MEDIA_Exported_Types USBD_MEDIA_Exported_Types* @brief Types.* @{*//* USER CODE BEGIN EXPORTED_TYPES *//* USER CODE END EXPORTED_TYPES *//*** @}*//** @defgroup USBD_MEDIA_Exported_Macros USBD_MEDIA_Exported_Macros* @brief Aliases.* @{*//* USER CODE BEGIN EXPORTED_MACRO *//* USER CODE END EXPORTED_MACRO *//*** @}*//** @defgroup USBD_MEDIA_Exported_Variables USBD_MEDIA_Exported_Variables* @brief Public variables.* @{*//** MEDIA Interface callback. */
extern USBD_DFU_MediaTypeDef USBD_DFU_fops_FS;/* USER CODE BEGIN EXPORTED_VARIABLES *//* USER CODE END EXPORTED_VARIABLES *//*** @}*//** @defgroup USBD_MEDIA_Exported_FunctionsPrototype USBD_MEDIA_Exported_FunctionsPrototype* @brief Public functions declaration.* @{*//* USER CODE BEGIN EXPORTED_FUNCTIONS *//* USER CODE END EXPORTED_FUNCTIONS *//*** @}*//*** @}*//*** @}*/#ifdef __cplusplus
}
#endif#endif /* __USBD_DFU_IF_H__ *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

2、打开usbd_dfu_if.c填充下面函数

    MEM_If_Init_FS,             闪存初始化,解锁内部flash。
    MEM_If_DeInit_FS,        闪存反(取消)初始化,上锁内部flash。
    MEM_If_Erase_FS,        闪存擦除。
    MEM_If_Write_FS,         闪存写入。
    MEM_If_Read_FS,         闪存读取。
    MEM_If_GetStatus_FS  获取闪存状态,返回写入或擦除操作所需的时间。

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : usbd_dfu_if.c* @brief          : Usb device for Download Firmware Update.******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under Ultimate Liberty license* SLA0044, the "License"; You may not use this file except in compliance with* the License. You may obtain a copy of the License at:*                             www.st.com/SLA0044********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "usbd_dfu_if.h"/* USER CODE BEGIN INCLUDE *//* USER CODE END INCLUDE *//* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*//* USER CODE END PV *//** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY* @brief Usb device.* @{*//** @defgroup USBD_DFU* @brief Usb DFU device module.* @{*//** @defgroup USBD_DFU_Private_TypesDefinitions* @brief Private types.* @{*//* USER CODE BEGIN PRIVATE_TYPES *//* USER CODE END PRIVATE_TYPES *//*** @}*//** @defgroup USBD_DFU_Private_Defines* @brief Private defines.* @{*/#define FLASH_DESC_STR      "@Internal Flash   /0x08000000/04*016Ka,01*064Kg,07*128Kg"/* USER CODE BEGIN PRIVATE_DEFINES */
#define FLASH_ERASE_TIME    (uint16_t)50
#define FLASH_PROGRAM_TIME  (uint16_t)50
/* USER CODE END PRIVATE_DEFINES *//*** @}*//** @defgroup USBD_DFU_Private_Macros* @brief Private macros.* @{*//* USER CODE BEGIN PRIVATE_MACRO *//* USER CODE END PRIVATE_MACRO *//*** @}*//** @defgroup USBD_DFU_Private_Variables* @brief Private variables.* @{*//* USER CODE BEGIN PRIVATE_VARIABLES *//* USER CODE END PRIVATE_VARIABLES *//*** @}*//** @defgroup USBD_DFU_Exported_Variables* @brief Public variables.* @{*/extern USBD_HandleTypeDef hUsbDeviceFS;/* USER CODE BEGIN EXPORTED_VARIABLES *//* USER CODE END EXPORTED_VARIABLES *//*** @}*//** @defgroup USBD_DFU_Private_FunctionPrototypes* @brief Private functions declaration.* @{*/static uint16_t MEM_If_Init_FS(void);
static uint16_t MEM_If_Erase_FS(uint32_t Add);
static uint16_t MEM_If_Write_FS(uint8_t *src, uint8_t *dest, uint32_t Len);
static uint8_t *MEM_If_Read_FS(uint8_t *src, uint8_t *dest, uint32_t Len);
static uint16_t MEM_If_DeInit_FS(void);
static uint16_t MEM_If_GetStatus_FS(uint32_t Add, uint8_t Cmd, uint8_t *buffer);/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
static uint32_t GetSector(uint32_t Address);
static uint32_t GetBank(uint32_t Addr);
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION *//*** @}*/#if defined ( __ICCARM__ ) /* IAR Compiler */#pragma data_alignment=4
#endif
__ALIGN_BEGIN USBD_DFU_MediaTypeDef USBD_DFU_fops_FS __ALIGN_END =
{(uint8_t*)FLASH_DESC_STR,MEM_If_Init_FS,MEM_If_DeInit_FS,MEM_If_Erase_FS,MEM_If_Write_FS,MEM_If_Read_FS,MEM_If_GetStatus_FS
};/* Private functions ---------------------------------------------------------*/
/*** @brief  Memory initialization routine.* @retval USBD_OK if operation is successful, MAL_FAIL else.*/
uint16_t MEM_If_Init_FS(void)
{/* USER CODE BEGIN 0 */HAL_FLASH_Unlock();return (USBD_OK);/* USER CODE END 0 */
}/*** @brief  De-Initializes Memory* @retval USBD_OK if operation is successful, MAL_FAIL else*/
uint16_t MEM_If_DeInit_FS(void)
{/* USER CODE BEGIN 1 */HAL_FLASH_Lock();return (USBD_OK);/* USER CODE END 1 */
}/*** @brief  Erase sector.* @param  Add: Address of sector to be erased.* @retval 0 if operation is successful, MAL_FAIL else.*/
uint16_t MEM_If_Erase_FS(uint32_t Add)
{/* USER CODE BEGIN 2 */uint32_t startsector = 0, sectorerror = 0;/* Variable contains Flash operation status */HAL_StatusTypeDef status;FLASH_EraseInitTypeDef eraseinitstruct;/* Get the number of sector */startsector = GetSector(Add);eraseinitstruct.TypeErase = FLASH_TYPEERASE_SECTORS;eraseinitstruct.Banks = GetBank(Add);eraseinitstruct.Sector = startsector;eraseinitstruct.NbSectors = 1;eraseinitstruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;status = HAL_FLASHEx_Erase(&eraseinitstruct, &sectorerror);if (status != HAL_OK){return USBD_FAIL;}return (USBD_OK);/* USER CODE END 2 */
}/*** @brief  Memory write routine.* @param  src: Pointer to the source buffer. Address to be written to.* @param  dest: Pointer to the destination buffer.* @param  Len: Number of data to be written (in bytes).* @retval USBD_OK if operation is successful, MAL_FAIL else.*/
uint16_t MEM_If_Write_FS(uint8_t *src, uint8_t *dest, uint32_t Len)
{/* USER CODE BEGIN 3 */uint32_t i = 0;for (i = 0; i < Len; i += 4){/* Device voltage range supposed to be [2.7V to 3.6V], the operation will* be done by byte */if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t) (dest + i),*(uint32_t*) (src + i)) == HAL_OK){/* Check the written value */if (*(uint32_t*) (src + i) != *(uint32_t*) (dest + i)){/* Flash content doesn't match SRAM content */return USBD_FAIL;}}else{/* Error occurred while writing data in Flash memory */return USBD_FAIL;}}return (USBD_OK);/* USER CODE END 3 */
}/*** @brief  Memory read routine.* @param  src: Pointer to the source buffer. Address to be written to.* @param  dest: Pointer to the destination buffer.* @param  Len: Number of data to be read (in bytes).* @retval Pointer to the physical address where data should be read.*/
uint8_t *MEM_If_Read_FS(uint8_t *src, uint8_t *dest, uint32_t Len)
{/* Return a valid address to avoid HardFault *//* USER CODE BEGIN 4 */uint32_t i = 0;uint8_t *psrc = src;for (i = 0; i < Len; i++){dest[i] = *psrc++;}return (uint8_t*) (dest);/* USER CODE END 4 */
}/*** @brief  Get status routine* @param  Add: Address to be read from* @param  Cmd: Number of data to be read (in bytes)* @param  buffer: used for returning the time necessary for a program or an erase operation* @retval USBD_OK if operation is successful*/
uint16_t MEM_If_GetStatus_FS(uint32_t Add, uint8_t Cmd, uint8_t *buffer)
{/* USER CODE BEGIN 5 */switch (Cmd){case DFU_MEDIA_PROGRAM:buffer[1] = (uint8_t) FLASH_PROGRAM_TIME;buffer[2] = (uint8_t) (FLASH_PROGRAM_TIME << 8);buffer[3] = 0;break;case DFU_MEDIA_ERASE:buffer[1] = (uint8_t) FLASH_ERASE_TIME;buffer[2] = (uint8_t) (FLASH_ERASE_TIME << 8);buffer[3] = 0;default:break;}return (USBD_OK);/* USER CODE END 5 */
}/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
static uint32_t GetSector(uint32_t Address)
{#if 1if (Address < ADDR_FLASH_SECTOR_1)return FLASH_SECTOR_0;else if (Address < ADDR_FLASH_SECTOR_2)return FLASH_SECTOR_1;else if (Address < ADDR_FLASH_SECTOR_3)return FLASH_SECTOR_2;else if (Address < ADDR_FLASH_SECTOR_4)return FLASH_SECTOR_3;else if (Address < ADDR_FLASH_SECTOR_5)return FLASH_SECTOR_4;else if (Address < ADDR_FLASH_SECTOR_6)return FLASH_SECTOR_5;else if (Address < ADDR_FLASH_SECTOR_7)return FLASH_SECTOR_6;else if (Address < ADDR_FLASH_SECTOR_8)return FLASH_SECTOR_7;else if (Address < ADDR_FLASH_SECTOR_9)return FLASH_SECTOR_8;else if (Address < ADDR_FLASH_SECTOR_10)return FLASH_SECTOR_9;else if (Address < ADDR_FLASH_SECTOR_11)return FLASH_SECTOR_10;return FLASH_SECTOR_11;#elseif(Address < ADDR_FLASH_SECTOR_1)       return FLASH_SECTOR_0;else if(Address < ADDR_FLASH_SECTOR_2)  return FLASH_SECTOR_1;else if(Address < ADDR_FLASH_SECTOR_3)  return FLASH_SECTOR_2;else if(Address < ADDR_FLASH_SECTOR_4)  return FLASH_SECTOR_3;else if(Address < ADDR_FLASH_SECTOR_5)  return FLASH_SECTOR_4;else if(Address < ADDR_FLASH_SECTOR_6)  return FLASH_SECTOR_5;else if(Address < ADDR_FLASH_SECTOR_7)  return FLASH_SECTOR_6;else if(Address < ADDR_FLASH_SECTOR_8)  return FLASH_SECTOR_7;else if(Address < ADDR_FLASH_SECTOR_9)  return FLASH_SECTOR_8;else if(Address < ADDR_FLASH_SECTOR_10) return FLASH_SECTOR_9;else if(Address < ADDR_FLASH_SECTOR_11) return FLASH_SECTOR_10;else if(Address < ADDR_FLASH_SECTOR_12) return FLASH_SECTOR_11;else if(Address < ADDR_FLASH_SECTOR_13) return FLASH_SECTOR_12;else if(Address < ADDR_FLASH_SECTOR_14) return FLASH_SECTOR_13;else if(Address < ADDR_FLASH_SECTOR_15) return FLASH_SECTOR_14;else if(Address < ADDR_FLASH_SECTOR_16) return FLASH_SECTOR_15;else if(Address < ADDR_FLASH_SECTOR_17) return FLASH_SECTOR_16;else if(Address < ADDR_FLASH_SECTOR_18) return FLASH_SECTOR_17;else if(Address < ADDR_FLASH_SECTOR_19) return FLASH_SECTOR_18;else if(Address < ADDR_FLASH_SECTOR_20) return FLASH_SECTOR_19;else if(Address < ADDR_FLASH_SECTOR_21) return FLASH_SECTOR_20;else if(Address < ADDR_FLASH_SECTOR_22) return FLASH_SECTOR_21;else if(Address < ADDR_FLASH_SECTOR_23) return FLASH_SECTOR_22;return FLASH_SECTOR_23;#endif
}/*** @brief  Gets the bank of a given address* @param  Addr: Address of the FLASH Memory* @retval The bank of a given address*/
static uint32_t GetBank(uint32_t Addr)
{uint32_t bank = 0;/* Sector in bank 1 */#if 1bank = FLASH_BANK_1;#elseif(Addr < ADDR_FLASH_SECTOR_12) bank = FLASH_BANK_1;else bank = FLASH_BANK_2;#endifreturn bank;
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION *//*** @}*//*** @}*//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

main.c

static void USB_GPIO_DeInit(void); USB引脚复位功能,效果就是模拟上电USB拔出100ms再插上。以前博客有详细说。

static void JumpToApp(void);跳转到APP函数。

#include <stdio.h>int fputc(int ch, FILE* FILE)
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);return ch;
}static void USB_GPIO_DeInit(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11 | GPIO_PIN_12, GPIO_PIN_RESET);/*Configure GPIO pin : BLINK_LED_Pin */GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLDOWN;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);HAL_Delay(100);
}static void JumpToApp(void)
{typedef  void (*pFunction)(void);static pFunction JumpToApplication;static uint32_t JumpAddress;/* Test if user code is programmed starting from USBD_DFU_APP_DEFAULT_ADD * address */if (((*(__IO uint32_t *) USBD_DFU_APP_DEFAULT_ADD) & 0x2FFC0000) == 0x20000000){/* Jump to user application */JumpAddress = *(__IO uint32_t *) (USBD_DFU_APP_DEFAULT_ADD + 4);JumpToApplication = (pFunction) JumpAddress;/* Initialize user application's Stack Pointer */__set_MSP((*(__IO uint32_t *) USBD_DFU_APP_DEFAULT_ADD));JumpToApplication();}
}int main(void)
{/* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();USB_GPIO_DeInit();MX_USART1_UART_Init();if(HAL_GPIO_ReadPin(WKUP_KEY_GPIO_Port, WKUP_KEY_Pin) != GPIO_PIN_SET){JumpToApp(); printf("跳转失败,可能跳转区域为空白\r\n");printf("开始进入DFU模式\r\n");}MX_USB_DEVICE_Init();printf("sudaroot DFU\r\n");HAL_GPIO_WritePin(RUN_LED_GPIO_Port, RUN_LED_Pin, GPIO_PIN_RESET);   /* Infinite loop */while (1){}
}

解释一下,if (((*(__IO uint32_t *) USBD_DFU_APP_DEFAULT_ADD) & 0x2FFC0000) == 0x20000000)这代码。

第一:USBD_DFU_APP_DEFAULT_ADD这个地址存放的是栈顶地址。

第二:有效的SRAM空间,SRAM基地址是0x20000000, F429IGT6的SRAM大小是256KB = 0x40000 byte

           由于地址是从0x20000000开始的,故0x20000000 ~ 0x2003FFFF为有效空间。‭                                                                  

第三:栈顶地址 & 0x2FFC0000 == 0x20000000,的意思是判断栈顶是否合法有效,即是否在0x20000000 ~ 0x2003FFFF为有               效空间内。

            那么0x2FFC0000又是怎么算出来的?把0x3FFFF取反得到0xFFFC 0000‬,由于且不小于0x20000000,
           所以0x20000000 | 0xFFFC 0000 = 0x2 FFFC 0000;

现象:

1、正常上电,有APP就跳转,没有就进入DFU模式。

2、按住按键再上电,进入DFU模式。

进入DFU模式后,插上板子通过USB连接到电脑,打开设备管理器 和 上面安装的DfuSe_Demo

双击分区,得到各个分区的权限。

  全篇完。

本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解,记录成长笔记。
笔记是以最简单的方式,只展示最核心的原理。
若有与 大神大大 见解有歧义,我绝对坚信 大神大大 见解是对的,我的是错的。
若无积分等无法下载源码,可加入QQ群657407920下载交流经验。感谢~!

 

 

这篇关于STM32CbueMX之 USB下载更新固件Download Firmware Update(DFU)之一BootLoader程序编写的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/697395

相关文章

uniapp接入微信小程序原生代码配置方案(优化版)

uniapp项目需要把微信小程序原生语法的功能代码嵌套过来,无需把原生代码转换为uniapp,可以配置拷贝的方式集成过来 1、拷贝代码包到src目录 2、vue.config.js中配置原生代码包直接拷贝到编译目录中 3、pages.json中配置分包目录,原生入口组件的路径 4、manifest.json中配置分包,使用原生组件 5、需要把原生代码包里的页面修改成组件的方

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

Lipowerline5.0 雷达电力应用软件下载使用

1.配网数据处理分析 针对配网线路点云数据,优化了分类算法,支持杆塔、导线、交跨线、建筑物、地面点和其他线路的自动分类;一键生成危险点报告和交跨报告;还能生成点云数据采集航线和自主巡检航线。 获取软件安装包联系邮箱:2895356150@qq.com,资源源于网络,本介绍用于学习使用,如有侵权请您联系删除! 2.新增快速版,简洁易上手 支持快速版和专业版切换使用,快速版界面简洁,保留主

Android多线程下载见解

通过for循环开启N个线程,这是多线程,但每次循环都new一个线程肯定很耗内存的。那可以改用线程池来。 就以我个人对多线程下载的理解是开启一个线程后: 1.通过HttpUrlConnection对象获取要下载文件的总长度 2.通过RandomAccessFile流对象在本地创建一个跟远程文件长度一样大小的空文件。 3.通过文件总长度/线程个数=得到每个线程大概要下载的量(线程块大小)。

一道经典Python程序样例带你飞速掌握Python的字典和列表

Python中的列表(list)和字典(dict)是两种常用的数据结构,它们在数据组织和存储方面有很大的不同。 列表(List) 列表是Python中的一种有序集合,可以随时添加和删除其中的元素。列表中的元素可以是任何数据类型,包括数字、字符串、其他列表等。列表使用方括号[]表示,元素之间用逗号,分隔。 定义和使用 # 定义一个列表 fruits = ['apple', 'banana

brew install opencv@2 时报错 Error: Can't create update lock in /usr/local/var/homebrew/locks!

解决方案,报错里已经说明了: 我的解决方案: sudo chown -R "$USER":admin /usr/local   stackoverflow上的答案 I was able to solve the problem by using chown on the folder: sudo chown -R "$USER":admin /usr/local Also you'

MySQL理解-下载-安装

MySQL理解: mysql:是一种关系型数据库管理系统。 下载: 进入官网MySQLhttps://www.mysql.com/  找到download 滑动到最下方:有一个开源社区版的链接地址: 然后就下载完成了 安装: 双击: 一直next 一直next这一步: 一直next到这里: 等待加载完成: 一直下一步到这里

美容美发店营销版微信小程序源码

打造线上生意新篇章 一、引言:微信小程序,开启美容美发行业新纪元 在数字化时代,微信小程序以其便捷、高效的特点,成为了美容美发行业营销的新宠。本文将带您深入了解美容美发营销微信小程序,探讨其独特优势及如何助力商家实现业务增长。 二、微信小程序:美容美发行业的得力助手 拓宽客源渠道:微信小程序基于微信社交平台,轻松实现线上线下融合,帮助商家快速吸引潜在客户,拓宽客源渠道。 提升用户体验:

BD错误集锦8——在集成Spring MVC + MyBtis编写mapper文件时需要注意格式 You have an error in your SQL syntax

报错的文件 <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.yuan.dao.YuanUserDao"><!

如何利用echarts编写立体的柱状图表

1、引入 import * as echarts from 'echarts' 2、创建图标容器 3、调用渲染 <template><div ref="eachrtsBox" style="width: 200px;height: 200px;"></div></template><script>import * as echarts from 'echarts'export d