GD32篇 记录

一、GD32开发版程序设置读保护,防止程序被读取

二、GD32TIMER输出PWM

平台:PC
系统:Win10 1909
开发版:GD32F103RCT6
软件:Keil、STM32 ST-LINK Utility

STM32 ST-LINK Utility下载链接:密码2022


文章目录

  • [GD32篇 记录](https://blog.csdn.net/qq_41930631/category_12031278.html)
    • 一、GD32开发版程序设置读保护,防止程序被读取
    • 二、GD32TIMER输出PWM
  • 前言
  • 一、STM32 ST-LINK Utility?
  • 二、使用步骤
    • 1.ST-LINK Utility界面介绍
      • 点击Target
      • 接着点击Connect
    • 2.写入数据
  • 三、GD32FMC介绍
    • 可选项字节块编程
      • 闪存结构
    • FMC相关的寄存器
    • FMC_CTLx 寄存器解锁
    • 可选项字节块编程
    • 可选字节块说明
    • 页擦除/编程保护
    • 安全保护,也称读保护
  • 使能读保护
  • 效果
  • 总结

前言

在实际发布的产品中,在GD32芯片的内部FLASH存储了控制程序,如果不作任何保护措施的话,可以使用下载器直接把内部FLASH的内容读取回来,得到bin或hex文件格式的代码拷贝,别有用心的厂商会利用该方法山寨产品。
为了解决这个问题,GD32芯片提供了好几种保护内部Flash不被轻易读取的方式,但是一般在默认的情况下这个功能是没有打开的。


一、STM32 ST-LINK Utility?

STM32 ST-LINK Utility这个软件工具其实主要就是配套“ST-LINK”这个下载工具一起使用的上位机软件。因此使用STM32 ST-LINK Utility上位机软件需要有一个ST-LINK工具才行。它的功能和J-Link对应的工具类似,用于烧写代码。

STM32 ST-LINK Utility工具在产品开发过程中测试一些其他版本的代码,可以直接下载hex,而不用打开工程再编译去下载。 当你开发完一个STM32产品,需要量产的时候,就可以用这个工具直接下载hex代码,对代码加密(读保护)

二、使用步骤

1.ST-LINK Utility界面介绍

安装下载完成之后打开就是这个界面

点击Target

接着点击Connect

出现一下信息就说明成功读取到了内部的Flash了

很明显,已经通过ST-Link用 STM32 ST-LINK Utility读取出来了Flash 的内容,我甚至还可以保存成BIN文件

2.写入数据

接下来往Flash里面写一些内容,测试一下

代码如下(示例):

const char FIRMWARE[] __attribute__((section(".ARM.__at_0x08010000")))   ={"WRITE FLASH"};
const char g_revision_datetime[]__attribute__((section(".ARM.__at_0x08010020")))  = __DATE__" "  __TIME__;

在0x08010000这里写入“ WRITE FLASH”
在0x08010020 纪录编译代码时间

完成后编译代码,写入到芯片上,然后打开ST-LINK Utility
如下图

时间差不多

可以看到,用ST-link脸上GD32 的芯片,用ST-LINK Utility完全可以读出Flash的内容


三、GD32FMC介绍

可选项字节块编程

闪存结构

对于GD32F10x_MD,闪存页大小为1KB。
对于主存储闪存容量不多于512KB的GD32F10x_CL 和GD32F10x_HD,闪存页大小为2KB。例如RCT6
对于主存储闪存容量不少于768KB的GD32F10x_CL和
GD32F10x_XD,使用了两片闪存;前512KB容量在第一片闪存(bank0)中,后续的容量在第
二片闪存(bank1)中。其中bank0的闪存页大小为2KB,bank1的闪存页大小为4KB。主存储
闪存的每页都可以单独擦除。闪存结构见下图。

GD32F103RCT6属于GD32F10x_HD系列产品,每页的字节是2K,总共的Flash有256K,也就是0-127页

FMC相关的寄存器

/* FMC and option byte definition */
#define FMC                        FMC_BASE                       /*!< FMC register base address */
#define OB                         OB_BASE                        /*!< option bytes base address *//* registers definitions */
#define FMC_WS                     REG32((FMC) + 0x00U)                          /*!< FMC wait state register */
#define FMC_KEY0                   REG32((FMC) + 0x04U)                          /*!< FMC unlock key register 0 */
#define FMC_OBKEY                  REG32((FMC) + 0x08U)                          /*!< FMC option bytes unlock key register */
#define FMC_STAT0                  REG32((FMC) + 0x0CU)                          /*!< FMC status register 0 */
#define FMC_CTL0                   REG32((FMC) + 0x10U)                          /*!< FMC control register 0 */
#define FMC_ADDR0                  REG32((FMC) + 0x14U)                          /*!< FMC address register 0 */
#define FMC_OBSTAT                 REG32((FMC) + 0x1CU)                          /*!< FMC option bytes status register */
#define FMC_WP                     REG32((FMC) + 0x20U)                          /*!< FMC erase/program protection register */
#define FMC_KEY1                   REG32((FMC) + 0x44U)                          /*!< FMC unlock key register 1 */
#define FMC_STAT1                  REG32((FMC) + 0x4CU)                          /*!< FMC status register 1 */
#define FMC_CTL1                   REG32((FMC) + 0x50U)                          /*!< FMC control register 1 */
#define FMC_ADDR1                  REG32((FMC) + 0x54U)                          /*!< FMC address register 1 */
#define FMC_WSEN                   REG32((FMC) + 0xFCU)                          /*!< FMC wait state enable register */
#define FMC_PID                    REG32((FMC) + 0x100U)                         /*!< FMC product ID register */#define OB_SPC                     REG16((OB) + 0x00U)                           /*!< option byte security protection value */
#define OB_USER                    REG16((OB) + 0x02U)                           /*!< option byte user value*/
#define OB_WP0                     REG16((OB) + 0x08U)                           /*!< option byte write protection 0 */
#define OB_WP1                     REG16((OB) + 0x0AU)                           /*!< option byte write protection 1 */
#define OB_WP2                     REG16((OB) + 0x0CU)                           /*!< option byte write protection 2 */
#define OB_WP3                     REG16((OB) + 0x0EU)                           /*!< option byte write protection 3 */

FMC_CTLx 寄存器解锁

复位后,FMC_CTLx寄存器进入锁定状态,LK位置为1。通过先后向FMC_KEY0寄存器写入
0x45670123和0xCDEF89AB,可以使得FMC_CTL0寄存器解锁。两次写操作后,FMC_CTL0
寄存器的LK位被硬件清0。可以通过软件设置FMC_CTL0寄存器的LK位为1再次锁定
FMC_CTL0寄存器。任何对FMC_KEY0寄存器的错误操作都会将LK位置1,从而锁定
FMC_CTL0寄存器,并引发一个总线错误。
FMC_CTL0寄存器的OBPG位和OBER位在FMC_CTL0寄存器第一层解锁后,仍然需要第二层
解锁。第二层解锁过程也是两次写操作,向FMC_OBKEY寄存器先后写入0x45670123和
0xCDEF89AB,然后硬件将FMC_CTL0寄存器的OBWEN位置1。软件可以将FMC_CTL0的
OBWEN位清0来锁定FMC_CTL0的OBPG位和OBER位。
对于GD32F10x_CL和GD32F10x_XD,FMC_CTL0寄存器用来设置对bank0和选项字节块的
操作,FMC_CTL1寄存器用来设置对bank1的擦写操作。FMC_CTL1的解锁和锁定机制和
FMC_CTL0类似。对FMC_KEY1写解锁序列可解除FMC_CTL1的锁定。

代码解释如下:

/*!\brief      unlock the main FMC operation\param[in]  none\param[out] none\retval     none
*/
void fmc_unlock(void)
{if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){/* write the FMC unlock key */FMC_KEY0 = UNLOCK_KEY0;FMC_KEY0 = UNLOCK_KEY1;}if(FMC_BANK0_SIZE < FMC_SIZE){/* write the FMC unlock key */if(RESET != (FMC_CTL1 & FMC_CTL1_LK)){FMC_KEY1 = UNLOCK_KEY0;FMC_KEY1 = UNLOCK_KEY1;}}
}/*!\brief      unlock the option byte operation\param[in]  none\param[out] none\retval     none
*/
void ob_unlock(void)
{if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){/* write the FMC key */FMC_OBKEY = UNLOCK_KEY0;FMC_OBKEY = UNLOCK_KEY1;}//FMC_CTL0 |= 0x200;FMC_CTL0 |= ~FMC_CTL0_OBWEN;/* wait until OBWEN bit is set by hardware */while(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){}
}/* unlock key */
#define UNLOCK_KEY0                ((uint32_t)0x45670123U)                       /*!< unlock key 0 */
#define UNLOCK_KEY1                ((uint32_t)0xCDEF89ABU)                       /*!< unlock key 1 */

