STM32HAL库-F1内部Flash读写操作(官网驱动)
目录
一、代码
二、运行结果
三、总结
概述
本文章内部Flash,驱动代码参考ST官网代码综合修改完成,调试没有问题,在此提供该大家参考,同时做个笔录也方便后续自己查阅,直接上代码。Flash合理分配方便后续添加IAP功能做准备。
硬件:STM32F103CBT6最小系统板
软件:Keil 5.29 + STM32CubeMX5.6.1

每个型号对应的FLASH操作都不一样,需要查阅对应的datasheet,这里不再赘述,也可以参考我这篇文章前面部分
链接,网上也有类似文章。
想更详细的了解,请阅读《STM32中文参考手册》,自行上网查找资料下载。
一、代码
1、usart.c
/* USER CODE BEGIN Header */
/********************************************************************************* @file usart.c* @brief This file provides code for the configuration* of the USART instances.******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"/* USER CODE BEGIN 0 *//* USER CODE END 0 */UART_HandleTypeDef huart1;/* USART1 init function */void MX_USART1_UART_Init(void)
{/* USER CODE BEGIN USART1_Init 0 *//* USER CODE END USART1_Init 0 *//* USER CODE BEGIN USART1_Init 1 *//* USER CODE END USART1_Init 1 */huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN USART1_Init 2 *//* USER CODE END USART1_Init 2 */}void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspInit 0 *//* USER CODE END USART1_MspInit 0 *//* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**USART1 GPIO ConfigurationPA9 ------> USART1_TXPA10 ------> USART1_RX*/GPIO_InitStruct.Pin = GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_10;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USER CODE BEGIN USART1_MspInit 1 *//* USER CODE END USART1_MspInit 1 */}
}void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspDeInit 0 *//* USER CODE END USART1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_USART1_CLK_DISABLE();/**USART1 GPIO ConfigurationPA9 ------> USART1_TXPA10 ------> USART1_RX*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);/* USER CODE BEGIN USART1_MspDeInit 1 *//* USER CODE END USART1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */
#include "stdio.h"#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printfset to 'Yes') calls __io_putchar() */#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/*** @brief Retargets the C library printf function to the USART.* @param None* @retval None*/
PUTCHAR_PROTOTYPE
{/* Place your implementation of fputc here *//* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);return ch;
}int fgetc(FILE * f)
{uint8_t ch = 0;HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 0xffff);return ch;
}
/* USER CODE END 1 */
2、flash_if.h
/** flash_if.h** Created on: September 5th, 2020* Author: Champion*//* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FLASH_IF_H
#define __FLASH_IF_H/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/#ifdef STORAGE_BLK_SIZ
#undef STORAGE_BLK_SIZ
#endif#ifdef STORAGE_BLK_NBR
#undef STORAGE_BLK_NBR
#endif//#ifdef STORAGE_LUN_NBR
//#undef STORAGE_LUN_NBR
//#endif//#define STORAGE_LUN_NBR 1u
#define STORAGE_BLOCK_SIZE (2)
#define STORAGE_BLK_SIZ (1024/STORAGE_BLOCK_SIZE)
#define STORAGE_BLK_NBR ((50*1024)/STORAGE_BLK_SIZ) //分配地址以页对齐//#define FLASH_PAGE_SIZE 1024 //1 Kbyte per page
#define FLASH_START_ADDR 0x08000000 //Origin
#define FLASH_MAX_SIZE 0x00020000 //Max FLASH size = 128 Kbyte
#define FLASH_END_ADDR (FLASH_START_ADDR + FLASH_MAX_SIZE) //FLASH end address
#define FLASH_BOOT_START_ADDR (FLASH_START_ADDR) //Bootloader start address
#define FLASH_BOOT_SIZE 0x00006800 //26 Kbyte for bootloader
#define FLASH_APP_START_ADDR (FLASH_BOOT_START_ADDR + FLASH_BOOT_SIZE) //User application start address
#define FLASH_APP_SIZE 0x0000C800 //50 Kbyte for user application
#define FLASH_MSD_START_ADDR (FLASH_APP_START_ADDR + FLASH_APP_SIZE) //USB MSD start address
#define FLASH_MSD_SIZE 0x0000c800 //50 Kbyte for USB MASS Storage
#define FLASH_OTHER_START_ADDR (FLASH_MSD_START_ADDR + FLASH_MSD_SIZE) //Other free memory start address
#define FLASH_OTHER_SIZE (FLASH_END_ADDR - FLASH_OTHER_START_ADDR) //Free memory size 2Kbyte#define FLASH_MSD_BLK_NBR ((FLASH_END_ADDR - FLASH_MSD_START_ADDR - FLASH_OTHER_SIZE) / 1024) //50块
//#define FLASH_MSD_BLK_NBR ((FLASH_END_ADDR - FLASH_MSD_START_ADDR) / 1024) //100块//#define FLASH_START_ADDR_1 0x08008000#pragma pack (1)
typedef struct
{uint32_t FLASH_SIZE; /* Get flash size */ uint32_t SECTOR_COUNT; /* Get media size */ uint32_t SECTOR_SIZE; /* Get sector size */uint32_t BLOCK_SIZE; /* Block Size in Bytes */uint32_t STORAGE_LUN_NBr; /* 分区 */uint32_t STORAGE_BLOCK_NBR; /* 块数量(U盘总容量) */uint32_t STORAGE_BLOCK_SIZ; /* 块大小(U盘分配单元大小) */uint32_t PAGE_SIZE;
}Flash_Parameter;
#pragma pack ()
extern Flash_Parameter Flash_Paramet;/* Error code */
enum
{FLASHIF_OK = 0,FLASHIF_ERASEKO,FLASHIF_WRITINGCTRL_ERROR,FLASHIF_WRITING_ERROR,FLASHIF_PROTECTION_ERRROR
};/* protection type */
enum{FLASHIF_PROTECTION_NONE = 0,FLASHIF_PROTECTION_PCROPENABLED = 0x1,FLASHIF_PROTECTION_WRPENABLED = 0x2,FLASHIF_PROTECTION_RDPENABLED = 0x4,
};/* protection update */
enum {FLASHIF_WRP_ENABLE,FLASHIF_WRP_DISABLE
};/* Define the address from where user application will be loaded.Note: this area is reserved for the IAP code */
#define FLASH_PAGE_STEP FLASH_PAGE_SIZE /* Size of page : 1024 Kbytes */
#define APPLICATION_ADDRESS FLASH_USER_APP_START_ADDR //(uint32_t)0x08008000 /* Notable Flash addresses */
#define USER_FLASH_END_ADDRESS FLASH_END_ADDR///* Define the user application size */
#define USER_FLASH_SIZE FLASH_BOOT_SIZE /* Small default template application *//* Define bitmap representing user flash area that could be write protected (check restricted to pages 3-63). */
#define FLASH_PAGE_TO_BE_PROTECTED (OB_WRP_PAGES0TO3 | OB_WRP_PAGES4TO7 | OB_WRP_PAGES8TO11 | OB_WRP_PAGES12TO15 | \OB_WRP_PAGES16TO19 | OB_WRP_PAGES20TO23 | OB_WRP_PAGES24TO27 | OB_WRP_PAGES28TO31 | \OB_WRP_PAGES32TO35 | OB_WRP_PAGES36TO39 | OB_WRP_PAGES40TO43 | OB_WRP_PAGES44TO47 | \OB_WRP_PAGES48TO51 | OB_WRP_PAGES52TO55 | OB_WRP_PAGES56TO59 | OB_WRP_PAGES60TO63 )extern uint32_t AppAddresssCurren;/* Exported functions ------------------------------------------------------- */
void FLASH_If_Init(void);
uint32_t FLASH_If_Erase(uint32_t startSectorAddr, uint32_t NbrOfPages);
uint32_t FLASH_If_GetWriteProtectionStatus(void);
uint32_t FLASH_If_Write(uint32_t FlashAddress, uint32_t* pData, uint32_t DataLength);
uint32_t FLASH_If_Write2Byte(uint32_t FlashAddress, uint16_t* pData, uint32_t DataLength);
uint32_t FLASH_If_WriteProtectionConfig(uint32_t protectionstate);
uint32_t FLASH_If_Read(uint32_t FlashAddress, uint32_t* pData, uint32_t DataLength);
uint32_t FLASH_If_Read2Byte(uint32_t FlashAddress, uint16_t* pData, uint32_t DataLength);uint32_t FLASH_If_Write_Ex(uint32_t FlashAddress, uint32_t* Data, uint32_t DataLength, uint8_t is32bit);
uint32_t FLASH_If_Read_Ex(uint32_t FlashAddress, uint32_t* Data, uint32_t DataLength, uint8_t is32bit);
#endif /* __FLASH_IF_H *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
3、flash_if.c
/** flash_if.c** Created on: September 5th, 2020* Author: Champion*//** @addtogroup STM32F1xx_IAP* @{*//* Includes ------------------------------------------------------------------*/
#include "flash_if.h"
#include "stdio.h"uint32_t AppAddresssCurren = 0;
Flash_Parameter Flash_Paramet; //内部Flashuint8_t FLASH_Parameter_Init(Flash_Parameter *Para)
{Para->FLASH_SIZE = FLASH_MAX_SIZE;Para->SECTOR_COUNT = 45; /* Get media size */ Para->SECTOR_SIZE = 1024; /* Get sector size */Para->BLOCK_SIZE = 1024;Para->STORAGE_LUN_NBr = 1; /* 分区 */Para->STORAGE_BLOCK_NBR = 45; /* 块数量 */Para->STORAGE_BLOCK_SIZ = 512; /* 块大小 */Para->PAGE_SIZE = FLASH_PAGE_SIZE; /* 每一页大小 1024Kbyte */return 0;
}/*** @brief Unlocks Flash for write access* @param None* @retval None*/
void FLASH_If_Init(void)
{/* Unlock the Program memory */HAL_FLASH_Unlock();/* Clear all FLASH flags */__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
// /* Unlock the Program memory */
// HAL_FLASH_Lock();FLASH_Parameter_Init(&Flash_Paramet);
}/*** @brief Locks Flash for write access* @param None* @retval None*/
void FLASH_If_DeInit(void)
{HAL_FLASH_Lock();
}/*** @brief This function does an erase of all user flash area* @param startSectorAddr: start of user flash area* @retval FLASHIF_OK : user flash area successfully erased* FLASHIF_ERASEKO : error occurred*/
uint32_t FLASH_If_Erase(uint32_t startSectorAddr, uint32_t NbrOfPages)
{uint32_t NbrPages = 0;uint32_t PageError = 0;FLASH_EraseInitTypeDef pEraseInit;HAL_StatusTypeDef status = HAL_OK;/* Unlock the Flash to enable the flash control register access *************/ HAL_FLASH_Unlock();/* Get the sector where start the user flash area */NbrPages = (FLASH_END_ADDR - startSectorAddr)/FLASH_PAGE_SIZE;if(NbrOfPages > NbrPages) return FLASHIF_ERASEKO;pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;pEraseInit.PageAddress = startSectorAddr;pEraseInit.Banks = FLASH_BANK_1;pEraseInit.NbPages = NbrOfPages;status = HAL_FLASHEx_Erase(&pEraseInit, &PageError);/* Lock the Flash to disable the flash control register access (recommendedto protect the FLASH memory against possible unwanted operation) *********/HAL_FLASH_Lock();if (status != HAL_OK){/* Error occurred while page erase */return FLASHIF_ERASEKO;}return FLASHIF_OK;
}/* Public functions ---------------------------------------------------------*/
/*** @brief This function writes a data buffer in flash (data are 32-bit aligned).* @note After writing data buffer, the flash content is checked.* @param FlashAddress: start address for target location* @param pData: pointer on buffer with data to write* @param DataLength: length of data buffer (unit is 32-bit word)* @retval uint32_t 0: Data successfully written to Flash memory* 1: Error occurred while writing data in Flash memory* 2: Written Data in flash memory is different from expected one*/
uint32_t FLASH_If_Write(uint32_t FlashAddress, uint32_t* pData, uint32_t DataLength)
{uint32_t i = 0;/* Unlock the Flash to enable the flash control register access *************/HAL_FLASH_Unlock();for (i = 0; (i < DataLength) && (FlashAddress <= (FLASH_END_ADDR-4)); i++){/* Device voltage range supposed to be [2.7V to 3.6V], the operation willbe done by word */ if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FlashAddress, *(uint32_t*)(pData+i)) == HAL_OK) {printf("> Word FlashAddress:0x%X, pData[%d]:0x%X\r\n", FlashAddress, i, pData[i]);/* Check the written value */if (*(uint32_t*)FlashAddress != *(uint32_t*)(pData+i)){/* Flash content doesn't match SRAM content */printf("Word FLASHIF_WRITINGCTRL_ERROR\r\n");return(FLASHIF_WRITINGCTRL_ERROR);}/* Increment FLASH destination address */FlashAddress += 4;}else{/* Error occurred while writing data in Flash memory */printf("Word FLASHIF_WRITING_ERROR\r\n");return (FLASHIF_WRITING_ERROR);}}/* Lock the Flash to disable the flash control register access (recommendedto protect the FLASH memory against possible unwanted operation) *********/printf("Word FLASHIF_OK\r\n");HAL_FLASH_Lock();return (FLASHIF_OK);
}uint32_t FLASH_If_Write2Byte(uint32_t FlashAddress, uint16_t* pData, uint32_t DataLength)
{uint32_t i = 0;FLASH_If_Init();for (i = 0; (i < DataLength) && (FlashAddress <= USER_FLASH_END_ADDRESS); i++){/* Device voltage range supposed to be [2.7V to 3.6V], the operation willbe done by halfword */if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, FlashAddress, pData[i]) == HAL_OK){printf("> HalfWord FlashAddress:0x02%X, pData[%d]:0x%X\r\n", FlashAddress, i, pData[i]);/* Check the written value */if (*(uint16_t*)FlashAddress != pData[i]){FLASH_If_DeInit();/* Flash content doesn't match SRAM content */printf("HalfWord FLASHIF_WRITINGCTRL_ERROR\r\n");return(FLASHIF_WRITINGCTRL_ERROR);}/* Increment FLASH destination address */FlashAddress += 2;}else{FLASH_If_DeInit();/* Error occurred while writing data in Flash memory */printf("HalfWord FLASHIF_WRITING_ERROR\r\n");return (FLASHIF_WRITING_ERROR);}}FLASH_If_DeInit();printf("HalfWord FLASHIF_OK\r\n");return (FLASHIF_OK);
}uint32_t FLASH_If_WriteByte(uint32_t FlashAddress, uint8_t* pData, uint32_t DataLength)
{uint32_t i = 0;
// uint16_t pData_t = ((*pData << 8) | (*pData & 0x00));FLASH_If_Init();for (i = 0; (i < DataLength) && (FlashAddress <= USER_FLASH_END_ADDRESS); i++){/* Device voltage range supposed to be [2.7V to 3.6V], the operation willbe done by halfword */if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, FlashAddress, pData[i]) == HAL_OK){printf("> Byte FlashAddress:0x02%X, pData_t[%d]:0x%X\r\n", FlashAddress, i, pData[i]);/* Check the written value */if (*(uint16_t*)FlashAddress != pData[i]){FLASH_If_DeInit();/* Flash content doesn't match SRAM content */printf("Byte FLASHIF_WRITINGCTRL_ERROR\r\n");return(FLASHIF_WRITINGCTRL_ERROR);}/* Increment FLASH destination address */FlashAddress += 2;}else{FLASH_If_DeInit();/* Error occurred while writing data in Flash memory */printf("Byte FLASHIF_WRITING_ERROR\r\n");return (FLASHIF_WRITING_ERROR);}}FLASH_If_DeInit();printf("Byte FLASHIF_OK\r\n");return (FLASHIF_OK);
}uint32_t FLASH_If_Read(uint32_t FlashAddress, uint32_t* pData, uint32_t DataLength)
{uint32_t i = 0;for(i = 0; i < DataLength; i++){pData[i] = *(uint32_t*)FlashAddress;FlashAddress += 4;}return (FLASHIF_OK);
}uint32_t FLASH_If_Read2Byte(uint32_t FlashAddress, uint16_t* pData, uint32_t DataLength)
{uint32_t i = 0;for(i = 0; i < DataLength; i++){pData[i] = *(uint16_t*)FlashAddress;FlashAddress += 2;}return (FLASHIF_OK);
}uint32_t FLASH_If_ReadByte(uint32_t FlashAddress, uint8_t* pData, uint32_t DataLength)
{uint32_t i = 0;for(i = 0; i < DataLength; i++){pData[i] = *(uint16_t*)FlashAddress;FlashAddress += 2;}return (FLASHIF_OK);
}/*** @brief Returns the write protection status of application flash area.* @param None* @retval If a sector in application area is write-protected returned value is a combinaisonof the possible values : FLASHIF_PROTECTION_WRPENABLED, FLASHIF_PROTECTION_PCROPENABLED, ...* If no sector is write-protected FLASHIF_PROTECTION_NONE is returned.*/
uint32_t FLASH_If_GetWriteProtectionStatus(void)
{uint32_t ProtectedPAGE = FLASHIF_PROTECTION_NONE;FLASH_OBProgramInitTypeDef OptionsBytesStruct;/* Unlock the Flash to enable the flash control register access *************/FLASH_If_Init();/* Check if there are write protected sectors inside the user flash area ****/HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);/* Lock the Flash to disable the flash control register access (recommendedto protect the FLASH memory against possible unwanted operation) *********/FLASH_If_DeInit();/* Get pages already write protected ****************************************/ProtectedPAGE = ~(OptionsBytesStruct.WRPPage) & FLASH_PAGE_TO_BE_PROTECTED;/* Check if desired pages are already write protected ***********************/if(ProtectedPAGE != 0){/* Some sectors inside the user flash area are write protected */return FLASHIF_PROTECTION_WRPENABLED;}else{ /* No write protected sectors inside the user flash area */return FLASHIF_PROTECTION_NONE;}
}/*** @brief Configure the write protection status of user flash area.* @param protectionstate : FLASHIF_WRP_DISABLE or FLASHIF_WRP_ENABLE the protection* @retval uint32_t FLASHIF_OK if change is applied.*/
uint32_t FLASH_If_WriteProtectionConfig(uint32_t protectionstate)
{uint32_t ProtectedPAGE = 0x0;FLASH_OBProgramInitTypeDef config_new, config_old;HAL_StatusTypeDef result = HAL_OK;/* Get pages write protection status ****************************************/HAL_FLASHEx_OBGetConfig(&config_old);/* The parameter says whether we turn the protection on or off */config_new.WRPState = (protectionstate == FLASHIF_WRP_ENABLE ? OB_WRPSTATE_ENABLE : OB_WRPSTATE_DISABLE);/* We want to modify only the Write protection */config_new.OptionType = OPTIONBYTE_WRP;/* No read protection, keep BOR and reset settings */config_new.RDPLevel = OB_RDP_LEVEL_0;config_new.USERConfig = config_old.USERConfig; /* Get pages already write protected ****************************************/ProtectedPAGE = config_old.WRPPage | FLASH_PAGE_TO_BE_PROTECTED;/* Unlock the Flash to enable the flash control register access *************/ FLASH_If_Init();/* Unlock the Options Bytes *************************************************/HAL_FLASH_OB_Unlock();/* Erase all the option Bytes ***********************************************/result = HAL_FLASHEx_OBErase();if (result == HAL_OK){config_new.WRPPage = ProtectedPAGE;result = HAL_FLASHEx_OBProgram(&config_new);}return (result == HAL_OK ? FLASHIF_OK: FLASHIF_PROTECTION_ERRROR);
}
/*** @}*/uint32_t FLASH_If_Write_Ex(uint32_t FlashAddress, uint32_t* Data, uint32_t DataLength, uint8_t is32bit)
{
// uint8_t is32bit = (((uint32_t)Data)%4)? 0 : 1;FLASH_If_Init();if (FLASH_If_Erase(FlashAddress, 1) != FLASHIF_OK) {printf("Erase_error \n");}if (is32bit == 1) {FLASH_If_Write(FlashAddress, (uint32_t*)Data, DataLength);} else {FLASH_If_Write2Byte(FlashAddress, (uint16_t*)Data, DataLength);}return (FLASHIF_OK);
}uint32_t FLASH_If_Read_Ex(uint32_t FlashAddress, uint32_t* Data, uint32_t DataLength, uint8_t is32bit)
{
// uint8_t is32bit = (((uint32_t)Data)%4)? 0 : 1;FLASH_If_Init();if (is32bit == 1) {FLASH_If_Read(FlashAddress, (uint32_t*)Data, DataLength);} else {FLASH_If_Read2Byte(FlashAddress, (uint16_t*)Data, DataLength);}return (FLASHIF_OK);
} void Flash_ErasePage(uint32_t pageAddr)
{FLASH_EraseInitTypeDef EraseInitTypeDef;uint32_t pageError = 0;HAL_FLASH_Unlock();EraseInitTypeDef.TypeErase = FLASH_TYPEERASE_PAGES;EraseInitTypeDef.PageAddress = pageAddr;EraseInitTypeDef.NbPages = 1;if (HAL_FLASHEx_Erase(&EraseInitTypeDef, &pageError) != HAL_OK) {//打印错误码}HAL_FLASH_Lock();
}HAL_StatusTypeDef Flash_WriteHalfWord(uint32_t FlashAddress, uint16_t Data)
{HAL_StatusTypeDef status;HAL_FLASH_Unlock();status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, FlashAddress, Data);if (status != HAL_OK) {return HAL_ERROR;}HAL_FLASH_Lock();return (HAL_OK);
}uint16_t Flash_ReadHalfWord(uint32_t FlashAddress)
{return *(__IO uint16_t*) FlashAddress;
}void Flash_WriteBuffer(uint32_t FlashAddress, uint16_t* pData, uint32_t Len)
{HAL_FLASH_Unlock();for(uint32_t i = 0; i < Len; i++){HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, FlashAddress + i*2, pData[i]);}HAL_FLASH_Lock();
}void Flash_ReadBuffer(uint32_t FlashAddress, uint16_t* pData, uint32_t Len)
{for(uint32_t i = 0; i < Len; i++){pData[i] = *(__IO uint16_t*) (FlashAddress + i*2);}
}void test_flash_demo(void)
{#define DATA_LEN 5uint8_t write_data_8[DATA_LEN] = {0x11, 0x22, 0x33, 0x44, 0x55};uint8_t read_data_8[DATA_LEN] = {0};uint16_t write_data_16[DATA_LEN] = {0x1111, 0x2222, 0x3333, 0x4444, 0x5555};uint16_t read_data_16[DATA_LEN] = {0};uint32_t write_data_32[DATA_LEN] = {0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555};uint32_t read_data_32[DATA_LEN] = {0};// Flash_ErasePage(FLASH_APP_START_ADDR);// FLASH_If_Erase(FLASH_APP_START_ADDR, 1);// Flash_WriteBuffer(FLASH_APP_START_ADDR, write_data_16, DATA_LEN);// Flash_ReadBuffer(FLASH_APP_START_ADDR, read_data_16, DATA_LEN);
// for (uint16_t i = 0; i < DATA_LEN; i++)
// {
// printf("FLASH_OTHER_START_ADDR:0x%X, read_data_16[%d]:0x%X\r\n", FLASH_APP_START_ADDR + i*2, i, read_data_16[i]);
// }// FLASH_If_Erase(FLASH_OTHER_START_ADDR, 1);
// FLASH_If_Write(FLASH_OTHER_START_ADDR, write_data_32, DATA_LEN);
// FLASH_If_Read(FLASH_OTHER_START_ADDR, read_data_32, DATA_LEN);
// for (uint8_t i = 0; i < DATA_LEN; i++)
// {
// printf("FLASH_APP_START_ADDR:0x%X, read_data_32[%d]:0x%X\r\n", FLASH_OTHER_START_ADDR + i*4, i, read_data_32[i]);
// }FLASH_If_Write_Ex(FLASH_OTHER_START_ADDR, (uint32_t*)write_data_32, DATA_LEN, 1);FLASH_If_Read_Ex(FLASH_OTHER_START_ADDR, (uint32_t*)read_data_32, DATA_LEN, 1);for (uint16_t i = 0; i < DATA_LEN; i++){printf("FLASH_OTHER_START_ADDR:0x%X, read_data_16[%d]:0x%X\r\n", FLASH_OTHER_START_ADDR + i*4, i, read_data_32[i]);}FLASH_If_Erase(FLASH_APP_START_ADDR, 1);FLASH_If_Write2Byte(FLASH_APP_START_ADDR, (uint16_t*)write_data_16, DATA_LEN);FLASH_If_Read2Byte(FLASH_APP_START_ADDR, (uint16_t*)read_data_16, DATA_LEN);for (uint16_t i = 0; i < DATA_LEN; i++){printf("FLASH_OTHER_START_ADDR:0x%X, read_data_16[%d]:0x%X\r\n", FLASH_APP_START_ADDR + i*2, i, read_data_16[i]);} FLASH_If_Erase(FLASH_MSD_START_ADDR, 1);FLASH_If_WriteByte(FLASH_MSD_START_ADDR, write_data_8, DATA_LEN);FLASH_If_ReadByte(FLASH_MSD_START_ADDR, read_data_8, DATA_LEN);for (uint16_t i = 0; i < DATA_LEN; i++){printf("FLASH_OTHER_START_ADDR:0x%X, read_data_16[%d]:0x%X\r\n", FLASH_MSD_START_ADDR + i*2, i, read_data_8[i]);}
}/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
4、main.c
/* USER CODE BEGIN Header */
/********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "fatfs.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "flash_if.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* 创建产品信息文件 */
void create_product_info_file(void)
{FIL file;UINT bw;char info[] = "产品名称: STM32F103设备\n版本号: 1.0.0\n制造商: Your Company";if (f_open(&file, "产品信息.txt", FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) {f_write(&file, info, strlen(info), &bw);f_close(&file);}
}/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
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();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_FATFS_Init();MX_USB_DEVICE_Init();/* USER CODE BEGIN 2 */create_product_info_file();printf ("-----START LOG----- \n\r\n\r");printf ("FLASH_START_ADDR : %#x \n\r", FLASH_START_ADDR);printf ("FLASH_MAX_SIZE : %dKByte \n\r", FLASH_MAX_SIZE/1024);printf ("BOOT_START_ADDR : %#x \n\r", FLASH_BOOT_START_ADDR);printf ("BOOT_MEM_SIZE : %dKByte \n\r", FLASH_BOOT_SIZE/1024);printf ("APP_START_ADDR : %#x \n\r", FLASH_APP_START_ADDR);printf ("APP_MEM_SIZE : %dKByte \n\r", FLASH_APP_SIZE/1024);printf ("FLASH_MSD_START_ADDR : %#x \n\r", FLASH_MSD_START_ADDR);printf ("MSD_MEM_SIZE : %dKByte \n\r", FLASH_MSD_SIZE/1024);printf ("OTHER_START_ADDR : %#x \n\r", FLASH_OTHER_START_ADDR);printf ("OTHER_MEM_SIZE : %dKByte \n\r\n\r", FLASH_OTHER_SIZE/1024);printf ("FLASH_MSD_BLK_NBR : %dKByte \n\r\n\r", FLASH_MSD_BLK_NBR);extern void test_flash_demo(void);test_flash_demo();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);printf("Runing, I'm an MSD USB Bootloader... \r\n");HAL_Delay(1000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
二、运行结果

三、总结
好了,就介绍到此,感谢参阅,小小心得分享,希望能帮助到需要的攻城狮们^_^。
