/************************************************************************************************/
/**
* @file               std_flash.h
* @author             MCU Ecosystem Development Team
* @brief              FLASH STD库驱动头文件。
*                     提供FLASH相关的STD库操作函数声明、数据类型以及常量的定义。                         
*
*
**************************************************************************************************
* @attention
* Copyright (c) CEC Huada Electronic Design Co.,Ltd. All rights reserved.
*
**************************************************************************************************
*/

/*避免头文件重复引用*/
#ifndef STD_FLASH_H
#define STD_FLASH_H

/************************************************************************************************/
/** 
* @addtogroup STD_Driver
* @{
*/

/**
* @defgroup FLASH FLASH
* @brief FLASH存储器的STD库驱动
* @{
*/
/************************************************************************************************/



#ifdef __cplusplus
 extern "C" {
#endif

/*------------------------------------------includes--------------------------------------------*/
#include "std_common.h"

     
/*-----------------------------------------type define------------------------------------------*/

/************************************************************************************************/
/** 
* @defgroup FLASH_Types FLASH Types
* @brief    FLASH数据类型定义
* @{
*/
/************************************************************************************************/

/**
* @brief  FLASH选项字节配置结构体定义
*/
typedef struct
{
    uint32_t config_select;          /**< 选项字节配置选择，未被选中的选项字节将使用出厂默认值，
                                          选中的选项字节将使用选项字节配置结构体对应成员变量的值更新
                                              @arg FLASH_OB_CONFIG_RDP
                                              @arg FLASH_OB_CONFIG_PVD
                                              ...
                                              @arg FLASH_OB_CONFIG_ALL                                          */
    
    uint32_t rdp_level;              /**< FLASH读出保护等级选择                               
                                              @arg FLASH_RDP_LEVEL_0
                                              @arg FLASH_RDP_LEVEL_1                                            
                                              @arg FLASH_RDP_LEVEL_2                                            */
    
    uint32_t pvd_enable;             /**< PVD使能控制
                                              @arg FLASH_PVD_ENABLE
                                              @arg FLASH_PVD_DISABLE                                            */
    
    uint32_t pvd_level;              /**< PVD档位选择
                                              @arg FLASH_PVD_LEVEL_0 
                                              @arg FLASH_PVD_LEVEL_1
                                              ...
                                              @arg FLASH_PVD_LEVEL_7                                            */

    uint32_t boot_config;            /**< 启动配置选择
                                              @arg FLASH_USE_PIN_BOOT                             
                                              @arg FLASH_USE_SW_USER_BOOT                                            
                                              @arg FLASH_USE_SW_BOOTLOADER_BOOT                                 */
    
    uint32_t iwdg_stop;              /**< 独立看门狗低功耗模式（Stop或Deepstop）计数器计数控制
                                              @arg FLASH_IWDG_STOP_MODE_STOP
                                              @arg FLASH_IWDG_STOP_MODE_NORMAL                                  */
                                              
}std_flash_option_config_t;
/**
* @}
*/

/*-------------------------------------------define---------------------------------------------*/

/************************************************************************************************/
/**
* @defgroup FLASH_Constants FLASH Constants 
* @brief  FLASH常量定义及宏定义
* @{
*
*/
/************************************************************************************************/

/* Flash读取访问等待周期 */      
#define FLASH_LATENCY_0CLK                FLASH_ACR_LATENCY_0CLK                     /**< 等待周期：0 HCLK         */
#define FLASH_LATENCY_1CLK                FLASH_ACR_LATENCY_1CLK                     /**< 等待周期：1 HCLK         */

/* Flash操作等待时间 */                                                              
#define FLASH_WAIT_PROGRAM                (1U)                                       /**< Flash编程等待时间（ms）  */
#define FLASH_WAIT_PAGE_ERASE             (5U)                                       /**< Flash页擦等待时间（ms）  */
#define FLASH_WAIT_MASS_ERASE             (50U)                                      /**< Flash片擦等待时间（ms）  */
#define FLASH_WAIT_MAX                    (50U)                                      /**< FLASH最大等待时间（ms）  */

/* Flash控制寄存器解锁密钥 */                                                        
#define FLASH_CR_KEY1                     (0xE57A1A85U)                              /**< Flash控制寄存器解锁密钥1 */
#define FLASH_CR_KEY2                     (0x7C6E8391U)                              /**< Flash控制寄存器解锁密钥2 */

/* Flash选项字节解锁密钥 */                                                          
#define FLASH_OPT_KEY1                    (0x6A894D7BU)                              /**< Flash选项字节解锁密钥1   */
#define FLASH_OPT_KEY2                    (0x7C311F5AU)                              /**< Flash选项字节解锁密钥2   */

/* Flash操作状态 */                                                                  
#define FLASH_FLAG_EOP                    FLASH_SR_EOP                               /**< Flash操作完成标志              */
#define FLASH_FLAG_BSY                    FLASH_SR_BSY                               /**< Flash操作状态标志              */
#define FLASH_FLAG_OPTVERR                FLASH_SR_OPTVERR                           /**< Flash option bytes校验错误标志 */
#define FLASH_FLAG_WRPERR                 FLASH_SR_WRPERR                            /**< Flash写保护错误标志            */

/* Flash中断源 */                      
#define FLASH_INTERRUPT_OPERR             FLASH_CR_OPERRIE                           /**< Flash操作异常中断        */
#define FLASH_INTERRUPT_EOP               FLASH_CR_EOPIE                             /**< Flash操作完成中断        */

/* Flash操作模式 */                                                                  
#define FLASH_OPERATE_DISABLE             FLASH_CR_OP_MODE_IDLE                      /**< Flash退出擦除编程模式    */
#define FLASH_ERASE_PAGE                  FLASH_CR_OP_MODE_PAGE_ERASE                /**< Flash页擦除模式          */
#define FLASH_ERASE_MASS                  FLASH_CR_OP_MODE_MASS_ERASE                /**< Flash批量擦除模式        */
#define FLASH_PROGRAM                     FLASH_CR_OP_MODE_PROGRAM                   /**< Flash编程模式            */

/* 选项字节配置相关宏定义 */
/* 选项字节配置选择 */
#define FLASH_OB_CONFIG_RDP               (0x00000001U)                              /**< 选项字节选择更新RDP配置            */
#define FLASH_OB_CONFIG_PVD               (0x00000002U)                              /**< 选项字节选择更新PVD配置            */
#define FLASH_OB_CONFIG_BOOT              (0x00000004U)                              /**< 选项字节选择更新BOOT配置           */
#define FLASH_OB_CONFIG_IWDG_STOP         (0x00000008U)                              /**< 选项字节选择更新低功耗复位配置     */
#define FLASH_OB_CONFIG_ALL               (0x0000000FU)                              /**< 选项字节选择全部更新               */

/* 选项字节1 RDP等级定义 */
#define FLASH_RDP_LEVEL_MASK              FLASH_OPTR1_RDPRP_MASK                     /**< RDP配置域       */
#define FLASH_RDP_LEVEL_0                 (0x00000000U)                              /**< RDP保护等级0    */
#define FLASH_RDP_LEVEL_1                 (0x00000001U)                              /**< RDP保护等级1    */
#define FLASH_RDP_LEVEL_2                 (0x00000002U)                              /**< RDP保护等级2    */

/* 选项字节1 PVD配置使能及档位有关定义：
   PVD选项字节加载寄存器相关配置请参考PMU寄存器中PVD有关定义
*/
#define FLASH_PVD_EN_POS                  (8U)
#define FLASH_PVD_EN_MASK                 (0x1UL << FLASH_PVD_EN_POS)                /**< 选项字节PVD_EN配置域               */
#define FLASH_PVD_DISABLE                 (0x00000000U)                              /**< 选项字节PVD_EN=0                   */
#define FLASH_PVD_ENABLE                  FLASH_PVD_EN_MASK                          /**< 选项字节PVD_EN=1                   */
#define FLASH_PVD_LEVEL_POS               (9U)
#define FLASH_PVD_LEVEL_MASK              (0x7UL << FLASH_PVD_LEVEL_POS)             /**< 选项字节PVD_LEVEL配置域            */
#define FLASH_PVD_LEVEL_0                 (0x0UL << FLASH_PVD_LEVEL_POS)             /**< PVD检测电压上升/下降阈值：2.1/2.0V */
#define FLASH_PVD_LEVEL_1                 (0x1UL << FLASH_PVD_LEVEL_POS)             /**< PVD检测电压上升/下降阈值：2.5/2.4V */
#define FLASH_PVD_LEVEL_2                 (0x2UL << FLASH_PVD_LEVEL_POS)             /**< PVD检测电压上升/下降阈值：2.6/2.5V */
#define FLASH_PVD_LEVEL_3                 (0x3UL << FLASH_PVD_LEVEL_POS)             /**< PVD检测电压上升/下降阈值：2.7/2.6V */
#define FLASH_PVD_LEVEL_4                 (0x4UL << FLASH_PVD_LEVEL_POS)             /**< PVD检测电压上升/下降阈值：2.8/2.7V */
#define FLASH_PVD_LEVEL_5                 (0x5UL << FLASH_PVD_LEVEL_POS)             /**< PVD检测电压上升/下降阈值：2.9/2.8V */
#define FLASH_PVD_LEVEL_6                 (0x6UL << FLASH_PVD_LEVEL_POS)             /**< PVD检测电压上升/下降阈值：3.0/2.9V */
#define FLASH_PVD_LEVEL_7                 (0x7UL << FLASH_PVD_LEVEL_POS)             /**< PVD检测电压上升/下降阈值：3.1/3.0V */

/* 选项字节2 配置参数定义 */
#define FLASH_BOOT_SEL_MASK               FLASH_OPTR2_BOOT_SEL_MASK                  /**< 选项字节BOOT_SEL配置掩码             */
#define FLASH_BOOT_SEL_PIN                (0x00000000U)                              /**< 启动条件使用BOOT0引脚配置            */
#define FLASH_BOOT_SEL_SW                 FLASH_OPTR2_BOOT_SEL                       /**< 启动条件使用选项字节BOOT0_SW配置     */
#define FLASH_BOOT0_SW_MASK               FLASH_OPTR2_BOOT0_SW_MASK                  /**< 选项字节BOOT0_SW配置掩码             */
#define FLASH_BOOT0_SW_0                  (0x00000000U)                              /**< 配置BOOT0_SW为0                      */
#define FLASH_BOOT0_SW_1                  FLASH_OPTR2_BOOT0_SW                       /**< 配置BOOT0_SW为1                      */

#define FLASH_USE_PIN_BOOT                FLASH_BOOT_SEL_PIN                         /**< 启动模式由BOOT0引脚确定                  */
#define FLASH_USE_SW_USER_BOOT            (FLASH_BOOT_SEL_SW | FLASH_BOOT0_SW_1)     /**< 启动模式由BOOT0_SW确定: 从User flash启动 */
#define FLASH_USE_SW_BOOTLOADER_BOOT      FLASH_BOOT_SEL_SW                          /**< 启动模式由BOOT0_SW决定: 从Bootloader启动 */

#define FLASH_IWDG_STOP_MASK              FLASH_OPTR2_IWDG_STOP_MASK                 /**< 选项字节IWDG_STOP配置掩码            */
#define FLASH_IWDG_STOP_MODE_STOP         (0x00000000U)                              /**< IWDG在Stop模式下停止计数             */
#define FLASH_IWDG_STOP_MODE_NORMAL       FLASH_OPTR2_IWDG_STOP                      /**< IWDG在Stop模式下正常计数             */

/* 选项字节数量 */
#define FLASH_OB_NUM                      (2U)                                       /**< 选项字节个数            */

/* 选择字节出厂默认值 */
#define FLASH_OB1_DEFULT_VALUE            (0xFF5500AAU)                              /**< 选项字节1出厂默认值     */
#define FLASH_OB2_DEFULT_VALUE            (0xDFDF2020U)                              /**< 选项字节2出厂默认值     */

/* 选项字节RDP编程位域及编程值 */
#define FLASH_OB_CONFIG_RDP_MASK          (0x000000FFU)                              /**< 选项字节RDPRP配置掩码   */
#define FLASH_OB_CONFIG_RDP_RDP0          (0x000000AAU)                              /**< 选项字节RDPRP配置为RDP0 */
#define FLASH_OB_CONFIG_RDP_RDP1          (0x00000000U)                              /**< 选项字节RDPRP配置为RDP1 */
#define FLASH_OB_CONFIG_RDP_RDP2          (0x00000055U)                              /**< 选项字节RDPRP配置为RDP2 */

/* 写保护区域配置 */
#define FLASH_WRP_AREA_ALL                (0x00000000U)                              /**< User flash区域全部写保护             */
#define FLASH_WRP_AREA_NONE               (0x000000FFU)                              /**< User flash区域写保护失效             */

/* 写保护区域单位 */
#define FLASH_SINGLE_WRP_SIZE             (0x00002000U)                              /**< 单个写保护区域大小（单位为字节）     */

/**
* @brief  计算Option Bytes区编程值
* @param  VAL OB区低16位预期编程值 
* @retval OB高16位取反后与低16位相加的值
*/
#define FLASH_OB_DATA_CALCULATE(VAL)      ((uint32_t)(((VAL) & 0xFFFF) | ((~(VAL & 0xFFFF)) << 16)))

/**
* @} 
*/

/*-------------------------------------------functions------------------------------------------*/

/************************************************************************************************/
/**
* @defgroup FLASH_External_Functions FLASH External Functions
* @brief    FLASH对外函数
* @{
*
*/
/************************************************************************************************/

/** 
* @brief  Flash控制寄存器解锁
* @retval 无
*/
__STATIC_INLINE void std_flash_unlock(void)
{
    FLASH->CRKEY = FLASH_CR_KEY1;
    FLASH->CRKEY = FLASH_CR_KEY2;
}

/** 
* @brief  Flash控制寄存器锁定
* @retval 无
*/
__STATIC_INLINE void std_flash_lock(void)
{
    FLASH->CR |= FLASH_CR_LOCK;
}

/** 
* @brief  读取Flash锁定状态
* @retval bool Flash锁定状态
*             @arg true  表示锁定状态
*             @arg false 表示解锁状态
*/
__STATIC_INLINE bool std_flash_get_lock_status(void)
{
    return ((FLASH->CR & FLASH_CR_LOCK) == FLASH_CR_LOCK);
}

/** 
* @brief  Flash选项字节解锁
* @retval 无
*/
__STATIC_INLINE void std_flash_opt_unlock(void)
{
    FLASH->OPTKEY = FLASH_OPT_KEY1;
    FLASH->OPTKEY = FLASH_OPT_KEY2; 
}

/** 
* @brief  Flash选项字节锁定
* @retval 无
*/
__STATIC_INLINE void std_flash_opt_lock(void)
{
    FLASH->CR |= FLASH_CR_OPTLOCK;
}

/** 
* @brief  读取Flash选项字节锁定状态
* @retval bool Flash选项字节锁定状态
*             @arg true  表示锁定状态
*             @arg false 表示解锁状态
*/
__STATIC_INLINE bool std_flash_get_opt_lock_status(void)
{
    return ((FLASH->CR & FLASH_CR_OPTLOCK) == FLASH_CR_OPTLOCK);
}

/**
* @brief  设置FLASH读取访问等待周期
* @param  latency 读取访问等待周期
*             @arg  FLASH_LATENCY_0CLK
*             @arg  FLASH_LATENCY_1CLK
* @retval 无
*/
__STATIC_INLINE void std_flash_set_latency(uint32_t latency)
{
    MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, latency);
} 

