5.14 Flash 使用说明

本章说明 N32H49x 标准外设库中 Flash 驱动的文件组成、55 个公开函数,以及 DualBankSwap、Flash_Program、Flash_Row_Program、OptionByte_Config、Run_In_CCM、SingleBankRemap 6 个示例。读等待周期、编程与擦除解锁、选项字节、写保护与双 Bank 等机制请配合用户手册的“存储器和总线架构”章节阅读。

5.14.1 相关文件

相对路径 作用
firmware/n32h49x_std_periph_driver/inc/n32h49x_flash.h 定义 FLASH_STS 状态枚举、读保护与中断标志、选项字节、写保护页、行编程等宏,并声明 55 个公开函数
firmware/n32h49x_std_periph_driver/src/n32h49x_flash.c 实现上述 55 个函数:等待周期与缓存控制、编程与擦除解锁序列、页与 Bank 擦除、双字与行编程、选项字节编程与读取、标志与中断管理、CCM SRAM 控制
projects/n32h49x_EVAL/examples/Flash/ Flash 示例根目录,含 DualBankSwap、Flash_Program、Flash_Row_Program、OptionByte_Config、Run_In_CCM、SingleBankRemap 6 个示例
projects/n32h49x_EVAL/examples/Flash/Flash_Program/ 该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt
projects/n32h49x_EVAL/bsp/ 6 个示例共用的板级支持文件:评估板 LED 定义、串口日志初始化与毫秒延时函数

5.14.2 API 参考

搜索 API共 55 个函数

以下 55 个公开函数按 n32h49x_flash.h 的声明顺序分为 9 组;每个条目给出功能摘要与 n32h49x_flash.c 中该函数正上方的注释原文。

取指延迟与缓存

FLASH_SetLatency、FLASH_GetLatency、FLASH_PrefetchBufSet、FLASH_iCacheRST、FLASH_iCacheCmd、FLASH_DCacheRST、FLASH_DCacheCmd

解锁与锁定

FLASH_Unlock、FLASH_Lock、Flash_GetLockStatus、Option_Bytes_Unlock、Option_Bytes_Lock、OB_GetLockStatus

擦除

FLASH_EraseOnePage、FLASH_MassErase、FLASH_BankErase

编程

FLASH_ProgramdoubleWord、FLASH_RowProgramSet、FLASH_RowProgramAreaSet、FLASH_RowProgram

选项字节编程

FLASH_EraseOB、FLASH_ProgramOB_RRDC、FLASH_ProgramOB_U1U2、FLASH_EnWriteProtection、FLASH_ProgramOB_Data、FLASH_ProgramOB_SRAMECC、FLASH_ReadOutProtectionL1、FLASH_ReadOutProtectionL2_ENABLE

选项字节读取

FLASH_GetUserOB、FLASH_GetUser2、FLASH_GetOptionBytes_Data0、FLASH_GetOptionBytes_Data1、FLASH_GetWriteProtectionSTS、FLASH_GetReadOutProtectionSTS、FLASH_GetReadOutProtectionL2STS、FLASH_GetPrefetchBufSTS

中断与标志

FLASH_INTConfig、FLASH_GetFlagSTS、FLASH_ClearFlag、FLASH_GetSTS、FLASH_WaitForLastOpt

CCM SRAM

CCM_EnWriteProtection、CCM_GetWriteProtectionSTS、CCM_Earse_Unlock、CCM_EarseEN、CCM_EarseSTS、CCM_ModeSet

解密与 UID

XSPI_DESRangeSet、FEMC_DESRangeSet、RTP_DESKeySet、GetRTP_DESKeyWnum、Jtag_SealSet、XSPI_FEMC_DESSet、Get_XFUID、Get_CCMUID

void FLASH_SetLatency(uint32_t FLASH_Latency)设置闪存读操作的等待周期数。
源码注释
name    FLASH_SetLatency
fun     Sets the code latency value.
param   FLASH_Latency :(The input parameters must be the following values)
            - FLASH_LATENCY_0    FLASH Zero Latency cycle, 0 < SYSCLK <= 48MHz
            - FLASH_LATENCY_1    FLASH One Latency cycle, 48MHz < SYSCLK<= 96MHz
            - FLASH_LATENCY_2    FLASH Two Latency cycle, 96MHz < SYSCLK<= 144MHz
            - FLASH_LATENCY_3    FLASH Three Latency cycle,144MHz < SYSCLK<= 192MHz
            - FLASH_LATENCY_4    FLASH Four Latency cycle, 192MHz < SYSCLK<= 240MHz
return  none
note    The larger the latency, the longer the flash read operation will take.
        If not necessary, it is recommended to use a smaller latency.
uint8_t FLASH_GetLatency(void)获取闪存读操作的当前等待周期数。
源码注释
name    FLASH_GetLatency
fun     Get the code latency value.
param   none
return  FLASH_LATENCY :(The input parameters must be the following values)
            - FLASH_LATENCY_0    FLASH Zero Latency cycle, 0 < SYSCLK <= 48MHz
            - FLASH_LATENCY_1    FLASH One Latency cycle, 48MHz < SYSCLK<= 96MHz
            - FLASH_LATENCY_2    FLASH Two Latency cycle, 96MHz < SYSCLK<= 144MHz
            - FLASH_LATENCY_3    FLASH Three Latency cycle,144MHz < SYSCLK<= 192MHz
            - FLASH_LATENCY_4    FLASH Four Latency cycle, 192MHz < SYSCLK<= 240MHz
void FLASH_PrefetchBufSet(uint32_t FLASH_PrefetchBuf)使能或禁止预取缓冲区。
源码注释
name    FLASH_PrefetchBufSet
fun     Enables or disables the Prefetch Buffer.
param   FLASH_PrefetchBuf:(The input parameters must be the following values)
            - FLASH_PrefetchBuf_EN
            - FLASH_PrefetchBuf_DIS
return  none
note  Prefetch feature must be disabled for this bit.
void FLASH_iCacheRST(uint32_t Bank)复位指令缓存(iCache)。
源码注释
name    FLASH_iCacheRST
fun     ICache Reset.
param   Bank:(The input parameters must be the following values)
            - FLASH_BANK1
            - FLASH_BANK2
return  none
void FLASH_iCacheCmd(uint32_t Bank, uint32_t FLASH_iCache)使能或禁止指令缓存(iCache)。
源码注释
name    FLASH_iCacheCmd
fun     Enables or disables the iCache.
param   Bank:(The input parameters must be the following values)
            - FLASH_BANK1
            - FLASH_BANK2
param   FLASH_iCache:(The input parameters must be the following values)
            - FLASH_iCache_EN FLASH iCache Enable
            - FLASH_iCache_DIS FLASH iCache Disable
return  none
void FLASH_DCacheRST(void)复位数据缓存(DCache)。
源码注释
name    FLASH_DCacheRST
fun     DCache Reset.
param   none
return  none
void FLASH_DCacheCmd(uint32_t FLASH_DCache)使能或禁止数据缓存(DCache)。
源码注释
name    FLASH_DCacheCmd
fun     Enables or disables the DCache.
param   FLASH_DCache:(The input parameters must be the following values)
            - FLASH_DCache_EN FLASH DCache Enable
            - FLASH_DCache_DIS FLASH DCache Disable
return  none
note
void FLASH_Unlock(void)解锁 Flash 编程/擦除控制器。
源码注释
name   FLASH_Unlock
fun    Unlocks the FLASH Program Erase Controller.
param  none
return none
void FLASH_Lock(void)锁定 Flash 编程/擦除控制器。
源码注释
name   FLASH_Lock
fun    Locks the FLASH Program Erase Controller.
param  none
return none
FlagStatus Flash_GetLockStatus(void)获取 Flash 编程/擦除控制器的锁定状态。
源码注释
name   Flash_GetLockStatus
fun    Get the Flash lock status.
param  none
return FlagStatus :
            - SET     FLASH is in Lock state
            - RESET   FLASH is in Unlock state
void Option_Bytes_Unlock(void)解锁选项字节编程/擦除控制器。
源码注释
name   Option_Bytes_Unlock
fun    Unlocks the Option_Bytes Program Erase Controller.
param  none
return none
void Option_Bytes_Lock(void)锁定选项字节编程/擦除控制器。
源码注释
name   Option_Bytes_Lock
fun    Locks the Option_Bytes Program Erase Controller.
param  none
return none
FlagStatus OB_GetLockStatus(void)获取选项字节编程/擦除控制器的锁定状态。
源码注释
name   OB_GetLockStatus
fun    Get the Option Bytes lock status.
param  none
return FlagStatus :
            - SET     Option byte is in Lock state
            - RESET   Option byte is in Unlock state
FLASH_STS FLASH_EraseOnePage(uint32_t Page_Address)擦除指定的主存储区 Flash 页。
源码注释
name   FLASH_EraseOnePage
fun    Erases a specified main FLASH page.
param  Page_Address :(The input parameters must be the following values)
            - it ranges from 0x08000000 to 0x080FFFFF
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_ADD  FLASH address error
note    If FLASH is in single bank mode,Page_Address must be a multiple of 0x4000;
        If FLASH is in dual bank mode,Page_Address must be a multiple of 0x2000.
