你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32H7的内部Flash基础知识和HAL库API

[复制链接]
STMCU小助手 发布时间:2021-11-2 23:53
70.1 初学者重要提示
  本章2.5小节里面的Flash三级读保护是重点,务必要掌握明白。
  STM32H743XI有两个独立的BANK,一个BANK的编程和擦除操作对另一个BANK没有任何影响。但是如果用户应用程序和要擦写的Flash扇区在同一个BANK,在执行擦写操作时,用户应用程序将停止运行,包括中断服务程序。
  STM32H7的两个Flash BANK是256bit带宽,CPU访问是采用的两个64bit AXI总线。
  HAL库的内部Flash编程函数HAL_FLASH_Program固定编写32字节数据。
70.2 内部Flash基础知识
70.2.1 内部Flash的硬件框图
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解内部Flash的基本功能,然后再看手册了解细节。

aHR0cHM6Ly9pbWcyMDIwLmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDIwMDMvMTM3OTEwNy0yMDIw.png


通过这个框图,我们可以得到如下信息:

  sys_ck时钟输入
D1域总线时钟。

  po_rst输入
Power on reset 上电复位。

  d1_rst输入
D1域系统复位。

  flash_it输出
flash中断请求输出。

aHR0cHM6Ly9pbWcyMDIwLmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDIwMDMvMTM3OTEwNy0yMDIw.png


STM32H7的两个Flash BANK是独立的,读写和擦除互补影响,256bit带宽,CPU访问是采用的两个64bit AXI总线。

70.2.2 内部Flash框架
关于内部Flash的框架,了解以下几个知识点即可:

  256bit为单位,即32字节,并且每个单位配10bit的ECC校验位。正是这个原因要求大家对Flash进行编程时,必须以32字节为单位。
  两个独立的BANK,每个BANK有1MB容量。并且每个BANK的扇区大小固定为128KB,即8个扇区。



BANK1的地址范围:0x0800 0000到0x080F FFFF。

BANK2的地址范围:0x0810 0000到0x081F FFFF。

70.2.3 内部Flash读操作
STM32H7的内部Flash读操作跟内部RAM的读操作是一样的,支持64bit,32bit,16bt和8bit,使用比较简单。这里我们重点普及一个知识点,H7的内部Flash在不同主频下需要做的延迟参数:

aHR0cHM6Ly9pbWcyMDIwLmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDIwMDMvMTM3OTEwNy0yMDIw.png


对于上面的表格,大家可以看到,当延迟等待设置为0的时候,即无等待,单周期访问,速度可以做到70MHz。增加1个Flash周期后,访问速度可以做到140MHz。当增加到3个或4个Flash周期后,最高速度可以做到225MHz。

了解了这个知识点后,再来看下面的时序,非常具有参考意义:

注:ACLK、ARADDR、ARVALID、RDATA、RVALID 和RLAST是AXI总线信号。Flash读和Flash数据是 Flash 接口信号。

aHR0cHM6Ly9pbWcyMDIwLmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDIwMDMvMTM3OTEwNy0yMDIw.png


关于这个时序要要认识到以下几点:

  AXI总线发起读取信号后,Flash端等待了3个时钟周期(注意延迟三个周期,支持的Flash速度),之后连续读取了4个64bit数据。
  由于AXI总线是64bit的,所以1次读取就可以读出64bit数据,连续读取4次后,就是256bit,即Flash接口的一组数据,因为H7的Flash接口带宽是256bit的。
  如果不开Flash Cache的情况下,连续读可以提升性能。
下面是连续读取8个64bit数据的时序图,跟连续读取4个64bit数据基本是一样的,只是多读取了4组数据。

aHR0cHM6Ly9pbWcyMDIwLmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDIwMDMvMTM3OTEwNy0yMDIw.png


70.2.4 内部Flash写入和擦除操作
最重要的知识点放在开头说:STM32H7内部Flash的写操作地址必须是32字节对齐(此地址对32求余数为0),写入的数据量也必须是32字节整数倍,不足32字节整数倍,补0也要是整数倍。

这里我们重点了解Flash的写入和擦除流程。Flash的写入扇区流程如下:

