打印

stm32f103rc设置读保护后不能正常运行???

[复制链接]
7702|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 huhuhu_1 于 2010-1-22 10:46 编辑

MCU型号:STM32F103RC。
问题:设置读保护后程序不能正常运行。
操作:
1、一个能够正常运行的程序,没有对前4KB代码空间进行写入操作。使用j-link进行secure操作后不能正常运行。之后进行unsecure,重新装载代码,不进行secure操作,运行正常。
2、在代码中加入读保护指令(先解锁,再修改RDP由0xA5到0x11,重启),运行不正常。取消读出保护指令,unsecure芯片,重新烧入代码,运行正常。

清香主指导一下,可能是什么原因?
这个问题我已经搞了一整天了。。。。。
沙发
香水城| | 2010-1-22 10:59 | 只看该作者
怀疑你在操作读保护的选项字节时,写入了其他的选项字节。你可以读出所有的选项字节,对照手册看看是否有不应该设置的部分。

使用特权

评论回复
板凳
午夜霓虹| | 2010-1-22 11:43 | 只看该作者
呵呵  他已经置了读保护,怎么读出数据呢。

使用特权

评论回复
地板
香水城| | 2010-1-22 15:21 | 只看该作者
读保护只限制通过程序之外的手段读出Flash的内容,并不限制从程序中读出。

只要写一个小程序,只包含较少的内容,测试一下就知道了。

使用特权

评论回复
5
huhuhu_1|  楼主 | 2010-1-25 10:42 | 只看该作者
本帖最后由 huhuhu_1 于 2010-1-25 10:56 编辑

香主的主意不错,问题有些进展,情况如下:
在没有读保护时,读出的option bytes是正确的(RDP是0xA5,Data0被我使用,是0x1E,其它是0xff)。使用j-link加上读保护后,读出的option bytes,RDP是0xff,Data0也成了0xff。分析可能是j-link把整个option bytes都擦除了。
于是我在程序中加入Data0检测功能,如果发现其不是0x1e,则修改成0x1e,并在修改前后都打印出option bytes的内容。之后测试中发现在没有读保护时,Data0可以从0xff修改成0x1E,有读保护时,Data0总是0xff。
我的程序中使用到这个Data0,它引导程序加载,看来读保护后程序不能运行就是因为Data0不正常造成的。
请香主看看我的分析是否正确,如果是,那该如何在写保护后还能修改Data0、Data1???
下面是相关的代码:
int main()
{
    。。。

    OB_TypeDef obTmp;
    obTmp = *OB;  //读出选项字节,保存在临时缓冲区
   
    if(((u8)(OB->Data0) != 0x1e) && ((u8)(OB->Data0) != 0x2d)) { //(u8*)0x1ffff804
      printf("last\r\n");
      printf("OB->RDP=0x%x\r\n", OB->RDP);
      printf("OB->USER=0x%x\r\n", OB->USER);
      printf("OB->Data0=0x%x\r\n", OB->Data0);
      printf("OB->Data1=0x%x\r\n", OB->Data1);
      printf("OB->WRP0=0x%x\r\n", OB->WRP0);
      printf("OB->WRP1=0x%x\r\n", OB->WRP1);
      printf("OB->WRP2=0x%x\r\n", OB->WRP2);
      printf("OB->WRP3=0x%x\r\n", OB->WRP3);
      delay1ms(200);
      
      //FLASH_Unlock();
      FLASH_EraseOptionBytes();
      FLASH_ProgramOptionByteData((u32)(&(OB->Data0)), 0x1e);  //0x1ffff804
      //恢复其它的option bytes
      FLASH_ProgramOptionByteData((u32)(&(OB->RDP)), obTmp.RDP);  //0x1ffff800
      FLASH_ProgramOptionByteData((u32)(&(OB->USER)), obTmp.USER);  //0x1ffff802
      FLASH_ProgramOptionByteData((u32)(&(OB->Data1)), obTmp.Data1);  //0x1ffff806
      FLASH_ProgramOptionByteData((u32)(&(OB->WRP0)), obTmp.WRP0);  //0x1ffff808
      FLASH_ProgramOptionByteData((u32)(&(OB->WRP1)), obTmp.WRP1);  //0x1ffff80a
      FLASH_ProgramOptionByteData((u32)(&(OB->WRP2)), obTmp.WRP2);  //0x1ffff80c
      FLASH_ProgramOptionByteData((u32)(&(OB->WRP3)), obTmp.WRP3);  //0x1ffff80e
      
      //FLASH_WaitForLastOperation(0xfff);
      //FLASH_Lock();
      printf("last2\r\n");
      printf("OB->RDP=0x%x\r\n", OB->RDP);
      printf("OB->USER=0x%x\r\n", OB->USER);
      printf("OB->Data0=0x%x\r\n", OB->Data0);
      printf("OB->Data1=0x%x\r\n", OB->Data1);
      printf("OB->WRP0=0x%x\r\n", OB->WRP0);
      printf("OB->WRP1=0x%x\r\n", OB->WRP1);
      printf("OB->WRP2=0x%x\r\n", OB->WRP2);
      printf("OB->WRP3=0x%x\r\n", OB->WRP3);
      delay1ms(200);
      NVIC_GenerateSystemReset();
    }

    printf("next\r\n");
    printf("OB->RDP=0x%x\r\n", OB->RDP);
    printf("OB->USER=0x%x\r\n", OB->USER);
    printf("OB->Data0=0x%x\r\n", OB->Data0);
    printf("OB->Data1=0x%x\r\n", OB->Data1);
    printf("OB->WRP0=0x%x\r\n", OB->WRP0);
    printf("OB->WRP1=0x%x\r\n", OB->WRP1);
    printf("OB->WRP2=0x%x\r\n", OB->WRP2);
    printf("OB->WRP3=0x%x\r\n", OB->WRP3);
    delay1ms(200);
    。。。。。。。
}

