概述

本篇文章介绍如何使用STM32HAL库,内部Flash在特定页读写保护示例。

硬件:STM32F103CBU6最小系统板
软件:Keil 5.29  + STM32CubeMX5.6.1

一、使用方法

通过参阅《STM32中文参考手册》得知,不同型号的芯片对应FLASH大小不一样,如下所示:

在《STM32中文参考手册》pdf文档中找到,第2.3.3小节:嵌入式闪存,对应的页数30。

这里我使用的是STM32F103CBU6的FLASH是128k,通过手册得知是属于中容量,所以只需看下面FLASH地址分配图与每一页对应的大小(字节)即可。

想更详细的了解,请阅读《STM32中文参考手册》,网上大把可以下载,这里就给出此文档的下载链接了。

二、STM32CubeMx配置

三、Examples

打开STM32CubeMx生成的keil工程,新建bsp文件夹,同时分别新建bsp_readWriteProtect.c与bsp_readWriteProtect.h文件,并把这两个文件,添加keil工程中来即可。

添加头文件路径

1、bsp_readWriteProtect.h文件

#ifndef __BSP_READWRITEPROTECT_H
#define __BSP_READWRITEPROTECT_H
#ifdef __cplusplusextern "C" {
#endif#define   WRITE_PROTECTION_DISABLE  1
#define     WRITE_PROTECTION_ENABLE   1#define  PASSED      1
#define     FAILED      0
#define     TestStatus  int//写入的起始地址与结束地址
#define FLASH_USER_START_ADDR ((uint32_t)0x08008000)
#define FLASH_USER_END_ADDR     ((uint32_t)0x0800C000)#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  )/* ALL PAGES */
//#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 | \
//                                  OB_WRP_PAGES64TO67 | OB_WRP_PAGES68TO71 | OB_WRP_PAGES72TO75 | OB_WRP_PAGES76TO79 | \
//                                  OB_WRP_PAGES80TO83 | OB_WRP_PAGES84TO87 | OB_WRP_PAGES88TO91 | OB_WRP_PAGES92TO95 | \
//                                  OB_WRP_PAGES96TO99 | OB_WRP_PAGES100TO103 | OB_WRP_PAGES104TO107 | OB_WRP_PAGES108TO111 | \
//                                  OB_WRP_PAGES112TO115 | OB_WRP_PAGES116TO119 | OB_WRP_PAGES120TO123 | OB_WRP_PAGES124TO127 )void FLASH_Test(void);#endif

2、bsp_readWriteProtect.c文件