先保证这块扇区空间之前已经擦除过了。
解锁Flash,通过HAL库的函数HAL_FLASH_Unlock实现。
检查是否写保护,使能Flash可以编程,然后对其进行编程操作,编程完毕后,等待编程完成,然后禁止Flash编程位。具体操作可以通过HAL库的函数HAL_FLASH_Program实现。


Flash的擦除流程如下:

解锁Flash,通过HAL库的函数HAL_FLASH_Unlock实现。
如果是BANK1或者BANK2需要擦除,调用函数FLASH_MassErase,然后等待擦除完成,完成之后关闭BANK1和BANK2的擦除请求位BER1/BER2
如果是扇区擦除,调用函数FLASH_Erase_Sector,然后等待擦除完成,完成之后关闭扇区的擦除请求位SER。
70.2.5 内部Flash读保护
内部Flash支持三级读保护RDP(read out protection)。

  Level 0(无保护)
默认设置,所有读写和擦除操作都可以正常支持。

  Level 1 (Flash连接保护)
  可以防止连接调试器时读取Flash内容,或者RAM中存有恶意获取代码,也是禁止的。因此只要调试器连接芯片,或者从内部RAM启动运行代码,都是禁止访问内部Flash的。
  如果没有检测到从内部RAM启动和系统bootloader启动且没有连接调试器,对用户Flash的读写和擦除操作都是允许的,并且其它安全存储区也是可以访问的。否则是禁止访问的,一旦检测到对Flash的读请求,将产生总线错误。
  如果将Level 1切换到Level 0时,用户Flash区和安全区域将被擦除。
  Level 2(设备保护和自举保护)
  所有调试特性被关闭。
  禁止从RAM启动。
  除了选项字节里面的SWAP位可以配置,其它位都无法更改。
  禁止了调试功能,且禁止了从RAM和系统bootloader启动,用户Flash区是可以执行读写和擦除操作的,访问其它安全存储区也是可以的。
特别注意:Level2修改是永久性的,一旦配置为Level2将不再支持被修改。

如果大家要设置读保护的话,使用HAL的API可以设置,也可以使用STM32CubeProg设置:

aHR0cHM6Ly9pbWcyMDIwLmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDIwMDMvMTM3OTEwNy0yMDIw.png


70.2.6 内部Flash选项字节
Flash选项字节主要用于boot地址设置,安全保护,Flash扇区保护等,涉及到的选项比较多。如果大家打算了解这一部分的话,使用STM32CubeProg进行设置即可,也比较方便。

aHR0cHM6Ly9pbWcyMDIwLmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDIwMDMvMTM3OTEwNy0yMDIw.png


70.2.7 内部Flash的ECC校验
这里先说下为什么内部Flash要带ECC校验,因为随着芯片的制造工艺水平越高,带电粒子产生的位翻转就越多,此时的ECC是必须要有的,一般可以纠正1-2个bit,安全等级高的Flash类存储器和RAM类都是必须要带ECC的。

对于STM32H7带的ECC校验,一般不需要用户去管理。

70.3 内部Flash的HAL库用法
70.3.1 内部Flash结构体FLASH_TypeDef
内部Flash相关的寄存器是通过HAL库中的结构体FLASH_TypeDef定义的,在stm32h743xx.h中可以找到这个类型定义:

  1. typedef struct
  2. {
  3.   __IO uint32_t ACR;            
  4.   __IO uint32_t KEYR1;           
  5.   __IO uint32_t OPTKEYR;         
  6.   __IO uint32_t CR1;            
  7.   __IO uint32_t SR1;            
  8.   __IO uint32_t CCR1;         
  9.   __IO uint32_t OPTCR;           
  10.   __IO uint32_t OPTSR_CUR;      
  11.   __IO uint32_t OPTSR_PRG;      
  12.   __IO uint32_t OPTCCR;         
  13.   __IO uint32_t PRAR_CUR1;      
  14.   __IO uint32_t PRAR_PRG1;      
  15.   __IO uint32_t SCAR_CUR1;      
  16.   __IO uint32_t SCAR_PRG1;      
  17.   __IO uint32_t WPSN_CUR1;      
  18.   __IO uint32_t WPSN_PRG1;      
  19.   __IO uint32_t BOOT_CUR;      
  20.   __IO uint32_t BOOT_PRG;      
  21.   uint32_t      RESERVED0[2];   
  22.   __IO uint32_t CRCCR1;         
  23.   __IO uint32_t CRCSADD1;      
  24.   __IO uint32_t CRCEADD1;        
  25.   __IO uint32_t CRCDATA;         
  26.   __IO uint32_t ECC_FA1;         
  27.   uint32_t      RESERVED1[40];  
  28.   __IO uint32_t KEYR2;           
  29.   uint32_t      RESERVED2;      
  30.   __IO uint32_t CR2;            
  31.   __IO uint32_t SR2;            
  32.   __IO uint32_t CCR2;            
  33.   uint32_t      RESERVED3[4];   
  34.   __IO uint32_t PRAR_CUR2;      
  35.   __IO uint32_t PRAR_PRG2;      
  36.   __IO uint32_t SCAR_CUR2;      
  37.   __IO uint32_t SCAR_PRG2;      
  38.   __IO uint32_t WPSN_CUR2;      
  39.   __IO uint32_t WPSN_PRG2;      
  40.   uint32_t      RESERVED4[4];   
  41.   __IO uint32_t CRCCR2;         
  42.   __IO uint32_t CRCSADD2;        
  43.   __IO uint32_t CRCEADD2;        
  44.   __IO uint32_t CRCDATA2;        
  45.   __IO uint32_t ECC_FA2;         
  46. } FLASH_TypeDef;