/**
* @brief  读取FLASH读取访问等待周期
* @retval uint32_t 读取访问等待周期
*             @arg  FLASH_LATENCY_0CLK
*             @arg  FLASH_LATENCY_1CLK
*/
__STATIC_INLINE uint32_t std_flash_get_latency(void)
{
    return (FLASH->ACR & FLASH_ACR_LATENCY);
} 

/**
* @brief  使能FLASH中断
* @param  interrupts 中断源
*             @arg FLASH_INTERRUPT_OPERR
*             @arg FLASH_INTERRUPT_EOP 
* @retval 无
*/
__STATIC_INLINE void std_flash_interrupt_enable(uint32_t interrupts)
{
    FLASH->CR |= interrupts;
}

/**
* @brief  禁止FLASH中断
* @param  interrupts 中断源
*             @arg FLASH_INTERRUPT_OPERR
*             @arg FLASH_INTERRUPT_EOP 
* @retval 无
*/
__STATIC_INLINE void std_flash_interrupt_disable(uint32_t interrupts)
{
    FLASH->CR &= (~interrupts);
}

/**
* @brief  读取FLASH中断使能状态
* @param  interrupt 中断源
*             @arg FLASH_INTERRUPT_OPERR
*             @arg FLASH_INTERRUPT_EOP 
* @retval bool FLASH中断使能状态
*             @arg true  表示中断已使能
*             @arg false 表示中断未使能
*/
__STATIC_INLINE bool std_flash_get_interrupt_enable(uint32_t interrupt)
{
    return ((FLASH->CR & interrupt) == interrupt);
}