使用特权

评论回复
6
香水城| | 2010-1-25 10:49 | 只看该作者
本帖最后由 香水城 于 2010-1-27 13:52 编辑

应该在没有设置保护的情况下,写入Option bytes。

基本过程是:
1)解除保护
2)掉电
3)上电
4)擦除Option bytes
5)设置保护,同时设置Option bytes
6)掉电
7)上电

上述的2)、3)和6)、7)的掉电和上电过程是非常必要的。


上述过程可以实现需要的操作,但是有更简单的操作方式,请看13楼的说明。对由此引起的误会和造成的麻烦,表示道歉。

使用特权

评论回复
7
yybj| | 2010-1-25 16:02 | 只看该作者
为什么要这样反复的掉电上电呢

使用特权

评论回复
8
香水城| | 2010-1-25 16:09 | 只看该作者
为什么要这样反复的掉电上电呢
yybj 发表于 2010-1-25 16:02


因为Option bytes的内容只有在上电时才被读到内部的寄存器,而真正起作用的是内部寄存器的内容。如果修改了Option bytes的配置,在没有重新上电之前,新的配置内容不会被刷新到内部寄存器中,因此它不能起作用。

使用特权

评论回复
9
huhuhu_1|  楼主 | 2010-1-26 12:42 | 只看该作者
应该在没有设置保护的情况下,写入Option bytes。
香水城 发表于 2010-1-25 10:49

香主,你说的这种约束条件在ST的datasheet中找不到相关的支持,datasheet是否要及时更新一下。我一向都是先仔细研究文档,然后再动手写代码,资料要不完整,那就太折腾人了,你说是不?
如果是这样,那这边Data0 Data1的作用就打折扣了,我的程序就不能使用这两个变量了。只能在Flash中令开一个区间来代替。
最后,谢谢香主!

使用特权

评论回复
10
香水城| | 2010-1-26 13:55 | 只看该作者
“应该在没有设置保护的情况下,写入Option bytes。”

因为我没有动手做过,这一点我不敢十分肯定,我需要测试一下再说。

另外,我看到5楼给出的程序中,为什么你把FLASH_Unlock()那行注释掉了,是否会因为这个原因造成不能写入呢?

使用特权

