一.前言4 G, ?# c* E; A8 s9 R3 F
Proprietary Code Read Out Protection (PCROP) ----- 专有代码读取保护
8 K9 l# x$ L- D现在产品开发过程中,二次开发将会越来越多,设计公司开发出自己产品后交给终端客户进行二次功能或补充开发,简称二次开发,设计公司某些程序代码不希望公开给终端客户,但同时又希望部分函数功能可以给终端客户使用,这时就需要有一种专有代码保护机制供客户使用,STM32F4xx 芯片中的PCROP 可以解决类似问题。% K- ~$ D0 U1 h, c: S
8 ^* x* X7 E1 F$ b二.PCROP 简要描述
- t$ U U$ Y: ZPCROP 功能在 STM32F42xxx 和 STM32F43xxx 芯片中包含,当使用 PCROP 时,用户扇区(0--23)Flash 能够阻止 D-Bus 的读取指令;保护功能选择通过 FLASH_OPTCR 寄存器的 SPRMOD 选择位进行选择:( l; F! G. k2 o; e
• SPRMOD = 0: nWRPi 用于控制用户扇区写保护7 |3 \+ |1 k8 Y# l/ W& Z3 q
• SPRMOD = 1: nWRPi 用于控制 PCROP 读写保护
+ H9 L; l! e3 S1 h5 `, y, ^% H! f当 PCROP 功能使能时:
9 w+ h( [6 \* m; I9 ? S 任何通过 D-Buss 的读取动作将会有 RDERR 错误标志; _% x8 \" {( B5 r
任何对 PCROP 保护的扇区的擦除/写入操作将会有 WRPERR 错误标志
7 q( _9 N6 {4 h0 sPCROP 保护等级设定如下:) L# O' {6 E: s' e$ y2 d5 e. X
5 N' |) A0 l' `% p0 c3 V' k4 N
0 E) j. c& o" [
1 n9 b# S# e, R+ w$ S9 U% h' N
三. 如何使用 PCROP 功能# M7 R$ s) h% }
1. 需要使用 6.50 以上版本的 EWARM(IAR),使能 C/C++ Complier --> Code--> No data reads in code memory ;
$ h2 ~) d5 s$ j! R- [" e/ |2 l' H3 Y# {0 @3 @; r
1 b, [" R; D- }- t* |) H
+ V3 I2 s @* K# {3 s. U/ H2. 修改 stm32f4xx_flash.icf 文件,定义 PCROP 保护的地址空间;
# l, V# [9 ^# w
! p% Z: e$ e0 D; }/ r* Z
" M. T# c8 l0 i$ j. H. z; k; m3 b( {
本文使用 STM32F429NIH6 芯片的 0x08008000---0x0800BFFF(Sector 2)作为 PCROP 保护区域,stm32f4xx_flash.icf 修改如下:- X M, k. g' h C4 ~( {6 b4 w
- /*###ICF### Section handled by ICF editor, don't touch! ****/
$ ~3 m2 T. b7 l: Z" J2 D9 I - /*-Editor annotation file-*/
" _+ R& l1 C$ @/ Q- [/ E - /* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
3 A6 e& ]: b+ x' W# z - /*-Specials-*/
& K/ [% a3 ]5 E2 D - define symbol __ICFEDIT_intvec_start__ = 0x08000000;
1 S3 C3 M) _' E0 x$ I% U$ d - /*-Memory Regions-*/
4 E6 g! z7 z( A: Z# t - define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;" e U2 \- `" \5 Q1 Z0 A) q. c
- define symbol __ICFEDIT_region_ROM_end__ = 0x08003FFF;
+ j# @# E& r; ]; v5 T - define symbol __ICFEDIT_region_CODE_start__ = 0x08008000;4 B. Q/ I1 }0 y; _/ o
- define symbol __ICFEDIT_region_CODE_end__ = 0x0800BFFF;
0 u3 e' @ O& h4 U- j! X5 C
8 Z, ^- Q N9 O7 z- define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;+ |/ b, u: w2 H* M
- define symbol __ICFEDIT_region_RAM_end__ = 0x2002FFFF;5 c& V# b$ D5 s' }% M
- define symbol __ICFEDIT_region_CCMRAM_start__ = 0x10000000;
* o* l9 W8 U- l2 m2 ^3 I$ h5 A - define symbol __ICFEDIT_region_CCMRAM_end__ = 0x1000FFFF;
9 H1 |% `! y, A" }( J+ A - /*-Sizes-*/8 O$ G6 C( z) m! ?( V
- define symbol __ICFEDIT_size_cstack__ = 0x400;
/ e [$ f# P; w# W - define symbol __ICFEDIT_size_heap__ = 0x200;
- _' a) |6 @' D- X - /**** End of ICF editor section. ###ICF###*/
0 X' A9 w9 ^$ _+ X- t - define memory mem with size = 4G;% R6 V+ ]) ]5 A' ] B! r
- define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to
- Q# G6 D, `* l( [" P - __ICFEDIT_region_ROM_end__];: t: W4 |1 L" e, Q+ K! b7 L9 S
- define region CODE_region = mem:[from __ICFEDIT_region_CODE_start__ to7 z7 }# _1 G1 g
- __ICFEDIT_region_CODE_end__];$ [1 r/ s T5 V, G
- define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to
, [! ?8 N3 T' Q# z, c4 D" H - __ICFEDIT_region_RAM_end__];( N+ f. U2 P2 O5 _' Z2 T# B4 [
- define region CCMRAM_region = mem:[from __ICFEDIT_region_CCMRAM_start__ to- A) T3 ^$ Q( `$ s8 }8 i0 J" P5 ~
- __ICFEDIT_region_CCMRAM_end__];
" j, |! Q$ d5 p/ a& _0 \1 Z9 z+ s - define region TabCode = [from 0x08004000 to 0x08007FFF];
/ M8 V; `. p K+ X. {& m - place in TabCode { ro section .tab, };
; r/ ]/ M. P: a% i. V5 X - define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };$ ?6 p$ A; Q) x, e( d
- define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
& i( S1 l- e7 x* B+ | - initialize by copy { readwrite };
; z5 |$ t4 r% ~ - do not initialize { section .noinit };
. j# k3 G" H) j, _3 A7 o% X* m* Q - place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };- X, g5 K- ~# i7 O; `
- place in CODE_region {section .CODE_Flash};
" a. w* \& W+ ^$ P! U. [ - place in ROM_region { readonly };& ^1 Q: S, v& K3 t! [
- place in RAM_region { readwrite,# g/ F- t( @7 |) q$ R+ k, f" R
- block CSTACK, block HEAP };
复制代码 " S8 t) N+ `2 \) h& h
3. 修改 startup file (.s)文件 Reset_Handler 中 LDR 修改为 BLX:3 e" @" Y, k# C$ h
- Reset_Handler
# a J) a- W6 Q* i% M, Q* l" T, H - LDR R0, =SystemInit
6 P5 N: k5 F) B! v* [1 k* l2 v - BLX R0* h6 A3 T* G) h' ?' K4 d6 |
- LDR R0, =__iar_program_start
: u, D, c! g/ h ^) a - BX R0
1 V z) s5 \! b - 修改为:& l' m$ n- K5 j$ D
- Reset_Handler. U- A; s% d) J6 r# M1 F+ h, U
- BLX SystemInit/ [3 T* Y9 P Q9 X& @
- BLX __iar_program_start+ D1 }7 t. ?3 J/ C1 U6 ]* Y
复制代码
`* Y# D# e8 [6 ], I; ~- \) d4. 定义程序到 PCROP 保护区域中:
' H1 R% T7 `8 ]* @. W$ c 本文实例文件 Sector_Test.c 中定义 Light_Togger()函数定义在 0x08008000-0x0800BFFF 区域:. ~7 }, U% U6 r$ M
- #include "stm32f4xx.h"
9 D% V$ |6 m/ K! r& C) J - #pragma location = ".CODE_Flash"
- i7 n1 ]' r& j$ q- \& |' \; k& A - void Light_Toggle(void)6 ^$ G5 h4 C5 C0 e
- {! C" z1 Z0 \ q* q
- GPIOG->BSRRH = GPIO_Pin_6 | GPIO_Pin_7;
% s/ t' e1 U. U/ G% ~+ P3 Z) }0 [ - }
复制代码 4 R# o& i U; ]! Z+ \4 w( o
5. 使用 STVP 对 OPTION BYTE 进行编程,使能 PCROP,并且选择保护区域:) S4 Y7 v2 w0 ~. ]* U
, G: A/ w1 z) H7 L6 i" d
* r2 @/ B4 j! U! Z& F
: }" _9 J$ {0 J F# e此时可以读取下 0x08008000---0x0800BFFF 区域的数据,可以看到改 PCROP 空间数据不可读,但程序依然可以调用该区域函数---- Light_Togger()8 O0 e$ `: z- ~ D4 U6 f( T
# p, n K. Q: w6 m
: u' I5 d1 K" Q2 c
* J$ l a6 J7 _. h: F+ C0 r. [四.本文所用测试代码说明以及代码# O4 |* f8 ]; h; ~
) k& m2 b! q9 {# T- q WMain 函数作为客户程序代码,而需要调用的函数 Light_Togger()位于 PCROP 保护区域(0x08008000---0x0800BFFF),实现 GPIOG_6/GPIOG_7 端口的 Toggle;
6 h" m! }* {, A* H; aMain.c 文件如下:
x, k* \5 c* G E! x* c+ v1 s- /* Includes ------------------------------------------------------------------*/
8 m: B7 }& g2 ~* h* g - #include "main.h"8 H3 L0 J" E+ e- j
- extern void Light_Toggle(void);# [( z5 r1 g6 `5 ^( A# W
- int main(void)% B: _8 Z4 m& s. x4 q
- {. G& b+ c9 ~1 @* [( c3 _
- unsigned int i;! \3 S* m- }, ?$ z: X w2 d
- GPIO_InitTypeDef GPIO_InitStructure;% I6 v6 s- L( P: o
- /* GPIOG Peripheral clock enable */
% q7 _6 ^. b/ j! N. \# F' x - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
; o: \1 v, d) F) G! _8 h - /* Configure PG6 and PG8 in output pushpull mode */$ p% x2 K) _0 F
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; N5 ^, Y+ A* ~& }0 Z9 r2 a1 c
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
7 w, n' p( K9 f - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;; X3 z4 k h! d" U# Y- S& J
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
0 l6 c% {8 W- R* y( Z+ ` - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
) o$ z; a% q* d& D - GPIO_Init(GPIOG, &GPIO_InitStructure);
( X2 |7 ]5 q8 c% c8 M5 C, f7 {
1 ?# K, V k& J5 y& {5 t& z- while(1)
; M4 T' {5 G* F0 B' E% k7 o - {
* n h: i' T3 q* s; V# R - GPIOG->BSRRL = GPIO_Pin_6 | GPIO_Pin_7;; Y# g$ T& z/ K4 L
- i = 0xFFFFFF;
. J" Q9 `7 w d: E/ m - while(i--);
9 z# L7 C. S" o( \8 g) } - Light_Toggle();8 p5 G/ L. `0 n/ E
- ; b4 o! I/ N# p' n! ?# C, F
- i = 0xFFFFFF;
$ U9 c9 _2 `7 o* P% N9 { - while(i--);
; s3 j* G* j/ P ] - }$ { e6 P# Z% p T u
- }
复制代码 9 k( x" W6 r% h6 a7 J# n) A
Sector_Test.c 如下:
* L: d6 l( g7 d- #include "stm32f4xx.h"
; h) s0 z7 o6 I' n1 `1 E - #pragma location = ".CODE_Flash"
5 L: _" S$ F& j+ I - void Light_Toggle(void)
& R& ?/ Y2 Z+ } - {2 u6 |' C1 t( I/ D
- GPIOG->BSRRH = GPIO_Pin_6 | GPIO_Pin_7;
" C2 M) f8 B3 |4 z, e - }
复制代码 ( p7 o- S: x9 c+ ^( q- i9 A1 v
$ b/ v6 n* g9 D5 C4 Q |