#include "bsp_readWriteProtect.h"
#include "stdio.h"
#include "stm32f1xx_hal.h"FLASH_OBProgramInitTypeDef  OptionsBytesStruct;
FLASH_EraseInitTypeDef          EraseInitStruct;uint32_t Address = 0x00; //记录写入的地址
uint32_t DATA_32 = 0x3210ABCD; //记录写入的数据
uint32_t PageError = 0;void FLASH_Test(void)
{printf("Beginning of the test\r\n");/* 初始化测试状态 */ TestStatus MemoryProgramStatus = PASSED;/* 解锁 Flash 以启用闪存控制寄存器访问*/HAL_FLASH_Unlock();/* 解锁选项字节*/HAL_FLASH_OB_Unlock();/* 获取页面写保护状态*/HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);#if WRITE_PROTECTION_DISABLE     #if 0   /* 检查所需页面是否已被写保护*/if ((OptionsBytesStruct.WRPPage & OB_WRP_ALLPAGES) != OB_WRP_ALLPAGES) {/*恢复写保护页面 */OptionsBytesStruct.OptionType = OPTIONBYTE_WRP;OptionsBytesStruct.WRPState = OB_WRPSTATE_DISABLE;OptionsBytesStruct.WRPPage = OB_WRP_ALLPAGES;if (HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK) {while (1) {//printf("Run failed\r\n");}}/* 生成系统重置以加载新选项字节值*/HAL_FLASH_OB_Launch();}#else/* 检查所需页面是否已被写保护*/if ((OptionsBytesStruct.WRPPage & FLASH_PAGE_TO_BE_PROTECTED) != FLASH_PAGE_TO_BE_PROTECTED) {/*恢复写保护页面 */OptionsBytesStruct.OptionType = OPTIONBYTE_WRP;OptionsBytesStruct.WRPState = OB_WRPSTATE_DISABLE;OptionsBytesStruct.WRPPage = FLASH_PAGE_TO_BE_PROTECTED;if (HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK) {while (1) {//printf("Run failed\r\n");}}/* 生成系统重置以加载新选项字节值*/HAL_FLASH_OB_Launch();}#endif
#elif defined WRITE_PROTECTION_ENABLE /* 检查所需页面是否尚未写保护*/if (((~OptionsBytesStruct.WRPPage) & FLASH_PAGE_TO_BE_PROTECTED )   != FLASH_PAGE_TO_BE_PROTECTED) {/* 启用页面写保护*/OptionsBytesStruct.OptionType = OPTIONBYTE_WRP;OptionsBytesStruct.WRPState = OB_WRPSTATE_ENABLE;OptionsBytesStruct.WRPPage = FLASH_PAGE_TO_BE_PROTECTED; if (HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK) {while (1) {//LED1_ONprintf("Run failed\r\n");}}/* 生成系统重置以加载新选项字节值*/HAL_FLASH_OB_Launch();}
#endif /* WRITE_PROTECTION_DISABLE *//*锁定选项字节*/printf("Lock option byte\r\n");HAL_FLASH_OB_Lock();/* 所选页面未被写保护*/if ((OptionsBytesStruct.WRPPage & FLASH_PAGE_TO_BE_PROTECTED) != FLASH_PAGE_TO_BE_PROTECTED) {/*填写 EraseInit 结构*/EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;EraseInitStruct.PageAddress = FLASH_USER_START_ADDR;EraseInitStruct.NbPages = (FLASH_USER_END_ADDR - FLASH_USER_START_ADDR)    / FLASH_PAGE_SIZE;if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK){/*页面擦除时发生错误。用户可以在这里添加一些代码来处理这个错误PageError 将包含有问题的页面,然后知道此页面上的代码错误,用户可以调用函数'HAL_FLASH_GetError() '*/while (1) {printf("Run failed\r\n");}}/*由 FLASH_USER_START_ADDR 和 FLASH_USER_END_ADDR 定义的地址处的 DATA_32 FLASH 字程序 */Address = FLASH_USER_START_ADDR;while (Address < FLASH_USER_END_ADDR) {if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, DATA_32) == HAL_OK) {Address = Address + 4;} else {while (1) {printf("Run failed\r\n");}}}/*检查书面数据的正确性*/ Address = FLASH_USER_START_ADDR; while (Address < FLASH_USER_END_ADDR) {if ((*(__IO uint32_t*) Address) != DATA_32) {MemoryProgramStatus = FAILED;}Address += 4;}} else {/*所需页面受写保护 *//* 检查是否允许在此页面中写入 */Address = FLASH_USER_START_ADDR;if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, DATA_32)!= HAL_OK) {/* 编程期间返回错误。 *//* 检查 WRPERR 标志是否设置良好 */if (HAL_FLASH_GetError() == HAL_FLASH_ERROR_WRP) {MemoryProgramStatus = FAILED;} else {while (1) {printf("Run failed\r\n");}}} else {while (1) {printf("Run failed\r\n");}}}HAL_FLASH_Lock();/*检查程序数据是否存在问题*/if (MemoryProgramStatus == PASSED) {//printf("Run successful\r\n");} else {while (1) {printf("Run failed\r\n");}}while (1) {}
}

