新闻  |   论坛  |   博客  |   在线研讨会
GD32F4x 如何开启读保护功能(芯片加密)?
鱼鹰谈单片机 | 2021-11-21 17:21:39    阅读:1167   发布文章

来源:公众号【鱼鹰谈单片机】

作者:鱼鹰Osprey

ID   :emOsprey

在芯片加密时,时常会用到读保护功能,这个功能可以保证你的代码不被 J-link,ST-link 之类的调试器读取,STM32 系列相关资料网上有很多,但是 GD32 的资料目前来说还是比较少。

GD32F103 、GD32F303 与 STM32F103 基本上兼容的,甚至可以直接使用ST 的库操作,所以替换起来还是相当方便的。

但是 F4 系列的差别还是很大的,官方的例子也不是很多,网上的资料也不是很全,所以不得不啃文档了。

本来鱼鹰准备直接搜 STM32F4x 关于读保护的,看看能不能从 ST 的代码中找到相关的函数,从而替换成 GD 的库操作,但最终没有找到,还好从参考手册中找到了。

说实话,GD 的库操作有两点非常不满意:

直接操作地址,而不是像 ST 一样通过结构体指针间接操作,给调试带来不便。

没有参数检查功能,这样导致任何参数都能进入函数,从而造成不可预知的破坏。

牢骚归牢骚,在目前缺芯的大环境下,也只能用国产替代了,谁叫它便宜呢,再怎么说也不能和钱过不去是吧。

所以今天鱼鹰就来谈谈如何启用芯片的读保护功能,这应该是所有产品上市前都会添加的一个功能。

首先看看 GD32F1的或者说 STM32F1的:

开启读保护:

if(FLASH_GetReadOutProtectionStatus() != SET)
{
  FLASH_Unlock();
  FLASH_ReadOutProtection(ENABLE);
  FLASH_Lock();
}

关闭:

if(FLASH_GetReadOutProtectionStatus() != RESET)
{
  FLASH_Unlock();
  FLASH_ReadOutProtection(DISABLE);
  FLASH_Lock();
}

事实上,读保护一旦开启,如果解除读保护,同时也会由硬件自动清除掉代码,所以如果你通过调试器取消读保护时,会自动清除代码,防止被它人读取数据。

而一旦开启了读保护,你是无法通过调试器读取 FLASH 的,你读取的数据全是 0xff ,同时也无法通过调试器在线调试,所以,正在开发的产品一般不会加入这个功能,只有量产时才会加入,否则出现问题难定位。

如果需要重新下载,可以使用 KEIL 软件的这个擦除按钮:

1.jpg

擦除之后就可以继续下载了(最好调试器里有复位引脚控制芯片复位)。

当然,你也可以先用工具解除读保护,如何解除自行上网搜索即可。

另外,还有一种方式是使用 KEIL  RAM 运行的方式,直接在芯片 RAM 中执行相关代码解除读保护,这样就不需要其它工具了,有时间鱼鹰会具体介绍如何操作,记得关注鱼鹰。

然后再看 GD32F4x的操作,这个操作鱼鹰在网上找了一圈,没有发现,觉得有必要写一写,方便大家:

if(ob_spc_get() != SET)
{
  ob_unlock();
  ob_security_protection_config(FMC_LSPC);
  ob_start();  // 特别注意这条语句
  ob_lock();
}

可以看到其实也是很简单的操作类似库函数即可,有几点需要注意:

ob_security_protection_config 函数有参数,目前的参数表示低级别的保护,还有更高级别的保护,但是那种保护是永久性的,无法解除,也就是说你无法通过调试器下载代码了,只能通过你编写的程序里面自带更新的代码更新,否则就变成砖头了(芯片可以用,但无法调试与更新程序)。一般来说低级别保护足够了。

必须调用 ob_start 函数启动改写,否则无法真正写入到寄存器(上电会恢复)。ST 好像没有这个。

ob_start 函数里面有死循环,所以不建议大家直接使用该库函数,而是自己按它的实现方法重新写一个,这样出现问题,可以快速定位(毕竟很少人有勇气怀疑库函数有问题而去查看库函数实现),最起码在死循环前加一条打印信息吧。

另外,产品一般会禁用 SW 引脚的调试功能,F1 和 F4 的方式不一样:

F1 的由专门语句负责:

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,DISABLE);

而F4 就是把 PA13、P14 重新配置即可(即不使用默认功能,可设置为下拉输入):

rcu_periph_clock_enable(RCU_GPIOA);
gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN,  GPIO_PIN_13 | GPIO_PIN_14);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13 | GPIO_PIN_14);

ST 也是操作类似的库函数实现。

本周的分享到此结束,有帮助的话,欢迎转发支持鱼鹰。

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客