/**
* @brief  读取FLASH状态标志
* @param  flag 状态标志
*             @arg FLASH_FLAG_EOP
*             @arg FLASH_FLAG_BSY
*             @arg FLASH_FLAG_OPTVERR
*             @arg FLASH_FLAG_WRPERR
* @retval bool FLASH状态标志
*             @arg true  表示标志置位
*             @arg false 表示标志未置位
*/
__STATIC_INLINE bool std_flash_get_flag(uint32_t flag)
{
    return ((FLASH->SR & flag) == flag);
}

/**
* @brief  清除FLASH状态标志
* @param  flags 状态标志
*             @arg FLASH_FLAG_EOP
*             @arg FLASH_FLAG_WRPERR
* @retval 无
*/
__STATIC_INLINE void std_flash_clear_flag(uint32_t flags)
{
    FLASH->SR = flags;
}

/** 
* @brief  设置Flash操作模式
* @param  mode 擦除模式
*             @arg FLASH_OPERATE_DISABLE
*             @arg FLASH_ERASE_PAGE
*             @arg FLASH_ERASE_MASS
*             @arg FLASH_PROGRAM
* @retval 无
*/
__STATIC_INLINE void std_flash_set_operate_mode(uint32_t mode)
{
    MODIFY_REG(FLASH->CR, FLASH_CR_OP_MODE, mode);
}