FLASH_STS FLASH_MassErase(void)擦除主存储区的全部页面(整片擦除)。
源码注释
name   FLASH_MassErase
fun    Erases all main FLASH pages.
param  none
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RPADD   FLASH Row programmer address error
FLASH_STS FLASH_BankErase(uint32_t Bank)擦除指定 Bank 主存储区的全部页面。
源码注释
name   FLASH_BankErase
fun    Erases Bank's all main FLASH pages.
param   Bank:(The input parameters must be the following values)
            - FLASH_BANK1
            - FLASH_BANK2
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RPADD   FLASH Row programmer address error
FLASH_STS FLASH_ProgramdoubleWord(uint32_t address, uint32_t data0,uint32_t data1)在指定地址编程两个 32 位字(双字)。
源码注释
name   FLASH_ProgramdoubleWord
fun    Programs two words at a specified address.
param  address :(The input parameters must be the following values)
            - main flash, it ranges from 0x08000000 to 0x080FFFFF, it must be a multiple of 0x08
param  data0 :(The input parameters must be the following values)
            - It ranges from 0x00000000 to 0xFFFFFFFF
param  data1 :(The input parameters must be the following values)
            - It ranges from 0x00000000 to 0xFFFFFFFF
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_ADD  FLASH address error
            - FLASH_ERR_RPADD   FLASH Row programmer address error
            - FLASH_TIMEOUT  FLASH operation timeout
void FLASH_RowProgramSet(FunctionalState Cmd)使能或禁止行编程器。
源码注释
name   FLASH_RowProgramSet
fun    Enables or disables row programmer.
param  Cmd :(The input parameters must be the following values)
            - ENABLE  Enable Row programmer
            - DISABLE Disable Row programmer
return none
void FLASH_RowProgramAreaSet(FunctionalState Cmd)配置行编程器的操作区域。
源码注释
name   FLASH_RowProgramAreaSet
fun    Configure row programmer area.
param  Cmd :(The input parameters must be the following values)
            - ENABLE  Row programmer in system memory
            - DISABLE Row programmer in main flash
return none
FLASH_STS FLASH_RowProgram(uint32_t address, uint32_t row_num, uint32_t *data)在指定地址连续编程 x 个字。
源码注释
name   FLASH_RowProgram
fun    Programs x words at a specified address.
param  address :(The input parameters must be the following values)
            - main flash, it ranges from 0x08000000 to 0x080FFFFF, it must be a multiple of 0x08
param  row_num :(The input parameters must be the following values)
            - It ranges from 0x02 to 0x10,it must be a multiple of 0x02
param  data[] :(The input parameters must be the following values)
            - It ranges from 0x00000000 to 0xFFFFFFFF
return FLASH_STS :
            - FLASH_BUSY        FLASH is busy
            - FLASH_ERR_PG      FLASH programming error
            - FLASH_ERR_WRP     FLASH Write protected error
            - FLASH_EOP         FLASH End of Operation
            - FLASH_ERR_PV      Programmer Verification Error
            - FLASH_ERR_EV      Erase Verification Error
            - FLASH_ERR_ADD     FLASH address error
            - FLASH_ERR_RPADD   FLASH Row programmer address error
            - FLASH_TIMEOUT     FLASH operation timeout
            - FLASH_ERR_RPADD   FLASH Row programmer address error
note Row programming cannot span 512 bytes.
FLASH_STS FLASH_EraseOB(void)擦除 Flash 选项字节。
源码注释
name   FLASH_EraseOB
fun    Erases the FLASH option bytes.
param  none
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RDP2 FLASH is in read protection L2 status
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_RPADD   FLASH Row programmer address error
FLASH_STS FLASH_ProgramOB_RRDC(uint32_t option_byte_rpd1, uint32_t option_byte_rpd2, \ uint32_t option_byte_DBANK,uint32_t option_byte_CCMSRAM)编程选项字节 RDP1、RDP2、DBANK 与 CCMSRAM_RST 位。
源码注释
name   FLASH_ProgramOB_RRDC
fun    Programs the Option Byte: RDP1/RDP2/DBANK/CCMSRAM_RST.
param  option_byte_rpd1 :(The input parameters must be the following values)
            - FLASH_OB_RDP1_ENABLE   Enable read protection L1
            - FLASH_OB_RDP1_DISABLE  Disable read protection L1
param  option_byte_rpd2 :(The input parameters must be the following values)
            - FLASH_OB_RDP2_ENABLE   Enable read protection L2
            - FLASH_OB_RDP2_DISABLE  Disable read protection L2
param  option_byte_DBANK :(The input parameters must be the following values)
            - FLASH_SINGLE_BANK      Single Bank Mode
            - FLASH_DUAL_BANK        Dual Bank Mode
param  option_byte_CCMSRAM :(The input parameters must be the following values)
            - CCMSRAM_RST_NERASE   CCMSRAM reset not erase
            - CCMSRAM_RST_ERASE    CCMSRAM reset erase
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RDP2 FLASH is in read protection L2 status
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_RPADD   FLASH Row programmer address error
FLASH_STS FLASH_ProgramOB_U1U2(uint32_t option_byte_iwdg, uint32_t option_byte_stop,\ uint32_t option_byte_stdby, uint32_t option_byte_iwdg_stop, uint32_t option_byte_iwdg_stdby,\ uint32_t option_byte_iwdg_sleep,uint32_t option_byte2_nBOOT0, uint32_t option_byte2_nBOOT1,\ uint32_t option_byte2_nSWBOOT0, uint32_t option_byte2_FlashBoot,uint32_t option_byte2_DAC,\ uint32_t option_byte2_BOR)编程选项字节 USER 与 USER2 位。
源码注释
name   FLASH_ProgramOB_U1U2
fun    Programs the Option Byte: USER/USER2.
param  option_byte_iwdg :(The input parameters must be the following values)
            - FLASH_OB_IWDG_SOFTWARE Software IWDG selected
            - FLASH_OB_IWDG_HARDWARE Hardware IWDG selected
param  option_byte_stop :(The input parameters must be the following values)
            - FLASH_OB_STOP_NORST No reset generated when entering in STOP
            - FLASH_OB_STOP_RST Reset generated when entering in STOP
param  option_byte_stdby :(The input parameters must be the following values)
            - FLASH_OB_STDBY_NORST No reset generated when entering in standby
            - FLASH_OB_STDBY_RST Reset generated when entering in standby
param  option_byte_iwdg_stop :(The input parameters must be the following values)
            - FLASH_OB_IWDG_STOP_FRZ IWDG freeze in stop
            - FLASH_OB_IWDG_STOP_NOFRZ Default no freeze
param  option_byte_iwdg_stdby :(The input parameters must be the following values)
            - FLASH_OB_IWDG_STDBY_FRZ IWDG freeze in standby
            - FLASH_OB_IWDG_STDBY_NOFRZ Default no freeze
param  option_byte_iwdg_sleep :(The input parameters must be the following values)
            - FLASH_OB_IWDG_SLEEP_FRZ IWDG freeze in sleep
            - FLASH_OB_IWDG_SLEEP_NOFRZ Default no freeze
param   option_byte2_nBOOT0 :(The input parameters must be the following values)
            - FLASH_OB2_NBOOT0_SET Set nBOOT0
            - FLASH_OB2_NBOOT0_CLR Clear nBOOT0
param   option_byte2_nBOOT1 :(The input parameters must be the following values)
            - FLASH_OB2_NBOOT1_SET Set nBOOT1
            - FLASH_OB2_NBOOT1_CLR Clear nBOOT1
param   option_byte2_nSWBOOT0 :(The input parameters must be the following values)
            - FLASH_OB2_NSWBOOT0_SET Set nSWBOOT0
            - FLASH_OB2_NSWBOOT0_CLR Clear nSWBOOT0
param   option_byte2_FlashBoot :(The input parameters must be the following values)
            - FLASH_OB2_FLASHBOOT_SET Main flash forward section boot
            - FLASH_OB2_FLASHBOOT_CLR Main flash back part boot
param   option_byte2_DAC :(The input parameters must be the following values)
            - FLASH_OB2_DAC_SET System reset, DAC voltage value maintained
            - FLASH_OB2_DAC_CLR System reset, DAC voltage value not maintained