可选项字节块编程

FMC提供了一个32位整字/16位半字编程功能,可用来修改可选字节块内容。可选字节块共有
8对可选字节。每对可选字节的高字节是低字节的补。当低字节被修改时,FMC自动生成该选
项字节的高字节。字节块编程操作过程如下。
 确保FMC_CTL0寄存器不处于锁定状态;
 等待FMC_STAT0寄存器的BUSY位变为0;
 解锁FMC_CTL0寄存器的可选字节操作位;
 等待FMC_CTL0寄存器的OBWEN位置1;
 置位FMC_CTL0寄存器的OBPG位;
 DBUS写一个32位整字/16位半字到目的地址;
 等待编程指令执行完毕,FMC_STAT寄存器的BUSY位清0;
 如果需要,使用DBUS读并验证是否编程成功。
当可选字节块编程成功执行,FMC_STAT0寄存器的ENDF位置位。若FMC_CTL0寄存器的
ENDIE位被置1, FMC将触发一个中断。需要注意的是,执行整字/半字编程操作需要检查目
的地址是否已经被擦除。如果该地址没有被擦除,对该地址写一个非0x0值,FMC_STAT0寄存
器的PGERR位将被置1,对该地址的编程操作无效(当写内容为0x0时,即使目的地址没有被
正常擦除,也可以正确编程)。
当可选字节被改变时,需要系统复位使之生效。