/**
* @brief  读取选项字节寄存器1
* @retval uint32_t 选项字节1加载值
*/
__STATIC_INLINE uint32_t std_flash_get_opt1(void)
{
    return (FLASH->OPTR1);
}

/**
* @brief  读取FLASH读保护等级
* @retval uint32_t FLASH读保护等级
*             @arg FLASH_RDP_LEVEL_0
*             @arg FLASH_RDP_LEVEL_1
*             @arg FLASH_RDP_LEVEL_2
*/
__STATIC_INLINE uint32_t std_flash_get_rdp_level(void)
{
    return (FLASH->OPTR1 & FLASH_OPTR1_RDPRP);
}

/**
* @brief  读取选项字节寄存器2
* @retval uint32_t 选项字节2加载值
*/
__STATIC_INLINE uint32_t std_flash_get_opt2(void)
{
    return (FLASH->OPTR2);
}

/** 
* @brief  读取芯片启动模式BOOT_SEL
* @retval bool BOOT_SEL位配置值
*             @arg true  启动条件使用选项字节BOOT0_SW配置
*             @arg false 启动条件使用BOOT0引脚配置
*/
__STATIC_INLINE bool std_flash_get_boot_sel(void)
{
    return ((FLASH->OPTR2 & FLASH_OPTR2_BOOT_SEL) == FLASH_OPTR2_BOOT_SEL);
}