param   option_byte2_BOR :(The input parameters must be the following values)
            - BOR_LEVEL_1_6V Reset level threshold 1.6V (Up 1.66V / Down 1.62V)
            - BOR_LEVEL_2_0V Reset level threshold 2.0V (Up 2.1V / Down 2.0V)
            - BOR_LEVEL_2_2V Reset level threshold 2.2V (Up 2.3V / Down 2.2V)
            - BOR_LEVEL_2_5V Reset level threshold 2.5V (Up 2.6V / Down 2.5V)
            - BOR_LEVEL_2_8V Reset level threshold 2.8V (Up 2.9V / Down 2.8V)
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RDP2 FLASH is in read protection L2 status
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_RPADD   FLASH Row programmer address error
FLASH_STS FLASH_EnWriteProtection(uint32_t FLASH_Pages)对指定的页使能写保护。
源码注释
name   FLASH_EnWriteProtection
fun    Write protects the desired pages.
param  FLASH_Pages :(The input parameters must be the following values)
            - FLASH_WRP_NUM0   Single Bank: page 0 to 1  , Dual Banke: page 0   to 3
            - FLASH_WRP_NUM1   Single Bank: page 2 to 3  , Dual Banke: page 4   to 7
            - FLASH_WRP_NUM2   Single Bank: page 4 to 5  , Dual Banke: page 8   to 11
            - FLASH_WRP_NUM3   Single Bank: page 6 to 7  , Dual Banke: page 12  to 15
            - FLASH_WRP_NUM4   Single Bank: page 8 to 9  , Dual Banke: page 16  to 19
            - FLASH_WRP_NUM5   Single Bank: page 10 to 11, Dual Banke: page 20  to 23
            - FLASH_WRP_NUM6   Single Bank: page 12 to 13, Dual Banke: page 24  to 27
            - FLASH_WRP_NUM7   Single Bank: page 14 to 15, Dual Banke: page 28  to 31
            - FLASH_WRP_NUM8   Single Bank: page 16 to 17, Dual Banke: page 32  to 35
            - FLASH_WRP_NUM9   Single Bank: page 18 to 19, Dual Banke: page 36  to 39
            - FLASH_WRP_NUM10  Single Bank: page 20 to 21, Dual Banke: page 40  to 43
            - FLASH_WRP_NUM11  Single Bank: page 22 to 23, Dual Banke: page 44  to 47
            - FLASH_WRP_NUM12  Single Bank: page 24 to 25, Dual Banke: page 48  to 51
            - FLASH_WRP_NUM13  Single Bank: page 26 to 27, Dual Banke: page 52  to 55
            - FLASH_WRP_NUM14  Single Bank: page 28 to 29, Dual Banke: page 56  to 59
            - FLASH_WRP_NUM15  Single Bank: page 30 to 31, Dual Banke: page 60  to 63
            - FLASH_WRP_NUM16  Single Bank: page 32 to 33, Dual Banke: page 64  to 67
            - FLASH_WRP_NUM17  Single Bank: page 34 to 35, Dual Banke: page 68  to 71
            - FLASH_WRP_NUM18  Single Bank: page 36 to 37, Dual Banke: page 72  to 75
            - FLASH_WRP_NUM19  Single Bank: page 38 to 39, Dual Banke: page 76  to 79
            - FLASH_WRP_NUM20  Single Bank: page 40 to 41, Dual Banke: page 80  to 83
            - FLASH_WRP_NUM21  Single Bank: page 42 to 43, Dual Banke: page 84  to 87
            - FLASH_WRP_NUM22  Single Bank: page 44 to 45, Dual Banke: page 88  to 91
            - FLASH_WRP_NUM23  Single Bank: page 46 to 47, Dual Banke: page 92  to 95
            - FLASH_WRP_NUM24  Single Bank: page 48 to 49, Dual Banke: page 96  to 99
            - FLASH_WRP_NUM25  Single Bank: page 50 to 51, Dual Banke: page 100 to 103
            - FLASH_WRP_NUM26  Single Bank: page 52 to 53, Dual Banke: page 104 to 107
            - FLASH_WRP_NUM27  Single Bank: page 54 to 55, Dual Banke: page 108 to 111
            - FLASH_WRP_NUM28  Single Bank: page 56 to 57, Dual Banke: page 112 to 115
            - FLASH_WRP_NUM29  Single Bank: page 58 to 59, Dual Banke: page 116 to 119
            - FLASH_WRP_NUM30  Single Bank: page 60 to 61, Dual Banke: page 120 to 123
            - FLASH_WRP_NUM31  Single Bank: page 62 to 63, Dual Banke: page 124 to 127
            - FLASH_WRP_AllPages      all Pages
            - ~FLASH_WRP_AllPages     Disable Write protection of all Pages
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RDP2 FLASH is in read protection L2 status
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_RPADD   FLASH Row programmer address error
FLASH_STS FLASH_ProgramOB_Data(uint32_t option_byte_data0, uint32_t option_byte_data1,\ uint32_t option_byte_data2, uint32_t option_byte_data3)编程选项字节 DATA0、DATA1、DATA2 与 DATA3。
源码注释
name   FLASH_ProgramOB_Data
fun    Programs the Option Byte: DATA0/DATA1/DATA2/DATA3.
param  option_byte_data0:(The input parameters must be the following values)
            - 0x00 to 0xFF
param  option_byte_data1:(The input parameters must be the following values)
            - 0x00 to 0xFF
param  option_byte_data2:(The input parameters must be the following values)
            - 0x00 to 0xFF
param  option_byte_data3:(The input parameters must be the following values)
            - 0x00 to 0xFF
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RDP2 FLASH is in read protection L2 status
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_RPADD   FLASH Row programmer address error
FLASH_STS FLASH_ProgramOB_SRAMECC(uint32_t option_byte_SRAM2,uint32_t option_byte_SRAM3)编程选项字节中的 SRAM2、SRAM3 ECC 使能位。
源码注释
name   FLASH_ProgramOB_SRAMECC
fun    Programs the Option Byte: SRAM2_ECC_ENABLE,SRAM3_ECC_ENABLE.
param  option_byte_SRAM2 :(The input parameters must be the following values)
            - SRAM2_ECC_ENABLE   SRAM2 ECC ENABLE
            - SRAM2_ECC_DISABLE  SRAM2 ECC DISABLE
param  option_byte_SRAM3 :(The input parameters must be the following values)
            - SRAM3_ECC_ENABLE   SRAM3 ECC ENABLE
            - SRAM3_ECC_DISABLE  SRAM3 ECC DISABLE
return FLASH_STS : (The input parameters must be the following values)
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RDP2 FLASH is in read protection L2 status
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_RPADD   FLASH Row programmer address error
FLASH_STS FLASH_ReadOutProtectionL1(FunctionalState Cmd)使能或禁止读出保护 L1 等级。
源码注释
name   FLASH_ReadOutProtectionL1
fun    Enables or disables the read out protection.
param  Cmd:(The input parameters must be the following values)
            - ENABLE   Enable read protection L1
            - DISABLE  Disable read protection L1
return FLASH_STS : (The input parameters must be the following values)
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RDP2 FLASH is in read protection L2 status
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_RPADD   FLASH Row programmer address error
note   If the user has already programmed the other option bytes before calling
       this function, he must re-program them since this function erases all option bytes.
FLASH_STS FLASH_ReadOutProtectionL2_ENABLE(void)使能读出保护 L2 等级。
源码注释
name   FLASH_ReadOutProtectionL2_ENABLE
fun    Enables the read out protection L2.
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RDP2 FLASH is in read protection L2 status
            - FLASH_TIMEOUT  FLASH operation timeout
            - FLASH_ERR_RPADD   FLASH Row programmer address error
note   If the user has already programmed the other option bytes before calling
       this function, he must re-program them since this function erases all option bytes.
uint32_t FLASH_GetUserOB(void)读取 Flash USER 选项字节的值。
源码注释
name   FLASH_GetUserOB
fun    Returns the FLASH User Option Bytes values.
param  none
return The FLASH User Option Bytes values:IWDG_SW(Bit0), nRST_STOP(Bit1),
       nRST_STDBY(Bit2), IWDGSTOPFRZ(Bit3), IWDGSTDBYFRZ(Bit5) and IWDGSLEEPFRZ(Bit6).
FlagStatus FLASH_GetUser2(uint32_t option_byte_bit)读取 Flash USER2 选项字节指定配置位的值。
源码注释
name   FLASH_GetUser2
fun    Returns the FLASH User2 Option Bytes values.
param  option_byte_bit: (The input parameters must be the following values)
            - FLASH_OB2_NBOOT0_SET          nBOOT0 configuration bit
            - FLASH_OB2_NBOOT1_SET          nBOOT1 configuration bit
            - FLASH_OB2_NSWBOOT0_SET        nSWBOOT0 configuration bit
return FlagStatus :
            - SET      Enter this mode without resetting
            - RESET    Enter this mode reset
uint32_t FLASH_GetOptionBytes_Data0(void)读取选项字节 DATA0 的值。
源码注释
name   FLASH_GetOptionBytes_Data0
fun    Returns the FLASH User Option Bytes values.
param  none
return data0:
            - 0x00 to 0xFF.
uint32_t FLASH_GetOptionBytes_Data1(void)读取选项字节 DATA1 的值。
源码注释
name   FLASH_GetOptionBytes_Data1
fun    Returns the FLASH User Option Bytes values.
param  none
return data1:
            - 0x00 to 0xFF.
uint32_t FLASH_GetWriteProtectionSTS(void)读取 Flash 写保护选项字节寄存器的值。
源码注释
name   FLASH_GetWriteProtectionSTS
fun    Returns the FLASH Write Protection Option Bytes Register value.
param  none
return The FLASH Write Protection  Option Bytes Register value :
            - Bit31 - Bit0 write-protects dual bank: pages (62~63) - page (0~1)
FlagStatus FLASH_GetReadOutProtectionSTS(void)查询 Flash 读出保护 L1 是否已使能。
源码注释
name   FLASH_GetReadOutProtectionSTS
fun    Checks whether the FLASH Read Out Protection L1 status_value is set or not.
param  none
return FlagStatus :
        - SET    Read protection L1 enable
        - RESET  Read protection L1 disable
FlagStatus FLASH_GetReadOutProtectionL2STS(void)查询 Flash 读出保护 L2 是否已使能。
源码注释
name   FLASH_GetReadOutProtectionL2STS
fun    Checks whether the FLASH Read Out Protection L2 status_value is set or not.
param  none
return FlagStatus :
        - SET    Read protection L2 enable
        - RESET  Read protection L2 disable
FlagStatus FLASH_GetPrefetchBufSTS(void)查询 Flash 预取缓冲区当前是否使能。
源码注释
name   FLASH_GetPrefetchBufSTS
fun    Checks whether the FLASH Prefetch Buffer status_value is set or not.
param  none
return FlagStatus :
        - SET    Flash prefetch buffer enable
        - RESET  Flash prefetch buffer disable
void FLASH_INTConfig(uint32_t FLASH_INT, FunctionalState Cmd)使能或禁止指定的 Flash 中断源。
源码注释
name   FLASH_INTConfig
fun    Enables or disables the specified FLASH interrupts.
param  Cmd:(The input parameters must be the following values)
            - ENABLE
            - DISABLE
