STM32的PCROP代码保护功能

本文介绍了STM32微控制器如何利用Read Protection, Write Protection及Proprietary Code Read Out Protection (PCROP)功能来保护知识产权。PCROP允许对Flash的特定区域进行代码读写保护,防止IP代码被直接访问。在Keil和IAR开发环境中,详细阐述了如何配置项目以启用PCROP,并通过STM32F4的案例展示了问题排查和解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

软件供应商们在致力于开发属于自己的知识产权的软件产品,尤其是那些中间件产品的同时,如何保护这些知识产权[IP]实际上也是他们非常关心和重视的问题。基于各类微处理器的嵌入式产品对IP保护的要求也日益明显和迫切。

为了满足对产品IP保护的需求,STM32的各系列MCU都提供芯片读保护写保护。除此之外,目前STM32家族10个产品线中,除了STM32F1等个别早期产品线外,还增加了专有代码读保护功能,即Proprietary Code Read Out Protection (PCROP)。

• Read Protection(RDP): 对整个芯片实施读出保护;
• Write Protection: 防止意外的对存储器的擦、写操作;
• PCROP: 针对指定扇区进行读写保护;

PCROP为Proprietarycode readout protection 的缩写,是一个专有代码读出保护的功能。与RDP 对整片Flash读保护不同的是,它只是针对Flash 的某些特定区域进行代码的读写保护。它可以被用来保护一些IP代码,方便进行二次开发。ST公司的多个STM32产品系列,比如STM32L1、STM32F4、STM32L4、STM32F7、STM32H7等都支持PCROP功能。
受PCROP保护的IP代码可以随意地被用户应用程序调用运行,同时又防止外界对IP代码的直接读写访问。一咋看这句话理解起来可能有点别扭,稍微琢磨下应可反应过来。相信不少软件工程师在开发中有时会用到第三方库代码,有些库代码是编译过的lib库,看不到source code,但你能使用调用它,有点类似。

写保护和PRROP保护都可以针对指定的扇区配置,但是在同一存储器内要么针对扇区实施写保护,要么针对扇区进行PCROP保护。不可以一部分扇区配置写保护,另一部分扇区配置PCROP保护。

 PCROP区的代码也可以调用PCROP区外的处于固定地址的函数。

受PCROP保护的区域是无法使用D-Code 总线进行读访问的,所以在这片区域中只允许执行指令代码(通过I-Code 总线取指令),数据读取是被禁止的。因此,受保护的IP代码不能访问存储于同一块区域内的关联数据,比如文字池(literal pools)、分支表(branch tables)以及在执行过程中需要通过D-code总线进行读取的常量数据。

换言之,受PCROP 保护的代码只能是只执行的指令代码,而不包含任何数据。因此,我们在编译受PCROP保护的IP代码时,必须对其进行相应配置,以避免在PRROP区域生成文字池、常量数据等。
我们知道STM32的中断向量表里都是些常量数据,所以包含中断向量表的扇区不可进行PCROP。一般来讲向量表放在第一个扇区,所以该扇区不可进行PCROP。

不同的编译工具链有其自己的配置方式去阻止编译器生成文字池和分支表。我们来看一下基于MDKKeil中和IAR 开发环境的设置操作。

Keil:使用Execute-only命令
1) 右击项目中的IP代码文件组(比如ST 官方应用笔记AN4701例子中的FIR-Filter),选择“Options for Group‘FIR-Filter’”

在对话框中选择“C/C++”页面,选中“Execute-onlycode”,点“OK”。

2) 另外,还需修改Keilscatter file(.sct文件),设置IP 代码为只可执行代码: 

LR_PCROP 0x08008000 0x00004000 {
    ER_PCROP 0x08008000 0x00004000 { ; load address = execution address
        arm_fir_f32.o (+XO)
        arm_fir_init_f32.o (+XO)
        FIR_Filter.o (+XO)
    }
}

IAR:代码内存中不进行数据读取
对于IAR,必须使用选项“No data reads in code memory”来防止编译器对代码扇区生成任何数据访问。要激活此选项,请右键单击包含IP-Code源文件的文件组“FIR-Filter”,然后选择Options。

然后,在以下窗口中,选择选项“No data reads in code memory”,如图所示。

 IAR ICF文件
要使用IAR将IP-Code放在Sector 2中,请打开ICF文件并添加新的加载区域,如下所示:

define symbol __ICFEDIT_region_PCROP_start__ = 0x08008000;
define symbol __ICFEDIT_region_PCROP_end__ = 0x0800BFFF;
define region PCROP_region = mem:[from __ICFEDIT_region_PCROP_start__ to __ICFEDIT_region_PCROP_end__];
place in PCROP_region { ro object arm_fir_f32.o,
                        ro object arm_fir_init_f32.o,
                        ro object FIR_Filter.o};
最后以一个基于STM32F4的PCROP实际应用案例分享结尾。
某客户使用了STM32F446ZET6,开启PCROP 的功能,对他们的算法代码进行保护。在使用过程中,他发现位于PCROP 区的函数无法被用户程序调用。