/** 
* @brief  读取芯片启动模式BOOT0_SW
* @retval bool BOOT0_SW位配置值
*             @arg true  表示BOOT0_SW为1
*             @arg false 表示BOOT0_SW为0
*/
__STATIC_INLINE bool std_flash_get_boot0_sw(void)
{
    return ((FLASH->OPTR2 & FLASH_OPTR2_BOOT0_SW) == FLASH_OPTR2_BOOT0_SW);
}

/** 
* @brief  读取IWDG在STOP模式下计数器停止控制
* @retval bool IWDG_STOP设置
*             @arg true  IWDG在STOP模式下计数器正常运行
*             @arg false IWDG在STOP模式下计数器停止计数
*/
__STATIC_INLINE bool std_flash_get_iwdg_stop(void)
{
    return ((FLASH->OPTR2 & FLASH_OPTR2_IWDG_STOP) == FLASH_OPTR2_IWDG_STOP);
}

/**
* @brief  直接配置写保护区
* @param  wrp 写保护区配置值（0x00~0xFF）
* @retval 无 
*/
__STATIC_INLINE void std_flash_set_wrp(uint32_t wrp)
{
    FLASH->WRP = wrp;
}

/**
* @brief  解除全片Flash的写保护
* @retval 无 
*/
__STATIC_INLINE void std_flash_set_wrp_unlock_all(void)
{
    FLASH->WRP = FLASH_WRP_AREA_NONE;
}