param  FLASH_INT :
            - FLASH_INT_EOP      FLASH end of operation Interrupt
            - FLASH_INT_ERR      PGERR WRPERR ERROR interrupt source
            - FLASH_INT_FERR     EVERR PVERR ERROR interrupt source
            - FLASH_INT_ECC1     1 bit ECC error interrupt source
            - FLASH_INT_JS       jtag seal error interrupt source
            - FLASH_INT_ECC2     2 bit ECC error interrupt source
            - FLASH_INT_DECC     XSPI/FEMC decryption misconfiguration interrupt source
            - FLASH_INT_RPADD    Row programmer address error interrupt source
            - FLASH_INT_BANKEX   BANK exchange error interrupt Enable
return none
FlagStatus FLASH_GetFlagSTS(uint32_t FLASH_FLAG)查询指定的 Flash 标志位是否置位。
源码注释
name   FLASH_GetFlagSTS
fun    Checks whether the specified FLASH flag is set or not.
param  FLASH_FLAG :(The input parameters must be the following values)
            - FLASH_FLAG_EOP        FLASH End of Operation flag
            - FLASH_FLAG_BUSY       FLASH Busy flag
            - FLASH_FLAG_PGERR      FLASH Program error flag
            - FLASH_FLAG_WRPERR     FLASH Write protected error flag
            - FLASH_FLAG_PVERR      FLASH Program Verify ERROR flag
            - FLASH_FLAG_EVERR      FLASH Erase Verify ERROR flag
            - FLASH_FLAG_ECC1ERR    FLASH 1 bit ECC ERROR flag
            - FLASH_FLAG_RDKEYERR   read key error flag
            - FLASH_FLAG_RDXKEYERR  xKEY match error flag
            - FLASH_FLAG_NRDXKEYEN  Not allowed to read RTPD_KEY enable flag
            - FLASH_FLAG_JSERR      JTAG/SRAM access JTAG_SEAL error flag
            - FLASH_FLAG_RTPKEYERR  read RTPD_KEY error flag
            - FLASH_FLAG_ECC2ERR    FLASH 2 bit ECC error flag
            - FLASH_FLAG_DECCRDF    XSPI/FEMC Decryption Configuration Completion Flag
            - FLASH_FLAG_DECCERR    XSPI/FEMC Decryption Configuration sequences error Flag
            - FLASH_FLAG_FWORDF     first word write completion flag
            - FLASH_FLAG_RPADDERR   row programmmer address error
            - FLASH_FLAG_BANKEXERR  BANK exchange error
            - FLASH_FLAG_BANKMODE   BANK mode
            - FLASH_FLAG_OBERR      FLASH Option Byte error flag
return bitstatus :
        - SET
        - RESET
void FLASH_ClearFlag(uint32_t FLASH_FLAG)清除 Flash 的待处理标志。
源码注释
name   FLASH_ClearFlag
fun    Clears the FLASH's pending flags.
param  FLASH_FLAG :(The input parameters must be the following values)
            - FLASH_FLAG_EOP        FLASH End of Operation flag
            - FLASH_FLAG_PGERR      FLASH Program error flag
            - FLASH_FLAG_WRPERR     FLASH Write protected error flag
            - FLASH_FLAG_PVERR      FLASH Program Verify ERROR flag
            - FLASH_FLAG_EVERR      FLASH Erase Verify ERROR flag
            - FLASH_FLAG_ECC1ERR    FLASH 1 bit ECC ERROR flag
            - FLASH_FLAG_JSERR      JTAG/SRAM access JTAG_SEAL error flag
            - FLASH_FLAG_RTPKEYERR  read RTPD_KEY error flag
            - FLASH_FLAG_ECC2ERR    FLASH 2 bit ECC error flag
            - FLASH_FLAG_DECCRDF    XSPI/FEMC Decryption Configuration Completion Flag
            - FLASH_FLAG_DECCERR    XSPI/FEMC Decryption Configuration sequences error Flag
            - FLASH_FLAG_RPADDERR   row programmmer address error
            - FLASH_FLAG_BANKEXERR  BANK exchange error
return none
FLASH_STS FLASH_GetSTS(void)返回 Flash 当前的操作状态。
源码注释
name   FLASH_GetSTS
fun    Returns the FLASH Status.
param  none
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RPADD   FLASH Row programmer address error
FLASH_STS FLASH_WaitForLastOpt(uint32_t Timeout)等待 Flash 操作完成或发生超时。
源码注释
name   FLASH_WaitForLastOpt
fun    Waits for a Flash operation to complete or a TIMEOUT to occur.
param  Timeout:(The input parameters must be the following values)
            - EraseTimeout
            - ProgramTimeout
            - RowProgramTimeout
return FLASH_STS :
            - FLASH_BUSY     FLASH is busy
            - FLASH_ERR_PG   FLASH programming error
            - FLASH_ERR_WRP  FLASH Write protected error
            - FLASH_EOP      FLASH End of Operation
            - FLASH_ERR_PV   Programmer Verification Error
            - FLASH_ERR_EV   Erase Verification Error
            - FLASH_ERR_RPADD   FLASH Row programmer address error
void CCM_EnWriteProtection(uint32_t CCM_Pages)对指定的 CCM SRAM 页使能写保护。
源码注释
name   CCM_EnWriteProtection
fun    Enables write protection CCM x page.
param  CCM_Pages:(The input parameters must be the following values)
            - Bit31 - Bit0 write-protects pages (31) - page (0)
return none
uint32_t CCM_GetWriteProtectionSTS(void)读取 CCM SRAM 写保护选项字节寄存器的值。
源码注释
name   CCM_GetWriteProtectionSTS
fun    Returns the CCM Write Protection Option Bytes Register value.
param  none
return The CCM Write Protection  Option Bytes Register value :
            - Bit31 - Bit0 write-protects pages (31) - page (0)
void CCM_Earse_Unlock(void)解锁 CCM SRAM 擦除控制器。
源码注释
name   CCM_ERASE_Unlock
fun    Unlocks the CCM Erase Controller.
param  none
return none

使用提示: 头文件第 376 行的声明为 CCM_Earse_Unlock,而源码注释的 name 字段写作 CCM_ERASE_Unlock,二者不一致。

void CCM_EarseEN(void)使能 CCM SRAM 擦除。
源码注释
name   CCM_ERASE_EN
fun    ENABLE CCM Erase.
param  none
return none

使用提示: 头文件第 377 行的声明为 CCM_EarseEN,而源码注释的 name 字段写作 CCM_ERASE_EN,二者不一致。

FlagStatus CCM_EarseSTS(void)获取 CCM SRAM 擦除状态。
源码注释
name   CCM_EarseSTS
fun    Get CCM Erase Status.
param  none
return FlagStatus :
        - SET    CCM SRAM erase operation
        - RESET  No CCM SRAM erase operation
void CCM_ModeSet(FunctionalState Cmd)使能或禁止 CCM 模式。
源码注释
name   CCM_ModeSet
fun    Enables or disables CCM mode.
param  Cmd:(The input parameters must be the following values)
            - ENABLE
            - DISABLE
return none
void XSPI_DESRangeSet(uint32_t start_add,uint32_t end_add)设置 XSPI 解密地址范围。
源码注释
name   XSPI_DESRangeSet
fun    XSPI Decryption address range setting.
param  start_add:(The input parameters must be the following values)
            - It ranges from 0x90000000 to 0x9FFFFFFF
param  end_add:(The input parameters must be the following values)
            - It ranges from 0x90000000 to 0x9FFFFFFF
return none
void FEMC_DESRangeSet(uint32_t start_add,uint32_t end_add)设置 FEMC 解密地址范围。
源码注释
name   FEMC_DESRangeSet
fun    FEMC Decryption address range setting.
param  start_add:(The input parameters must be the following values)
            - It ranges from 0x60000000 to 0x8FFFFFFF
param  end_add:(The input parameters must be the following values)
            - It ranges from 0x60000000 to 0x8FFFFFFF
return none
void RTP_DESKeySet(uint32_t* DES_key)设置 128 位 RTPD 解密密钥。
源码注释
name   RTP_DESKeySet
fun    128bit RTPD decryption key setting.
param  DES_key:(The input parameters must be the following values)
            - A 128-bit key
return none
uint32_t GetRTP_DESKeyWnum(void)获取 RTPD_KEY 的写入次数。
源码注释
name   GetRTP_DESKeyWnum
fun    get RTPD_KEY Write Count.
param  none
return CNT:
            - RTPD_KEY write cnt
void Jtag_SealSet(FunctionalState Cmd)使能或禁止 JTAG 密封(Jtag_Seal)。
源码注释
name   Jtag_SealSet
fun    Enables or disables Jtag_Seal.
param  Cmd:(The input parameters must be the following values)
            - ENABLE
            - DISABLE
return none
void XSPI_FEMC_DESSet(FunctionalState Cmd)使能或禁止 XSPI/FEMC 解密功能。
源码注释
name   XSPI_FEMC_DESSet
fun    Enables or disables XSPI/FEMC decryption.
param  Cmd:(The input parameters must be the following values)
            - ENABLE
            - DISABLE
return none
uint32_t Get_XFUID(void)获取 XSPI/FEMC 的配置 UID。
源码注释
name   Get_XFUID
fun    get XSPI/FEMC configure UID.
param  none
return UID:
            - 0x01  BOOT user
            - 0x02  FLASH user1
            - 0x04  FLASH user2
            - 0x08  FLASH user3
            - 0x10  SRAM user
uint32_t Get_CCMUID(void)获取 CCM 的配置 UID。
源码注释
name   Get_CCMUID
fun    get CCM configure UID.
param  none
return UID:
            - 0x01  BOOT user
            - 0x02  FLASH user1
            - 0x04  FLASH user2
            - 0x08  FLASH user3
            - 0x10  SRAM user

