GD32的flash读保护和写保护
Posted qlexcel
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GD32的flash读保护和写保护相关的知识,希望对你有一定的参考价值。
介绍
在实际发布的产品中,在GD32芯片的内部FLASH存储了控制程序,如果不作任何保护措施的话,可以使用下载器直接把内部FLASH的内容读取回来,得到bin或hex文件格式的代码拷贝,别有用心的厂商会利用该方法山寨产品。为此,GD32芯片提供了多种方式保护内部FLASH的程序不被非法读取,但在默认情况”下该保护功能是不开启的,若要开启该功能,需要改写内部FLASH选项字节(Option Bytes)中的配置。
GD32的选项字节地址和功能都跟STM32一样:
其中前面带“n”的是不带“n”的取反,即nUSER的值等于(~USER)、nRDP的值等于(~RDP),GD32利用反码来确保选项字节内容的正确性。
每次系统复位后,闪存的可选字节块被重加载到FMC_OBSTAT和FMC_WP寄存器,可选字节生效。可选字节的补字节具体为可选字节取反。当可选字节被重装载时,如果可选字节的补字节和可选字节不匹配,FMC_OBSTAT寄存器的OBERR位将被置1,可选字节被强制设置为0xFF。若可选字节和其补字节同为0xFF,则OBERR位不置位。可选字节详情见下表。
选项字节操作函数
选项字节锁定和解锁
和flash一样,对选项字节进行擦除和编程都需要先解锁。
ob_unlock();
ob_lock();
选项字节擦除函数
/* erase all the option Bytes */
fmc_state = ob_erase();
选项字节编程函数
FMC提供了一个32位整字/16位半字编程功能,可用来修改可选字节块内容。可选字节块共有8对可选字节。每对可选字节的高字节是低字节的补。当低字节被修改时,FMC自动生成该选项字节的高字节。
需要注意的是,执行整字/半字编程操作需要检查目的地址是否已经被擦除。 如果该地址没有被擦除, 对该地址写一个非0x0值, FMC_STAT0寄存器的PGERR位将被置1,对该地址的编程操作无效(当写内容为0x0时,即使目的地址没有被
正常擦除,也可以正确编程)。
当可选字节被改变时,需要系统复位使之生效。
使能写保护
/*!
\\brief enable write protection
\\param[in] ob_wp: specify sector to be write protected, set the bit to 1 if
you want to protect the corresponding pages. meanwhile, sector
macro could used to set specific sector write protected.
one or more parameters can be selected which are shown as below:
\\arg OB_WPx(x = 0..31): write protect specify sector
\\arg OB_WP_ALL: write protect all sector
\\param[out] none
\\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum ob_write_protection_enable(uint32_t ob_wp)
选项字节的WP[30:0]中的每个bit设置每4KB flash空间的保护状态,比如最低位设置最开始4KB空间的写保护状态,即0x0800 0000 - 0x0800 0FFF。这31位总计可设置前124KB的闪存保护状态。 WP[31],第31位可设置闪存剩下部分的保护状态。
库函数都已经把每个扇区的宏定义写好了:
/* option bytes write protection */
#define OB_WP_0 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 0 */
#define OB_WP_1 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 1 */
#define OB_WP_2 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 2 */
#define OB_WP_3 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 3 */
#define OB_WP_4 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 4 */
#define OB_WP_5 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 5 */
#define OB_WP_6 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 6 */
#define OB_WP_7 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 7 */
#define OB_WP_8 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 8 */
#define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */
#define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */
#define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */
#define OB_WP_12 ((uint32_t)0x00001000U) /*!< erase/program protection of sector 12 */
#define OB_WP_13 ((uint32_t)0x00002000U) /*!< erase/program protection of sector 13 */
#define OB_WP_14 ((uint32_t)0x00004000U) /*!< erase/program protection of sector 14 */
#define OB_WP_15 ((uint32_t)0x00008000U) /*!< erase/program protection of sector 15 */
#define OB_WP_16 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 16 */
#define OB_WP_17 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 17 */
#define OB_WP_18 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 18 */
#define OB_WP_19 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 19 */
#define OB_WP_20 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 20 */
#define OB_WP_21 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 21 */
#define OB_WP_22 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 22 */
#define OB_WP_23 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 23 */
#define OB_WP_24 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 24 */
#define OB_WP_25 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 25 */
#define OB_WP_26 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 26 */
#define OB_WP_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 27 */
#define OB_WP_28 ((uint32_t)0x10000000U) /*!< erase/program protection of sector 28 */
#define OB_WP_29 ((uint32_t)0x20000000U) /*!< erase/program protection of sector 29 */
#define OB_WP_30 ((uint32_t)0x40000000U) /*!< erase/program protection of sector 30 */
#define OB_WP_31 ((uint32_t)0x80000000U) /*!< erase/program protection of sector 31 */
#define OB_WP_ALL ((uint32_t)0xFFFFFFFFU) /*!< erase/program protection of all sectors */
比如,要写保护扇区0,执行:
ob_write_protection_enable(OB_WP_0);
要写保护扇区0、1、2,执行:
ob_write_protection_enable(OB_WP_0|OB_WP_1|OB_WP_2);
使能读保护
FMC提供了一个安全保护功能来阻止非法读取闪存。 此功能可以很好地保护软件和固件免受非法的用户操作。
未保护状态:当将SPC字节和它的补字节被设置为0x5AA5,系统复位以后,闪存将处于非安全保护状态。主存储块和可选字节块可以被所有操作模式访问。
已保护状态:当设置SPC字节和它的补字节值为任何除0x5AA5外的值,系统复位以后,安全保护状态生效。需要注意的是, 若该修改过程中,MCU的调试模块依然和外部JTAG/SWD设备相连,需要用上电复位代替系统复位以使得修改后的保护状态生效。在安全保护状态下,主存储闪存块仅能被用户代码访问且前4KB的闪存自动处于页擦除/编程保护状态下。 在调试模式下,或从SRAM中启动时,以及从boot loader区启动时,这些模式下对主存储块的操作都被禁止。如果在这些模式下读主存储块,将产生总线错误。如果在这些模式下,对主存储块进行编程或擦除操作, FMC_STAT寄存器的WPERR位将被置1。 但这些模式下都可以对可选字节块进行操作,从而可以通过该方式失能安全保护功能。如果将SPC字节和它的补字节设置为0x5AA5,安全保护功能将失效,并自动触发一次整片擦除操作。
/*!
\\brief configure security protection
\\param[in] ob_spc: specify security protection
only one parameter can be selected which is shown as below:
\\arg FMC_NSPC: no security protection
\\arg FMC_USPC: under security protection
\\param[out] none
\\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
要使能读保护,执行
ob_security_protection_config(FMC_USPC);
要取消读保护,执行
ob_security_protection_config(FMC_NSPC);
以上是关于GD32的flash读保护和写保护的主要内容,如果未能解决你的问题,请参考以下文章
STM32F407 读保护,写保护,解锁过程芯片已设置读保护,无法读取更多信息
st link flash timeout reset the target try it againt
使用ST Flash Download也无法擦除读保护的问题修复