STM32G4x FLASH 读写(修改HAL库驱动)

主要工作就是把HAL的超时用LL库延时替代,保留了中断擦写模式、轮询等待擦写,待验证哈。

笔者用的芯片为STM32G473CBT6 128KB Flash,开环环境为CUBEMX+MDK5.32,因为G4已经没有标准库了,笔者还是习惯使用标准库的开发方式,所以选择了LL库开发应用,但是LL库没有对Flash进行支持,所以笔者想通过修改HAL库的Flash驱动来使用。

介绍下Datasheet内容,STM32G473系列有支持 ECC 的 最大512 KB 闪存、两个边写边读的存储体、专有代码读出保护 (PCROP)、安全存储区域、1 KB OTP区域。

STM32G473xB/xC/xE 器件具有高达 512 KB 的嵌入式闪存,可用于存储程序和数据。

闪存接口特性:

        – 单存储体或双存储体操作模式

        – 双存储体模式下的边写边读 (RWW)

此功能允许在对另一存储体执行擦除或编程操作的同时从一个存储体执行读取操作。还支持双组启动。(双分区升级貌似很方便)

通过选项字节可以配置灵活的保护:

• 读出保护(RDP),用于保护整个存储器。提供三种保护级别:

        – 0 级:无读出保护

        – 1 级:存储器读出保护;如果连接了调试功能或选择了 RAM 启动或启动加载程序,则无法读取或写入闪存

        – 第 2 级:芯片读出保护;调试功能(Cortex-M4 JTAG 和串行线)、RAM 中的引导和引导加载程序选择被禁用(JTAG 熔丝)。这种选择是不可逆转的。(产品定型之后)

• 写保护(WRP):保护区域不被擦除和编程。

• 专有代码读出保护(PCROP):可以保护闪存的一部分,防止第三方读写。该保护区是只执行的,只能由STM32 CPU作为指令代码访问,而严格禁止所有其他访问(DMA、调试和CPU数据读取、写入和擦除)。当 RDP 保护从级别 1 更改为级别 0 时,附加选项位 (PCROP_RDP) 允许选择是否擦除 PCROP 区域。

• 安全存储区域:闪存的一部分可以通过选项字节配置为安全的。复位后,该安全存储区域不受保护,其行为类似于主闪存的其余部分(执行、读取、写入访问)。当安全时,对该安全存储区域的任何访问都会产生相应的读/写错误。

安全内存区域的目的是保护敏感代码和数据(安全密钥存储),这些代码和数据只能在启动时执行一次,除非发生新的重置,否则永远不会再次执行。

闪存嵌入纠错码 (ECC) 功能,支持:

• 单错误检测和纠正(应该指字节)

• 双错误检测

• ECC 失败的地址可在 ECC 寄存器中读取

• 1 KB(128 个双字)OTP(单字节)时间可编程)用于用户数据。 OTP 区域仅在 Bank 1 中可用。 OTP 数据无法擦除且只能写入一次。(常用来写密钥)

Flash的相关特性

查看参考手册发现STM32G4系列芯片FLASH分成好几类

4类器件

• 高达512 KB 的闪存(单块)

• 64 位数据宽度的闪存读取操作

• 页擦除和批量擦除

2类设备

• 高达128 KB 的闪存(单块)

• 64 位数据宽度的闪存读取操作

• 页擦除和批量擦除

 3类器件

• 高达 512 KB 的闪存,采用双存储体架构,支持边写边读功能 (RWW)

• 支持两种数据宽度模式的闪存读取操作:

        – 单存储体模式 DBANK=0:128 位读访问

        – 双存储体模式 DBANK=1:64 位读访问

• 页擦除、存储体擦除和批量擦除(两个存储体)

根据描述,STM32G473应该是第3类器件

接着来看,闪存结构

该闪存具有以下主要特性:

• 容量高达 512 KB,单存储体模式(读取宽度为 128 位)或双存储体模式(读取宽度为 64 位)

• 通过 BFB2 选项支持双启动模式位(仅在双存储体模式下)

• 当 DBANK 位置 1 时,为双存储体模式:

        – 512 KB 组织为 2 个存储体作为主存储器

        – 页大小为 2 KB

        – 72 位宽数据读取(64 位加 8 ECC 位)

        – Bank和批量擦除

• DBANK 复位时,为单存储体模式:

        – 512 KB 组织在一个存储体中作为主存储器

        – 页大小为 4 KB

        – 144 位宽数据读取(128 位加 2x8 ECC 位)

        – 批量擦除

结构划分如下:

• 根据双存储体配置位划分的主存储器块结构:

        – 当使能双存储体(DBANK 位置位)时,闪存分为 2 个 256 KB 的存储体,每个存储体的组织方式如下:

                主存储器块包含 128 个 2 KB 页

                每页由 8 行 256 字节组成

        – 当禁用双存储体(DBANK 位复位)时,主存储器块被组织为一个 512 KB 的单存储体,如下所示:

                主存储器包含 128 个 4 KB 页的块

                每个页由 8 行 512 字节组成

• 信息块包含:

        – 设备在系统内存引导模式下从其引导的系统内存。该区域保留供 STMicroElectronics 使用,包含引导加载程序,用于通过以下接口之一对闪存重新编程:USART、SPI、I2C、FDCAN、USB。它在设备制造时由意法半导体进行编程,并防止虚假写入/擦除操作。如需了解更多详细信息,请参阅 www.st.com 上提供的 AN2606。(就是ST的bootloader,如ISP下载等)

        – 1 KB(128 个双字)OTP(一次性可编程)字节用于用户数据。 OTP 区域仅在 Bank 1 中可用。 OTP 数据无法擦除且只能写入一次。如果只有一位为 0,则即使值为 0x0000 0000 0000 0000,也无法再写入整个双字。

        – 用户配置的选项字节。

存储器结构基于主区域和信息块,如表所示。

查看G473的配置文件,可以看大看到DBANK初始化置位,为双区模式,128KB划分两个64KB分区,每一个从页0到页31,32x2KBx2=128KB。后面为功能介绍,因为移植官方驱动,我决定现在去测试一下代码。

直接给代码。