5.14.3 Demo 示例说明

本节说明 Flash 的 6 个示例:Flash_Program 演示页擦除与双字编程,Flash_Row_Program 演示行编程,OptionByte_Config 演示选项字节的擦除与编程,SingleBankRemap 演示单 Bank 模式下的启动重映射,DualBankSwap 演示双 Bank 的三种切换方式,Run_In_CCM 演示把函数代码放到 CCM SRAM 中执行。

5.14.3.1 DualBankSwap 双 Bank 切换

工程目录: projects/n32h49x_EVAL/examples/Flash/DualBankSwap/

初始化串口并打开 HSI 时钟→初始化板载 LED→检查当前 Bank 模式并要求为双 Bank→读取选项字节中的启动 Bank 与重映射 Bank→恢复上次运行的工作模式标记→主循环按串口指令以 Retry、Backup、Reload 三种方式切换 Bank→切换前点亮全部 LED 并复位或重映射

项目 源码解读
功能 演示双 Bank 模式下的三种 Bank 切换:Retry 通过重映射切换,Backup 通过改写选项字节并复位切换,Reload 组合使用重映射与选项字节改写。
MCU 工作在 Bank1 时 LED1 闪烁,工作在 Bank2 时 LED2 闪烁;
发生重映射后,闪烁的 LED 对应的另一只 LED 常亮。
源码组成 src/main.c:main、ConfigBootBank、SetModeMark、ClrModeMark、GetModeMark;
inc/main.h:OB_BUF_ADDRESS、MODE_MARK_ADDR、三种模式标记宏、LED 操作宏与 ConfigBootBank 声明;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务函数;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 示例要求双 Bank 模式(DBANK=1),单 Bank 模式下停在提示循环不执行。
选项字节缓冲区 OB_BUF_ADDRESS 为 0x40023000,工作模式标记 MODE_MARK_ADDR 为 0x40023080,均位于备份 SRAM。
系统时钟 240 MHz,打印串口 USART1 TX PA9、RX PA10,波特率 115200。
程序与数据路径 main 先 log_init,打开 HSI 并等待稳定,初始化 LED;
读取 FLASH_FLAG_BANKMODE 判断 Bank 模式,再读取选项字节的启动 Bank 与 RCC 的重映射 Bank,并用两个互补标记读出上次的工作模式;
主循环轮询 USART1,收到 0x55 走 Retry、0x66 走 Backup、0x77 走 Reload;
Retry 与 Reload 在 SetModeMark 后调用 RCC_ConfigRemapMode、RCC_EnableRemap,Backup 在 ConfigBootBank 成功后调用 NVIC_SystemReset。
主要 API FLASH_GetFlagSTS、FLASH_Unlock、FLASH_EraseOB、Option_Bytes_Unlock、Option_Bytes_Lock、FLASH_ClearFlag、FLASH_WaitForLastOpt、FLASH_Lock
验证方法 复位运行后串口打印当前 Bank 与启动地址 0x08000000;
下发 0x55 观察 Retry 重映射,下发 0x66 观察 Backup 复位后从另一 Bank 启动,下发 0x77 观察 Reload 组合切换;
每次切换成功时对应 LED 开始闪烁。
使用提示 启动地址始终是 0x08000000,切换的是代码实际存储位置。
Backup 与 Reload 会改写选项字节,属于 Flash 编程,运行前须保证 HSI 已打开。
开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。
核心代码解读与移植

示例通过重映射或改写选项字节在两只 Bank 之间切换启动代码,并用备份 SRAM 中的标记跨复位传递工作模式。

数据路径: 串口指令 → SetModeMark 写入 MODE_MARK_ADDR → RCC_ConfigRemapMode/RCC_EnableRemap 或 ConfigBootBank 改写选项字节 → NVIC_SystemReset 复位 → GetModeMark 恢复工作模式

1. 打开 HSI 并检查 Bank 模式。 Flash 编程或擦除要求 HSI 打开,示例在初始化后立即打开 HSI;随后检查 FLASH_FLAG_BANKMODE,单 Bank 模式下停在提示循环,不再执行后续切换逻辑。

src/main.csrc/main.c · main
    /* When performing Flash programming operations(write or erase), HSI must be enable*/
    RCC_EnableHsi(ENABLE);
    RCC_WaitHsiStable();
    
    /* User LED Init */
    Hardware_Board_Led_Init();
    
    /* Check current Bank mode, must be in dual Bank mode */
    if(FLASH_GetFlagSTS(FLASH_FLAG_BANKMODE) == SET)
    {
        log_info("\r\nFLASH is dual Bank mode!\r\n");
    }
    else
    {
        log_info("\r\nFLASH is single Bank mode!\r\n");
        log_info("This demo can not be used!\r\n");
        while(1)
        {
            /* Dual Bank swap demo is only used for dual Bank mode */
        }
    }

2. Retry 方式通过重映射切换。 收到 0x55 后,示例按当前工作 Bank 选择重映射目标,先写入工作模式标记,再点亮全部 LED,最后配置并启动重映射,代码存储位置随之改变但启动地址不变。

src/main.csrc/main.c · main
        if(UartCmd == 0x55U) /* Retry */
        {
            if(FLASH_BANK2 == WorkBankNum)
            {
                Value_temp = RCC_REMAP_BFLASH;
                log_info("Remap to Bank1!\r\n");
            }
            else
            {
                Value_temp = RCC_REMAP_AFLASH;
                log_info("Remap to Bank2!\r\n");
            }
            
            /* Set the mark of work mode */
            SetModeMark(RETRY_MARK);
            
            /* Turn on all LED before remap */
            ALL_BANK_LED_ON;
            systick_delay_ms(5);
            
            /* Config remap bank and remap */
            RCC_ConfigRemapMode(Value_temp);
            RCC_EnableRemap();
        }

3. 直接改写选项字节切换启动 Bank。 ConfigBootBank 先把当前选项字节读入备份 SRAM,修改 USER2 的启动 Bank 字段,再按双字为单位逐组编程;只有上一次编程返回 FLASH_EOP 才继续下一组。

src/main.csrc/main.c · ConfigBootBank
    /* Erase */
    ConfigSts = FLASH_EraseOB();
    
    /* Erase success, write the new value of option byte */
    if(FLASH_EOP == ConfigSts)
    {
        /* Unlock option byte */
        Option_Bytes_Unlock();
        
        /* Clears the FLASH's pending flags */
        FLASH_ClearFlag(FLASH_STS_CLRFLAG);
        
        /* Enables the Option Bytes Programming operation */
        FLASH->CTRL |= CTRL_Set_OPTPG;
        
        /* Option byte must be programming in the unit of double-word */
        /* Programming the 1st double word at 0x1FFF_E000 */
        OBT->RDP2_RDP1          = pBuf[0];
        OBT->CCMSRAM_RST_DBANK  = pBuf[1];
        
        /* Wait for the programming operation to complete */
        ConfigSts = FLASH_WaitForLastOpt(ProgramTimeout);
        
        /* Disable the Option Bytes Programming operation */
        FLASH->CTRL &= CTRL_Reset_OPTPG;
    }

4. 用互补标记跨复位传递工作模式。 工作模式写入 MODE_MARK_ADDR 所在备份 SRAM,写入原值与按位取反两个整数;读取时二者不互补即视为无效标记,复位后据此恢复上一次的切换方式。

src/main.csrc/main.c · SetModeMark
static void SetModeMark(uint32_t mark)
{
    uint32_t *pMark;

    pMark = (uint32_t *)MODE_MARK_ADDR;
    
    pMark[0]    = mark;
    pMark[1]    = (~mark);
}
src/main.csrc/main.c · GetModeMark
static uint32_t GetModeMark(void)
{
    uint32_t *pMark;
    uint32_t tMode;

    pMark = (uint32_t *)MODE_MARK_ADDR;
    
    tMode = pMark[0];
    if(tMode != (~pMark[1]) )
    {
        tMode = 0xFFFFFFFFU;
    }
    
    return tMode;
}

对应源码: src/main.c、inc/main.h

5.14.3.2 Flash_Program 页擦除与双字编程

工程目录: projects/n32h49x_EVAL/examples/Flash/Flash_Program/

初始化串口→解锁 Flash 编程/擦除控制器→擦除起始地址所在页→按双字步进写入整页数据→锁定控制器→按字读回并逐字比对→打印测试结果

项目 源码解读
功能 演示主存储区页的擦除与双字编程。
擦除 0x08008000 起始的一页后,以 8 字节为步长把固定数据写入整页,锁定控制器后逐字读回比对,并打印测试结果。
源码组成 src/main.c:main,以及页大小与地址宏 FLASH_PAGE_SIZE、FLASH_WRITE_START_ADDR、FLASH_WRITE_END_ADDR;
inc/main.h:公共头文件;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务函数;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程,工程文件名为 Flash_Program_Proj。
关键配置 页大小 FLASH_PAGE_SIZE 为 0x2000(双 Bank 模式 8KB 一页);
写入区间为 0x08008000~0x08010000;
写入数据固定为 0xCDEF89AB。
系统时钟 240 MHz,打印串口 USART1 TX PA9、RX PA10,波特率 115200。
程序与数据路径 main 先 log_init,调用 FLASH_Unlock;
用 FLASH_EraseOnePage 擦除起始地址所在页,返回非 FLASH_EOP 时停在错误提示;
以 8 字节为步长把同一双字写入整页,返回非 FLASH_EOP 同样停在错误提示;
FLASH_Lock 后以 4 字节为步长读回比对,一致时打印测试结束。
主要 API FLASH_Unlock、FLASH_EraseOnePage、FLASH_ProgramdoubleWord、FLASH_Lock
验证方法 复位运行后串口打印 Flash Program Test Start;
擦除、编程与读回比对全部通过时打印 Flash Program Test End;
任一环节失败时停在对应错误提示。
使用提示 写入只支持双字,编程循环步长为 8 字节而读回步长为 4 字节。
写入前必须擦除,示例擦除的是 0x08008000 起始的一页。
开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。
核心代码解读与移植