评论回复
11
huhuhu_1|  楼主 | 2010-1-27 09:19 | 只看该作者
哦,是这样。
注释掉Flash_Unlock()是因为测试中发现它没有任何作用,并且在坛子里也看到相关的描述。ST的资料上说是要先解锁以启动FPEC,并且上电复位之后是自动加锁的(从写main Flash的操作能够看出来,如果没有解锁操作,main Flash是写不进任何数据的),看来写main flash和写option bytes不同的,这里应该是是资料说错了。
另外我觉得这里的解锁操作应该和读保护没有关系的。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
李晓倩 + 1 www.jinjidejuren.tv/heizidelanqiu/
12
香水城| | 2010-1-27 10:13 | 只看该作者
哦,是这样。
注释掉Flash_Unlock()是因为测试中发现它没有任何作用,并且在坛子里也看到相关的描述。ST的资料上说是要先解锁以启动FPEC,并且上电复位之后是自动加锁的(从写main Flash的操作能够看出来,如果没有 ...
huhuhu_1 发表于 2010-1-27 09:19


我不这么认为,写Option bytes之前也是要进行解锁操作的。

在《STM32F10xxx闪存编程手册》(PM0042)中的第2.4.3节说明了这一点:

2.4.3 选项字节块写保护
默认状态下,选项字节块始终是可以读且被写保护。要想对选项字节块进行写操作(编程/擦除)首先要在OPTKEYR中写入正确的键序列(与上锁时一样),随后允许对选项字节块的写操作,FLASH_CR寄存器的OPTWRE位标示允许写,清除这位将禁止写操作。

你把FLASH_Unlock()那行恢复了再试试看?

STM32_Option_Byte_Protection.gif (10.27 KB )

STM32_Option_Byte_Protection.gif

使用特权

评论回复
13
香水城| | 2010-1-27 13:50 | 只看该作者
因为之前没有进行实际测试,仅凭楼主的描述,误以为写Option bytes也需要解除Flash的写保护。

今天我们按照楼主的需求进行了测试,证实手册中的描述是准确地,只要在写Option bytes之前,按照12楼的描述解开对Option byte block的写保护,就可以写入Option bytes中的Data0,这个操作与整个Flash区的写保护是否存在无关。

估计楼主的问题有2种可能,1)写Option byte之前没有解除Option byte block的写保护;2)写入Data0之前,Data0的内容不是0xFFFF。请再检查一下。

使用特权

评论回复
14
huhuhu_1|  楼主 | 2010-1-28 18:03 | 只看该作者
下面是我在5楼的代码节选:
     FLASH_EraseOptionBytes();
      FLASH_ProgramOptionByteData((u32)(&(OB->Data0)), 0x1e);  //0x1ffff804
      //恢复其它的option bytes
      FLASH_ProgramOptionByteData((u32)(&(OB->RDP)), obTmp.RDP);  //0x1ffff800
。。。 。。。
huhuhu_1 发表于 2010-1-25 10:42

请看代码,我是先擦除,再写Data,再恢复其它的内容。在函数FLASH_EraseOptionBytes()和FLASH_ProgramOptionByteData()的内部都是有Option bytes区解锁的操作,(这是ST的库函数)。所以我不认为存在没有解锁和Data0不是0xffff的情况。
另外,我还有一点奇怪的,修改Option bytes之后,软件复位竟然不管用,一定要掉电、上电才会正常运行???这样就给使用带来很大的不便,远程断电有时候不容易做到。

使用特权

评论回复
15
香水城| | 2010-1-28 18:27 | 只看该作者
“我还有一点奇怪的,修改Option bytes之后,软件复位竟然不管用,一定要掉电、上电才会正常运行”

这并不奇怪,在STM32F10xxx编程手册中写得很清楚:如果在设置了读保护时,调试器仍然连接到JTAG/SWD接口,需要执行一次上电复位,而不是(没有调试器时的)系统复位。

而在STM32参考手册中也说明了:软件复位属于一种系统复位。

STM32_RDP.GIF (19.8 KB )

STM32_RDP.GIF

STM32_System_Reset.GIF (29.56 KB )

STM32_System_Reset.GIF

使用特权

评论回复
16
huhuhu_1|  楼主 | 2010-1-29 11:30 | 只看该作者
嗯,知道了。我当时看datasheet时可能没有注意到这个Note。
谢谢啦。
我现在已经改用Flash中的一个页来代替Option bytes 中的Data0,反正Flash也有富余,1个page无所谓的。读保护测试也没问题,对我这个项目,这样就OK了。
由于时间的原因,关于在读保护之后,Option bytes中的Data0修改的问题,以后有需要再来研究。
再次感谢香主!

使用特权

评论回复
17
无冕之王| | 2010-1-29 15:01 | 只看该作者
讨论过程,也是大家学习的过程,很不错

使用特权

评论回复
18
s284630173| | 2015-7-13 16:51 | 只看该作者
香水城 发表于 2010-1-22 15:21
读保护只限制通过程序之外的手段读出Flash的内容,并不限制从程序中读出。

只要写一个小程序,只包含较少 ...

你好,能帮忙看一下https://bbs.21ic.com/forum.php?mo ... ghlight=STM32L152CC这个帖子么?这是stm32L152CC系列的,我也遇到了同样的问题,能帮帮忙吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

23

主题

62

帖子

0

粉丝