/********************************************************************************* @file       flash.h* @author     Amos* @brief      Header for flash.c file.* @version    v1.0.0******************************************************************************* @attention*******************************************************************************//* Define to prevent recursive inclusion -------------------------------------*/
#ifndef FLASH_H__
#define FLASH_H__#ifdef __cplusplus
extern "C" {
#endif/* Includes ------------------------------------------------------------------*/
#include "main.h"/* Exported constants --------------------------------------------------------*/
/*** @brief  FLASH_Error FLASH Error*/
#define FLASH_ERROR_NONE        0x00000000U
#define FLASH_ERROR_OP          FLASH_FLAG_OPERR
#define FLASH_ERROR_PROG        FLASH_FLAG_PROGERR
#define FLASH_ERROR_WRP         FLASH_FLAG_WRPERR
#define FLASH_ERROR_PGA         FLASH_FLAG_PGAERR
#define FLASH_ERROR_SIZ         FLASH_FLAG_SIZERR
#define FLASH_ERROR_PGS         FLASH_FLAG_PGSERR
#define FLASH_ERROR_MIS         FLASH_FLAG_MISERR
#define FLASH_ERROR_FAST        FLASH_FLAG_FASTERR
#define FLASH_ERROR_RD          FLASH_FLAG_RDERR
#define FLASH_ERROR_OPTV        FLASH_FLAG_OPTVERR
#define FLASH_ERROR_ECCC        FLASH_FLAG_ECCC
#define FLASH_ERROR_ECCD        FLASH_FLAG_ECCD
#if defined (FLASH_OPTR_DBANK)
#define FLASH_ERROR_ECCC2       FLASH_FLAG_ECCC2
#define FLASH_ERROR_ECCD2       FLASH_FLAG_ECCD2
#endif/*** @brief  FLASH_Type_Erase FLASH Erase Type*/
#define FLASH_TYPEERASE_PAGES       0x00U     /*!<Pages erase only*/
#define FLASH_TYPEERASE_MASSERASE   0x01U     /*!<Flash mass erase activation*//*** @brief  FLASH_Banks FLASH Banks*/
#define FLASH_BANK_1            0x00000001U                   /*!< Bank 1   */
#if defined (FLASH_OPTR_DBANK)
#define FLASH_BANK_2            0x00000002U                   /*!< Bank 2   */
#define FLASH_BANK_BOTH         (FLASH_BANK_1 | FLASH_BANK_2) /*!< Bank1 and Bank2  */
#else
#define FLASH_BANK_BOTH         FLASH_BANK_1                  /*!< Bank 1   */
#endif/*** @brief  FLASH_Type_Program FLASH Program Type*/
#define FLASH_TYPEPROGRAM_DOUBLEWORD        0x00U   /*!< Program a double-word (64-bit) at a specified address.*/
#define FLASH_TYPEPROGRAM_FAST              0x01U   /*!< Fast program a 32 row double-word (64-bit) at a specified address.And another 32 row double-word (64-bit) will be programmed */
#define FLASH_TYPEPROGRAM_FAST_AND_LAST     0x02U   /*!< Fast program a 32 row double-word (64-bit) at a specified address.And this is the last 32 row double-word (64-bit) programmed */
/*** @brief  FLASH_OB_Type FLASH Option Bytes Type*/
#define OPTIONBYTE_WRP          0x01U   /*!< WRP option byte configuration */
#define OPTIONBYTE_RDP          0x02U   /*!< RDP option byte configuration */
#define OPTIONBYTE_USER         0x04U   /*!< USER option byte configuration */
#define OPTIONBYTE_PCROP        0x08U   /*!< PCROP option byte configuration */
#define OPTIONBYTE_BOOT_LOCK    0x10U   /*!< Boot lock option byte configuration */
#define OPTIONBYTE_SEC          0x20U   /*!< Securable memory option byte configuration *//*** @brief  FLASH_OB_WRP_Area FLASH WRP Area*/
#define OB_WRPAREA_BANK1_AREAA  0x00U   /*!< Flash Bank 1 Area A */
#define OB_WRPAREA_BANK1_AREAB  0x01U   /*!< Flash Bank 1 Area B */
#if defined (FLASH_OPTR_DBANK)
#define OB_WRPAREA_BANK2_AREAA  0x02U   /*!< Flash Bank 2 Area A */
#define OB_WRPAREA_BANK2_AREAB  0x04U   /*!< Flash Bank 2 Area B */
#endif/*** @brief  FLASH_OB_Boot_Lock FLASH Boot Lock*/
#define OB_BOOT_LOCK_DISABLE    0x00000000U             /*!< Boot Lock Disable */
#define OB_BOOT_LOCK_ENABLE     FLASH_SEC1R_BOOT_LOCK   /*!< Boot Lock Enable *//*** @brief  FLASH_OB_Read_Protection FLASH Option Bytes Read Protection*/
#define OB_RDP_LEVEL_0          0xAAU
#define OB_RDP_LEVEL_1          0xBBU
#define OB_RDP_LEVEL_2          0xCCU   /*!< Warning: When enabling read protection level 2 it's no more possible to go back to level 1 or 0 */
/*** @brief  FLASH_OB_USER_Type FLASH Option Bytes User Type*/
#define OB_USER_BOR_LEV         0x00000001U     /*!< BOR reset Level */
#define OB_USER_nRST_STOP       0x00000002U     /*!< Reset generated when entering the stop mode */
#define OB_USER_nRST_STDBY      0x00000004U     /*!< Reset generated when entering the standby mode */
#define OB_USER_IWDG_SW         0x00000008U     /*!< Independent watchdog selection */
#define OB_USER_IWDG_STOP       0x00000010U     /*!< Independent watchdog counter freeze in stop mode */
#define OB_USER_IWDG_STDBY      0x00000020U     /*!< Independent watchdog counter freeze in standby mode */
#define OB_USER_WWDG_SW         0x00000040U     /*!< Window watchdog selection */
#if defined (FLASH_OPTR_DBANK)
#define OB_USER_BFB2            0x00000080U     /*!< Dual-bank boot */
#define OB_USER_DBANK           0x00000100U     /*!< Single bank with 128-bits data or two banks with 64-bits data */
#endif
#if defined (FLASH_OPTR_PB4_PUPEN)
#define OB_USER_PB4_PUPEN       0x00000100U     /*!< USB power delivery dead-battery/TDI pull-up */
#endif
#define OB_USER_nBOOT1          0x00000200U     /*!< Boot configuration */
#define OB_USER_SRAM_PE         0x00000400U     /*!< SRAM parity check enable (first 32kB of SRAM1 + CCM SRAM) */
#define OB_USER_CCMSRAM_RST     0x00000800U     /*!< CCMSRAM Erase when system reset */
#define OB_USER_nRST_SHDW       0x00001000U     /*!< Reset generated when entering the shutdown mode */
#define OB_USER_nSWBOOT0        0x00002000U     /*!< Software BOOT0 */
#define OB_USER_nBOOT0          0x00004000U     /*!< nBOOT0 option bit */
#define OB_USER_NRST_MODE       0x00008000U     /*!< Reset pin configuration */
#define OB_USER_IRHEN           0x00010000U     /*!< Internal Reset Holder enable *//*** @brief  FLASH_OB_USER_BOR_LEVEL FLASH Option Bytes User BOR Level*/
#define OB_BOR_LEVEL_0          FLASH_OPTR_BOR_LEV_0    /*!< Reset level threshold is around 1.7V */
#define OB_BOR_LEVEL_1          FLASH_OPTR_BOR_LEV_1    /*!< Reset level threshold is around 2.0V */
#define OB_BOR_LEVEL_2          FLASH_OPTR_BOR_LEV_2    /*!< Reset level threshold is around 2.2V */
#define OB_BOR_LEVEL_3          FLASH_OPTR_BOR_LEV_3    /*!< Reset level threshold is around 2.5V */
#define OB_BOR_LEVEL_4          FLASH_OPTR_BOR_LEV_4    /*!< Reset level threshold is around 2.8V *//*** @brief  FLASH_OB_USER_nRST_STOP FLASH Option Bytes User Reset On Stop*/
#define OB_STOP_RST             0x00000000U             /*!< Reset generated when entering the stop mode */
#define OB_STOP_NORST           FLASH_OPTR_nRST_STOP    /*!< No reset generated when entering the stop mode *//*** @brief  FLASH_OB_USER_nRST_STANDBY FLASH Option Bytes User Reset On Standby*/
#define OB_STANDBY_RST          0x00000000U             /*!< Reset generated when entering the standby mode */
#define OB_STANDBY_NORST        FLASH_OPTR_nRST_STDBY   /*!< No reset generated when entering the standby mode *//*** @brief  FLASH_OB_USER_nRST_SHUTDOWN FLASH Option Bytes User Reset On Shutdown*/
#define OB_SHUTDOWN_RST         0x00000000U             /*!< Reset generated when entering the shutdown mode */
#define OB_SHUTDOWN_NORST       FLASH_OPTR_nRST_SHDW    /*!< No reset generated when entering the shutdown mode *//*** @brief  FLASH_OB_USER_IWDG_SW FLASH Option Bytes User IWDG Type*/
#define OB_IWDG_HW              0x00000000U             /*!< Hardware independent watchdog */
#define OB_IWDG_SW              FLASH_OPTR_IWDG_SW      /*!< Software independent watchdog *//*** @brief  FLASH_OB_USER_IWDG_STOP FLASH Option Bytes User IWDG Mode On Stop*/
#define OB_IWDG_STOP_FREEZE     0x00000000U             /*!< Independent watchdog counter is frozen in Stop mode */
#define OB_IWDG_STOP_RUN        FLASH_OPTR_IWDG_STOP    /*!< Independent watchdog counter is running in Stop mode *//*** @brief  FLASH_OB_USER_IWDG_STANDBY FLASH Option Bytes User IWDG Mode On Standby*/
#define OB_IWDG_STDBY_FREEZE    0x00000000U             /*!< Independent watchdog counter is frozen in Standby mode */
#define OB_IWDG_STDBY_RUN         FLASH_OPTR_IWDG_STDBY /*!< Independent watchdog counter is running in Standby mode *//*** @brief  FLASH_OB_USER_WWDG_SW FLASH Option Bytes User WWDG Type*/
#define OB_WWDG_HW              0x00000000U             /*!< Hardware window watchdog */
#define OB_WWDG_SW              FLASH_OPTR_WWDG_SW      /*!< Software window watchdog */#if defined (FLASH_OPTR_DBANK)
/*** @brief  FLASH_OB_USER_BFB2 FLASH Option Bytes User BFB2 Mode*/
#define OB_BFB2_DISABLE         0x00000000U             /*!< Dual-bank boot disable */
#define OB_BFB2_ENABLE          FLASH_OPTR_BFB2         /*!< Dual-bank boot enable *//*** @brief  FLASH_OB_USER_DBANK FLASH Option Bytes User DBANK Type*/
#define OB_DBANK_128_BITS       0x00000000U             /*!< Single-bank with 128-bits data */
#define OB_DBANK_64_BITS        FLASH_OPTR_DBANK        /*!< Dual-bank with 64-bits data */
#endif#if defined (FLASH_OPTR_PB4_PUPEN)
/*** @brief  FLASH_OB_USER_PB4_PUPEN FLASH Option Bytes User PB4 PUPEN bit*/
#define OB_PB4_PUPEN_DISABLE    0x00000000U             /*!< USB power delivery dead-battery enabled/ TDI pull-up deactivated */
#define OB_PB4_PUPEN_ENABLE     FLASH_OPTR_PB4_PUPEN    /*!< USB power delivery dead-battery disabled/ TDI pull-up activated */
#endif/*** @brief  FLASH_OB_USER_nBOOT1 FLASH Option Bytes User BOOT1 Type*/
#define OB_BOOT1_SRAM           0x00000000U             /*!< Embedded SRAM1 is selected as boot space (if BOOT0=1) */
#define OB_BOOT1_SYSTEM         FLASH_OPTR_nBOOT1       /*!< System memory is selected as boot space (if BOOT0=1) *//*** @brief  FLASH_OB_USER_SRAM_PE FLASH Option Bytes User SRAM Parity Check Type*/
#define OB_SRAM_PARITY_ENABLE   0x00000000U              /*!< SRAM parity check enable (first 32kB of SRAM1 + CCM SRAM) */
#define OB_SRAM_PARITY_DISABLE  FLASH_OPTR_SRAM_PE       /*!< SRAM parity check disable (first 32kB of SRAM1 + CCM SRAM) *//*** @brief  FLASH_OB_USER_CCMSRAM_RST FLASH Option Bytes User CCMSRAM Erase On Reset Type*/
#define OB_CCMSRAM_RST_ERASE        0x00000000U             /*!< CCMSRAM erased when a system reset occurs */
#define OB_CCMSRAM_RST_NOT_ERASE    FLASH_OPTR_CCMSRAM_RST  /*!< CCMSRAM is not erased when a system reset occurs *//*** @brief  FLASH_OB_USER_nSWBOOT0 FLASH Option Bytes User Software BOOT0*/
#define OB_BOOT0_FROM_OB        0x00000000U             /*!< BOOT0 taken from the option bit nBOOT0 */
#define OB_BOOT0_FROM_PIN       FLASH_OPTR_nSWBOOT0     /*!< BOOT0 taken from PB8/BOOT0 pin *//*** @brief  FLASH_OB_USER_nBOOT0 FLASH Option Bytes User nBOOT0 option bit*/
#define OB_nBOOT0_RESET         0x00000000U             /*!< nBOOT0 = 0 */
#define OB_nBOOT0_SET           FLASH_OPTR_nBOOT0       /*!< nBOOT0 = 1 *//*** @brief  FLASH_OB_USER_NRST_MODE FLASH Option Bytes User NRST mode bit*/
#define OB_NRST_MODE_INPUT_ONLY     FLASH_OPTR_NRST_MODE_0  /*!< Reset pin is in Reset input mode only */
#define OB_NRST_MODE_GPIO           FLASH_OPTR_NRST_MODE_1  /*!< Reset pin is in GPIO mode only */
#define OB_NRST_MODE_INPUT_OUTPUT   FLASH_OPTR_NRST_MODE    /*!< Reset pin is in reset input and output mode *//*** @brief  FLASH_OB_USER_INTERNAL_RESET_HOLDER FLASH Option Bytes User internal reset holder bit*/
#define OB_IRH_DISABLE          0x00000000U             /*!< Internal Reset holder disable */
#define OB_IRH_ENABLE           FLASH_OPTR_IRHEN        /*!< Internal Reset holder enable *//*** @brief  FLASH_OB_PCROP_RDP FLASH Option Bytes PCROP On RDP Level Type*/
#define OB_PCROP_RDP_NOT_ERASE  0x00000000U                 /*!< PCROP area is not erased when the RDP level is decreased from Level 1 to Level 0 */
#define OB_PCROP_RDP_ERASE      FLASH_PCROP1ER_PCROP_RDP    /*!< PCROP area is erased when the RDP level is decreased from Level 1 to Level 0 (full mass erase) */
/*** @brief  FLASH_Latency FLASH Latency*/
#define FLASH_LATENCY_0         FLASH_ACR_LATENCY_0WS   /*!< FLASH Zero wait state */
#define FLASH_LATENCY_1         FLASH_ACR_LATENCY_1WS   /*!< FLASH One wait state */
#define FLASH_LATENCY_2         FLASH_ACR_LATENCY_2WS   /*!< FLASH Two wait states */
#define FLASH_LATENCY_3         FLASH_ACR_LATENCY_3WS   /*!< FLASH Three wait states */
#define FLASH_LATENCY_4         FLASH_ACR_LATENCY_4WS   /*!< FLASH Four wait states */
#define FLASH_LATENCY_5         FLASH_ACR_LATENCY_5WS   /*!< FLASH Five wait state */
#define FLASH_LATENCY_6         FLASH_ACR_LATENCY_6WS   /*!< FLASH Six wait state */
#define FLASH_LATENCY_7         FLASH_ACR_LATENCY_7WS   /*!< FLASH Seven wait states */
#define FLASH_LATENCY_8         FLASH_ACR_LATENCY_8WS   /*!< FLASH Eight wait states */
#define FLASH_LATENCY_9         FLASH_ACR_LATENCY_9WS   /*!< FLASH Nine wait states */
#define FLASH_LATENCY_10        FLASH_ACR_LATENCY_10WS  /*!< FLASH Ten wait state */
#define FLASH_LATENCY_11        FLASH_ACR_LATENCY_11WS  /*!< FLASH Eleven wait state */
#define FLASH_LATENCY_12        FLASH_ACR_LATENCY_12WS  /*!< FLASH Twelve wait states */
#define FLASH_LATENCY_13        FLASH_ACR_LATENCY_13WS  /*!< FLASH Thirteen wait states */
#define FLASH_LATENCY_14        FLASH_ACR_LATENCY_14WS  /*!< FLASH Fourteen wait states */
#define FLASH_LATENCY_15        FLASH_ACR_LATENCY_15WS  /*!< FLASH Fifteen wait states *//*** @brief  FLASH_Keys FLASH Keys*/
#define FLASH_KEY1              0x45670123U     /*!< Flash key1 */
#define FLASH_KEY2              0xCDEF89ABU     /*!< Flash key2: used with FLASH_KEY1 to unlock the FLASH registers access */#define FLASH_PDKEY1            0x04152637U     /*!< Flash power down key1 */
#define FLASH_PDKEY2            0xFAFBFCFDU     /*!< Flash power down key2: used with FLASH_PDKEY1 to unlock the RUN_PD bit in FLASH_ACR */#define FLASH_OPTKEY1           0x08192A3BU     /*!< Flash option byte key1 */
#define FLASH_OPTKEY2           0x4C5D6E7FU     /*!< Flash option byte key2: used with FLASH_OPTKEY1 to allow option bytes operations */
/*** @brief  FLASH_Flags FLASH Flags Definition*/
#define FLASH_FLAG_EOP          FLASH_SR_EOP        /*!< FLASH End of operation flag */
#define FLASH_FLAG_OPERR        FLASH_SR_OPERR      /*!< FLASH Operation error flag */
#define FLASH_FLAG_PROGERR      FLASH_SR_PROGERR    /*!< FLASH Programming error flag */
#define FLASH_FLAG_WRPERR       FLASH_SR_WRPERR     /*!< FLASH Write protection error flag */
#define FLASH_FLAG_PGAERR       FLASH_SR_PGAERR     /*!< FLASH Programming alignment error flag */
#define FLASH_FLAG_SIZERR       FLASH_SR_SIZERR     /*!< FLASH Size error flag  */
#define FLASH_FLAG_PGSERR       FLASH_SR_PGSERR     /*!< FLASH Programming sequence error flag */
#define FLASH_FLAG_MISERR       FLASH_SR_MISERR     /*!< FLASH Fast programming data miss error flag */
#define FLASH_FLAG_FASTERR      FLASH_SR_FASTERR    /*!< FLASH Fast programming error flag */
#define FLASH_FLAG_RDERR        FLASH_SR_RDERR      /*!< FLASH PCROP read error flag */
#define FLASH_FLAG_OPTVERR      FLASH_SR_OPTVERR    /*!< FLASH Option validity error flag  */
#define FLASH_FLAG_BSY          FLASH_SR_BSY        /*!< FLASH Busy flag */
#define FLASH_FLAG_ECCC         FLASH_ECCR_ECCC     /*!< FLASH ECC correction in 64 LSB bits */
#define FLASH_FLAG_ECCD         FLASH_ECCR_ECCD     /*!< FLASH ECC detection in 64 LSB bits */
#if defined (FLASH_OPTR_DBANK)
#define FLASH_FLAG_ECCC2        FLASH_ECCR_ECCC2    /*!< FLASH ECC correction in 64 MSB bits (mode 128 bits only) */
#define FLASH_FLAG_ECCD2        FLASH_ECCR_ECCD2    /*!< FLASH ECC detection in 64 MSB bits (mode 128 bits only) */
#endif#define FLASH_FLAG_SR_ERRORS    (FLASH_FLAG_OPERR | FLASH_FLAG_PROGERR | FLASH_FLAG_WRPERR | \FLASH_FLAG_PGAERR | FLASH_FLAG_SIZERR | FLASH_FLAG_PGSERR | \FLASH_FLAG_MISERR | FLASH_FLAG_FASTERR | FLASH_FLAG_RDERR | \FLASH_FLAG_OPTVERR)
#if defined (FLASH_OPTR_DBANK)
#define FLASH_FLAG_ECCR_ERRORS  (FLASH_FLAG_ECCC | FLASH_FLAG_ECCD | FLASH_FLAG_ECCC2 | FLASH_FLAG_ECCD2)
#else
#define FLASH_FLAG_ECCR_ERRORS  (FLASH_FLAG_ECCC | FLASH_FLAG_ECCD)
#endif
#define FLASH_FLAG_ALL_ERRORS   (FLASH_FLAG_SR_ERRORS | FLASH_FLAG_ECCR_ERRORS)/*** @brief  FLASH_Interrupt_definition FLASH Interrupts Definition*/
#define FLASH_IT_EOP            FLASH_CR_EOPIE              /*!< End of FLASH Operation Interrupt source */
#define FLASH_IT_OPERR          FLASH_CR_ERRIE              /*!< Error Interrupt source */
#define FLASH_IT_RDERR          FLASH_CR_RDERRIE            /*!< PCROP Read Error Interrupt source*/
#define FLASH_IT_ECCC           (FLASH_ECCR_ECCIE >> 24U)   /*!< ECC Correction Interrupt source *//* Exported types ------------------------------------------------------------*/
/*** @brief  FLASH Status structures definition*/
typedef enum
{FLASH_OK       = 0x00U,FLASH_ERROR    = 0x01U,FLASH_BUSY     = 0x02U,FLASH_TIMEOUT  = 0x03U
} FLASH_StatusTypeDef;/*** @brief  FLASH Lock structures definition*/
typedef enum
{UNLOCKED = 0x00U,LOCKED   = 0x01U
} FLASH_LockTypeDef;/*** @brief  FLASH Erase structure definition*/
typedef struct
{uint32_t TypeErase;   /*!< Mass erase or page erase.This parameter can be a value of @ref FLASH_Type_Erase */uint32_t Banks;       /*!< Select bank to erase.This parameter must be a value of @ref FLASH_Banks(FLASH_BANK_BOTH should be used only for mass erase) */uint32_t Page;        /*!< Initial Flash page to erase when page erase is disabled.This parameter must be a value between 0 and (max number of pages in the bank - 1)(eg : 127 for 512KB dual bank) */uint32_t NbPages;     /*!< Number of pages to be erased.This parameter must be a value between 1 and (max number of pages in the bank - value of initial page)*/
} FLASH_EraseInitTypeDef;/*** @brief  FLASH Option Bytes Program structure definition*/
typedef struct
{uint32_t OptionType;     /*!< Option byte to be configured.This parameter can be a combination of the values of @ref FLASH_OB_Type */uint32_t WRPArea;        /*!< Write protection area to be programmed (used for OPTIONBYTE_WRP).Only one WRP area could be programmed at the same time.This parameter can be value of @ref FLASH_OB_WRP_Area */uint32_t WRPStartOffset; /*!< Write protection start offset (used for OPTIONBYTE_WRP).This parameter must be a value between 0 and (max number of pages in the bank - 1) */uint32_t WRPEndOffset;   /*!< Write protection end offset (used for OPTIONBYTE_WRP).This parameter must be a value between WRPStartOffset and (max number of pages in the bank - 1) */uint32_t RDPLevel;       /*!< Set the read protection level.. (used for OPTIONBYTE_RDP).This parameter can be a value of @ref FLASH_OB_Read_Protection */uint32_t USERType;       /*!< User option byte(s) to be configured (used for OPTIONBYTE_USER).This parameter can be a combination of @ref FLASH_OB_USER_Type */uint32_t USERConfig;     /*!< Value of the user option byte (used for OPTIONBYTE_USER).This parameter can be a combination of @ref FLASH_OB_USER_BOR_LEVEL,@ref FLASH_OB_USER_nRST_STOP, @ref FLASH_OB_USER_nRST_STANDBY,@ref FLASH_OB_USER_nRST_SHUTDOWN, @ref FLASH_OB_USER_IWDG_SW,@ref FLASH_OB_USER_IWDG_STOP, @ref FLASH_OB_USER_IWDG_STANDBY,@ref FLASH_OB_USER_WWDG_SW, @ref FLASH_OB_USER_BFB2 (*),@ref FLASH_OB_USER_nBOOT1, @ref FLASH_OB_USER_SRAM_PE,@ref FLASH_OB_USER_CCMSRAM_RST@note (*) availability depends on devices */uint32_t PCROPConfig;    /*!< Configuration of the PCROP (used for OPTIONBYTE_PCROP).This parameter must be a combination of @ref FLASH_Banks (except FLASH_BANK_BOTH)and @ref FLASH_OB_PCROP_RDP */uint32_t PCROPStartAddr; /*!< PCROP Start address (used for OPTIONBYTE_PCROP).This parameter must be a value between begin and end of bank=> Be careful of the bank swapping for the address */uint32_t PCROPEndAddr;   /*!< PCROP End address (used for OPTIONBYTE_PCROP).This parameter must be a value between PCROP Start address and end of bank */uint32_t BootEntryPoint; /*!< Set the Boot Lock (used for OPTIONBYTE_BOOT_LOCK).This parameter can be a value of @ref FLASH_OB_Boot_Lock */uint32_t SecBank;        /*!< Bank of securable memory area to be programmed (used for OPTIONBYTE_SEC).Only one securable memory area could be programmed at the same time.This parameter can be one of the following values:FLASH_BANK_1: Securable memory area to be programmed in bank 1FLASH_BANK_2: Securable memory area to be programmed in bank 2 (*)@note (*) availability depends on devices */uint32_t SecSize;        /*!< Size of securable memory area to be programmed (used for OPTIONBYTE_SEC),in number of pages. Securable memory area is starting from first page of the bank.Only one securable memory could be programmed at the same time.This parameter must be a value between 0 and (max number of pages in the bank - 1) */
} FLASH_OBProgramInitTypeDef;/*** @brief  FLASH Procedure structure definition*/
typedef enum
{FLASH_PROC_NONE = 0,FLASH_PROC_PAGE_ERASE,FLASH_PROC_MASS_ERASE,FLASH_PROC_PROGRAM,FLASH_PROC_PROGRAM_LAST
} FLASH_ProcedureTypeDef;/*** @brief  FLASH Cache structure definition*/
typedef enum
{FLASH_CACHE_DISABLED = 0,FLASH_CACHE_ICACHE_ENABLED,FLASH_CACHE_DCACHE_ENABLED,FLASH_CACHE_ICACHE_DCACHE_ENABLED
} FLASH_CacheTypeDef;/*** @brief  FLASH handle Structure definition*/
typedef struct
{FLASH_LockTypeDef Lock;                       /* FLASH locking object */__IO uint32_t ErrorCode;                      /* FLASH error code */__IO FLASH_ProcedureTypeDef ProcedureOnGoing; /* Internal variable to indicate which procedure is ongoing or not in IT context */__IO uint32_t Address;                        /* Internal variable to save address selected for program in IT context */__IO uint32_t Bank;                           /* Internal variable to save current bank selected during erase in IT context */__IO uint32_t Page;                           /* Internal variable to define the current page which is erasing in IT context */__IO uint32_t NbPagesToErase;                 /* Internal variable to save the remaining pages to erase in IT context */__IO FLASH_CacheTypeDef CacheToReactivate;    /* Internal variable to indicate which caches should be reactivated */
} FLASH_ProcessTypeDef;/* Exported macro ------------------------------------------------------------*/
/*** @brief  Set the FLASH Latency.* @param  __LATENCY__ FLASH Latency.*         This parameter can be one of the following values :*           @arg FLASH_LATENCY_0:  FLASH Zero wait state*           @arg FLASH_LATENCY_1:  FLASH One wait state*           @arg FLASH_LATENCY_2:  FLASH Two wait states*           @arg FLASH_LATENCY_3:  FLASH Three wait states*           @arg FLASH_LATENCY_4:  FLASH Four wait states*           @arg FLASH_LATENCY_5:  FLASH Five wait states*           @arg FLASH_LATENCY_6:  FLASH Six wait states*           @arg FLASH_LATENCY_7:  FLASH Seven wait states*           @arg FLASH_LATENCY_8:  FLASH Eight wait states*           @arg FLASH_LATENCY_9:  FLASH Nine wait states*           @arg FLASH_LATENCY_10: FLASH Ten wait state*           @arg FLASH_LATENCY_11: FLASH Eleven wait state*           @arg FLASH_LATENCY_12: FLASH Twelve wait states*           @arg FLASH_LATENCY_13: FLASH Thirteen wait states*           @arg FLASH_LATENCY_14: FLASH Fourteen wait states*           @arg FLASH_LATENCY_15: FLASH Fifteen wait states* @retval None*/
#define FLASH_SET_LATENCY(__LATENCY__)      MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (__LATENCY__))/*** @brief  Get the FLASH Latency.* @retval FLASH_Latency.*         This parameter can be one of the following values :*           @arg FLASH_LATENCY_0:  FLASH Zero wait state*           @arg FLASH_LATENCY_1:  FLASH One wait state*           @arg FLASH_LATENCY_2:  FLASH Two wait states*           @arg FLASH_LATENCY_3:  FLASH Three wait states*           @arg FLASH_LATENCY_4:  FLASH Four wait states*           @arg FLASH_LATENCY_5:  FLASH Five wait states*           @arg FLASH_LATENCY_6:  FLASH Six wait states*           @arg FLASH_LATENCY_7:  FLASH Seven wait states*           @arg FLASH_LATENCY_8:  FLASH Eight wait states*           @arg FLASH_LATENCY_9:  FLASH Nine wait states*           @arg FLASH_LATENCY_10: FLASH Ten wait state*           @arg FLASH_LATENCY_11: FLASH Eleven wait state*           @arg FLASH_LATENCY_12: FLASH Twelve wait states*           @arg FLASH_LATENCY_13: FLASH Thirteen wait states*           @arg FLASH_LATENCY_14: FLASH Fourteen wait states*           @arg FLASH_LATENCY_15: FLASH Fifteen wait states*/
#define FLASH_GET_LATENCY()                 READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY)/*** @brief  Enable the FLASH prefetch buffer.* @retval None*/
#define FLASH_PREFETCH_BUFFER_ENABLE()      SET_BIT(FLASH->ACR, FLASH_ACR_PRFTEN)/*** @brief  Disable the FLASH prefetch buffer.* @retval None*/
#define FLASH_PREFETCH_BUFFER_DISABLE()     CLEAR_BIT(FLASH->ACR, FLASH_ACR_PRFTEN)/*** @brief  Enable the FLASH instruction cache.* @retval none*/
#define FLASH_INSTRUCTION_CACHE_ENABLE()    SET_BIT(FLASH->ACR, FLASH_ACR_ICEN)/*** @brief  Disable the FLASH instruction cache.* @retval none*/
#define FLASH_INSTRUCTION_CACHE_DISABLE()   CLEAR_BIT(FLASH->ACR, FLASH_ACR_ICEN)/*** @brief  Enable the FLASH data cache.* @retval none*/
#define FLASH_DATA_CACHE_ENABLE()           SET_BIT(FLASH->ACR, FLASH_ACR_DCEN)/*** @brief  Disable the FLASH data cache.* @retval none*/
#define FLASH_DATA_CACHE_DISABLE()          CLEAR_BIT(FLASH->ACR, FLASH_ACR_DCEN)/*** @brief  Reset the FLASH instruction Cache.* @note   This function must be used only when the Instruction Cache is disabled.* @retval None*/
#define FLASH_INSTRUCTION_CACHE_RESET()     do { \SET_BIT(FLASH->ACR, FLASH_ACR_ICRST);   \CLEAR_BIT(FLASH->ACR, FLASH_ACR_ICRST); \} while (0)/*** @brief  Reset the FLASH data Cache.* @note   This function must be used only when the data Cache is disabled.* @retval None*/
#define FLASH_DATA_CACHE_RESET()            do { \SET_BIT(FLASH->ACR, FLASH_ACR_DCRST);   \CLEAR_BIT(FLASH->ACR, FLASH_ACR_DCRST); \} while (0)/*** @brief  Enable the FLASH power down during Low-power run mode.* @note   Writing this bit to 1, automatically the keys are*         lost and a new unlock sequence is necessary to re-write it to 0.*/
#define FLASH_POWER_DOWN_ENABLE()           do { \WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY1); \WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY2); \SET_BIT(FLASH->ACR, FLASH_ACR_RUN_PD);   \} while (0)/*** @brief  Disable the FLASH power down during Low-power run mode.* @note   Writing this bit to 0, automatically the keys are*         lost and a new unlock sequence is necessary to re-write it to 1.*/
#define FLASH_POWER_DOWN_DISABLE()          do { \WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY1); \WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY2); \CLEAR_BIT(FLASH->ACR, FLASH_ACR_RUN_PD); \} while (0)/*** @brief  Enable the FLASH power down during Low-Power sleep mode* @retval none*/
#define FLASH_SLEEP_POWERDOWN_ENABLE()      SET_BIT(FLASH->ACR, FLASH_ACR_SLEEP_PD)/*** @brief  Disable the FLASH power down during Low-Power sleep mode* @retval none*/
#define FLASH_SLEEP_POWERDOWN_DISABLE()     CLEAR_BIT(FLASH->ACR, FLASH_ACR_SLEEP_PD)/*** @brief  Enable the specified FLASH interrupt.* @param  __INTERRUPT__ FLASH interrupt*         This parameter can be any combination of the following values:*     @arg FLASH_IT_EOP: End of FLASH Operation Interrupt*     @arg FLASH_IT_OPERR: Error Interrupt*     @arg FLASH_IT_RDERR: PCROP Read Error Interrupt*     @arg FLASH_IT_ECCC: ECC Correction Interrupt* @retval none*/
#define FLASH_ENABLE_IT(__INTERRUPT__)      do { \if (((__INTERRUPT__) & FLASH_IT_ECCC) != 0U) \{ \SET_BIT(FLASH->ECCR, FLASH_ECCR_ECCIE); \} \if (((__INTERRUPT__) & (~FLASH_IT_ECCC)) != 0U) \{ \SET_BIT(FLASH->CR, ((__INTERRUPT__) & (~FLASH_IT_ECCC))); \} \} while (0)/*** @brief  Disable the specified FLASH interrupt.* @param  __INTERRUPT__ FLASH interrupt*         This parameter can be any combination of the following values:*     @arg FLASH_IT_EOP: End of FLASH Operation Interrupt*     @arg FLASH_IT_OPERR: Error Interrupt*     @arg FLASH_IT_RDERR: PCROP Read Error Interrupt*     @arg FLASH_IT_ECCC: ECC Correction Interrupt* @retval none*/
#define FLASH_DISABLE_IT(__INTERRUPT__)     do { \if (((__INTERRUPT__) & FLASH_IT_ECCC) != 0U) \{ \CLEAR_BIT(FLASH->ECCR, FLASH_ECCR_ECCIE); \} \if (((__INTERRUPT__) & (~FLASH_IT_ECCC)) != 0U) \{ \CLEAR_BIT(FLASH->CR, ((__INTERRUPT__) & (~FLASH_IT_ECCC))); \} \} while (0)/*** @brief  Check whether the specified FLASH flag is set or not.* @param  __FLAG__ specifies the FLASH flag to check.*   This parameter can be one of the following values:*     @arg FLASH_FLAG_EOP: FLASH End of Operation flag*     @arg FLASH_FLAG_OPERR: FLASH Operation error flag*     @arg FLASH_FLAG_PROGERR: FLASH Programming error flag*     @arg FLASH_FLAG_WRPERR: FLASH Write protection error flag*     @arg FLASH_FLAG_PGAERR: FLASH Programming alignment error flag*     @arg FLASH_FLAG_SIZERR: FLASH Size error flag*     @arg FLASH_FLAG_PGSERR: FLASH Programming sequence error flag*     @arg FLASH_FLAG_MISERR: FLASH Fast programming data miss error flag*     @arg FLASH_FLAG_FASTERR: FLASH Fast programming error flag*     @arg FLASH_FLAG_RDERR: FLASH PCROP read  error flag*     @arg FLASH_FLAG_OPTVERR: FLASH Option validity error flag*     @arg FLASH_FLAG_BSY: FLASH write/erase operations in progress flag*     @arg FLASH_FLAG_ECCC: FLASH one ECC error has been detected and corrected in 64 LSB bits*     @arg FLASH_FLAG_ECCD: FLASH two ECC errors have been detected in 64 LSB bits*     @arg FLASH_FLAG_ECCC2(*): FLASH one ECC error has been detected and corrected in 64 MSB bits (mode 128 bits only)*     @arg FLASH_FLAG_ECCD2(*): FLASH two ECC errors have been detected in 64 MSB bits (mode 128 bits only)* @note  (*) availability depends on devices* @retval The new state of FLASH_FLAG (SET or RESET).*/
#define FLASH_GET_FLAG(__FLAG__)            ((((__FLAG__) & FLASH_FLAG_ECCR_ERRORS) != 0U) ? \(READ_BIT(FLASH->ECCR, (__FLAG__)) == (__FLAG__)) : \(READ_BIT(FLASH->SR, (__FLAG__)) == (__FLAG__)))/*** @brief  Clear the FLASH's pending flags.* @param  __FLAG__ specifies the FLASH flags to clear.*   This parameter can be any combination of the following values:*     @arg FLASH_FLAG_EOP: FLASH End of Operation flag*     @arg FLASH_FLAG_OPERR: FLASH Operation error flag*     @arg FLASH_FLAG_PROGERR: FLASH Programming error flag*     @arg FLASH_FLAG_WRPERR: FLASH Write protection error flag*     @arg FLASH_FLAG_PGAERR: FLASH Programming alignment error flag*     @arg FLASH_FLAG_SIZERR: FLASH Size error flag*     @arg FLASH_FLAG_PGSERR: FLASH Programming sequence error flag*     @arg FLASH_FLAG_MISERR: FLASH Fast programming data miss error flag*     @arg FLASH_FLAG_FASTERR: FLASH Fast programming error flag*     @arg FLASH_FLAG_RDERR: FLASH PCROP read  error flag*     @arg FLASH_FLAG_OPTVERR: FLASH Option validity error flag*     @arg FLASH_FLAG_ECCC: FLASH one ECC error has been detected and corrected in 64 LSB bits*     @arg FLASH_FLAG_ECCD: FLASH two ECC errors have been detected in 64 LSB bits*     @arg FLASH_FLAG_ECCC2(*): FLASH one ECC error has been detected and corrected in 64 MSB bits (mode 128 bits only)*     @arg FLASH_FLAG_ECCD2(*): FLASH two ECC errors have been detected in 64 MSB bits (mode 128 bits only)*     @arg FLASH_FLAG_SR_ERRORS: FLASH All SR errors flags*     @arg FLASH_FLAG_ECCR_ERRORS: FLASH All ECCR errors flags* @note  (*) availability depends on devices* @retval None*/
#define FLASH_CLEAR_FLAG(__FLAG__)          do { \if (((__FLAG__) & FLASH_FLAG_ECCR_ERRORS) != 0U) \{ \SET_BIT(FLASH->ECCR, ((__FLAG__) & FLASH_FLAG_ECCR_ERRORS)); \} \if (((__FLAG__) & ~(FLASH_FLAG_ECCR_ERRORS)) != 0U) \{ \WRITE_REG(FLASH->SR, ((__FLAG__) & ~(FLASH_FLAG_ECCR_ERRORS))); \} \} while (0)#define FLASH_LOCK(__HANDLE__)              do { \if((__HANDLE__)->Lock == LOCKED) \{ \return FLASH_BUSY; \} \else \{ \(__HANDLE__)->Lock = LOCKED; \} \} while (0)#define FLASH_UNLOCK(__HANDLE__)            do{ \(__HANDLE__)->Lock = UNLOCKED; \} while (0)/*** @brief  __RAM_FUNC definition*/
#if defined (__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
/* ARM Compiler V4/V5 and V6--------------------------RAM functions are defined using the toolchain options.Functions that are executed in RAM should reside in a separate source module.Using the 'Options for File' dialog you can simply change the 'Code / Const'area of a module to a memory space in physical RAM.Available memory areas are declared in the 'Target' tab of the 'Options for Target'dialog.
*/
#define __RAM_FUNC#elif defined ( __ICCARM__ )
/* ICCARM Compiler---------------RAM functions are defined using a specific toolchain keyword "__ramfunc".
*/
#define __RAM_FUNC __ramfunc#elif defined   (  __GNUC__  )
/* GNU Compiler------------RAM functions are defined using a specific toolchain attribute"__attribute__((section(".RamFunc")))".
*/
#define __RAM_FUNC __attribute__((section(".RamFunc")))#endif /* __CC_ARM *//* Exported variables --------------------------------------------------------*/
extern FLASH_ProcessTypeDef MCU_FLASH;/* Exported functions prototypes ---------------------------------------------*/
FLASH_StatusTypeDef FLASH_Unlock(void);
FLASH_StatusTypeDef FLASH_Lock(void);FLASH_StatusTypeDef FLASH_OB_Unlock(void);
FLASH_StatusTypeDef FLASH_OB_Lock(void);
FLASH_StatusTypeDef FLASH_OB_Launch(void);FLASH_StatusTypeDef FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);
FLASH_StatusTypeDef FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data);
void FLASH_IRQHandler(void);
void FLASH_EndOfOperationCallback(uint32_t ReturnValue);
void FLASH_OperationErrorCallback(uint32_t ReturnValue);
FLASH_StatusTypeDef FLASH_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError);FLASH_StatusTypeDef FLASH_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit);
void FLASH_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit);__RAM_FUNC FLASH_StatusTypeDef FLASH_EnableRunPowerDown(void);
__RAM_FUNC FLASH_StatusTypeDef FLASH_DisableRunPowerDown(void);
#if defined (FLASH_OPTR_DBANK)
__RAM_FUNC FLASH_StatusTypeDef FLASH_OB_DBankConfig(uint32_t DBankConfig);
#endifFLASH_StatusTypeDef FLASH_EnableSecMemProtection(uint32_t Bank);
void FLASH_EnableDebugger(void);
void FLASH_DisableDebugger(void);uint32_t FLASH_GetError(void);#ifdef __cplusplus
}
#endif#endif /* FLASH_H__ */
/********************************************************************************* @file       flash.c* @author     Amos* @brief      MCU flash program body.******************************************************************************* @attention*******************************************************************************//* Includes ------------------------------------------------------------------*/
#include "flash.h"
#ifdef  USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT *//* External variables declaration --------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define FLASH_SIZE_DATA_REGISTER        FLASHSIZE_BASE#if defined (FLASH_OPTR_DBANK)
#define FLASH_SIZE                      ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFFU)) ? (0x200UL << 10U) : \(((*((uint32_t *)FLASH_SIZE_DATA_REGISTER)) & 0xFFFFUL) << 10U))
#define FLASH_BANK_SIZE                 (FLASH_SIZE >> 1)
#define FLASH_PAGE_NB                   128U
#define FLASH_PAGE_SIZE_128_BITS        0x1000U /* 4 KB */
#else
#define FLASH_SIZE                      ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFFU)) ? (0x80UL << 10U) : \(((*((uint32_t *)FLASH_SIZE_DATA_REGISTER)) & 0xFFFFUL) << 10U))
#define FLASH_BANK_SIZE                 (FLASH_SIZE)
#define FLASH_PAGE_NB                   ((FLASH_SIZE == 0x00080000U) ? 256U : \((FLASH_SIZE == 0x00040000U) ? 128U : 64U))
#endif#define FLASH_PAGE_SIZE                 0x800U  /* 2 KB */#define FLASH_TIMEOUT_VALUE             1000U   /* 1 s  */#define FLASH_NB_DOUBLE_WORDS_IN_ROW    32U/* Private typedef -----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
FLASH_StatusTypeDef  FLASH_WaitForLastOperation(uint32_t Timeout);static FLASH_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout);
static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data);
static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress);static void FLASH_MassErase(uint32_t Banks);
static void FLASH_PageErase(uint32_t Page, uint32_t Banks);
static void FLASH_FlushCaches(void);
static FLASH_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset);
static FLASH_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel);
static FLASH_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig);
static FLASH_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr);
static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset);
static uint32_t FLASH_OB_GetRDP(void);
static uint32_t FLASH_OB_GetUser(void);
static void FLASH_OB_GetPCROP(uint32_t *PCROPConfig, uint32_t *PCROPStartAddr, uint32_t *PCROPEndAddr);
static FLASH_StatusTypeDef FLASH_OB_SecMemConfig(uint32_t SecMemBank, uint32_t SecMemSize);
static void FLASH_OB_GetSecMem(uint32_t SecMemBank, uint32_t *SecMemSize);
static FLASH_StatusTypeDef FLASH_OB_BootLockConfig(uint32_t BootLockConfig);
static uint32_t FLASH_OB_GetBootLock(void);/* Private macro -------------------------------------------------------------*/
#define IS_FLASH_TYPEERASE(VALUE)           (((VALUE) == FLASH_TYPEERASE_PAGES) || \((VALUE) == FLASH_TYPEERASE_MASSERASE))#if defined (FLASH_OPTR_DBANK)
#define IS_FLASH_BANK(BANK)                 (((BANK) == FLASH_BANK_1) || \((BANK) == FLASH_BANK_2) || \((BANK) == FLASH_BANK_BOTH))#define IS_FLASH_BANK_EXCLUSIVE(BANK)       (((BANK) == FLASH_BANK_1)  || ((BANK) == FLASH_BANK_2))
#else
#define IS_FLASH_BANK(BANK)                 ((BANK) == FLASH_BANK_1)#define IS_FLASH_BANK_EXCLUSIVE(BANK)       ((BANK) == FLASH_BANK_1)
#endif#define IS_FLASH_TYPEPROGRAM(VALUE)         (((VALUE) == FLASH_TYPEPROGRAM_DOUBLEWORD) || \((VALUE) == FLASH_TYPEPROGRAM_FAST) || \((VALUE) == FLASH_TYPEPROGRAM_FAST_AND_LAST))#define IS_FLASH_MAIN_MEM_ADDRESS(ADDRESS)  (((ADDRESS) >= FLASH_BASE) && ((ADDRESS) < (FLASH_BASE+FLASH_SIZE)))#define IS_FLASH_OTP_ADDRESS(ADDRESS)       (((ADDRESS) >= 0x1FFF7000U) && ((ADDRESS) <= 0x1FFF73FFU))#define IS_FLASH_PROGRAM_ADDRESS(ADDRESS)   (IS_FLASH_MAIN_MEM_ADDRESS(ADDRESS) || IS_FLASH_OTP_ADDRESS(ADDRESS))#define IS_FLASH_PAGE(PAGE)                 ((PAGE) < FLASH_PAGE_NB)#define IS_OPTIONBYTE(VALUE)                (((VALUE) <= (OPTIONBYTE_WRP | OPTIONBYTE_RDP | OPTIONBYTE_USER | \OPTIONBYTE_PCROP | OPTIONBYTE_BOOT_LOCK | OPTIONBYTE_SEC)))#if defined (FLASH_OPTR_DBANK)
#define IS_OB_WRPAREA(VALUE)                (((VALUE) == OB_WRPAREA_BANK1_AREAA) || ((VALUE) == OB_WRPAREA_BANK1_AREAB) || \((VALUE) == OB_WRPAREA_BANK2_AREAA) || ((VALUE) == OB_WRPAREA_BANK2_AREAB))
#else
#define IS_OB_WRPAREA(VALUE)                (((VALUE) == OB_WRPAREA_BANK1_AREAA) || ((VALUE) == OB_WRPAREA_BANK1_AREAB))
#endif#define IS_OB_BOOT_LOCK(VALUE)              (((VALUE) == OB_BOOT_LOCK_ENABLE) || ((VALUE) == OB_BOOT_LOCK_DISABLE))#define IS_OB_RDP_LEVEL(LEVEL)              (((LEVEL) == OB_RDP_LEVEL_0) || ((LEVEL) == OB_RDP_LEVEL_1) || \((LEVEL) == OB_RDP_LEVEL_2))#define IS_OB_USER_TYPE(TYPE)               (((TYPE) <= 0x1FFFFU) && ((TYPE) != 0U))#define IS_OB_USER_BOR_LEVEL(LEVEL)         (((LEVEL) == OB_BOR_LEVEL_0) || ((LEVEL) == OB_BOR_LEVEL_1) || \((LEVEL) == OB_BOR_LEVEL_2) || ((LEVEL) == OB_BOR_LEVEL_3) || \((LEVEL) == OB_BOR_LEVEL_4))#define IS_OB_USER_STOP(VALUE)              (((VALUE) == OB_STOP_RST) || ((VALUE) == OB_STOP_NORST))#define IS_OB_USER_STANDBY(VALUE)           (((VALUE) == OB_STANDBY_RST) || ((VALUE) == OB_STANDBY_NORST))#define IS_OB_USER_SHUTDOWN(VALUE)          (((VALUE) == OB_SHUTDOWN_RST) || ((VALUE) == OB_SHUTDOWN_NORST))#define IS_OB_USER_IWDG(VALUE)              (((VALUE) == OB_IWDG_HW) || ((VALUE) == OB_IWDG_SW))#define IS_OB_USER_IWDG_STOP(VALUE)         (((VALUE) == OB_IWDG_STOP_FREEZE) || ((VALUE) == OB_IWDG_STOP_RUN))#define IS_OB_USER_IWDG_STDBY(VALUE)        (((VALUE) == OB_IWDG_STDBY_FREEZE) || ((VALUE) == OB_IWDG_STDBY_RUN))#define IS_OB_USER_WWDG(VALUE)              (((VALUE) == OB_WWDG_HW) || ((VALUE) == OB_WWDG_SW))#if defined (FLASH_OPTR_DBANK)
#define IS_OB_USER_BFB2(VALUE)              (((VALUE) == OB_BFB2_DISABLE) || ((VALUE) == OB_BFB2_ENABLE))#define IS_OB_USER_DBANK(VALUE)             (((VALUE) == OB_DBANK_128_BITS) || ((VALUE) == OB_DBANK_64_BITS))
#endif#if defined (FLASH_OPTR_PB4_PUPEN)
#define IS_OB_USER_PB4_PUPEN(VALUE)         (((VALUE) == OB_PB4_PUPEN_DISABLE) || ((VALUE) == OB_PB4_PUPEN_ENABLE))
#endif#define IS_OB_USER_BOOT1(VALUE)             (((VALUE) == OB_BOOT1_SRAM) || ((VALUE) == OB_BOOT1_SYSTEM))#define IS_OB_USER_SRAM_PARITY(VALUE)       (((VALUE) == OB_SRAM_PARITY_ENABLE) || ((VALUE) == OB_SRAM_PARITY_DISABLE))#define IS_OB_USER_CCMSRAM_RST(VALUE)       (((VALUE) == OB_CCMSRAM_RST_ERASE) || ((VALUE) == OB_CCMSRAM_RST_NOT_ERASE))#define IS_OB_USER_SWBOOT0(VALUE)           (((VALUE) == OB_BOOT0_FROM_OB) || ((VALUE) == OB_BOOT0_FROM_PIN))#define IS_OB_USER_BOOT0(VALUE)             (((VALUE) == OB_nBOOT0_RESET) || ((VALUE) == OB_nBOOT0_SET))#define IS_OB_USER_NRST_MODE(VALUE)         (((VALUE) == OB_NRST_MODE_GPIO) || ((VALUE) == OB_NRST_MODE_INPUT_ONLY) || \((VALUE) == OB_NRST_MODE_INPUT_OUTPUT))#define IS_OB_USER_IRHEN(VALUE)             (((VALUE) == OB_IRH_ENABLE) || ((VALUE) == OB_IRH_DISABLE))#define IS_OB_PCROP_RDP(VALUE)              (((VALUE) == OB_PCROP_RDP_NOT_ERASE) || ((VALUE) == OB_PCROP_RDP_ERASE))#define IS_OB_SECMEM_SIZE(VALUE)            ((VALUE) <= FLASH_PAGE_NB)#define IS_FLASH_LATENCY(LATENCY)           (((LATENCY) == FLASH_LATENCY_0) || ((LATENCY) == FLASH_LATENCY_1) || \((LATENCY) == FLASH_LATENCY_2) || ((LATENCY) == FLASH_LATENCY_3) || \((LATENCY) == FLASH_LATENCY_4) || ((LATENCY) == FLASH_LATENCY_5) || \((LATENCY) == FLASH_LATENCY_6) || ((LATENCY) == FLASH_LATENCY_7) || \((LATENCY) == FLASH_LATENCY_8) || ((LATENCY) == FLASH_LATENCY_9) || \((LATENCY) == FLASH_LATENCY_10) || ((LATENCY) == FLASH_LATENCY_11) || \((LATENCY) == FLASH_LATENCY_12) || ((LATENCY) == FLASH_LATENCY_13) || \((LATENCY) == FLASH_LATENCY_14) || ((LATENCY) == FLASH_LATENCY_15))
/* Exported variables --------------------------------------------------------*/
/*** @brief  Variable used for Program/Erase sectors under interruption*/
FLASH_ProcessTypeDef MCU_FLASH =
{.Lock = UNLOCKED,.ErrorCode = FLASH_ERROR_NONE,.ProcedureOnGoing = FLASH_PROC_NONE,.Address = 0U,.Bank = FLASH_BANK_1,.Page = 0U,.NbPagesToErase = 0U,.CacheToReactivate = FLASH_CACHE_DISABLED
};/* Exported functions --------------------------------------------------------*/
/*** @brief  Unlock the FLASH control register access.* @retval FLASH_Status*/
FLASH_StatusTypeDef FLASH_Unlock(void)
{FLASH_StatusTypeDef status = FLASH_OK;if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U){/* Authorize the FLASH Registers access */WRITE_REG(FLASH->KEYR, FLASH_KEY1);WRITE_REG(FLASH->KEYR, FLASH_KEY2);/* verify Flash is unlocked */if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U){status = FLASH_ERROR;}}return status;
}/*** @brief  Lock the FLASH control register access.* @retval FLASH_Status*/
FLASH_StatusTypeDef FLASH_Lock(void)
{FLASH_StatusTypeDef status = FLASH_ERROR;/* Set the LOCK Bit to lock the FLASH Registers access */SET_BIT(FLASH->CR, FLASH_CR_LOCK);/* verify Flash is locked */if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U){status = FLASH_OK;}return status;
}/*** @brief  Unlock the FLASH Option Bytes Registers access.* @retval FLASH_Status*/
FLASH_StatusTypeDef FLASH_OB_Unlock(void)
{FLASH_StatusTypeDef status = FLASH_OK;if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0U){/* Authorizes the Option Byte register programming */WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);/* verify option bytes are unlocked */if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0U){status = FLASH_ERROR;}}return status;
}/*** @brief  Lock the FLASH Option Bytes Registers access.* @retval FLASH_Status*/
FLASH_StatusTypeDef FLASH_OB_Lock(void)
{FLASH_StatusTypeDef status = FLASH_ERROR;/* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK);/* Verify option bytes are locked */if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0U){status = FLASH_OK;}return status;
}/*** @brief  Launch the option byte loading.* @retval FLASH_Status*/
FLASH_StatusTypeDef FLASH_OB_Launch(void)
{/* Set the bit to force the option byte reloading */SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);/* Wait for last operation to be completed */return (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE));
}/*** @brief  Program double word or fast program of a row at a specified address.* @param  TypeProgram Indicate the way to program at a specified address.*         This parameter can be a value of @ref FLASH_Type_Program.* @param  Address specifies the address to be programmed.* @param  Data specifies the data to be programmed.*         This parameter is the data for the double word program and the address where*         are stored the data for the row fast program.** @retval FLASH_Status*/
FLASH_StatusTypeDef FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
{FLASH_StatusTypeDef status;uint32_t prog_bit = 0;/* Check the parameters */assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));/* Process Locked */FLASH_LOCK(&MCU_FLASH);/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);if (status == FLASH_OK){MCU_FLASH.ErrorCode = FLASH_ERROR_NONE;if (TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD){/* Program double-word (64-bit) at a specified address */FLASH_Program_DoubleWord(Address, Data);prog_bit = FLASH_CR_PG;}else if ((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)){/* Fast program a 32 row double-word (64-bit) at a specified address */FLASH_Program_Fast(Address, (uint32_t)Data);/* If it is the last row, the bit will be cleared at the end of the operation */if (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST){prog_bit = FLASH_CR_FSTPG;}}else{/* Nothing to do */}/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);/* If the program operation is completed, disable the PG or FSTPG Bit */if (prog_bit != 0U){CLEAR_BIT(FLASH->CR, prog_bit);}}/* Process Unlocked */FLASH_UNLOCK(&MCU_FLASH);/* return status */return status;
}/*** @brief  Program double word or fast program of a row at a specified address with interrupt enabled.* @param  TypeProgram Indicate the way to program at a specified address.*         This parameter can be a value of @ref FLASH_Type_Program.* @param  Address specifies the address to be programmed.* @param  Data specifies the data to be programmed.*         This parameter is the data for the double word program and the address where*         are stored the data for the row fast program.** @retval FLASH_Status*/
FLASH_StatusTypeDef FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
{FLASH_StatusTypeDef status;/* Check the parameters */assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));/* Process Locked */FLASH_LOCK(&MCU_FLASH);/* Reset error code */MCU_FLASH.ErrorCode = FLASH_ERROR_NONE;/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);if (status != FLASH_OK){/* Process Unlocked */FLASH_UNLOCK(&MCU_FLASH);}else{/* Set internal variables used by the IRQ handler */if (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST){MCU_FLASH.ProcedureOnGoing = FLASH_PROC_PROGRAM_LAST;}else{MCU_FLASH.ProcedureOnGoing = FLASH_PROC_PROGRAM;}MCU_FLASH.Address = Address;/* Enable End of Operation and Error interrupts */FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);if (TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD){/* Program double-word (64-bit) at a specified address */FLASH_Program_DoubleWord(Address, Data);}else if ((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)){/* Fast program a 32 row double-word (64-bit) at a specified address */FLASH_Program_Fast(Address, (uint32_t)Data);}else{/* Nothing to do */}}return status;
}/*** @brief  Handle FLASH interrupt request.* @retval None*/
void FLASH_IRQHandler(void)
{uint32_t tmp_page;uint32_t error;FLASH_ProcedureTypeDef procedure;/* If the operation is completed, disable the PG, PNB, MER1, MER2 and PER Bit */CLEAR_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_MER1 | FLASH_CR_PER | FLASH_CR_PNB));
#if defined (FLASH_OPTR_DBANK)CLEAR_BIT(FLASH->CR, FLASH_CR_MER2);
#endif/* Disable the FSTPG Bit only if it is the last row programmed */if (MCU_FLASH.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST){CLEAR_BIT(FLASH->CR, FLASH_CR_FSTPG);}/* Check FLASH operation error flags */error = (FLASH->SR & FLASH_FLAG_SR_ERRORS);if (error != 0U){/* Save the error code */MCU_FLASH.ErrorCode |= error;/* Clear error programming flags */FLASH_CLEAR_FLAG(error);/* Flush the caches to be sure of the data consistency */FLASH_FlushCaches() ;/* FLASH error interrupt user callback */procedure = MCU_FLASH.ProcedureOnGoing;if (procedure == FLASH_PROC_PAGE_ERASE){FLASH_OperationErrorCallback(MCU_FLASH.Page);}else if (procedure == FLASH_PROC_MASS_ERASE){FLASH_OperationErrorCallback(MCU_FLASH.Bank);}else if ((procedure == FLASH_PROC_PROGRAM) ||(procedure == FLASH_PROC_PROGRAM_LAST)){FLASH_OperationErrorCallback(MCU_FLASH.Address);}else{/* Nothing to do */}/*Stop the procedure ongoing*/MCU_FLASH.ProcedureOnGoing = FLASH_PROC_NONE;}/* Check FLASH End of Operation flag  */if (FLASH_GET_FLAG(FLASH_FLAG_EOP)){/* Clear FLASH End of Operation pending bit */FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);if (MCU_FLASH.ProcedureOnGoing == FLASH_PROC_PAGE_ERASE){/* Nb of pages to erased can be decreased */MCU_FLASH.NbPagesToErase--;/* Check if there are still pages to erase*/if (MCU_FLASH.NbPagesToErase != 0U){/* Indicate user which page has been erased*/FLASH_EndOfOperationCallback(MCU_FLASH.Page);/* Increment page number */MCU_FLASH.Page++;tmp_page = MCU_FLASH.Page;FLASH_PageErase(tmp_page, MCU_FLASH.Bank);}else{/* No more pages to Erase *//* Reset Address and stop Erase pages procedure */MCU_FLASH.Page = 0xFFFFFFFFU;MCU_FLASH.ProcedureOnGoing = FLASH_PROC_NONE;/* Flush the caches to be sure of the data consistency */FLASH_FlushCaches() ;/* FLASH EOP interrupt user callback */FLASH_EndOfOperationCallback(MCU_FLASH.Page);}}else{/* Flush the caches to be sure of the data consistency */FLASH_FlushCaches() ;procedure = MCU_FLASH.ProcedureOnGoing;if (procedure == FLASH_PROC_MASS_ERASE){/* MassErase ended. Return the selected bank *//* FLASH EOP interrupt user callback */FLASH_EndOfOperationCallback(MCU_FLASH.Bank);}else if ((procedure == FLASH_PROC_PROGRAM) ||(procedure == FLASH_PROC_PROGRAM_LAST)){/* Program ended. Return the selected address *//* FLASH EOP interrupt user callback */FLASH_EndOfOperationCallback(MCU_FLASH.Address);}else{/* Nothing to do */}/*Clear the procedure ongoing*/MCU_FLASH.ProcedureOnGoing = FLASH_PROC_NONE;}}if (MCU_FLASH.ProcedureOnGoing == FLASH_PROC_NONE){/* Disable End of Operation and Error interrupts */FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);/* Process Unlocked */FLASH_UNLOCK(&MCU_FLASH);}
}/*** @brief  FLASH end of operation interrupt callback.* @param  ReturnValue The value saved in this parameter depends on the ongoing procedure:*           @arg Mass Erase: Bank number which has been requested to erase*           @arg Page Erase: Page which has been erased*                            (if 0xFFFFFFFF, it means that all the selected pages have been erased)*           @arg Program: Address which was selected for data program* @retval None*/
__weak void FLASH_EndOfOperationCallback(uint32_t ReturnValue)
{/* Prevent unused argument(s) compilation warning */UNUSED(ReturnValue);/* NOTE : This function should not be modified, when the callback is needed,the FLASH_EndOfOperationCallback could be implemented in the user file*/
}/*** @brief  FLASH operation error interrupt callback.* @param  ReturnValue The value saved in this parameter depends on the ongoing procedure:*           @arg Mass Erase: Bank number which has been requested to erase*           @arg Page Erase: Page number which returned an error*           @arg Program: Address which was selected for data program* @retval None*/
__weak void FLASH_OperationErrorCallback(uint32_t ReturnValue)
{/* Prevent unused argument(s) compilation warning */UNUSED(ReturnValue);/* NOTE : This function should not be modified, when the callback is needed,the FLASH_OperationErrorCallback could be implemented in the user file*/
}/*** @brief  Perform a mass erase or erase the specified FLASH memory pages.* @param[in]  pEraseInit pointer to an FLASH_EraseInitTypeDef structure that*         contains the configuration information for the erasing.* @param[out]  PageError pointer to variable that contains the configuration*         information on faulty page in case of error (0xFFFFFFFF means that all*         the pages have been correctly erased).* @retval FLASH_Status*/
FLASH_StatusTypeDef FLASH_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
{FLASH_StatusTypeDef status;uint32_t page_index;/* Check the parameters */assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));/* Process Locked */FLASH_LOCK(&MCU_FLASH);/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);if (status == FLASH_OK){MCU_FLASH.ErrorCode = FLASH_ERROR_NONE;/* Deactivate the cache if they are activated to avoid data misbehavior */if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != 0U){if (READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U){/* Disable data cache  */FLASH_DATA_CACHE_DISABLE();MCU_FLASH.CacheToReactivate = FLASH_CACHE_ICACHE_DCACHE_ENABLED;}else{MCU_FLASH.CacheToReactivate = FLASH_CACHE_ICACHE_ENABLED;}}else if (READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U){/* Disable data cache  */FLASH_DATA_CACHE_DISABLE();MCU_FLASH.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED;}else{MCU_FLASH.CacheToReactivate = FLASH_CACHE_DISABLED;}if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE){/* Mass erase to be done */FLASH_MassErase(pEraseInit->Banks);/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);#if defined (FLASH_OPTR_DBANK)/* If the erase operation is completed, disable the MER1 and MER2 Bits */CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2));
#else/* If the erase operation is completed, disable the MER1 Bit */CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1));
#endif}else{/*Initialization of PageError variable*/*PageError = 0xFFFFFFFFU;for (page_index = pEraseInit->Page; page_index < (pEraseInit->Page + pEraseInit->NbPages); page_index++){FLASH_PageErase(page_index, pEraseInit->Banks);/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);/* If the erase operation is completed, disable the PER Bit */CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));if (status != FLASH_OK){/* In case of error, stop erase procedure and return the faulty page */*PageError = page_index;break;}}}/* Flush the caches to be sure of the data consistency */FLASH_FlushCaches();}/* Process Unlocked */FLASH_UNLOCK(&MCU_FLASH);return status;
}/*** @brief  Program Option bytes.* @param  pOBInit pointer to an FLASH_OBInitStruct structure that*         contains the configuration information for the programming.* @note   To configure any option bytes, the option lock bit OPTLOCK must be*         cleared with the call of FLASH_OB_Unlock() function.* @note   New option bytes configuration will be taken into account in two cases:*         - after an option bytes launch through the call of FLASH_OB_Launch()*         - after a power reset (BOR reset or exit from Standby/Shutdown modes)* @retval FLASH_Status*/
FLASH_StatusTypeDef FLASH_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
{FLASH_StatusTypeDef status = FLASH_OK;/* Check the parameters */assert_param(IS_OPTIONBYTE(pOBInit->OptionType));/* Process Locked */FLASH_LOCK(&MCU_FLASH);MCU_FLASH.ErrorCode = FLASH_ERROR_NONE;/* Write protection configuration */if ((pOBInit->OptionType & OPTIONBYTE_WRP) != 0U){/* Configure of Write protection on the selected area */if (FLASH_OB_WRPConfig(pOBInit->WRPArea, pOBInit->WRPStartOffset, pOBInit->WRPEndOffset) != FLASH_OK){status = FLASH_ERROR;}}/* Read protection configuration */if ((pOBInit->OptionType & OPTIONBYTE_RDP) != 0U){/* Configure the Read protection level */if (FLASH_OB_RDPConfig(pOBInit->RDPLevel) != FLASH_OK){status = FLASH_ERROR;}}/* User Configuration */if ((pOBInit->OptionType & OPTIONBYTE_USER) != 0U){/* Configure the user option bytes */if (FLASH_OB_UserConfig(pOBInit->USERType, pOBInit->USERConfig) != FLASH_OK){status = FLASH_ERROR;}}/* PCROP Configuration */if ((pOBInit->OptionType & OPTIONBYTE_PCROP) != 0U){if (pOBInit->PCROPStartAddr != pOBInit->PCROPEndAddr){/* Configure the Proprietary code readout protection */if (FLASH_OB_PCROPConfig(pOBInit->PCROPConfig, pOBInit->PCROPStartAddr, pOBInit->PCROPEndAddr) != FLASH_OK){status = FLASH_ERROR;}}}/* Securable memory Configuration */if ((pOBInit->OptionType & OPTIONBYTE_SEC) != 0U){/* Configure the securable memory area */if (FLASH_OB_SecMemConfig(pOBInit->SecBank, pOBInit->SecSize) != FLASH_OK){status = FLASH_ERROR;}}/* Boot Entry Point Configuration */if ((pOBInit->OptionType & OPTIONBYTE_BOOT_LOCK) != 0U){/* Configure the boot unique entry point option */if (FLASH_OB_BootLockConfig(pOBInit->BootEntryPoint) != FLASH_OK){status = FLASH_ERROR;}}/* Process Unlocked */FLASH_UNLOCK(&MCU_FLASH);return status;
}/*** @brief  Get the Option bytes configuration.* @param  pOBInit pointer to an FLASH_OBInitStruct structure that contains the*         configuration information.* @note   The fields pOBInit->WRPArea and pOBInit->PCROPConfig should indicate*         which area is requested for the WRP and PCROP, else no information will be returned.* @retval None*/
void FLASH_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
{pOBInit->OptionType = (OPTIONBYTE_RDP | OPTIONBYTE_USER);#if defined (FLASH_OPTR_DBANK)if ((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB) ||(pOBInit->WRPArea == OB_WRPAREA_BANK2_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK2_AREAB))
#elseif ((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB))
#endif{pOBInit->OptionType |= OPTIONBYTE_WRP;/* Get write protection on the selected area */FLASH_OB_GetWRP(pOBInit->WRPArea, &(pOBInit->WRPStartOffset), &(pOBInit->WRPEndOffset));}/* Get Read protection level */pOBInit->RDPLevel = FLASH_OB_GetRDP();/* Get the user option bytes */pOBInit->USERConfig = FLASH_OB_GetUser();#if defined (FLASH_OPTR_DBANK)if ((pOBInit->PCROPConfig == FLASH_BANK_1) || (pOBInit->PCROPConfig == FLASH_BANK_2))
#elseif (pOBInit->PCROPConfig == FLASH_BANK_1)
#endif{pOBInit->OptionType |= OPTIONBYTE_PCROP;/* Get the Proprietary code readout protection */FLASH_OB_GetPCROP(&(pOBInit->PCROPConfig), &(pOBInit->PCROPStartAddr), &(pOBInit->PCROPEndAddr));}pOBInit->OptionType |= OPTIONBYTE_BOOT_LOCK;/* Get the boot entry point */pOBInit->BootEntryPoint = FLASH_OB_GetBootLock();/* Get the securable memory area configuration */
#if defined (FLASH_OPTR_DBANK)if ((pOBInit->SecBank == FLASH_BANK_1) || (pOBInit->SecBank == FLASH_BANK_2))
#elseif (pOBInit->SecBank == FLASH_BANK_1)
#endif{pOBInit->OptionType |= OPTIONBYTE_SEC;FLASH_OB_GetSecMem(pOBInit->SecBank, &(pOBInit->SecSize));}
}/*** @brief  Enable the Power down in Run Mode* @note   This function should be called and executed from SRAM memory.* @retval None*/
__RAM_FUNC FLASH_StatusTypeDef FLASH_EnableRunPowerDown(void)
{/* Enable the Power Down in Run mode*/FLASH_POWER_DOWN_ENABLE();return FLASH_OK;
}/*** @brief  Disable the Power down in Run Mode* @note   This function should be called and executed from SRAM memory.* @retval None*/
__RAM_FUNC FLASH_StatusTypeDef FLASH_DisableRunPowerDown(void)
{/* Disable the Power Down in Run mode*/FLASH_POWER_DOWN_DISABLE();return FLASH_OK;
}#if defined (FLASH_OPTR_DBANK)
/*** @brief  Program the FLASH DBANK User Option Byte.** @note   To configure the user option bytes, the option lock bit OPTLOCK must*         be cleared with the call of the FLASH_OB_Unlock() function.* @note   To modify the DBANK option byte, no PCROP region should be defined.*         To deactivate PCROP, user should perform RDP changing.** @param  DBankConfig The FLASH DBANK User Option Byte value.*         This parameter  can be one of the following values:*            @arg OB_DBANK_128_BITS: Single-bank with 128-bits data*            @arg OB_DBANK_64_BITS: Dual-bank with 64-bits data** @retval FLASH_Status*/
__RAM_FUNC FLASH_StatusTypeDef FLASH_OB_DBankConfig(uint32_t DBankConfig)
{uint32_t count, reg;FLASH_StatusTypeDef status = FLASH_ERROR;/* Process Locked */FLASH_LOCK(&MCU_FLASH);/* Check if the PCROP is disabled */reg = FLASH->PCROP1SR;if (reg > FLASH->PCROP1ER){reg = FLASH->PCROP2SR;if (reg > FLASH->PCROP2ER){/* Disable Flash prefetch */FLASH_PREFETCH_BUFFER_DISABLE();if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != 0U){/* Disable Flash instruction cache */FLASH_INSTRUCTION_CACHE_DISABLE();/* Flush Flash instruction cache */FLASH_INSTRUCTION_CACHE_RESET();}if (READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U){/* Disable Flash data cache */FLASH_DATA_CACHE_DISABLE();/* Flush Flash data cache */FLASH_DATA_CACHE_RESET();}/* Disable WRP zone A of 1st bank if needed */reg = FLASH->WRP1AR;if (((reg & FLASH_WRP1AR_WRP1A_STRT) >> FLASH_WRP1AR_WRP1A_STRT_Pos) <=((reg & FLASH_WRP1AR_WRP1A_END) >> FLASH_WRP1AR_WRP1A_END_Pos)){MODIFY_REG(FLASH->WRP1AR, (FLASH_WRP1AR_WRP1A_STRT | FLASH_WRP1AR_WRP1A_END), FLASH_WRP1AR_WRP1A_STRT);}/* Disable WRP zone B of 1st bank if needed */reg = FLASH->WRP1BR;if (((reg & FLASH_WRP1BR_WRP1B_STRT) >> FLASH_WRP1BR_WRP1B_STRT_Pos) <=((reg & FLASH_WRP1BR_WRP1B_END) >> FLASH_WRP1BR_WRP1B_END_Pos)){MODIFY_REG(FLASH->WRP1BR, (FLASH_WRP1BR_WRP1B_STRT | FLASH_WRP1BR_WRP1B_END), FLASH_WRP1BR_WRP1B_STRT);}/* Disable WRP zone A of 2nd bank if needed */reg = FLASH->WRP2AR;if (((reg & FLASH_WRP2AR_WRP2A_STRT) >> FLASH_WRP2AR_WRP2A_STRT_Pos) <=((reg & FLASH_WRP2AR_WRP2A_END) >> FLASH_WRP2AR_WRP2A_END_Pos)){MODIFY_REG(FLASH->WRP2AR, (FLASH_WRP2AR_WRP2A_STRT | FLASH_WRP2AR_WRP2A_END), FLASH_WRP2AR_WRP2A_STRT);}/* Disable WRP zone B of 2nd bank if needed */reg = FLASH->WRP2BR;if (((reg & FLASH_WRP2BR_WRP2B_STRT) >> FLASH_WRP2BR_WRP2B_STRT_Pos) <=((reg & FLASH_WRP2BR_WRP2B_END) >> FLASH_WRP2BR_WRP2B_END_Pos)){MODIFY_REG(FLASH->WRP2BR, (FLASH_WRP2BR_WRP2B_STRT | FLASH_WRP2BR_WRP2B_END), FLASH_WRP2BR_WRP2B_STRT);}/* Modify the DBANK user option byte */MODIFY_REG(FLASH->OPTR, FLASH_OPTR_DBANK, DBankConfig);/* Set OPTSTRT Bit */SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);/* Wait for last operation to be completed *//* 8 is the number of required instruction cycles for the below loop statement (timeout expressed in ms) */count = FLASH_TIMEOUT_VALUE * (SystemCoreClock / 8U / 1000U);do{if (count == 0U){break;}count--;}while (FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET);/* If the option byte program operation is completed, disable the OPTSTRT Bit */CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);/* Set the bit to force the option byte reloading */SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);}}/* Process Unlocked */FLASH_UNLOCK(&MCU_FLASH);return status;
}
#endif/*** @brief  Enable the FLASH Securable Memory protection.* @param  Bank: Bank to be protected*          This parameter can be one of the following values:*            @arg FLASH_BANK_1: Bank1 to be protected*            @arg FLASH_BANK_2: Bank2 to be protected (*)*            @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be protected (*)* @note   (*) availability depends on devices* @retval FLASH Status*/
FLASH_StatusTypeDef FLASH_EnableSecMemProtection(uint32_t Bank)
{
#if defined (FLASH_OPTR_DBANK)if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) != 0U){/* Check the parameters */assert_param(IS_FLASH_BANK(Bank));/* Enable the Securable Memory Protection Bit for the bank 1 if requested */if ((Bank & FLASH_BANK_1) != 0U){SET_BIT(FLASH->CR, FLASH_CR_SEC_PROT1);}/* Enable the Securable Memory Protection Bit for the bank 2 if requested */if ((Bank & FLASH_BANK_2) != 0U){SET_BIT(FLASH->CR, FLASH_CR_SEC_PROT2);}}else
#endif{SET_BIT(FLASH->CR, FLASH_CR_SEC_PROT1);}return FLASH_OK;
}/*** @brief  Enable Debugger.* @note   After calling this API, flash interface allow debugger intrusion.* @retval None*/
void FLASH_EnableDebugger(void)
{FLASH->ACR |= FLASH_ACR_DBG_SWEN;
}/*** @brief  Disable Debugger.* @note   After calling this API, Debugger is disabled: it's no more possible to*         break, see CPU register, etc...* @retval None*/
void FLASH_DisableDebugger(void)
{FLASH->ACR &= ~FLASH_ACR_DBG_SWEN;
}/*** @brief  Get the specific FLASH error flag.* @retval FLASH_ErrorCode. The returned value can be:*            @arg FLASH_ERROR_RD: FLASH Read Protection error flag (PCROP)*            @arg FLASH_ERROR_PGS: FLASH Programming Sequence error flag*            @arg FLASH_ERROR_PGP: FLASH Programming Parallelism error flag*            @arg FLASH_ERROR_PGA: FLASH Programming Alignment error flag*            @arg FLASH_ERROR_WRP: FLASH Write protected error flag*            @arg FLASH_ERROR_OPERATION: FLASH operation Error flag*            @arg FLASH_ERROR_NONE: No error set*            @arg FLASH_ERROR_OP: FLASH Operation error*            @arg FLASH_ERROR_PROG: FLASH Programming error*            @arg FLASH_ERROR_WRP: FLASH Write protection error*            @arg FLASH_ERROR_PGA: FLASH Programming alignment error*            @arg FLASH_ERROR_SIZ: FLASH Size error*            @arg FLASH_ERROR_PGS: FLASH Programming sequence error*            @arg FLASH_ERROR_MIS: FLASH Fast programming data miss error*            @arg FLASH_ERROR_FAST: FLASH Fast programming error*            @arg FLASH_ERROR_RD: FLASH PCROP read error*            @arg FLASH_ERROR_OPTV: FLASH Option validity error*/
uint32_t FLASH_GetError(void)
{return MCU_FLASH.ErrorCode;
}/* Private functions ---------------------------------------------------------*/
/*** @brief  Wait for a FLASH operation to complete.* @param  Timeout maximum flash operation timeout.* @retval FLASH_Status*/
static FLASH_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
{/* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.Even if the FLASH operation fails, the BUSY flag will be reset and an errorflag will be set */uint32_t MsCnt = 0;uint32_t ErrFlag;while (FLASH_GET_FLAG(FLASH_FLAG_BSY)){if (MsCnt++ > Timeout){return FLASH_TIMEOUT;}LL_mDelay(1);}/* Check FLASH operation error flags */ErrFlag = (FLASH->SR & FLASH_FLAG_SR_ERRORS);if (ErrFlag != 0u){/* Save the error code */MCU_FLASH.ErrorCode |= ErrFlag;/* Clear error programming flags */FLASH_CLEAR_FLAG(ErrFlag);return FLASH_ERROR;}/* Check FLASH End of Operation flag  */if (FLASH_GET_FLAG(FLASH_FLAG_EOP)){/* Clear FLASH End of Operation pending bit */FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);}/* If there is an error flag set */return FLASH_OK;
}/*** @brief  Program double-word (64-bit) at a specified address.* @param  Address specifies the address to be programmed.* @param  Data specifies the data to be programmed.* @retval None*/
static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
{/* Check the parameters */assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));/* Set PG bit */SET_BIT(FLASH->CR, FLASH_CR_PG);/* Program first word */*(uint32_t *)Address = (uint32_t)Data;/* Barrier to ensure programming is performed in 2 steps, in right order(independently of compiler optimization behavior) */__ISB();/* Program second word */*(uint32_t *)(Address + 4U) = (uint32_t)(Data >> 32U);
}/*** @brief  Fast program a row double-word (64-bit) at a specified address.* @param  Address specifies the address to be programmed.* @param  DataAddress specifies the address where the data are stored.* @retval None*/
static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress)
{uint8_t row_index = (2 * FLASH_NB_DOUBLE_WORDS_IN_ROW);uint32_t *dest_addr = (uint32_t *)Address;uint32_t *src_addr = (uint32_t *)DataAddress;uint32_t primask_bit;/* Check the parameters */assert_param(IS_FLASH_MAIN_MEM_ADDRESS(Address));/* Set FSTPG bit */SET_BIT(FLASH->CR, FLASH_CR_FSTPG);/* Enter critical section: Disable interrupts to avoid any interruption during the loop */primask_bit = __get_PRIMASK();__disable_irq();/* Program the double words of the row */do{*dest_addr = *src_addr;dest_addr++;src_addr++;row_index--;}while (row_index != 0U);/* Exit critical section: restore previous priority mask */__set_PRIMASK(primask_bit);
}/*** @brief  Mass erase of FLASH memory.* @param  Banks Banks to be erased.*         This parameter can be one of the following values:*            @arg FLASH_BANK_1: Bank1 to be erased*            @arg FLASH_BANK_2: Bank2 to be erased (*)*            @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased (*)* @note   (*) availability depends on devices* @retval None*/
static void FLASH_MassErase(uint32_t Banks)
{
#if defined (FLASH_OPTR_DBANK)if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) != 0U)
#endif{/* Check the parameters */assert_param(IS_FLASH_BANK(Banks));/* Set the Mass Erase Bit for the bank 1 if requested */if ((Banks & FLASH_BANK_1) != 0U){SET_BIT(FLASH->CR, FLASH_CR_MER1);}#if defined (FLASH_OPTR_DBANK)/* Set the Mass Erase Bit for the bank 2 if requested */if ((Banks & FLASH_BANK_2) != 0U){SET_BIT(FLASH->CR, FLASH_CR_MER2);}
#endif}
#if defined (FLASH_OPTR_DBANK)else{SET_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2));}
#endif/* Proceed to erase all sectors */SET_BIT(FLASH->CR, FLASH_CR_STRT);
}/*** @brief  Erase the specified FLASH memory page.* @param  Page FLASH page to erase.*         This parameter must be a value between 0 and (max number of pages in the bank - 1).* @param  Banks Bank where the page will be erased.*         This parameter can be one of the following values:*            @arg FLASH_BANK_1: Page in bank 1 to be erased*            @arg FLASH_BANK_2: Page in bank 2 to be erased (*)* @note   (*) availability depends on devices* @retval None*/
static void FLASH_PageErase(uint32_t Page, uint32_t Banks)
{/* Check the parameters */assert_param(IS_FLASH_PAGE(Page));#if defined (FLASH_OPTR_DBANK)if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == 0U){CLEAR_BIT(FLASH->CR, FLASH_CR_BKER);}else{assert_param(IS_FLASH_BANK_EXCLUSIVE(Banks));if ((Banks & FLASH_BANK_1) != 0U){CLEAR_BIT(FLASH->CR, FLASH_CR_BKER);}else{SET_BIT(FLASH->CR, FLASH_CR_BKER);}}
#endif/* Proceed to erase the page */MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((Page & 0xFFU) << FLASH_CR_PNB_Pos));SET_BIT(FLASH->CR, FLASH_CR_PER);SET_BIT(FLASH->CR, FLASH_CR_STRT);
}/*** @brief  Flush the instruction and data caches.* @retval None*/
static void FLASH_FlushCaches(void)
{FLASH_CacheTypeDef cache = MCU_FLASH.CacheToReactivate;/* Flush instruction cache  */if ((cache == FLASH_CACHE_ICACHE_ENABLED) ||(cache == FLASH_CACHE_ICACHE_DCACHE_ENABLED)){/* Disable instruction cache */FLASH_INSTRUCTION_CACHE_DISABLE();/* Reset instruction cache */FLASH_INSTRUCTION_CACHE_RESET();/* Enable instruction cache */FLASH_INSTRUCTION_CACHE_ENABLE();}/* Flush data cache */if ((cache == FLASH_CACHE_DCACHE_ENABLED) ||(cache == FLASH_CACHE_ICACHE_DCACHE_ENABLED)){/* Reset data cache */FLASH_DATA_CACHE_RESET();/* Enable data cache */FLASH_DATA_CACHE_ENABLE();}/* Reset internal variable */MCU_FLASH.CacheToReactivate = FLASH_CACHE_DISABLED;
}/*** @brief  Configure the write protection area into Option Bytes.* @note   When the memory read protection level is selected (RDP level = 1),*         it is not possible to program or erase Flash memory if the CPU debug*         features are connected (JTAG or single wire) or boot code is being*         executed from RAM or System flash, even if WRP is not activated.* @note   To configure any option bytes, the option lock bit OPTLOCK must be*         cleared with the call of FLASH_OB_Unlock() function.* @note   New option bytes configuration will be taken into account in two cases:*         - after an option bytes launch through the call of FLASH_OB_Launch()*         - after a power reset (BOR reset or exit from Standby/Shutdown modes)* @param  WRPArea specifies the area to be configured.*         This parameter can be one of the following values:*            @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A*            @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B*            @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A (*)*            @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B (*)* @note   (*) availability depends on devices* @param  WRPStartOffset specifies the start page of the write protected area.*         This parameter can be page number between 0 and (max number of pages in the bank - 1).* @param  WRDPEndOffset specifies the end page of the write protected area.*         This parameter can be page number between WRPStartOffset and (max number of pages in the bank - 1).* @retval FLASH_Status*/
static FLASH_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset)
{FLASH_StatusTypeDef status;/* Check the parameters */assert_param(IS_OB_WRPAREA(WRPArea));assert_param(IS_FLASH_PAGE(WRPStartOffset));assert_param(IS_FLASH_PAGE(WRDPEndOffset));/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);if (status == FLASH_OK){/* Configure the write protected area */if (WRPArea == OB_WRPAREA_BANK1_AREAA){FLASH->WRP1AR = ((WRDPEndOffset << FLASH_WRP1AR_WRP1A_END_Pos) | WRPStartOffset);}else if (WRPArea == OB_WRPAREA_BANK1_AREAB){FLASH->WRP1BR = ((WRDPEndOffset << FLASH_WRP1BR_WRP1B_END_Pos) | WRPStartOffset);}
#if defined (FLASH_OPTR_DBANK)else if (WRPArea == OB_WRPAREA_BANK2_AREAA){FLASH->WRP2AR = ((WRDPEndOffset << FLASH_WRP2AR_WRP2A_END_Pos) | WRPStartOffset);}else if (WRPArea == OB_WRPAREA_BANK2_AREAB){FLASH->WRP2BR = ((WRDPEndOffset << FLASH_WRP2BR_WRP2B_END_Pos) | WRPStartOffset);}
#endifelse{/* Nothing to do */}/* Set OPTSTRT Bit */SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);}return status;
}/*** @brief  Set the read protection level into Option Bytes.* @note   To configure any option bytes, the option lock bit OPTLOCK must be*         cleared with the call of FLASH_OB_Unlock() function.* @note   New option bytes configuration will be taken into account in two cases:*         - after an option bytes launch through the call of FLASH_OB_Launch()*         - after a power reset (BOR reset or exit from Standby/Shutdown modes)* @note   !!! Warning : When enabling OB_RDP level 2 it's no more possible*         to go back to level 1 or 0 !!!* @param  RDPLevel specifies the read protection level.*         This parameter can be one of the following values:*            @arg OB_RDP_LEVEL_0: No protection*            @arg OB_RDP_LEVEL_1: Memory Read protection*            @arg OB_RDP_LEVEL_2: Full chip protection** @retval FLASH_Status*/
static FLASH_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel)
{FLASH_StatusTypeDef status;/* Check the parameters */assert_param(IS_OB_RDP_LEVEL(RDPLevel));/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);if (status == FLASH_OK){/* Configure the RDP level in the option bytes register */MODIFY_REG(FLASH->OPTR, FLASH_OPTR_RDP, RDPLevel);/* Set OPTSTRT Bit */SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);}return status;
}/*** @brief  Program the FLASH User Option Bytes.* @note   To configure any option bytes, the option lock bit OPTLOCK must be*         cleared with the call of FLASH_OB_Unlock() function.* @note   New option bytes configuration will be taken into account in two cases:*         - after an option bytes launch through the call of FLASH_OB_Launch()*         - after a power reset (BOR reset or exit from Standby/Shutdown modes)* @param  UserType The FLASH User Option Bytes to be modified.*         This parameter can be a combination of @ref FLASH_OB_USER_Type.* @param  UserConfig The selected User Option Bytes values:*         This parameter can be a combination of @ref FLASH_OB_USER_BOR_LEVEL,*         @ref FLASH_OB_USER_nRST_STOP, @ref FLASH_OB_USER_nRST_STANDBY ,*         @ref FLASH_OB_USER_nRST_SHUTDOWN, @ref FLASH_OB_USER_IWDG_SW,*         @ref FLASH_OB_USER_IWDG_STOP, @ref FLASH_OB_USER_IWDG_STANDBY,*         @ref FLASH_OB_USER_WWDG_SW, @ref FLASH_OB_USER_WWDG_SW,*         @ref FLASH_OB_USER_BFB2 (*), @ref FLASH_OB_USER_nBOOT1,*         @ref FLASH_OB_USER_SRAM_PE, @ref FLASH_OB_USER_CCMSRAM_RST,*         @ref FLASH_OB_USER_nSWBOOT0, @ref FLASH_OB_USER_nBOOT0,*         @ref FLASH_OB_USER_NRST_MODE, @ref FLASH_OB_USER_INTERNAL_RESET_HOLDER* @note   (*) availability depends on devices* @retval FLASH_Status*/
static FLASH_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig)
{uint32_t optr_reg_val = 0;uint32_t optr_reg_mask = 0;FLASH_StatusTypeDef status;/* Check the parameters */assert_param(IS_OB_USER_TYPE(UserType));/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);if (status == FLASH_OK){if ((UserType & OB_USER_BOR_LEV) != 0U){/* BOR level option byte should be modified */assert_param(IS_OB_USER_BOR_LEVEL(UserConfig & FLASH_OPTR_BOR_LEV));/* Set value and mask for BOR level option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_BOR_LEV);optr_reg_mask |= FLASH_OPTR_BOR_LEV;}if ((UserType & OB_USER_nRST_STOP) != 0U){/* nRST_STOP option byte should be modified */assert_param(IS_OB_USER_STOP(UserConfig & FLASH_OPTR_nRST_STOP));/* Set value and mask for nRST_STOP option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STOP);optr_reg_mask |= FLASH_OPTR_nRST_STOP;}if ((UserType & OB_USER_nRST_STDBY) != 0U){/* nRST_STDBY option byte should be modified */assert_param(IS_OB_USER_STANDBY(UserConfig & FLASH_OPTR_nRST_STDBY));/* Set value and mask for nRST_STDBY option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STDBY);optr_reg_mask |= FLASH_OPTR_nRST_STDBY;}if ((UserType & OB_USER_nRST_SHDW) != 0U){/* nRST_SHDW option byte should be modified */assert_param(IS_OB_USER_SHUTDOWN(UserConfig & FLASH_OPTR_nRST_SHDW));/* Set value and mask for nRST_SHDW option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_SHDW);optr_reg_mask |= FLASH_OPTR_nRST_SHDW;}if ((UserType & OB_USER_IWDG_SW) != 0U){/* IWDG_SW option byte should be modified */assert_param(IS_OB_USER_IWDG(UserConfig & FLASH_OPTR_IWDG_SW));/* Set value and mask for IWDG_SW option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_SW);optr_reg_mask |= FLASH_OPTR_IWDG_SW;}if ((UserType & OB_USER_IWDG_STOP) != 0U){/* IWDG_STOP option byte should be modified */assert_param(IS_OB_USER_IWDG_STOP(UserConfig & FLASH_OPTR_IWDG_STOP));/* Set value and mask for IWDG_STOP option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STOP);optr_reg_mask |= FLASH_OPTR_IWDG_STOP;}if ((UserType & OB_USER_IWDG_STDBY) != 0U){/* IWDG_STDBY option byte should be modified */assert_param(IS_OB_USER_IWDG_STDBY(UserConfig & FLASH_OPTR_IWDG_STDBY));/* Set value and mask for IWDG_STDBY option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STDBY);optr_reg_mask |= FLASH_OPTR_IWDG_STDBY;}if ((UserType & OB_USER_WWDG_SW) != 0U){/* WWDG_SW option byte should be modified */assert_param(IS_OB_USER_WWDG(UserConfig & FLASH_OPTR_WWDG_SW));/* Set value and mask for WWDG_SW option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_WWDG_SW);optr_reg_mask |= FLASH_OPTR_WWDG_SW;}#if defined (FLASH_OPTR_BFB2)if ((UserType & OB_USER_BFB2) != 0U){/* BFB2 option byte should be modified */assert_param(IS_OB_USER_BFB2(UserConfig & FLASH_OPTR_BFB2));/* Set value and mask for BFB2 option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_BFB2);optr_reg_mask |= FLASH_OPTR_BFB2;}
#endifif ((UserType & OB_USER_nBOOT1) != 0U){/* nBOOT1 option byte should be modified */assert_param(IS_OB_USER_BOOT1(UserConfig & FLASH_OPTR_nBOOT1));/* Set value and mask for nBOOT1 option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT1);optr_reg_mask |= FLASH_OPTR_nBOOT1;}if ((UserType & OB_USER_SRAM_PE) != 0U){/* SRAM_PE option byte should be modified */assert_param(IS_OB_USER_SRAM_PARITY(UserConfig & FLASH_OPTR_SRAM_PE));/* Set value and mask for SRAM_PE option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM_PE);optr_reg_mask |= FLASH_OPTR_SRAM_PE;}if ((UserType & OB_USER_CCMSRAM_RST) != 0U){/* CCMSRAM_RST option byte should be modified */assert_param(IS_OB_USER_CCMSRAM_RST(UserConfig & FLASH_OPTR_CCMSRAM_RST));/* Set value and mask for CCMSRAM_RST option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_CCMSRAM_RST);optr_reg_mask |= FLASH_OPTR_CCMSRAM_RST;}if ((UserType & OB_USER_nSWBOOT0) != 0U){/* nSWBOOT0 option byte should be modified */assert_param(IS_OB_USER_SWBOOT0(UserConfig & FLASH_OPTR_nSWBOOT0));/* Set value and mask for nSWBOOT0 option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_nSWBOOT0);optr_reg_mask |= FLASH_OPTR_nSWBOOT0;}if ((UserType & OB_USER_nBOOT0) != 0U){/* nBOOT0 option byte should be modified */assert_param(IS_OB_USER_BOOT0(UserConfig & FLASH_OPTR_nBOOT0));/* Set value and mask for nBOOT0 option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT0);optr_reg_mask |= FLASH_OPTR_nBOOT0;}if ((UserType & OB_USER_NRST_MODE) != 0U){/* Reset Configuration option byte should be modified */assert_param(IS_OB_USER_NRST_MODE(UserConfig & FLASH_OPTR_NRST_MODE));/* Set value and mask for Reset Configuration option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_NRST_MODE);optr_reg_mask |= FLASH_OPTR_NRST_MODE;}if ((UserType & OB_USER_IRHEN) != 0U){/* IRH option byte should be modified */assert_param(IS_OB_USER_IRHEN(UserConfig & FLASH_OPTR_IRHEN));/* Set value and mask for IRH option byte */optr_reg_val |= (UserConfig & FLASH_OPTR_IRHEN);optr_reg_mask |= FLASH_OPTR_IRHEN;}/* Configure the option bytes register */MODIFY_REG(FLASH->OPTR, optr_reg_mask, optr_reg_val);/* Set OPTSTRT Bit */SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);}return status;
}/*** @brief  Configure the Proprietary code readout protection area into Option Bytes.* @note   To configure any option bytes, the option lock bit OPTLOCK must be*         cleared with the call of FLASH_OB_Unlock() function.* @note   New option bytes configuration will be taken into account in two cases:*         - after an option bytes launch through the call of FLASH_OB_Launch()*         - after a power reset (BOR reset or exit from Standby/Shutdown modes)* @param  PCROPConfig specifies the configuration (Bank to be configured and PCROP_RDP option).*         This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2 (*)*         with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE.* @note   (*) availability depends on devices* @param  PCROPStartAddr specifies the start address of the Proprietary code readout protection.*         This parameter can be an address between begin and end of the bank.* @param  PCROPEndAddr specifies the end address of the Proprietary code readout protection.*         This parameter can be an address between PCROPStartAddr and end of the bank.* @retval FLASH_Status*/
static FLASH_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr)
{FLASH_StatusTypeDef status;uint32_t reg_value;uint32_t bank1_addr;
#if defined (FLASH_OPTR_DBANK)uint32_t bank2_addr;
#endif/* Check the parameters */assert_param(IS_FLASH_BANK_EXCLUSIVE(PCROPConfig & FLASH_BANK_BOTH));assert_param(IS_OB_PCROP_RDP(PCROPConfig & FLASH_PCROP1ER_PCROP_RDP));assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPStartAddr));assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPEndAddr));/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);if (status == FLASH_OK){
#if defined (FLASH_OPTR_DBANK)/* Get the information about the bank swapping */if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0U){bank1_addr = FLASH_BASE;bank2_addr = FLASH_BASE + FLASH_BANK_SIZE;}else{bank1_addr = FLASH_BASE + FLASH_BANK_SIZE;bank2_addr = FLASH_BASE;}
#elsebank1_addr = FLASH_BASE;
#endif#if defined (FLASH_OPTR_DBANK)if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == 0U){/* Configure the Proprietary code readout protection */if ((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1){reg_value = ((PCROPStartAddr - FLASH_BASE) >> 4);MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value);reg_value = ((PCROPEndAddr - FLASH_BASE) >> 4);MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value);}else if ((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2){reg_value = ((PCROPStartAddr - FLASH_BASE) >> 4);MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value);reg_value = ((PCROPEndAddr - FLASH_BASE) >> 4);MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value);}else{/* Nothing to do */}}else
#endif{/* Configure the Proprietary code readout protection */if ((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1){reg_value = ((PCROPStartAddr - bank1_addr) >> 3);MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value);reg_value = ((PCROPEndAddr - bank1_addr) >> 3);MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value);}
#if defined (FLASH_OPTR_DBANK)else if ((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2){reg_value = ((PCROPStartAddr - bank2_addr) >> 3);MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value);reg_value = ((PCROPEndAddr - bank2_addr) >> 3);MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value);}
#endifelse{/* Nothing to do */}}MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP_RDP, (PCROPConfig & FLASH_PCROP1ER_PCROP_RDP));/* Set OPTSTRT Bit */SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);}return status;
}/*** @brief  Configure the Securable memory area into Option Bytes.* @note   To configure any option bytes, the option lock bit OPTLOCK must be*         cleared with the call of FLASH_OB_Unlock() function.* @note   New option bytes configuration will be taken into account in two cases:*         - after an option bytes launch through the call of FLASH_OB_Launch()*         - after a power reset (BOR reset or exit from Standby/Shutdown modes)* @param  SecBank specifies bank of securable memory area to be configured.*          This parameter can be one of the following values:*            @arg FLASH_BANK_1: Securable memory in Bank1 to be configured*            @arg FLASH_BANK_2: Securable memory in Bank2 to be configured (*)* @note   (*) availability depends on devices* @param  SecSize specifies the number of pages of the Securable memory area,*         starting from first page of the bank.*         This parameter can be page number between 0 and (max number of pages in the bank - 1)* @retval FLASH Status*/
static FLASH_StatusTypeDef FLASH_OB_SecMemConfig(uint32_t SecBank, uint32_t SecSize)
{FLASH_StatusTypeDef status;/* Check the parameters */assert_param(IS_FLASH_BANK_EXCLUSIVE(SecBank));assert_param(IS_OB_SECMEM_SIZE(SecSize));/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);if (status == FLASH_OK){/* Configure the write protected area */if (SecBank == FLASH_BANK_1){MODIFY_REG(FLASH->SEC1R, FLASH_SEC1R_SEC_SIZE1, SecSize);}
#if defined (FLASH_OPTR_DBANK)else if (SecBank == FLASH_BANK_2){MODIFY_REG(FLASH->SEC2R, FLASH_SEC2R_SEC_SIZE2, SecSize);}else{/* Nothing to do */}
#endif/* Set OPTSTRT Bit */SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);}return status;
}/*** @brief  Configure the Boot Lock into Option Bytes.* @note   To configure any option bytes, the option lock bit OPTLOCK must be*         cleared with the call of FLASH_OB_Unlock() function.* @note   New option bytes configuration will be taken into account in two cases:*         - after an option bytes launch through the call of FLASH_OB_Launch()*         - after a power reset (BOR reset or exit from Standby/Shutdown modes)* @param  BootLockConfig specifies the boot lock configuration.*          This parameter can be one of the following values:*            @arg OB_BOOT_LOCK_ENABLE: Enable Boot Lock*            @arg OB_BOOT_LOCK_DISABLE: Disable Boot Lock** @retval FLASH_Status*/
static FLASH_StatusTypeDef FLASH_OB_BootLockConfig(uint32_t BootLockConfig)
{FLASH_StatusTypeDef status;/* Check the parameters */assert_param(IS_OB_BOOT_LOCK(BootLockConfig));/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);if (status == FLASH_OK){MODIFY_REG(FLASH->SEC1R, FLASH_SEC1R_BOOT_LOCK, BootLockConfig);/* Set OPTSTRT Bit */SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);}return status;
}/*** @brief  Return the Securable memory area configuration into Option Bytes.* @param[in]  SecBank specifies the bank where securable memory area is located.*          This parameter can be one of the following values:*            @arg FLASH_BANK_1: Securable memory in Bank1*            @arg FLASH_BANK_2: Securable memory in Bank2 (*)* @note   (*) availability depends on devices* @param[out]  SecSize specifies the number of pages used in the securablememory area of the bank.* @retval None*/
static void FLASH_OB_GetSecMem(uint32_t SecBank, uint32_t *SecSize)
{/* Get the configuration of the securable memory area */if (SecBank == FLASH_BANK_1){*SecSize = READ_BIT(FLASH->SEC1R, FLASH_SEC1R_SEC_SIZE1);}
#if defined (FLASH_OPTR_DBANK)else if (SecBank == FLASH_BANK_2){*SecSize = READ_BIT(FLASH->SEC2R, FLASH_SEC2R_SEC_SIZE2);}else{/* Nothing to do */}
#endif
}/*** @brief  Return the Boot Lock configuration into Option Byte.* @retval BootLockConfig.*         This return value can be one of the following values:*            @arg OB_BOOT_LOCK_ENABLE: Boot lock enabled*            @arg OB_BOOT_LOCK_DISABLE: Boot lock disabled*/
static uint32_t FLASH_OB_GetBootLock(void)
{return (READ_REG(FLASH->SEC1R) & FLASH_SEC1R_BOOT_LOCK);
}/*** @brief  Return the Write Protection configuration into Option Bytes.* @param[in]  WRPArea specifies the area to be returned.*          This parameter can be one of the following values:*            @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A*            @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B*            @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A (don't apply to STM32G43x/STM32G44x devices)*            @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B (don't apply to STM32G43x/STM32G44x devices)* @param[out]  WRPStartOffset specifies the address where to copied the start page*              of the write protected area.* @param[out]  WRDPEndOffset specifies the address where to copied the end page of*              the write protected area.* @retval None*/
static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset)
{/* Get the configuration of the write protected area */if (WRPArea == OB_WRPAREA_BANK1_AREAA){*WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT);*WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> FLASH_WRP1AR_WRP1A_END_Pos);}else if (WRPArea == OB_WRPAREA_BANK1_AREAB){*WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT);*WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> FLASH_WRP1BR_WRP1B_END_Pos);}
#if defined (FLASH_OPTR_DBANK)else if (WRPArea == OB_WRPAREA_BANK2_AREAA){*WRPStartOffset = READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_STRT);*WRDPEndOffset = (READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_END) >> FLASH_WRP2AR_WRP2A_END_Pos);}else if (WRPArea == OB_WRPAREA_BANK2_AREAB){*WRPStartOffset = READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_STRT);*WRDPEndOffset = (READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_END) >> FLASH_WRP2BR_WRP2B_END_Pos);}
#endifelse{/* Nothing to do */}
}/*** @brief  Return the FLASH Read Protection level into Option Bytes.* @retval RDP_Level*         This return value can be one of the following values:*            @arg OB_RDP_LEVEL_0: No protection*            @arg OB_RDP_LEVEL_1: Read protection of the memory*            @arg OB_RDP_LEVEL_2: Full chip protection*/
static uint32_t FLASH_OB_GetRDP(void)
{uint32_t rdp_level = READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP);if ((rdp_level != OB_RDP_LEVEL_0) && (rdp_level != OB_RDP_LEVEL_2)){return (OB_RDP_LEVEL_1);}else{return rdp_level;}
}/*** @brief  Return the FLASH User Option Byte value.* @retval OB_user_config*         This return value is a combination of @ref FLASH_OB_USER_BOR_LEVEL,*         @ref FLASH_OB_USER_nRST_STOP, @ref FLASH_OB_USER_nRST_STANDBY,*         @ref FLASH_OB_USER_nRST_SHUTDOWN, @ref FLASH_OB_USER_IWDG_SW,*         @ref FLASH_OB_USER_IWDG_STOP, @ref FLASH_OB_USER_IWDG_STANDBY,*         @ref FLASH_OB_USER_WWDG_SW, @ref FLASH_OB_USER_WWDG_SW,*         @ref FLASH_OB_USER_BFB2 (*), @ref FLASH_OB_USER_DBANK (*),*         @ref FLASH_OB_USER_nBOOT1, @ref FLASH_OB_USER_SRAM_PE,*         @ref FLASH_OB_USER_CCMSRAM_RST, @ref OB_USER_nSWBOOT0,@ref FLASH_OB_USER_nBOOT0,*         @ref FLASH_OB_USER_NRST_MODE, @ref FLASH_OB_USER_INTERNAL_RESET_HOLDER* @note  (*) availability depends on devices*/
static uint32_t FLASH_OB_GetUser(void)
{uint32_t user_config = READ_REG(FLASH->OPTR);CLEAR_BIT(user_config, FLASH_OPTR_RDP);return user_config;
}/*** @brief  Return the FLASH PCROP configuration into Option Bytes.* @param[in,out] PCROPConfig specifies the configuration (Bank to be configured and PCROP_RDP option).*        This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2*        with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE.* @param[out] PCROPStartAddr specifies the address where to copied the start address*        of the Proprietary code readout protection.* @param[out] PCROPEndAddr specifies the address where to copied the end address of*        the Proprietary code readout protection.* @retval None*/
static void FLASH_OB_GetPCROP(uint32_t *PCROPConfig, uint32_t *PCROPStartAddr, uint32_t *PCROPEndAddr)
{uint32_t reg_value;uint32_t bank1_addr;
#if defined (FLASH_OPTR_DBANK)uint32_t bank2_addr;/* Get the information about the bank swapping */if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0U){bank1_addr = FLASH_BASE;bank2_addr = FLASH_BASE + FLASH_BANK_SIZE;}else{bank1_addr = FLASH_BASE + FLASH_BANK_SIZE;bank2_addr = FLASH_BASE;}
#elsebank1_addr = FLASH_BASE;
#endif#if defined (FLASH_OPTR_DBANK)if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == 0U){if (((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1){reg_value       = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT);*PCROPStartAddr = (reg_value << 4) + FLASH_BASE;reg_value     = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END);*PCROPEndAddr = (reg_value << 4) + FLASH_BASE;}else if (((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2){reg_value       = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT);*PCROPStartAddr = (reg_value << 4) + FLASH_BASE;reg_value     = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END);*PCROPEndAddr = (reg_value << 4) + FLASH_BASE;}else{/* Nothing to do */}}else
#endif{if (((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1){reg_value       = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT);*PCROPStartAddr = (reg_value << 3) + bank1_addr;reg_value     = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END);*PCROPEndAddr = (reg_value << 3) + bank1_addr;}
#if defined (FLASH_OPTR_DBANK)else if (((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2){reg_value       = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT);*PCROPStartAddr = (reg_value << 3) + bank2_addr;reg_value     = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END);*PCROPEndAddr = (reg_value << 3) + bank2_addr;}
#endifelse{/* Nothing to do */}}*PCROPConfig |= (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP_RDP);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/236368.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速能访问服务器的文件

1、背景 访问ubuntu上的文件 2、方法 python3 -m http.server 8081 --directory /home/ NAS 共享访问协议 — NFS、SMB、FTP、WebDAV 各有何优势&#xff1f;http://1 Ubuntu 搭建文件服务器&#xff08;Nginx&#xff09;

Git初始

一)git的介绍: 1)假设现在有一个文档&#xff0c;你的老板要求你针对于这份文件进行修改&#xff0c;进行完成的修改的版本是版本1&#xff0c;接下来是文档2&#xff0c;修改完文档2以后&#xff0c;接下来老板还不同意&#xff0c;于是又有了文档三&#xff0c;文档四&#x…