复制代码

这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。

__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:

  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

下面我们看下Flash的定义,在stm32h743xx.h文件。

  1. #define PERIPH_BASE              (0x40000000UL)
  2. #define D1_AHB1PERIPH_BASE       (PERIPH_BASE + 0x12000000UL)
  3. #define FLASH_R_BASE             (D1_AHB1PERIPH_BASE + 0x2000UL)
  4. #define FLASH                    ((FLASH_TypeDef *) FLASH_R_BASE) <----- 展开这个宏,(FLASH_TypeDef *)0x52002000
复制代码

我们访问Flash的CR1寄存器可以采用这种形式:FLASH->CR1 = 0。

70.3.2 内部Flash擦除结构体FLASH_EraseInitTypeDef
下面是做内部Flash擦除的结构体,用到的地方比较多:
  1. typedef struct
  2. {
  3.   uint32_t TypeErase;  
  4.   uint32_t Banks;      
  5.   uint32_t Sector;      
  6.   uint32_t NbSectors;   
  7.   uint32_t VoltageRange;
  8. } FLASH_EraseInitTypeDef;
复制代码

下面将结构体成员逐一做个说明:

  TypeErase
用于选择BANK擦除还是扇区擦除,H743有两个BANK,每个BANK有个8个扇区,每个扇区128KB。具体支持的参数如下:

  1. #define FLASH_TYPEERASE_SECTORS      0x00U  /* 扇区方式擦除 */
  2. #define FLASH_TYPEERASE_MASSERASE    0x01U  /* BANK方式擦除 */
复制代码

  Banks
用于选择要擦除的BANK,或者两个BANK都选择:

  1. #define FLASH_BANK_1             0x01U                         /* Bank 1 */
  2. #define FLASH_BANK_2             0x02U                         /* Bank 2 */
  3. #define FLASH_BANK_BOTH          (FLASH_BANK_1 | FLASH_BANK_2) /* Bank1 和 Bank2 */
复制代码
Sector
用于选择要擦除的扇区:

  1. #define FLASH_SECTOR_0             0U       /* Sector Number 0   */
  2. #define FLASH_SECTOR_1             1U       /* Sector Number 1   */
  3. #define FLASH_SECTOR_2             2U       /* Sector Number 2   */
  4. #define FLASH_SECTOR_3             3U       /* Sector Number 3   */
  5. #define FLASH_SECTOR_4             4U       /* Sector Number 4   */
  6. #define FLASH_SECTOR_5             5U       /* Sector Number 5   */
  7. #define FLASH_SECTOR_6             6U       /* Sector Number 6   */
  8. #define FLASH_SECTOR_7             7U       /* Sector Number 7   */
复制代码

  NbSectors
用于设置要擦除的扇区个数,对于STM32H743来说,范围1到8。

  VoltageRange