可选字节块说明

每次系统复位后,闪存的可选字节块被重加载到FMC_OBSTAT和FMC_WP寄存器,可选字节
生效。可选字节的补字节具体为可选字节取反。当可选字节被重装载时,如果可选字节的补字
节和可选字节不匹配,FMC_OBSTAT寄存器的OBERR位将被置1,可选字节被强制设置为
0xFF。若可选字节和其补字节同为0xFF,则OBERR位不置位。可选字节详情见下表。

页擦除/编程保护

FMC的页擦除/编程保护功能可以阻止对闪存的意外操作。当FMC对被保护页进行页擦除或编
程操作时,操作本身无效且FMC_STAT寄存器的WPERR位将被置1。如果WPERR位被置1且
FMC_CTL寄存器的ERRIE位也被置1来使能相应的中断,FMC将触发闪存操作出错中断,等待
CPU处理。配置可选字节块的WP [31:0]某位为0可以单独使能某几页的保护功能。如果在可选
字节块执行了擦除操作,所有的闪存页擦除和编程保护功能都将失效。当可选字节的WP被改
变时,需要系统复位使之生效。

安全保护,也称读保护

FMC提供了一个安全保护功能来阻止非法读取闪存。此功能可以很好地保护软件和固件免受非
法的用户操作。

未保护状态:当将SPC字节和它的补字节被设置为0x5AA5,系统复位以后,闪存将处于非安 全保护状态。主存储块和可选字节块可以被所有操作模式访问

已保护状态:当设置SPC字节和它的补字节值为任何除0x5AA5外的值,系统复位以后,安全 保护状态生效。

需要注意的是,若该修改过程中,MCU的调试模块依然和外部JTAG/SWD设备
相连,需要用上电复位代替系统复位以使得修改后的保护状态生效。

在安全保护状态下,主存储闪存块仅能被用户代码访问且前4KB的闪存自动处于页擦除/编程保护状态下。在调试模式下, 或从SRAM中启动时,以及从boot loader区启动时,这些模式下对主存储块的操作都被禁止。