示例把一整页擦除后按双字编程,再逐字读回验证数据一致性。

数据路径: FLASH_Unlock → FLASH_EraseOnePage(0x08008000) → FLASH_ProgramdoubleWord 按 8 字节步进写满一页 → FLASH_Lock → 逐字读回比对 → 串口打印结果

1. 解锁并擦除起始页。 示例先解锁编程/擦除控制器,再擦除写入区间起始地址所在页;擦除结果不等于 FLASH_EOP 时停在错误提示,不再执行编程。

src/main.csrc/main.c · main
    /* Unlocks the FLASH Program Erase Controller */
    FLASH_Unlock();

    /* Erase */
    if (FLASH_EOP != FLASH_EraseOnePage(FLASH_WRITE_START_ADDR))
    {
        while(1)
        {
            printf("Flash EraseOnePage Error. Please Deal With This Error Promptly\r\n");
        }
    }

2. 按双字步进写满整页。 循环以 8 字节为步长,每次把数据 0xCDEF89AB 作为两个 32 位字写入,步长与双字编程的对齐要求一致;返回非 FLASH_EOP 时停在错误提示。

src/main.csrc/main.c · main
    /* Program */
    for (Counter_Num = 0; Counter_Num < FLASH_PAGE_SIZE; Counter_Num += 8)
    {
        if (FLASH_EOP != FLASH_ProgramdoubleWord(FLASH_WRITE_START_ADDR + Counter_Num, Erase_Data,Erase_Data))
        {
            while(1)
            {
                log_info("Flash ProgramWord Error. Please Deal With This Error Promptly\r\n");
            }
        }
    }

3. 锁定后逐字读回比对。 编程结束后锁定控制器,再以 4 字节为步长逐字读回,与写入数据不一致时打印测试失败;一致则继续打印测试结束。

src/main.csrc/main.c · main
    /* Locks the FLASH Program Erase Controller */
    FLASH_Lock();

    /* Check */
    for (Counter_Num = 0; Counter_Num < FLASH_PAGE_SIZE; Counter_Num += 4)
    {
        if (Erase_Data != (*(__IO uint32_t*)(FLASH_WRITE_START_ADDR + Counter_Num)))
        {
            printf("Flash Program Test Failed\r\n");
            break;
        }
    }

对应源码: src/main.c

5.14.3.3 Flash_Row_Program 行编程

工程目录: projects/n32h49x_EVAL/examples/Flash/Flash_Row_Program/

初始化串口→解锁 Flash 编程/擦除控制器→擦除起始页→使能行编程器并选择主存储区→按 64 字节步长用 16 字连续编程→锁定控制器→逐字读回比对并打印结果

项目 源码解读
功能 演示行编程器的连续写入能力。
擦除一页后使能行编程器,以 64 字节为步长一次写入 16 个字,锁定后逐字读回比对并打印结果。
源码组成 src/main.c:main 与地址宏,以及 16 个元素的写入缓冲 Erase_Data;
inc/main.h:公共头文件;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务函数;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 写入缓冲区 Erase_Data[16] 全部为 0xCDEF89AB;
FLASH_RowProgramSet(ENABLE) 使能行编程器,FLASH_RowProgramAreaSet(DISABLE) 选择在主存储区操作;
行编程长度参数为 0x10,即 16 个字。
系统时钟 240 MHz,串口 USART1 TX PA9、RX PA10,波特率 115200。
程序与数据路径 与 Flash_Program 相同的解锁与页擦除流程;
擦除后依次使能行编程器并指定主存储区;
以 64 字节为步长调用 FLASH_RowProgram,每次写入 16 个字;
锁定后以 4 字节为步长读回比对缓冲首元素。
主要 API FLASH_Unlock、FLASH_EraseOnePage、FLASH_RowProgramSet、FLASH_RowProgramAreaSet、FLASH_RowProgram、FLASH_Lock
验证方法 复位运行后串口打印 Flash Row Program Test Start;
读回比对全部通过时打印 Flash Program Test End;
失败时打印 Flash Program Test Failed。
使用提示 行编程一次可写 2~16 个字且不能跨 512 字节,示例每次写 16 个字、步长 64 字节。
编程地址须为 8 字节对齐,字长度须为偶数。
开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。
核心代码解读与移植

示例用行编程器一次写入多个连续字,缩短整页写入的编程时间。

数据路径: FLASH_Unlock → FLASH_EraseOnePage → FLASH_RowProgramSet(ENABLE)/FLASH_RowProgramAreaSet(DISABLE) → FLASH_RowProgram 按 64 字节步进写 16 字 → FLASH_Lock

1. 使能行编程器并选择主存储区。 擦除完成后,示例先使能行编程器,再把操作区域设为主存储区;FLASH_RowProgramAreaSet(DISABLE) 对应在主存储区而非系统存储区编程。

src/main.csrc/main.c · main
    /* Flash row programmer configure*/
    FLASH_RowProgramSet(ENABLE);
    FLASH_RowProgramAreaSet(DISABLE);

2. 按 64 字节步长连续编程。 循环以 64 字节为步长,每次调用 FLASH_RowProgram 写入 16 个字;单次写入不跨 512 字节,返回非 FLASH_EOP 时停在错误提示。

src/main.csrc/main.c · main
    /*Row Program */
    for (Counter_Num = 0; Counter_Num < FLASH_PAGE_SIZE; Counter_Num += 64)
    {
        if (FLASH_EOP != FLASH_RowProgram(FLASH_WRITE_START_ADDR + Counter_Num,0x10U, Erase_Data))
        {
            while(1)
            {
                log_info("Flash ProgramWord Error. Please Deal With This Error Promptly\r\n");
            }
        }
    }

3. 锁定后读回比对。 锁定控制器后,示例以 4 字节为步长读回并与缓冲首个元素比对,不一致时打印测试失败,否则继续打印测试结束。

src/main.csrc/main.c · main
    /* Locks the FLASH Program Erase Controller */
    FLASH_Lock();

    /* Check */
    for (Counter_Num = 0; Counter_Num < FLASH_PAGE_SIZE; Counter_Num += 4)
    {
        if (Erase_Data[0] != (*(__IO uint32_t*)(FLASH_WRITE_START_ADDR + Counter_Num)))
        {
            printf("Flash Program Test Failed\r\n");
            break;
        }
    }

对应源码: src/main.c

5.14.3.4 OptionByte_Config 选项字节配置

工程目录: projects/n32h49x_EVAL/examples/Flash/OptionByte_Config/

初始化串口→解锁 Flash 与选项字节控制器→擦除选项字节→依次编程读保护、写保护、数据字节与 SRAM ECC→锁定两个控制器→等待串口下发 0x55 恢复默认值

项目 源码解读
功能 演示选项字节的擦除与编程。
复位后擦除选项字节并依次配置读保护、Bank 模式、USER/USER2、写保护、数据字节与 SRAM ECC,再等待串口下发 0x55 把选项字节恢复为默认值。
源码组成 src/main.c:main,包含默认配置与 0x55 恢复两段流程;
inc/main.h:公共头文件;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务函数;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 默认配置为双 Bank 模式、CCM SRAM 复位不擦除、软件 IWDG、BOR 阈值 1.6V;
写保护配置为 FLASH_WRP_NUM16(单 Bank 第 32~33 页,双 Bank 第 64~67 页);
选项字节数据写为 0x55、0x66、0x77、0xAA;
SRAM2、SRAM3 ECC 使能。
系统时钟 240 MHz,串口 USART1 TX PA9、RX PA10,波特率 115200。
程序与数据路径 main 先 log_init,调用 FLASH_Unlock 与 Option_Bytes_Unlock;
用 FLASH_EraseOB 擦除选项字节,返回 FLASH_EOP 后依次调用 FLASH_ProgramOB_RRDC、FLASH_ProgramOB_U1U2、FLASH_EnWriteProtection、FLASH_ProgramOB_Data、FLASH_ProgramOB_SRAMECC;
每一步用 FLASH_EOP 判断是否继续,全部完成后锁定两个控制器;
主循环等待 USART1 收到 0x55,再以默认参数重新编程一组选项字节。
主要 API FLASH_Unlock、Option_Bytes_Unlock、FLASH_EraseOB、FLASH_ProgramOB_RRDC、FLASH_ProgramOB_U1U2、FLASH_EnWriteProtection、FLASH_ProgramOB_Data、FLASH_ProgramOB_SRAMECC、FLASH_Lock、Option_Bytes_Lock
验证方法 复位运行后串口打印 Option Byte configure Test start;
五步编程全部成功时打印 Option Byte configure OK;
下发 0x55 后打印恢复默认值成功或失败。
使用提示 选项字节编程以双字为单位,先擦除再写,且需先解锁 Flash 与选项字节两个控制器。
读出保护 L2、Bank 模式切换等改动需重新刷写 Flash 才完全生效。
开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。
核心代码解读与移植

示例演示选项字节的整组擦除与逐项编程,以及如何把选项字节恢复为默认值。