Java 干净的Stream,Lambda代码写法

目录 一. 前期准备1.1 各种实体类1.2 生成List<CommonUser>的方法1.3 需求 二. 难以阅读的Lambda表达式三. 干净的Lambda表达式四. 效果 一. 前期准备 1.1 各种实体类 ⏹Address实体类&#xff0c;用来存储地址 import lombok.Builder; import lombok.Getter;Builder …

力扣刷题记录(17)LeetCode:416、1049

416. 分割等和子集 可以将该问题看成是一个背包问题。背包的容量就是nums数组和的一半。我们如果能够将背包装满就意味着可以将数组分割成两个元素和相等的子集。 1.确定dp[i]的含义 索引i表示背包的容量&#xff0c;dp[i]表示当前容量能够装载的最大值 2.确定动态转移方程 …

Uniapp + Vue3 封装请求工具挂载全局

新建request.js工具类 const http {// baseUrl 地址baseUrl: http://localhost:8080,// 请求方法request(config) {// config&#xff1a;请求配置对象&#xff0c;具体参照uniapp文档config beforeRequest(config)// 请求地址拼接config.url this.baseUrl config.url// 异…

Linux-----14、vim

# vim Linux平台下的文本编辑器&#xff1a; emacs、nano、gedit、vi、vim vi&#xff08;visual editor&#xff09;编辑器通常被简称为vi&#xff0c;它是Linux和Unix系统上最基本的文本编辑器&#xff0c;类似于Windows 系统下的记事本。学会它后&#xff0c;我们将在Linu…

Vue数组变更方法和替换方法

一、可以引起UI界面变化 Vue 将被侦听的数组的变更方法进行了包裹&#xff0c;所以它们也将会触发视图更新。这些被包裹过的方法包括&#xff1a; push()pop()shift()unshift()splice()sort()reverse() 以上七个数组都会改变原数组&#xff0c;下面来分别讲解它们的区别&…

【Unity】【WebRTC】如何用Unity而不是浏览器接收远程画面

【背景】 之前几篇我们讨论了如何设置信令服务器&#xff0c;如何发送画面给远端以及如何用浏览器查看同步画面&#xff0c;今天来讨论如何实现Unity内部接收画面。 看本篇之前请先看过之前将web服务器设置和基本远程画面功能的几篇博文。&#xff08;同专栏下查看&#xff09…

如何通过宝塔面板搭建一个MySQL数据库服务并实现无公网ip远程访问?

文章目录 前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道 4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 宝塔面板的简易操作性,使得运维难度降低,简化了Linux命令行进行繁琐的配置,下面简单几步,通过宝塔面板cp…

python-dlib实现人脸提取和分割

效果 → 参考资料和资源 GitHub - Onwaier/SegfaceAndAlignByDlib: 用dlib实现脸部分割和人脸对齐 shape_predictor_68_face_landmarks.dat 下载地址_shape_predictor_68_face_landmarks.dat下载-CSDN博客 未运行的参考资料 dlib实现脸部分割与人脸对齐 - 知乎 py代码 &…

【Lidar】Open3D点云DBSCAN聚类算法:基于密度的点云聚类(单木分割)附Python代码

1 DBSCAN算法介绍 DBSCAN聚类算法是一种基于密度的聚类算法&#xff0c;全称为“基于密度的带有噪声的空间聚类应用”&#xff0c;英文名称为Density-Based Spatial Clustering of Applications with Noise。 DBSCAN聚类算法能够发现任意形状的类别&#xff0c;并且对噪音数据具…

全网最全pytest大型攻略,单元测试学这就够了!

pytest 是一款以python为开发语言的第三方测试&#xff0c;主要特点如下&#xff1a; 比自带的 unittest 更简洁高效&#xff0c;兼容 unittest框架支持参数化可以更精确的控制要测试的测试用例丰富的插件&#xff0c;已有300多个各种各样的插件&#xff0c;也可自定义扩展&am…

数字化时代的智能支持:亚马逊云科技轻量应用服务器技术领先

轻量应用服务器是一种简化运维、门槛低的弹性服务器&#xff0c;它的"轻"主要体现在几个方面&#xff1a;开箱即用、应用优质、上手简洁、投入划算、运维简便以及稳定可靠。相较于普通的云服务器&#xff0c;轻量应用服务器简化了云服务的操作难度、使用和管理流程&a…

mysql:查询服务器当前打开的连接数量

使用命令show global status like Threads_connected;可以查询mysql服务器当前打开的连接数量。 例如&#xff0c;查询如下&#xff1a; 启动应用&#xff0c;连接数据库&#xff0c;占用了1个连接&#xff0c;再查询如下&#xff1a; 由输出可以看出&#xff0c;打开的连接…

低代码和纯代码:双向奔赴,共创未来ing……

低代码开发是近年来迅速崛起的软件开发方法&#xff0c;让编写应用程序变得更快、更简单。有人说它是美味的膳食&#xff0c;让开发过程高效而满足&#xff0c;但也有人质疑它是垃圾食品&#xff0c;缺乏定制性与深度。你认为低代码到底是美味的膳食还是垃圾食品呢&#xff0c;…

【方案】如何利用大数据+云计算技术打造智能环境监控系统?

小编在之前的文章中也提到过基于云计算的环境智能监控系统是什么样的&#xff0c;收到了很多朋友的关注&#xff0c;今天小编就再次根据智能监控为切入点&#xff0c;深入讲解智能环境监控系统方案的详细落实。 1、传感器节点&#xff1a;首先需要选择适合应用场景的各类传感器…

Actuator内存泄露及利用Swagger未授权自动化测试实现

目录 0x00 前言 0x01 Actuator 泄露及利用 1、Actuator heapdump 内存泄露 2、知道泄露后如何进一步利用 3、如何发现 Actuator 泄露&#xff08;白盒/黑盒&#xff09; 0x02 Swagger自动化测试 1、什么是Swagger&#xff1f; 2、PostmanBurpSuiteXray 联动 3、思考 0x…

JavaAwtSwing的JFrame的pack()方法,容器适配子组件大小,笔记231220

pack()是extends自Window类的方法 使此窗口的大小适合其子组件的首选大小和布局。如果其中一个尺寸小于上一次调用setMinimumSize方法指定的最小尺寸&#xff0c;则会自动放大窗口的宽度和高度。 如果窗口和/或其所有者还不可显示&#xff0c;则在计算首选大小之前&#xff0…

tf卡数据恢复怎么做?记好这4个步骤!

“为了更好的保存数据&#xff0c;我一直都是用TF卡的。很多重要的文件和数据都保存在里面。但是我最近使用时&#xff0c;发现有部分数据丢失了。不知道该怎么办&#xff0c;有没有朋友可以帮帮我呀&#xff1f;” TF卡是一种闪存存储卡&#xff0c;通常用于手机、平板电脑和其…

Linux shell编程学习笔记37:readarray命令和mapfile命令

目录 0 前言1 readarray命令的格式和功能 1.1 命令格式1.2 命令功能1.3 注意事项2 命令应用实例 2.1 从标准输入读取数据时不指定数组名&#xff0c;则数据会保存到MAPFILE数组中2.2 从标准输入读取数据并存储到指定的数组2.3 使用 -O 选项指定起始下标2.4 用-n指定有效行数…