/**
* @brief  设置全片Flash的写保护
* @retval 无 
*/
__STATIC_INLINE void std_flash_set_wrp_lock_all(void)
{
    FLASH->WRP = FLASH_WRP_AREA_ALL;
}

/**
* @brief  读取写保护区配置值
* @retval uint32_t 写保护区配置值
*/
__STATIC_INLINE uint32_t std_flash_get_wrp(void)
{
    return (FLASH->WRP & FLASH_WRP_WRP);
}

/** 
* @brief  读取Flash空间大小
* @retval uint32_t Flash空间大小
*/
__STATIC_INLINE uint32_t std_flash_get_flash_size(void)
{
    return (*(uint32_t *)USERFLASH_SIZE);
}

/** 
* @brief  读取SRAM空间大小
* @retval uint32_t SRAM空间大小
*/
__STATIC_INLINE uint32_t std_flash_get_sram_size(void)
{
    return (*(uint32_t *)SRAM_SIZE);
}


std_status_t std_flash_page_erase(uint32_t address);
std_status_t std_flash_mass_erase(void);
std_status_t std_flash_erase(uint32_t mode, uint32_t address);
std_status_t std_flash_word_program(uint32_t address, uint32_t prog_data);
std_status_t std_flash_option_bytes_config(std_flash_option_config_t *flash_option_config);
std_status_t std_flash_wait_for_last_operation(uint32_t timeout);

/** 
* @} 
*/

#ifdef __cplusplus
}
#endif

/**
* @} 
*/  

/**
* @}
*/

#endif /* STD_FLASH_H */