3、mian.c文件

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under BSD 3-Clause license,* the "License"; You may not use this file except in compliance with the* License. You may obtain a copy of the License at:*                        opensource.org/licenses/BSD-3-Clause********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp_readWriteProtect.h"
#include "stdio.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 *//* 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();/* USER CODE BEGIN 2 */FLASH_Test();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* 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};/** Initializes the CPU, AHB and APB busses clocks */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 busses 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();}
}/* 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 *//* 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,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

四、运行结果


指定页写保护
修改:bsp_readWriteProtect.h文件

下载代码运行:

编译,下载程序如下所示:

解除无法下载问题,使用ST-Link Utility工具


擦除失败

解除擦除问题:




再次擦除芯片,可以成功擦除。

传送门->代码
(注:提供的代码,与文章给出的有些地方需要做修改,按照文章给出代码即可)

五、总结

好了,就介绍到此。

STM32HAL库-内部Flash在指定页读写保护示例相关推荐

  1. HAL库内部flash及IAP(boot)升级

    1.内部flash的用法 1.闪存模块存储器组织(STM32F407) STM32的闪存模块由:主存储器.系统存储器.OPT区域和选项字节等4部分组成.如下图所示: 1.主储存器(flash):有11 ...

  2. stm32hal库应用笔记之 硬件I2C读写ZD24C64

    话不多说 直接上资料 这是ZD24C64 数据手册里面的读写操作时序. 数据手册网上有很多相信大家也能随便就找到. 如下图所示: 这是使用iic按字节写操作 器件地址:我的是0xA0 来不及解释了赶快 ...

  3. stm32hal库应用笔记之硬件IIC读写SHTC31000温湿度传感器

    话不多说上图: 完成的数据手册百度吧 嘻嘻 这是SHTC31000芯片的时序图: 这个怎么看我就不多解释了哈 SHTC3.h #ifndef SHTC3_SHTC3_H_ #define SHTC3_ ...

  4. stm32内部Flash读写

    文章目录 1.stm32内部flash介绍 2.读写驱动编写 3.源码 上篇文章讲到了STM32来驱动外部flah的操作,flash真是好东西啊,内存大,能存的东西多,这样我们就可以用它来做一些大点的 ...

  5. map文件分析 stm32_使用STM32内部Flash额外的空间来存储数据

    本次分享关于STM32内部FLASH的笔记. STM32 芯片内部的 FLASH 存储器,主要用于存储我们代码.如果内部FLASH存储完我们的代码还有剩余的空间,那么这些剩余的空间我们就可以利用起来, ...

  6. STM32内部flash详解(1)

    STM32 内部FLAsh概述 今天说一下STM32中的内部flash. 当我们把写好的代码下载MCU中,这个代码时存放在flash中的.当芯片重启复位上电后,会通过内核对flash进行代码的加载运行 ...

  7. APM32F103VCT6 写内部Flash失败解决方案(亲试可用)

    文章目录 1 前言 2 APM32F103xCxDxE 与 Sxx32F103xCxDxE 差异 3 两种解决方案 3.1 解决方案1 - 换芯片型号 3.2 解决方案2 - 改代码 4. 想说的话 ...

  8. STM32HAL库-针对芯片内部FLASH读保护实现防篡改、破解功能(详解)

    目录 概述 一.使用方法 二.STM32CubeMx配置​ 三.Examples 四.运行结果 五.总结 概述 本篇文章介绍如何使用STM32HAL库,针对芯片读写保护实现防篡改.破解功能(详解),本 ...

  9. STM32HAL库-F4-针对芯片内部FLASH读保护实现防篡改、破解功能(详解)

    概述 本篇文章介绍如何使用STM32HAL库,针对芯片读写保护实现防篡改.破解功能(详解),本案例还包含内部FLASH读写数据,本质就是操作Flash. 硬件:STM32F401CEU6最小系统板(内 ...

最新文章

  1. lvs+iptables持久连接
  2. sqlserver linkserver
  3. NSArray打印汉字的方法
  4. 从基础到高级讲解Kafka
  5. JEECG - 基于代码生成器的J2EE智能开发框架 杂记:【演示视频和源码】
  6. 【Kubernetes】mac 安装minikube
  7. web\app可视化图表设计模板,UI设计师临摹学习的帮手
  8. ADO.NET与ORM的比较(4):EntityFramework实现CRUD
  9. html audio无法播放,audio 无法播放的问题
  10. 机顶盒ttl无法输入_一个作业,多个TTL——Flink SQL 细粒度TTL配置的实现(二)
  11. android:textStyle 设置加粗并倾斜
  12. m126a linux驱动下载,hpm126a驱动下载
  13. CATIA怎么约束快捷键_Catia快捷键怎么设置?CATIA小技巧-设置快捷键方法
  14. 为什么我的QQ会被冻结?
  15. 谁是史上最强-用爬虫分析IMDB TOP250电影数据
  16. 云计算领域常见的一些专业术语、专有名词总结(一)
  17. 输入一个四位数将其加密后输出c语言,从键盘输入一个四位数-按如下规则加密后输出...
  18. 2015年度个人总结(公司版)
  19. 选购硬盘HDD、SSD、SSHD、IDE、SATA、SCSI、SAS、PCIe、M.2、USB
  20. 你想知道,Microsoft Edge这种巨型项目是如何进行版本管理的吗?

热门文章

  1. VLC for Android源码下载和编译
  2. 【万物物联】Siri+快捷指令+onenet控制掌控板
  3. 计算机考试的知识要记忆背,2017计算机等级考试(NCRE)备考小技巧
  4. 老人与海好词100英文带翻译_老人与海优美段落英文,英文的优美句子,带翻译,越多越好,谢谢...
  5. 从年轻大学教师待遇说到大学教学质量
  6. 大数据时代,IT行业的热门岗位有哪些?9大前景分析
  7. APP测试的主要内容
  8. 重庆科技学院计算机考研资料汇总
  9. html 转换 hta,HTA (HTML Application) 簡介
  10. invoke调用成员方法(无参和有参):