数据路径: FLASH_Unlock/Option_Bytes_Unlock → FLASH_EraseOB → FLASH_ProgramOB_RRDC 等五个编程函数 → FLASH_Lock/Option_Bytes_Lock → 串口 0x55 触发默认值恢复

1. 擦除选项字节并逐项编程。 示例先解锁两个控制器并擦除选项字节;擦除成功后按顺序编程 USER/USER2,每一步都以返回状态判断是否继续。

src/main.csrc/main.c · main
    /* Unlocks the FLASH Program Erase Controller */
    FLASH_Unlock();
    /* Unlocks the Option Byte Program Erase Controller */
    Option_Bytes_Unlock();
    /*  Erase Option Byte page */
    state_value = FLASH_EraseOB();
    
    if(state_value == FLASH_EOP)
    {
src/main.csrc/main.c · main
        if(state_value == FLASH_EOP)
        {
            /* Configure option bytes RDP2, user2 and user3 */
            state_value = FLASH_ProgramOB_U1U2(FLASH_OB_IWDG_SOFTWARE,FLASH_OB_STOP_NORST,FLASH_OB_STDBY_NORST,\
                                                FLASH_OB_IWDG_STOP_NOFRZ,FLASH_OB_IWDG_STDBY_NOFRZ,FLASH_OB_IWDG_SLEEP_NOFRZ,\
                                                FLASH_OB2_NBOOT0_SET,FLASH_OB2_NBOOT1_SET,FLASH_OB2_NSWBOOT0_SET,\
                                                FLASH_OB2_FLASHBOOT_SET,FLASH_OB2_DAC_SET,BOR_LEVEL_1_6V);
        }

2. 编程写保护、数据字节与 SRAM ECC。 同一层级的后续三步分别配置写保护页、选项字节数据与 SRAM2、SRAM3 的 ECC 使能位,写法与前一步一致,失败时进入空分支不处理。

src/main.csrc/main.c · main
        if(state_value == FLASH_EOP)
        {
            /* Enable writing protection Single Bank: page 32 to 33, Dual Banke: page 64  to 67 */
            state_value = FLASH_EnWriteProtection(FLASH_WRP_NUM16);
        }
        else
        {
            /* no process*/
        }
        
        if(state_value == FLASH_EOP)
        {
            /* Configure option byte datax */
            state_value = FLASH_ProgramOB_Data(0x55,0x66,0x77,0xAA);
src/main.csrc/main.c · main
        if(state_value == FLASH_EOP)
        {
            /* Configure option byte CCMSRAM reset without erasing */
            state_value = FLASH_ProgramOB_SRAMECC(SRAM2_ECC_ENABLE,SRAM3_ECC_ENABLE);
        }
        else
        {
            /* no process*/
        }

3. 用串口 0x55 恢复默认值。 主循环收到 0x55 后重复解锁与擦除流程,再以默认参数重新写读保护与 Bank 模式,从而把之前改动的选项字节恢复为默认值。

src/main.csrc/main.c · main
        UartCmd = USART_ReceiveData(USART1);
        if(UartCmd == 0x55)
        {
            /* Unlocks the FLASH Program Erase Controller */
            FLASH_Unlock();
            /* Unlocks the Option Byte Program Erase Controller */
            Option_Bytes_Unlock();
            /*  Erase Option Byte page */
            state_value = FLASH_EraseOB();

对应源码: src/main.c

5.14.3.5 Run_In_CCM 在 CCM SRAM 中运行代码

工程目录: projects/n32h49x_EVAL/examples/Flash/Run_In_CCM/

初始化串口→把启动代码已拷贝到 CCM SRAM 的函数字节镜像到普通 SRAM 备份→用 RCC 一键初始化把 CCM SRAM 填零并建立 ECC 位→把备份字节写回 CCM SRAM→打印三个函数执行地址并确认落在 CCM SRAM 范围→执行三级嵌套调用链并校验返回值

项目 源码解读
功能 演示把函数代码存放于 Flash、运行时复制到 CCM SRAM 并在其中执行的方法。
示例用三级嵌套调用链,打印三个函数的执行地址确认位于 CCM SRAM,并校验调用链返回值为 448。
源码组成 src/main.c:main、CCM_SRAM_Init、CCM_SRAM_SaveCode、CCM_SRAM_RestoreCode 与三个被标记的 CCM 函数;
inc/main.h:公共头文件;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务函数;
readme.txt:功能、环境与使用说明;
MDK-ARM/(含自定义分散加载文件 Run_In_CCM.sct)、EWARM/(含自定义 ICF 文件 Run_In_CCM.icf):Keil 与 IAR 工程。
关键配置 CCM SRAM 范围为 0x20070000~0x2007FFFF,大小 64KB;
备份缓冲 ccm_backup 为 256 个字;
__CCM_FUNC 宏按工具链把函数放到 CCM 段(Keil ccmram、IAR CCM_CODE),由自定义链接脚本指定函数的加载地址在 Flash、执行地址在 CCM SRAM。
系统时钟 240 MHz,串口 USART1 TX PA9、RX PA10,波特率 115200。
程序与数据路径 main 先 log_init;
调用 CCM_SRAM_SaveCode 把 CCM SRAM 现有内容镜像到 ccm_backup;
调用 CCM_SRAM_Init,依次写起始地址、配置初始化范围与值、启动一键初始化并等待完成,再调用 CCM_ModeSet;
CCM_SRAM_RestoreCode 把备份写回;
取三个函数地址判断是否落在 CCM SRAM 范围内,最后调用 CCM_WeightedSumOfSquares(5) 并校验返回 448。
主要 API CCM_ModeSet(CCM SRAM 一键初始化由 RCC->SRAMCFG1~SRAMCFG4 直接配置)
验证方法 串口依次打印 CCM Function Code Saved、CCM SRAM Initialized、CCM Function Code Restored;
三个函数执行地址均落在 CCM SRAM 范围时打印 [PASS];
调用链返回 448 时打印 Run_In_CCM Test Passed。
使用提示 CCM SRAM 默认使能 ECC,读取前须保证 ECC 位有效;
一键初始化会清零整个 CCM SRAM,包含启动代码已拷贝的函数代码,因此须在初始化后重新写回。
Keil 工程须使用 Run_In_CCM.sct,IAR 工程须使用 Run_In_CCM.icf。
开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。
核心代码解读与移植

示例说明如何把函数放到 CCM SRAM 执行,并用备份缓冲避免一键初始化清零代码。

数据路径: CCM_SRAM_SaveCode 镜像 CCM SRAM → CCM_SRAM_Init 一键初始化并 CCM_ModeSet → CCM_SRAM_RestoreCode 写回 → 校验函数地址在 CCM SRAM → CCM_WeightedSumOfSquares 返回 448

1. 用宏把函数放进 CCM 段。 示例按工具链定义 __CCM_FUNC,Keil 使用 ccmram 段、IAR 使用自定义的 CCM_CODE 段;标记后的函数加载地址仍在 Flash,由链接脚本决定执行地址在 CCM SRAM。

src/main.csrc/main.c
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
#define __CCM_FUNC  __attribute__((section("ccmram")))
#elif defined(__ICCARM__)
#define __CCM_FUNC  _Pragma("location=\"CCM_CODE\"")
#elif defined(__GNUC__)
#define __CCM_FUNC  __attribute__((section(".ccmram")))
#else
#define __CCM_FUNC
#endif

2. 一键初始化 CCM SRAM。 CCM_SRAM_Init 先向起始地址写一个初始化值,再配置初始化范围与值,启动一键初始化并等待完成标志,最后清使能位并打开 CCM 模式。

src/main.csrc/main.c · CCM_SRAM_Init
    *(__IO uint32_t *)CCM_SRAM_BASE = 0x00000000U;

    /* Step 1: Configure initialization range
       End address must differ from start address */
    RCC->SRAMCFG3 = (uint32_t)CCM_SRAM_BASE;
    RCC->SRAMCFG4 = (uint32_t)(CCM_SRAM_BASE + CCM_SRAM_SIZE - 4U);

    /* Step 2: Configure initialization value */
    RCC->SRAMCFG2 = 0x00000000U;

    /* Step 3: Start one-key initialization */
    RCC->SRAMCFG1 |= RCC_SRAMCFG1_SRINIEN;

    /* Step 4: Wait for initialization complete */
    while (!(RCC->SRAMCFG1 & RCC_SRAMCFG1_SRINIF))
    {
    }

    /* Clear initialization enable */
    RCC->SRAMCFG1 &= ~RCC_SRAMCFG1_SRINIEN;
    
    /* Enable CCM mode */
    CCM_ModeSet(ENABLE);

3. 备份代码、写回并校验执行地址。 一键初始化会覆盖启动代码已拷贝到 CCM SRAM 的函数字节,示例先把这些字镜像到普通 SRAM,初始化后再写回;随后取三个函数地址判断是否落在 CCM SRAM 范围内。

src/main.csrc/main.c · CCM_SRAM_SaveCode
    volatile uint32_t *src = (volatile uint32_t *)CCM_SRAM_BASE;
    uint32_t i;

    for (i = 0U; i < CCM_BACKUP_WORDS; i++)
    {
        ccm_backup[i] = src[i];
    }
src/main.csrc/main.c · main
    addr_square   = (uint32_t)CCM_Square              & ~1U;
    addr_sum      = (uint32_t)CCM_SumOfSquares         & ~1U;
    addr_weighted = (uint32_t)CCM_WeightedSumOfSquares & ~1U;

    printf("CCM_Square Address              : 0x%08X\r\n", (unsigned int)addr_square);
    printf("CCM_SumOfSquares Address        : 0x%08X\r\n", (unsigned int)addr_sum);
    printf("CCM_WeightedSumOfSquares Address: 0x%08X\r\n", (unsigned int)addr_weighted);
    printf("CCM SRAM Range: 0x%08X ~ 0x%08X\r\n",
           (unsigned int)CCM_SRAM_BASE, (unsigned int)CCM_SRAM_END);

    if ((addr_square   >= CCM_SRAM_BASE) && (addr_square   <= CCM_SRAM_END) &&
        (addr_sum      >= CCM_SRAM_BASE) && (addr_sum      <= CCM_SRAM_END) &&
        (addr_weighted >= CCM_SRAM_BASE) && (addr_weighted <= CCM_SRAM_END))
    {
        printf("All Functions In CCM SRAM [PASS]\r\n");
    }
    else
    {
        printf("Function NOT In CCM SRAM [FAIL]\r\n");
        while (1)
        {
        }
    }

对应源码: src/main.c

5.14.3.6 SingleBankRemap 单 Bank 启动重映射

工程目录: projects/n32h49x_EVAL/examples/Flash/SingleBankRemap/

初始化串口→读取并打印当前 Bank 模式→读取启动重映射状态→等待串口指令→改写启动区选项字节并复位或直接重映射→从主存储区前/后半段启动

项目 源码解读
功能 演示单 Bank 模式(DBANK=0)下的启动重映射。
示例读取当前 Bank 模式与启动重映射状态,通过串口指令改写启动区选项字节或直接重映射,使系统从主存储区前/后半段启动。
源码组成 src/main.c:main 与启动使能位宏 FLASH_BOOTENABLE;
inc/main.h:公共头文件;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务函数;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 启动使能标志位 FLASH_BOOTENABLE 为 0x00080000,通过系统存储区地址 0x1FFFE010 判断启动区;
启动区由选项字节 USER2 的 FLASH_OB2_FLASHBOOT 位决定;
重映射状态通过 RCC->BOOTREMAP 的 RCC_BOOTREMAP_REMAPSEL 域读取。
系统时钟 240 MHz,串口 USART1 TX PA9、RX PA10,波特率 115200。
程序与数据路径 main 先 log_init;
用 FLASH_GetFlagSTS(FLASH_FLAG_BANKMODE) 打印当前 Bank 模式,再读 RCC->BOOTREMAP 与 0x1FFFE010 判断当前启动区;
主循环轮询 USART1:0x55 配置前半段为启动区、0x66 配置后半段为启动区,二者改写选项字节后复位;
0x77 与 0x88 只做前后半段重映射。
主要 API FLASH_GetFlagSTS、FLASH_Unlock、FLASH_EraseOB、FLASH_ProgramOB_RRDC、FLASH_ProgramOB_U1U2
验证方法 复位运行后串口打印当前 Bank 模式和启动区;
下发 0x55 或 0x66 后系统复位并从对应半段启动;
下发 0x77 或 0x88 后直接重映射并从对应半段启动。
使用提示 单 Bank 模式下主存储区分前后两半段,启动地址始终是 0x08000000。
改写启动区选项字节后需要系统复位,示例用 NVIC_SystemReset 完成。
开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。
核心代码解读与移植

示例读取启动区来源,并通过选项字节或 RCC 重映射把启动区切换到主存储区的另一半。

数据路径: 读 FLASH_FLAG_BANKMODE 与 RCC->BOOTREMAP/0x1FFFE010 → 串口指令 → FLASH_ProgramOB_U1U2 改启动位并复位,或 RCC_ConfigRemapMode/RCC_EnableRemap 重映射

1. 读取 Bank 模式与启动区。 示例先打印 Bank 模式,再读重映射寄存器;未使能重映射时改读系统存储区的启动使能位,据此判断系统从主存储区的前半段还是后半段启动。

src/main.csrc/main.c · main
    /* Show bank mode */
    if(FLASH_GetFlagSTS(FLASH_FLAG_BANKMODE) == SET)
    {
        log_info("FLASH is dual bank mode!\r\n");
    }
    else
    {
        log_info("FLASH is single bank mode!\r\n");
    }

    Value_temp = RCC->BOOTREMAP  & RCC_BOOTREMAP_REMAPSEL;
    if(Value_temp == RCC_REMAP_BFLASH)
    {
        FlashRemap = RCC_REMAP_BFLASH;
        log_info("Flash starts from the forward half, with startup address 0x08000000!\r\n");
    }
    else if(Value_temp == RCC_REMAP_AFLASH)
    {
        FlashRemap = RCC_REMAP_AFLASH;
        log_info("Flash starts from the back half, with startup address 0x08000000!\r\n");
    }
    else
    {
        log_info("No boot remap!\r\n");
        if(((*(uint32_t*)(0x1FFFE010)) & FLASH_BOOTENABLE) ==  FLASH_BOOTENABLE)
        {
            FlashRemap = RCC_REMAP_BFLASH;
            printf("System start from the forward half,with startup address 0x08000000!\r\n");
        }
        else
        {
            FlashRemap = RCC_REMAP_AFLASH;
            printf("System start from the back half,with startup address 0x08000000!\r\n");
        }
    }

2. 改写启动区选项字节并复位。 需要持久改变启动区时,示例解锁并擦除选项字节,先配置为单 Bank 模式,再用 USER2 的启动位写入目标半段,最后调用 NVIC_SystemReset 复位。

src/main.csrc/main.c · main
        if(UartCmd == 0xDD) /* Modify OB */
        {
            FLASH_Unlock();
            FLASH_EraseOB();
            
            /* Configure FLASH to Single BANK mode */
            FLASH_ProgramOB_RRDC(FLASH_OB_RDP1_DISABLE,FLASH_OB_RDP2_DISABLE,FLASH_SINGLE_BANK,CCMSRAM_RST_NERASE);
            
            /* Configure FLASH BANK1 startup */
            FLASH_ProgramOB_U1U2(FLASH_OB_IWDG_SOFTWARE,FLASH_OB_STOP_NORST,FLASH_OB_STDBY_NORST,FLASH_OB_IWDG_STOP_NOFRZ,\
                                 FLASH_OB_IWDG_STDBY_NOFRZ,FLASH_OB_IWDG_SLEEP_NOFRZ,FLASH_OB2_NBOOT0_SET,FLASH_OB2_NBOOT1_SET,\
                                 FLASH_OB2_NSWBOOT0_SET,Value_temp,FLASH_OB2_DAC_SET, BOR_LEVEL_1_6V);
            
            log_info("System reset !\r\n");
            NVIC_SystemReset();
        }

3. 直接重映射启动区。 不需要改写选项字节时,示例只调用 RCC_ConfigRemapMode 与 RCC_EnableRemap 立即切换启动映射,不触发复位。

src/main.csrc/main.c · main
        else if(UartCmd == 0xEE)    /* Remap */
        {
            RCC_ConfigRemapMode(Value_temp);
            RCC_EnableRemap();
        }

对应源码: src/main.c

5.14.4 注意与排障

场景 检查与建议 来源
编程/擦除的时钟条件 进行 Flash 编程(写入或擦除)时必须打开内部 RC 振荡器(HSI);
低功耗模式下所有 Flash 操作都被中止。
用户手册
写操作与擦除粒度 Flash 写入只支持 64 位双字;
编程阶段写入半字会产生总线错误;
写入前须先擦除,双 BANK 模式最小擦除单位为 8KB 一页,单 BANK 模式为 16KB 一页。
用户手册
BUSY 期间的访问限制 FLASH_STS.BUSY 为 1 时不能对任何 Flash 寄存器执行写操作,也不能对同一片 Flash 同时读写。 用户手册
页擦除地址对齐 单 BANK 模式下 Page_Address 须为 0x4000 的整数倍(每页 16KB);
双 BANK 模式下须为 0x2000 的整数倍(每页 8KB)。
用户手册
整片擦除的 BANK 选择 DBANK=0(单 BANK)时,只置位 MER1 或 MER2 不会执行整片擦除。 用户手册
行编程的地址跨度 行编程不能跨 512 字节;
编程地址要与行编程的开始地址及字长度一致。
用户手册
双 BANK 读写并发 双 BANK 模式(DBANK=1)允许一个 Bank 擦除或编程的同时从另一个 Bank 读取;
不允许同时进行两次写操作;
选项字节与 BANK1 位于同一片 Flash,不能同时操作。
用户手册
选项字节解锁 对选项字节编程或擦除前须先解锁 Flash 与选项字节(FLASH_OPTKEY 写入 KEY1 0x45670123、KEY2 0xCDEF89AB);
OPTWE=0 时选项字节被锁定。
用户手册
BANK 模式切换后重刷 通过选项字节切换 BANK 模式后,主存储区结构发生变化,需要重新刷写 Flash。 用户手册
写保护生效条件 通过 WRP 配置写保护后,需进行一次系统复位才能生效;
对受保护的页编程或擦除会返回保护错误标志。
用户手册
读出保护 L1 使能读出保护 L1 后,除整片擦除外,全部主存储区页不允许在调试模式下或从内部 SRAM 启动后执行写或擦除。 用户手册
等待周期与预取 读等待周期须随 AHB 时钟提高而增大(48 MHz 内为 0、96 MHz 内为 1、144 MHz 内为 2、192 MHz 内为 3、240 MHz 内为 4);
等待周期不为零时启用预取缓冲可提高效率。
用户手册
国民技术开发套件文档中心

按芯片系列在线查阅国民技术 MCU 开发套件的芯片资料、SDK、驱动 API 与 Demo 示例说明。

© 2026 国民技术股份有限公司 版权所有粤ICP备11069485号本站使用不含 Cookie 的匿名访问统计