再问stellaris的FLASH保护



实际编程中,遇到一个问题:

stellaris芯片提供了FLASH保护的一个级别--只执行保护,但是如果某一个放置程序的扇区被设置了只执行保护,那么放置在该扇区的程序是不可能跑得起来的,因为很多变量也是放在这个扇区的,程序运行的时候会用到这些变量,那如果这些变量无法被读出,程序当然就跑不起来了。

那问题就来了,这个只执行保护到底有什么意义呢?我的理解是让某个扇区只能运行而不能被读取,难道只执行保护不是这个意思吗?还是用法不对?

  • 1.

    下面是文档原文对只执行保护的解释:

    Execute-only protection. The block may only be executed and may not be written or erased.

    This mode is used to protect code.

    意思是是说,只执行模式下,不允许写入或擦除,用来保护代码,数据是可以读取的。这样是只执行保护。

     

     

    2.

    当然也有另一种模式,这种才是楼主说的只执行、写入、擦除,但不能读取的模式。这种模式确实没有什么用,只是寄存器可以配置成这种状态:

    The block may be written, erased or executed, but not read. This combination is unlikely to be used.

  • Dear  Richard:

    不知道你是否做过相关实验,我写了以下代码:

    void main()

    {

    long i;

    fnTargetInit();   //system init

    FlashProtectSet(2048, FlashExecuteOnly);

    for(;;)

    {

    i+=1;

    }

    }

    进行仿真时,执行到FlashProtectSet之后芯片就进入FaultISR了,这个问题我还是不得其解。

  • 试了一天,我真的搞不懂datasheet的这个“只执行保护”是什么意思。

    我开始看IAR的编译结果,发现确实有的全局变量放到了CODE区(并且是被设置了只执行保护的),然后我就只开了顶端2KB的扇区来设置“只执行保护”,这2KB里面没有放任何东西,然后把3个函数用绝对地址的方式放在这2KB扇区内,然后用函数指针的方法来调用这3个函数,这个就是我理解的“只执行”,然而,还是不行,一调用这几个函数就进入硬件中断。唉~~

  • hi leo,

      我测试了一下你的代码,程序没有问题,没有进入FaultISR, 建议你在测试这个程序时,先使用JTAG对MCU进行解锁,这样做的目的是使MCU的FLASH恢复到出厂设置,即MCU的所有FLASH处于可编程,可写,可读状态。关于只执行保护,个人理解是有用的一项保护措施,表示该区域的程序只能被执行,不能被读取写入。

    打个比方,我们做一个字库将它放在该区域,然后通过查表法读取字库点阵,最终用来显示。如果存放字库区设置成了只执行保护,那么我们的程序将无法正确执行,一旦查表时将会产生Fault.

     

  • Dear JSW,

    以上代码在IAR下编译仿真,确实是会进入FAULTISR,而且,对于只执行,我修改了一些const常量(之前编译结果显示是定义在CODE区的),然后再编译仿真,FlashProtectSet之后,还是会进入FAULTISR。

  • 建议楼主设置FLASH前看看FMPRE和FMPPE,在复位后,FMPRE和FMPPE应该都是0xffffffff; 我拿你的代码是在keil环境下测试的,可以参考仿真结果。

  • 楼主查查自己器件上FMPRE和FMPPE两个寄存器的值,看看配置是否正确~

     

    另外,给楼主附了一个附件,楼主查查看进Fault前在哪里执行代码的,也许看到那个地址就会有些想法了。

    ARM_CORTEX_FAULT_DEBUG.rar
  • 非常非常感谢richard的分享,一直想找这个东西。

    我查看了FMPRE和FMPPE两个寄存器的值,无论死之前还是死之后,都是正确的。

    继续写代码:

    void main()

    {

    long i;

    fnTargetInit();

    HWREG(FLASH_FMPPE) = 0xfffffffd;

    HWREG(FLASH_FMPRE) = 0xfffffffd;

    HWREG(0x2202000c) = 1;    \\\   A

    for(;;)

    {

    i +=1;

    }

    }

    (IAR环境)程序在A处死掉了,我纳闷:我操作的是SRAM啊,我保护的是flash啊,怎么就死掉了呢?

    然后这样(调换了写FLASH_FMPRE和FLASH_FMPPE的位置):

    void main()

    {

    long i;

    fnTargetInit();

    HWREG(FLASH_FMPRE) = 0xfffffffd;

    HWREG(FLASH_FMPPE) = 0xfffffffd;  \\\   B

    HWREG(0x2202000c) = 1;    

    for(;;)

    {

    i +=1;

    }

    }

    程序在B处死掉,完全无解。。。。。

  • hi leo,

      HWREG(0x2202000C)应该已经超过SRAM的最大值了。

  • hi JSW-Token:

    HWREG(0x2202000C)应该是操作位带区,就算不这样操作,上面的例程改成HWREG(0x22001000),这样也会死,anyway,如果上面的代码屏蔽掉对FLASH进行保护的代码后,是一切正常的。

  •  我试了一下位带区,现附上例子,是MDK2.23工程。

    flashprotect.rar
  • hi jsw:

    因为我一直用的是IAR,KEIL不是很熟。

    我调试了你的工程,我发现执行完了FlashProtectSet(2048, FlashExecuteOnly);就不行了啊.....

  • 晕,看看你工程当前的 FLASH_FMPPE和FLASH_FMPRE是多少?我这边都是0xfffffffd,也就是说2048以后2k为只执行属性。由于在使用Flash保护后,MCU会保持上次设置的保护属性。如果要恢复其默认属性,可读,可写,可执行,则需要解锁。

  • 回JSW:

    FLASH_FMPPE和FLASH_FMPRE都是正确的,我觉得问题出在编译器身上,同样的代码,只要编译器把函数编译到了设置了FLASH保护的区域,就会出错,我看了一下你的代码,编译出来是没有任何东西放在2048(0x800)之后的区域的。如果把上面的代码改成(保护0区)

    HWREG(FLASH_FMPRE) = 0xfffffffe;

    HWREG(FLASH_FMPPE) = 0xfffffffe;

    就出错了。

  • 我写了代码测试了一下,好像(只是好像)一旦main的地址被编译器编到了设置了FLASH保护的区域,上面是0X800之后,就会出错。我查看编译后的.map文件,因为更改代码后变动的东西太多了,我也不确定是不是main的原因。

  • 确实,只要我把main函数的地址用绝对地址的方式定义到Flash保护区之外,所有的问题都解决了,不明白~~~~

    求解答~~~