使用stm32的usb做IAP升级功能,利用stm32cubemx生成代码。参考http://www.51hei.com/bbs/dpj-40235-1.html http://www.51hei.com/bbs/dpj-40938-1.html http://www.stm32cube.com/question/500
关键操作:
1.配置应用程序起始地址:0x8008000.打算使用32k空间作为boot程序空间,所以应用程序地址=起始地址+32k(0x8000)=0x8008000;
2.flash属性设置:由于使用的stm32F103zet6的flash是2k一页,共256页。所以前16页只读,后面240页可读写擦除。所以设置为16*02Ka,240*02Kg
3.生成代码后需增加usbd_dfu_if.c各函数内容如下:
在MEM_If_Erase_FS()函数中需特殊注意擦除地址为应用程序起始地址0x8008000,页数为总页数-boot占用的页数。
/**
******************************************************************************
* @file : usbd_dfu_if.c
* @brief :
******************************************************************************
*
* Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_dfu_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_DFU
* @brief usbd core module
* @{
*/
/** @defgroup USBD_DFU_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_DFU_Private_Defines
* @{
*/
#define FLASH_DESC_STR "@Internal Flash /0x08000000/16*02Ka,240*02Kg"
/* USER CODE BEGIN PRIVATE_DEFINES */
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_DFU_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_AUDIO_IF_Private_Variables
* @{
*/
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_DFU_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_DFU_Private_FunctionPrototypes
* @{
*/
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 */
/* 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 MEM_If_Init_FS
* Memory initialization routine.
* @param None
* @retval 0 if operation is successful, MAL_FAIL else.
*/
uint16_t MEM_If_Init_FS(void)
{
/* USER CODE BEGIN 0 */
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_BSY | FLASH_FLAG_WRPERR |FLASH_FLAG_PGERR);
return (USBD_OK);
/* USER CODE END 0 */
}
/**
* @brief MEM_If_DeInit_FS
* De-Initializes Memory.
* @param None
* @retval 0 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 MEM_If_Erase_FS
* 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 UserStartSector;
uint32_t SectorError;
FLASH_EraseInitTypeDef pEraseInit;
/* Unlock the Flash to enable the flash control register access *************/
MEM_If_Init_FS();
/* Get the sector where start the user flash area */
pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
pEraseInit.PageAddress = USBD_DFU_APP_DEFAULT_ADD;
pEraseInit.NbPages = 240;
if (HAL_FLASHEx_Erase(&pEraseInit, &SectorError) != HAL_OK)
{
/* Error occurred while page erase */
return (1);
}
return (USBD_OK);
/* USER CODE END 2 */
}
/**
* @brief MEM_If_Write_FS
* 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 0 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 2;
}
}
else
{
/* Error occurred while writing data in Flash memory */
return 1;
}
}
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief MEM_If_Read_FS
* 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);
// return (uint8_t*)(USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief Flash_If_GetStatus_FS
* 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 0 if operation is successful
*/
uint16_t MEM_If_GetStatus_FS (uint32_t Add, uint8_t Cmd, uint8_t *buffer)
{
/* USER CODE BEGIN 5 */
uint16_t FLASH_PROGRAM_TIME = 50;
uint16_t FLASH_ERASE_TIME = 50;
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:
default:
buffer[1] = (uint8_t)FLASH_ERASE_TIME;
buffer[2] = (uint8_t)(FLASH_ERASE_TIME << 8);
buffer[3] = 0;
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
在main.c中加入:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
if(HAL_GPIO_ReadPin( KEY0_GPIO_Port , KEY0_Pin ) != GPIO_PIN_RESET)
{
/* Test if user code is programmed starting from USBD_DFU_APP_DEFAULT_ADD address */
if(((*(__IO uint32_t*)USBD_DFU_APP_DEFAULT_ADD) & 0x2FFE0000 ) == 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();
}
}
MX_USB_DEVICE_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
编译烧录ok。
再生成app,需修改成这样:
并且修改宏#define VECT_TAB_OFFSET 0x8000,将应用程序中断向量表重映射到正确地址。
再使用DfuFileMgr转为dfu文件,然后使用DfuSeDemo升级即可;
以上是STM32F103zet6的操作,在STM32F0系列中有所不同。
由于M0并没有SCB->VTOR,所以无法直接在应用程序中直接修改VECT_TAB_OFFSET 来改变中断表。所以采用将表放入ram中。
关键操作:
1.将中断表复制到ram起始地址0x20000000,共48*4字节
2.配置存储地址的映射,存储地址的映射,即把SRAM映射到代码执行区的地址0X00处。SYSCFG_CFGR1|=3;
3.在工程设置中将已占用的ram让出来。其他操作与F103相同。
附F103zet6工程,http://pan.baidu.com/s/1hsBVCjU 3mfx
官方文档 http://pan.baidu.com/s/1kViJp1H, xki6