一、前言4 W( z% S" r: d3 K
有客户反馈,在使用 STM32H5 读取温度传感器校准值地址时,会进入 HardFault,而在其他系列芯片中读取这个参数时并没有此现象。在 NUCLEO-H563ZI 开发板上去复现此问题,发现只有开启 ICACHE 后才会复现,初步验证说明进入 HardFault 与 ICACHE 相关,如果直接关闭ICACHE 虽然可以解决进入 HardFault 的问题,但势必会影响代码执行的效率。所以,我们希望能找到一种更好的方式去处理此问题。
5 t" W N( M+ K+ p9 R4 k4 o) n# |) R9 i
二、问题分析1 S, C. J) [& i* i$ e
经 Datasheet 查询,两个温度传感器校准值 TS_CAL1 和 TS_CAL2 的地址分别为 0x08FF F814-0x08FF F815 和 0x08FF F818-0x08FF F819。1 q) o* O/ {# F+ a" Y- b, I
( Q3 I4 z* a; G
. G6 _2 n+ y9 j4 B9 X/ x; ~; V
. H# q6 i7 L) v$ E
根据下表,可以知道 TS_CAL1 和 TS_CAL2 是属于 Read-only 区域的,而 Read-only 区域是通过 AHB system bus 访问的。( E3 ?' J- c. L
4 c6 {$ q* o8 J6 |$ s1 Y0 y5 g: d
, |8 {8 Y3 C7 q6 N5 p/ P
0 c! o' t2 F" |8 l) b( P
3 h+ W" K7 U! R9 |' a* h
根据参考手册的描述,所有的 AHB memory 默认都是 cacheable 的,对于无法实现缓存的区域(OTP、RO、data area),必须使用 MPU 来禁用本地缓存。! @6 X2 s! c3 P5 r; F
9 C M9 v" T( e/ Q: U5 W
9 f" V" L; A) R3 y% l6 c) r& z3 G! ]* E4 S
也就是说,不仅是 TS_CAL1 和 TS_CAL2,其实整个 OTP、RO(Table 39)、data area区域的访问都无法经过 Cache,需要使用 MPU 将其配置为 none-cacheable 属性。
% ~; o9 ~% \5 j; O& U& h$ b7 s, d {% ^. w. n
既然知道了问题所在,那剩下的问题就是确定 OPT、RO、data area 各个区域的地址,data area 是由用户选项字节配置的可进行 100k 次擦除的区域,用于存储用户掉电不丢失的数据,需要根据实际的配置去设置 MPU 区域。剩下的就是 OPT 和 RO 区域,在 STM32H563 中,分别有 2K byte。
( } n0 e$ o* P3 s
* J, k6 b/ l: d+ {
% G) ^6 ^5 \0 Y6 h& P
: ~- \0 l7 k6 \3 \6 N# ~
OTP 的地址为[0x08FF F000-0x08FF F7FF]和 RO 的地址为[0x08FF F800-0x08FF FFFF],两个地址其实是连续的。9 ~- {% ?0 _! W+ {+ W7 n( u1 O
5 J9 L) \0 W" r9 e9 o& [
, b3 F _% W" e* u1 T; R
+ g4 R; E* ~: P3 }+ G
三、解决方法1 p5 b3 y) w" M% h3 r# X# B
经上述分析后,我们只需要把[0x08FF F000-0x08FF FFFF]这段地址区域设置为 none cacheable,通过 CubeMX 进行配置。
& f9 j. v3 \" k `5 f6 ]0 G
" ]* E$ B( o) j, C6 |
0 _7 b8 H. ?1 J+ i9 Z
: x: m! n2 y9 ~6 v2 I- void MPU_Config(void)
" I) S1 N' ]0 { - {& x( d) _5 u9 C/ p5 z1 [
- MPU_Region_InitTypeDef MPU_InitStruct = {0};6 }5 [+ P. ?- t% w2 w7 r( X/ L+ {
- MPU_Attributes_InitTypeDef MPU_AttributesInit = {0};# o% {4 `. P2 }$ L: k& e) ]" N3 b
- ; M) f6 I. C: J7 R% a
- . q5 k$ S9 p5 X4 U5 K
- /* Disables the MPU */
1 Q- B. y1 a+ z2 y+ ~9 q% J- m1 w - HAL_MPU_Disable();
" e8 d" D7 ~ X8 t; C5 ]$ ]( f
5 W2 P" t8 J& \4 s5 v+ J
. l$ W* H$ k. J5 }- /** Initializes and configures the Region and the memory to be protected
4 {. {; @4 ~5 d* Q* q - */
2 B2 g" O" I' S; { ^ - MPU_InitStruct.Enable = MPU_REGION_ENABLE;
: b8 r$ v$ ~7 J - MPU_InitStruct.Number = MPU_REGION_NUMBER0;
- g8 U: V1 \: G" c7 o - MPU_InitStruct.BaseAddress = 0x08FFF000;
/ q- M$ I: x$ |" S, j. _$ k9 p - MPU_InitStruct.LimitAddress = 0x08FFFFFF;
/ i- m1 n D# @" C& a2 j - MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
- O: ]# C5 E$ \! M - MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RO;
. l. }3 I' \' C1 d. o) g" j& Q - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;, D8 C+ O; P2 n5 U' u! t
- MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
4 |) f& U( k. k2 [; `2 \4 j+ T/ Q5 f
7 l% J7 ~5 V- ^5 O6 ~: Q. n( `
3 p" M, K; G# V* R0 \- HAL_MPU_ConfigRegion(&MPU_InitStruct);- e7 x0 \- Q7 ?3 ?- N
- MPU_AttributesInit.Number = MPU_REGION_NUMBER0;
K/ D' a# R' O* Q7 U - MPU_AttributesInit.Attributes = INNER_OUTER (MPU_DEVICE_nGnRnE | MPU_NOT_CACHEABLE
. W1 T5 [/ f: g- v* {- m9 z - | MPU_TRANSIENT | MPU_NO_ALLOCATE);
7 s9 L% q/ |6 d/ k - 2 |8 G6 N8 m) |9 r
0 t; [8 L5 g' r7 S9 m- HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
: F/ o3 n5 |; Z8 U5 c - /* Enables the MPU */
' ~8 r) X* ?3 e - HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
; i6 T9 ]) F" B( v+ s - }
复制代码
- Y$ F: i( r5 `经 MPU 配置 OTP 和 RO 的内存访问属性后,就可以正常去读取温度传感器校准值了,同时属于这两个区域的其他值,如 UID、Flash Size、Package 等信息也能正常读取了。* p/ P9 K0 Z7 m3 |$ ]5 ^5 J
$ C8 }% @7 u7 Y! ~- uint16_t TS_CAL1_Val,TS_CAL2_Val;( E5 k0 U6 u; d& ?+ }
- 0 Z* Q0 _* B7 n- b; i1 E m) ?5 V
- 6 W3 G6 {" P- S& n2 o$ n# u O
- uint16_t *TS_CAL1 = (uint16_t *)0x08fff814;
/ V4 O& b8 }" ? - uint16_t *TS_CAL2 = (uint16_t *)0x08fff818;
# U$ b" w2 e8 G3 i( B' t - TS_CAL1_Val = *TS_CAL1;. n0 R. _& p: _ `
- TS_CAL2_Val = *TS_CAL2;
复制代码
/ s4 l/ r" `# \& n: P8 D9 l四、总结
. h" h3 I4 b! X* A* r3 V% N温度传感器校准值及 UID 等一些信息在 H5 中属于只读区域,而这个区域在 AHB 访问时,默认内存属性为 cacheable,需要通过 MPU 把这些区域设置为 none-cacheable,才能正常访问。每个系列的芯片架构都或多或少有差别,当按以往经验操作不能实现功能时,不妨对照相应芯片的数据手册、参考手册、应用笔记、甚至勘误手册,也许就能发现问题所在。
: j( p6 T. n y0 R, t' i4 B% P# w- a7 v
6 K7 F) u H6 E @9 I Y& e转载自: STM32
9 f7 M0 \& i8 r) H如有侵权请联系删除
. T, b. N8 w6 Q
7 N2 ]% F( {$ a+ }$ d+ a D& J, v3 G5 _3 e0 i
|
一键三连,学习起来