用于设置编程的并行位数,电压不同,位数不同:

  1. #define FLASH_VOLTAGE_RANGE_1        0x00000000U       /* Flash program/erase by 8 bits  */
  2. #define FLASH_VOLTAGE_RANGE_2        FLASH_CR_PSIZE_0  /* Flash program/erase by 16 bits */
  3. #define FLASH_VOLTAGE_RANGE_3        FLASH_CR_PSIZE_1  /* Flash program/erase by 32 bits */
  4. #define FLASH_VOLTAGE_RANGE_4        FLASH_CR_PSIZE    /* Flash program/erase by 64 bits */
复制代码

70.3.3 内部Flash的操作总结
使用方法由HAL库提供:

  Flash编程函数操作流程
  Flash解锁函数HAL_FLASH_Unlock。
  Flash查询方式编程HAL_FLASH_Program。
  Flash中断方式编程HAL_FLASH_Program_IT。
  Flash上锁函数HAL_FLASH_Lock。
  选项字节编程流程
  选项字节解锁函数HAL_FLASH_OB_Unlock。
  选项字节加载函数HAL_FLASH_OB_Launch。
  选项字节编程函数HAL_FLASHEx_OBProgram。
  选项字节加锁函数HAL_FLASH_OB_Lock。
  Flash擦除流程
  Flash解锁函数HAL_FLASH_Unlock。
  Flash查询方式擦除HAL_FLASHEx_Erase。
  Flash中断方式擦除HAL_FLASHEx_Erase_IT。
  Flash上锁函数HAL_FLASH_Lock。
70.4 内部Flash源文件stm32h7xx_hal_flash.c
此文件涉及到的函数较多,这里把几个常用的函数做个说明:
  HAL_FLASH_Unlock
  HAL_FLASH_Lock
  HAL_FLASHEx_Erase
  HAL_FLASH_Program
70.4.1 函数HAL_FLASH_Lock
函数原型:

  1. HAL_StatusTypeDef HAL_FLASH_Lock(void)
  2. {
  3. /* 设置FLASH Bank1控制寄存器Lock位,即禁止访问 */
  4.   SET_BIT(FLASH->CR1, FLASH_CR_LOCK);

  5. /* 验证Flash Bank1是否已经被锁住 */
  6.   if (READ_BIT(FLASH->CR1, FLASH_CR_LOCK) == 0U)
  7.   {
  8.     return HAL_ERROR;
  9.   }

  10. /* 设置FLASH Bank2控制寄存器Lock位,即禁止访问 */
  11.   SET_BIT(FLASH->CR2, FLASH_CR_LOCK);

  12. /* 验证Flash Bank2是否已经被锁住 */
  13.   if (READ_BIT(FLASH->CR2, FLASH_CR_LOCK) == 0U)
  14.   {
  15.     return HAL_ERROR;
  16.   }

  17.   return HAL_OK;
  18. }
复制代码

函数描述:

用于Flash加锁,加锁后将不能对Flash进行编程和擦除。

70.4.2 函数HAL_FLASH_Unlock
函数原型:

  1. HAL_StatusTypeDef HAL_FLASH_Unlock(void)
  2. {
  3.   if(READ_BIT(FLASH->CR1, FLASH_CR_LOCK) != 0U)
  4.   {
  5.     /* 允许访问Flash Bank1 */
  6.     WRITE_REG(FLASH->KEYR1, FLASH_KEY1);
  7.     WRITE_REG(FLASH->KEYR1, FLASH_KEY2);

  8.     /* 验证是否已经解锁 */
  9.     if (READ_BIT(FLASH->CR1, FLASH_CR_LOCK) != 0U)
  10.     {
  11.       return HAL_ERROR;
  12.     }
  13.   }

  14.   if(READ_BIT(FLASH->CR2, FLASH_CR_LOCK) != 0U)
  15.   {
  16.     /* 允许访问Flash Bank2 */
  17.     WRITE_REG(FLASH->KEYR2, FLASH_KEY1);
  18.     WRITE_REG(FLASH->KEYR2, FLASH_KEY2);

  19.     /* 验证是否已经解锁 */
  20.     if (READ_BIT(FLASH->CR2, FLASH_CR_LOCK) != 0U)
  21.     {
  22.       return HAL_ERROR;
  23.     }
  24.   }

  25.   return HAL_OK;
  26. }
复制代码


函数描述:

此函数用于Flash解锁,解锁后可以对Flash进行擦除和编程。