如果在这些模式下读主存储块,将产生总线错误。如果在这些模式下,对主存储块进行编程或
擦除操作,FMC_STAT寄存器的WPERR位将被置1。但这些模式下都可以对可选字节块进行操
作,从而可以通过该方式失能安全保护功能。如果将SPC字节和它的补字节设置为0x5AA5,
安全保护功能将失效,并自动触发一次整片擦除操作。

操作函数:fmc_state_enum ob_security_protection_config(uint8_t ob_spc)

函数原型如下:

/*!\简短配置安全保护\param[in] ob_spc:指定安全保护只能选择一个参数,如下图所示:\arg FMC_NSPC:没有安全保护\arg FMC_USPC:在安全保护下\参数[出]\ FMC的retval状态,参考fmc_state_enum*/// FMC_USPCfmc_state_enum ob_security_protection_config(uint8_t ob_spc)
{fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);if(FMC_READY == fmc_state){FMC_CTL0 |= FMC_CTL0_OBER;FMC_CTL0 |= FMC_CTL0_START;/* wait for the FMC ready */fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);if(FMC_READY == fmc_state){/* reset the OBER bit */FMC_CTL0 &= ~FMC_CTL0_OBER;/* start the option byte program */FMC_CTL0 |= FMC_CTL0_OBPG;OB_SPC = (uint16_t)ob_spc;/* wait for the FMC ready */fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); if(FMC_TOERR != fmc_state){/* reset the OBPG bit */FMC_CTL0 &= ~FMC_CTL0_OBPG;}}else{if(FMC_TOERR != fmc_state){/* reset the OBER bit */FMC_CTL0 &= ~FMC_CTL0_OBER;}}}    /* return the FMC state */return fmc_state;
}
/* read protect configure */
#define FMC_NSPC                   ((uint8_t)0xA5U)                              /*!< no security protection */
#define FMC_USPC                   ((uint8_t)0xBBU)                              /*!< under security protection */

使能读保护:

ob_security_protection_config(FMC_USPC);

失能读保护

ob_security_protection_config(FMC_NSPC);

如果解除了读保护,系统会自动全芯片擦除。

使能读保护

失能读保护之前最好先判断一下系统是否处于读保护状态

ob_spc_get()
//函数原型
FlagStatus ob_spc_get(void)
{FlagStatus spc_state = RESET;if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){spc_state = SET;}else{spc_state = RESET;}return spc_state;
}

操作代码

//解锁保护,并使能读保护fmc_unlock();ob_unlock();ob_security_protection_config(FMC_USPC);//要使能读保护,执行fmc_lock();ob_lock();NVIC_SystemReset();
//解锁保护,并解除读保护fmc_unlock();ob_unlock();ob_security_protection_config(FMC_NSPC);//要取消读保护,执行fmc_lock();ob_lock();

效果

使能读保护后重新使用 ST-LINK Utility读取芯片
此时已经开始报错,无法读取Flash

使用ST-LINK Utility解除读保护

总结

记录于2022/09/27,以便以后方便找