经了解,客户使用Keil  MDK 进行项目的开发。检查客户的代码,看是否在项目中的IP代码的Options 中使能了“ExecuteonlyCode”选项,发现并没有将之使能。于是将此选项使能后,并编辑.sct 文件,再编译,运行代码。问题解决。

原因就在于客户未对IP 代码部分进行相应的配置处理,从而导致编译器未在PCROP区域避免生成文字池和分支表等数据。故而在调用PCROP内部的函数时触发了D-code 总线去访问PCROP 区域,导致错误发生。

对于PCROP 功能的详细使用说明,请参考应用笔记AN4701《Proprietary code read-out protectionon microcontrollers of theSTM32F4 series》及其相应的参考代码X-CUBE-PCROP.zip。

文章出处: 茶话MCU

<think>好的,我现在需要帮助用户了解STM32G4微控制器中的PCROP功能的配置和使用方法,特别是与内存保护相关的部分。首先,我得回忆一下PCROP的基本概念。PCROP全称是Proprietary CodeRead-Out Protection,主要用于防止代码被非法读取,保护知识产权。这一点和读保护(RDP)不同,RDP是防止整个Flash被读取,而PCROP可以更细粒度地保护特定扇区。接下来,我需要确定STM32G4系列是否支持PCROP。根据之前的知识,STM32系列中从某些型号开始支持PCROP,比如STM32L4和STM32G4。所以用户提到的STM32G4应该是支持的。需要确认具体的参考手册章节,通常是在Flash存储器的保护部分,比如参考手册的“Flash memoryprotection”章节。然后是配置步骤。PCROP的配置通常涉及选项字节(Option Bytes)的设置。用户需要配置哪些扇区启用PCROP,可能需要使用STM32CubeProgrammer或者通过软件修改选项字节。需要注意的是,修改选项字节需要先解锁,修改后再锁定,同时可能会引发系统复位。另外,内存保护方面,PCROP配置后,受保护的扇区在运行时不能被读取,这可以防止逆向工程,但代码可以正常执行。需要提醒用户注意,启用PCROP后,调试接口(如JTAG/SWD)可能无法访问受保护区域,影响调试。同时,PCROP和RDP的配合使用可能带来不同的安全级别,比如RDP级别1时PCROP生效,级别2时可能永久锁定。 用户可能的问题可能涉及具体代码实现、错误处理、与其他保护机制的交互,以及如何测试PCROP是否生效。比如,如何通过代码配置选项字节,或者如何验证保护是否起作用。需要确保回答中涵盖这些方面,并提供示例代码或步骤。最后,要确保回答符合格式要求:使用中文,数学公式正确,引用文献标注。同时生成相关问题,帮助用户进一步探索。需要检查是否有遗漏的关键点,比如FLASH_CR寄存器的位设置,或者使用HAL库的函数调用方法。</think>### STM32G4 PCROP功能配置与使用详解 PCROP(Proprietary Code Read-Out Protection)是STM32G4系列中用于保护指定Flash扇区代码的机制,允许代码执行但禁止外部读取,防止逆向工程。以下是具体配置方法: #### 一、PCROP基础配置步骤 1. **扇区选择** 通过选项字节`PCROP1ASR`和`PCROP1AER`定义受保护扇区范围。例如: $$ \text{PCROP1ASR} = 0x0800\ 8000,\ \text{PCROP1AER} = 0x0800\ FFFF $$ 表示保护起始地址`0x08008000`到结束地址`0x0800FFFF`的扇区[^1]。 2. **选项字节修改流程** ```c HAL_FLASH_OB_Unlock(); // 解锁选项字节 FLASH_OBProgramInitTypeDef obConfig; obConfig.OptionType = OPTIONBYTE_PCROP; obConfig.PCROPState = OB_PCROP_STATE_ENABLE; obConfig.Sectors = FLASH_SECTOR_2; // 选择扇区2 HAL_FLASHEx_OBProgram(&obConfig); // 写入配置 HAL_FLASH_OB_Lock(); // 重新锁定 HAL_FLASH_OB_Launch(); // 触发系统复位使配置生效 ``` #### 二、关键寄存器说明 - **FLASH_CR**:控制寄存器,需设置`SPRD`位启用扇区保护 - **FLASH_SECCR**:安全寄存器,配置信任域与非信任域边界(结合TrustZone使用) #### 三、内存保护关联特性 1. **与RDP协同** - RDP级别1时,PCROP生效且可逆 - RDP级别2永久锁定PCROP配置,无法修改[^1] 2. **调试接口限制** 启用PCROP后,调试器无法直接读取受保护区域的Flash内容,需通过`OB_BOOT_ADD0`配置安全启动地址。 #### 四、典型问题排查 - **误触发HardFault**:检查PCROP区域是否覆盖了中断向量表 - **配置未生效**:确认是否执行`HAL_FLASH_OB_Launch()`复位 - **边界对齐**:确保保护区域地址按4KB扇区对齐 ```c // 安全读取PCROP区域的示例(仅允许CPU执行) __attribute__((section(".pcrop"))) void SecureFunction(void) { // 受保护代码 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值