70.4.3 函数HAL_FLASH_Program
函数原型:

  1. HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t FlashAddress, uint32_t DataAddress)
  2. {
  3.   HAL_StatusTypeDef status;
  4.   __IO uint32_t *dest_addr = (__IO uint32_t *)FlashAddress;
  5.   __IO uint32_t *src_addr = (__IO uint32_t*)DataAddress;
  6.   uint32_t bank;
  7.   uint8_t row_index = FLASH_NB_32BITWORD_IN_FLASHWORD;

  8.   /* 检测参数 */
  9.   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
  10.   assert_param(IS_FLASH_PROGRAM_ADDRESS(FlashAddress));

  11.   /* 上锁 */
  12.   __HAL_LOCK(&pFlash);

  13. #if defined (FLASH_OPTCR_PG_OTP)
  14.   if((IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress)) || (IS_FLASH_PROGRAM_ADDRESS_OTP(FlashAddress)))
  15. #else
  16.   if(IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress))
  17. #endif
  18.   {
  19.     bank = FLASH_BANK_1;
  20.   }
  21.   else
  22.   {
  23.     bank = FLASH_BANK_2;
  24.   }

  25.   /* 错误标识,无错误 */
  26.   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;

  27.   /* 等待操作完成 */
  28.   status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, bank);

  29.   if(status == HAL_OK)
  30.   {
  31.     if(bank == FLASH_BANK_1)
  32.     {
  33. #if defined (FLASH_OPTCR_PG_OTP)
  34.       if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
  35.       {
  36.         /* 设置OTP寄存器的PG位,使能可以编程 */
  37.         SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
  38.       }
  39.       else
  40. #endif
  41.       {
  42.         /* 设置PG位,使能可编程 */
  43.         SET_BIT(FLASH->CR1, FLASH_CR_PG);
  44.       }
  45.     }
  46.     else
  47.     {
  48.       /* 设置PG位 */
  49.       SET_BIT(FLASH->CR2, FLASH_CR_PG);
  50.     }

  51.     __ISB();
  52.     __DSB();

  53. #if defined (FLASH_OPTCR_PG_OTP)
  54.     if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
  55.     {
  56.       /* 编程OTP(16 bits) */
  57.       *(__IO uint16_t *)FlashAddress = *(__IO uint16_t*)DataAddress;
  58.     }
  59.     else
  60. #endif
  61.     {
  62.       /* 对Flash进行编程 */
  63.       do
  64.       {
  65.         *dest_addr = *src_addr;
  66.         dest_addr++;
  67.         src_addr++;
  68.         row_index--;
  69.      } while (row_index != 0U);
  70.     }

  71.     __ISB();
  72.     __DSB();

  73.     /* 等待最后一次操作完成 */
  74.     status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, bank);

  75. #if defined (FLASH_OPTCR_PG_OTP)
  76.     if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
  77.     {
  78.       /* 如果编程操作完成,关闭OTP PG位 */
  79.       CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
  80.     }
  81.     else
  82. #endif
  83.     {
  84.       if(bank == FLASH_BANK_1)
  85.       {
  86.         /* 如果操作完成,关闭PG位 */
  87.         CLEAR_BIT(FLASH->CR1, FLASH_CR_PG);
  88.       }
  89.       else
  90.       {
  91.         /* 如果操作完成,关闭PG位 */
  92.         CLEAR_BIT(FLASH->CR2, FLASH_CR_PG);
  93.       }
  94.     }
  95.   }

  96.   /* 解锁 */
  97.   __HAL_UNLOCK(&pFlash);

  98.   return status;
  99. }
复制代码



函数描述:

此函数主要用于Flash编程,固定编程32个字节数据。

函数参数:

  第1个参数是要编程的Flash类型,支持两种参数:
  FLASH_TYPEPROGRAM_FLASHWORD,用于芯片内部Flash编程。
  FLASH_TYPEPROGRAM_OTPWORD,用于芯片内部OTP存储区编程,当前的H743并没有这个区域,所以可以忽略。
  第2个参数是要编程的Flash地址。
  第3个参数是要编程到Flash的数据地址。
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示串口忙,正在使用中。
注意事项:

  第2个参数的Flash地址要是32字节对齐的,即此地址对32求余等于0。
  第3个参数务必要是32字节的整数倍。