GD32篇 一、GD32程序设置读保护,防止程序被读取相关推荐

  1. stm32 软件怎么设置写保护_STM32F407 读保护,写保护,解锁过程【芯片已设置读保护,无法读取更多信息】...

    硬件准备: CH340 USB转TTL串口一个 STM32F407 板子一块 设置从ISP启动 软件准备: 1,flash_loader_demo_v2.8.0.exe 或者 FlashLoader ...

  2. STM32F407 读保护,写保护,解锁过程【芯片已设置读保护,无法读取更多信息】...

    问题描述: 从ISP方式连接STM32F407开发板,无法读取任何数据,无法下载程序. DTR电平置高(+3-+12V),复位 RTS置高(+3-+12V),选择进入BootLoader ...延时1 ...

  3. android系统应用程序设置时间,Android应用程序设置系统时间的方法

    Android应用程序获取系统时间的方法: System.currentTimeMillis(); Android SDK虽然提供了设置系统时间的方法SystemClock.setCurrentTim ...

  4. linux iscsi 发起程序,设置iSCSI的发起程序(客户端)(三)

    iSCSI 发起程序是一种用于同 iSCSI 目标器认证并访问服务器上共享的LUN的客户端.我们可以在本地挂载的硬盘上部署任何操作系统,只需要安装一个包来与目标器验证. 初始器客户端设置 功能可以处理 ...

  5. android 后台程序 设置 优先级,Android应用程序防止被LMK干掉

    引用 Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运信,系统内部会自动分配,控制程序的内存使用.当系统觉得当前的资源非常有限的时候,为了保 证一些优先级高的程序能运行,就会 ...

  6. STM32 读保护功能和清除读保护功能设置【转】

    1.STM32对内部Flash的保护措施  所有STM32的芯片都提供对Flash的保护,防止对Flash的非法访问 - 写保护和读保护.    1).读保护即大家通常说的"加密" ...

  7. STM32F4xx 读保护 写保护 芯片被锁 解锁

    问题描述: 从ISP方式连接STM32F407开发板,无法读取任何数据,无法下载程序. DTR电平置高(+3-+12V),复位 RTS置高(+3-+12V),选择进入BootLoader ...延时1 ...

  8. 正点原子 高速DAP 下载器解除芯片读保护

    使用正点原子高速DAP解除芯片读保护 用阿波罗F429开发板下载程序提示下面这个错误: 发现下载器是可以正常识别芯片的. 排查后发现很大可能是芯片被读保护了. 下面使用高速DAP下载器来解除这个芯片读 ...

  9. stm32的几种读保护措施讲解

    综合网上讲解的几种读保护措施,这里简单总结下: 采用stm32唯一ID作为加密的字符,使用固定密码,采用16位字节AES加密的方式生成密文,然后写进flash,,app程序执行的时候需要判断读取的st ...

最新文章

  1. [转]为什么程序员总是写糟糕的代码?这3个原因
  2. 计算机上没有找到服务was,win10系统搭建网站提示计算机“.”上没有找到wAs服务的步骤介绍...
  3. 多重应用SD-WAN如何实现业务连续性—Vecloud
  4. 树莓派3B用Ubuntu MATE安装ros
  5. sqlconfigdatasource mysql_MFC odbc 连接MySQL 的 (SQLConfigDataSource动态DSN)
  6. mysql5.6主从参数详解
  7. 你知道“拉黑”、“关注”、“点赞”、“转发”、“分享到朋友圈”等英语咋说吗?
  8. Java Swing/AWT和GTK混合GUI编程
  9. mysql group 最大值_MySQL groupwise最大值为字段的长度
  10. 现代多媒体通信技术【问答、分析、论述】
  11. 编程原则:戒虚而务实,谋定而后动
  12. 反欺诈概念库-物联卡/物联网卡/流量卡
  13. 过河问题(贪心算法)(python)
  14. 三星android5.0 蓝牙,蓝牙5.0手机有哪些 蓝牙5.0和4.2的区别是什么【区别介绍】
  15. 电脑配置ip--host修改ip地址然后刷新操作-win10
  16. linux系统下安装pfam数据库中hmmer软件以及python3非root用户的安装
  17. 浅析计算机信息管理系统任务书,计算机工程系学生就业信息管理系统任务书
  18. 【调剂】北京外国语大学人工智能与人类语言重点实验室2022年全国研招统考拟接收调剂公告...
  19. 利用MOG背景分割器实现物体追踪
  20. 苹果xr如何截屏_iphone敲两下截屏如何操作 苹果手机触控截屏方法【教程步骤】...

热门文章

  1. 谁是initiating loader
  2. Hive 如何设置ReduceTask的数量
  3. 今天遇到一个报错信息
  4. 无图形界面Linux安装chrome实现自动化测试
  5. edxposed显示未安装_Magisk与EdXposed框架安装实践(Android P及以上)
  6. MaxEnt软件的使用
  7. 天涯论坛——python舆情分析汇总(四)
  8. turf:计算面积、折线长度和两点距离
  9. 记一次面试准备(续上)
  10. 单片微型计算机徐春辉,单片微机原理及应用 徐春辉第12章 习题答案