70.4.4 函数HAL_FLASHEx_Erase
函数原型:

  1. HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError)
  2. {
  3.   HAL_StatusTypeDef status = HAL_OK;
  4.   uint32_t sector_index;

  5. /* 检查参数 */
  6.   assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
  7.   assert_param(IS_FLASH_BANK(pEraseInit->Banks));

  8. /* 上锁 */
  9.   __HAL_LOCK(&pFlash);

  10. /* 无错误 */
  11.   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;

  12. /* 等待BANK1的操作完成 */
  13.   if((pEraseInit->Banks & FLASH_BANK_1) == FLASH_BANK_1)
  14.   {
  15.     if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1) != HAL_OK)
  16.     {
  17.       status = HAL_ERROR;
  18.     }
  19.   }

  20. /* 等待BANK2的操作完成 */
  21.   if((pEraseInit->Banks & FLASH_BANK_2) == FLASH_BANK_2)
  22.   {
  23.     if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2) != HAL_OK)
  24.     {
  25.       status = HAL_ERROR;
  26.     }
  27.   }

  28.   if(status == HAL_OK)
  29.   {
  30.     if(pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
  31.     {
  32.   /* 整个BANK1或者BANK2擦除 */
  33.       FLASH_MassErase(pEraseInit->VoltageRange, pEraseInit->Banks);

  34.   /* 等待操作完成 */
  35.       if((pEraseInit->Banks & FLASH_BANK_1) == FLASH_BANK_1)
  36.       {
  37.         if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1) != HAL_OK)
  38.         {
  39.           status = HAL_ERROR;
  40.         }
  41.     /* 如果擦除完成,关闭BANK1的BER位 */
  42.         FLASH->CR1 &= (~FLASH_CR_BER);
  43.       }
  44.       if((pEraseInit->Banks & FLASH_BANK_2) == FLASH_BANK_2)
  45.       {
  46.         if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2) != HAL_OK)
  47.         {
  48.           status = HAL_ERROR;
  49.         }
  50.     /* 如果擦除操作完成,关闭BANK2的BER位 */
  51.         FLASH->CR2 &= (~FLASH_CR_BER);
  52.       }
  53.     }
  54.     else
  55.     {
  56.   /* 初始化扇区错误码 */
  57.       *SectorError = 0xFFFFFFFFU;

  58.   /* 扇区方式擦除 */
  59.       for(sector_index = pEraseInit->Sector; sector_index < (pEraseInit->NbSectors + pEraseInit->Sector);
  60. sector_index++)
  61.       {
  62.         FLASH_Erase_Sector(sector_index, pEraseInit->Banks, pEraseInit->VoltageRange);

  63.         if((pEraseInit->Banks & FLASH_BANK_1) == FLASH_BANK_1)
  64.         {
  65.       /* 等待BANK1操作完成 */
  66.           status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1);

  67.       /* 如果擦除操作完成,禁止SER位 */
  68.           FLASH->CR1 &= (~(FLASH_CR_SER | FLASH_CR_SNB));
  69.         }
  70.         if((pEraseInit->Banks & FLASH_BANK_2) == FLASH_BANK_2)
  71.         {
  72.       /* 等待BANK2操作完成 */
  73.           status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2);

  74.       /* 如果擦除操作完成,禁止SER位 */
  75.           FLASH->CR2 &= (~(FLASH_CR_SER | FLASH_CR_SNB));
  76.         }

  77.         if(status != HAL_OK)
  78.         {
  79.       /* 如果擦除出错,停止后续擦除,返回擦除异常的扇区号 */
  80.           *SectorError = sector_index;
  81.           break;
  82.         }
  83.       }
  84.     }
  85.   }

  86. /* 解锁 */
  87.   __HAL_UNLOCK(&pFlash);

  88.   return status;
  89. }
复制代码

函数描述:

用于内部Flash的批量擦除(BANK擦除)和扇区方式擦除。

函数参数:

  第1个参数是FLASH_EraseInitTypeDef类型结构体指针变量。
  第2个参数是错误码返回,返回0xFFFFFFFF表示全部正确,返回其它值是擦除过程中的错误扇区。
  返回值,返回HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
70.5 总结
本章节就为大家讲解这么多,对于内部Flash编程来说,掌握本章节的这些知识点就够用了,更多的知识点可以看STM32H7的参考手册学习。


收藏 评论0 发布时间:2021-11-2 23:53

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版