你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32H750 QSPI FLASH使用小结

[复制链接]
STMCU小助手 发布时间:2021-12-28 22:13
根据ST的参考手册描述,h750的片内flash只有128kb,在实际的项目应用中,128kb的容量有点太小了,有时候光光移植好lwip+freertos以后,flash的容量就所剩无几了,所幸可以使用QSPI FLASH来存放程序代码,可以把程序的部分或者整个程序都存放在QSPI FLASH中运行。这里介绍两种不同的方法。
, ~- m  Q: p9 w1 @- V
. b( T, K1 S3 S一、通过分散加载文件的方式
2 S9 [2 R! v4 j9 W) C  {9 n
/ r: Y+ e+ {' u7 K% q% B4 g    本文中使用的是正点原子北极星板子的例程,跑马灯实验。例程比较简单,主要是看分散加载文件,在最后有一个LR_m_qspiflash加载域,这个就是将代码存放到QSPI FLASH的。分散加载文件的具体细节就不在这边讨论了。# N% O7 F. P# M* @) U  ^
5 F3 J$ ~9 R- q( ?
    当然,光光靠配置分散加载文件,是无法把程序下载到板子上的,因为有一部分RO是要下载到片外的flash的,因此这边还需要使用特殊的片外flash算法。在正点的资料有有提供这一算法。通过添加算法的方式,这时应该能够将程序下载到板子上了,但是,这个时候程序不一定能够跑起来,还有一个重要的步骤,那就是初始化QSPI,并设置成内存映射模式。正点的例程中是将初始化操作放在了时钟初始化函数中。至此,程序就能够正常运行了。# M7 E' R/ X/ ]" f' U2 d7 T& y

9 s  f3 z% ?" S* }& w
  1. #! armcc -E ! A8 H1 U7 d' K9 T; L
  2. //  
    4 R9 g. U) C  \
  3. //STM32H750分散加载文件(.scf文件)$ ]6 L9 O0 f% a
  4. //ALIENTEK STM32开发板  % \4 Z' F$ L  G6 Q# P
  5. //正点原子@ALIENTEK0 X% r/ ?) L$ F2 t1 `8 ^
  6. //技术论坛:<a href="http://www.openedv.com" target="_blank">www.openedv.com</a>+ D3 }# [5 K1 D  m7 t
  7. //创建日期:2019/4/21
    - X3 i7 p% i) X1 r5 N! j9 O9 |# Q
  8. //版本:V1.0
    ! D/ M# H3 H$ S  n4 l( Y, |% U6 @
  9. //版权所有,盗版必究。& n4 s, ^# h$ N, j  Y
  10. //Copyright(C) 广州市星翼电子科技有限公司 2014-2024* L0 ?0 L- e9 s2 C7 \! P
  11. //All rights reserved
    : |: A( C( V* [* L
  12. //********************************************************************************3 }5 n7 u3 a3 @0 V$ u/ P; @6 m! ^9 f
  13. //修改说明! l# k  L7 _" D0 U( m
  14. //无
    8 X1 n/ L  e- i+ C6 \& V% l
  15. //
    ( f+ h. B  l9 I2 i' W

  16. 2 q  W/ p1 O4 S  f/ \
  17. # c2 f9 u8 d# O, J& W1 A+ F8 P
  18. #define m_stmflash_start                                0X08000000                //m_stmflash(STM32内部FLASH)域起始地址9 c% u! C, A: E% u4 x
  19. #define m_stmflash_size                                        0X20000                        //m_stmflash(STM32内部FLASH)大小,H750是128KB
    $ ~" D1 ?5 t  ~& t! q
  20. ( N) w4 Y( L6 O: [1 q$ f
  21. #define m_qspiflash_start                                0X90000000                //m_qspiflash(外扩QSPI FLASH)域起始地址
    2 \' e$ W4 b5 E6 c" n3 N# `9 n
  22. #define m_qspiflash_size                                0X800000                //m_qspiflash(外扩QSPI FLASH)大小,W25Q64是8MB
    2 t  b  d0 e3 z# C- e& \
  23. 1 h/ n2 {$ q# b8 D: G6 k9 o& p
  24. #define m_stmsram_start                                        0X24000000                //m_stmsram(STM32内部RAM)域起始地址,定义在D1,AXI SRAM
    ; t- Z9 i* l/ g; O8 O- k
  25. #define m_stmsram_size                                        0X80000                        //m_stmsram(STM32内部RAM)大小,AXI SRAM共512KB
    7 B1 `1 g* X$ \# q6 {, a
  26. * Q$ ~; ]) j2 B! o% O. V' G

  27. , F$ Y! V! e) b) Z

  28. - o0 w( g2 b0 F+ o/ e# P
  29. LR_m_stmflash m_stmflash_start m_stmflash_size {                //LR_m_stmflash加载域
    5 Z- ]6 ^1 G& V/ f5 e3 P% e
  30.   ER_m_stmflash m_stmflash_start m_stmflash_size {                //ER_m_stmfalsh运行域,起始地址为:m_stmflash_start,大小为:m_stmflash_size
    5 F- |3 ]6 _( ~; l/ ]( Q% S
  31.     *.o (RESET, +First)                                                                        //优先(+FIRST)将RESET(中断向量表)段放这个域,实际上就是把中断向量表拷贝到m_stmflash_start
    8 n9 ^7 S3 J, E/ t0 t7 U
  32.                                                                                                                 //RESET是一个段名,表示中断向量表(在.s文件定义);+FIRST表示时第一个要加载的.
    & q3 B3 s! C% U0 F
  33.         * (InRoot$Sections)                                                                //将所有的库段(C/C++标准库)放在root region.如__main.o,__scatter*.o等2 c- V- E  a! s7 Y' A
  34.         * (Veneer$Code)
    2 v# r2 a# d, H+ F3 Y" V$ I" u
  35.         libinit.o
    ! c. L# r, P8 c1 k/ I5 [4 f
  36.         libinit2.o% b" w* [/ I* g2 T7 o
  37.         libshutdown.o: r0 o4 _% g2 h. _
  38.         libshutdown2.o
    6 z/ g) _+ w3 H. c  a3 Y8 t
  39.         __rtentry.o8 E/ {3 ^0 V- A, h
  40.         __rtentry2.o
      [4 _; ^6 @2 P
  41.         __rtentry4.o2 Z' l  y5 G5 }7 t) |
  42.         rtexit.o; a  P' x, o9 ~) W- R' U. C8 Y
  43.         rtexit2.o
    $ s- `% Y" ?: w3 B
  44.         
    2 r8 i6 G+ ^6 z- e- `
  45.         use_no_semi_2.o/ |1 v# Q' J( W- F
  46.         heapauxi.o
    ! c- L, f% `# N: _
  47.         use_no_semi.o
    ) V/ g2 H; i) m, c& H. D
  48.         sys_stackheap_outer.o
    " W$ q* j+ C9 \. q6 _7 P, ]# a
  49.         exit.o
    2 w6 h# h: _2 `8 j
  50.         libspace.o/ F1 E- s0 L) H9 T
  51.         fpinit.o
    - Q# X- g: J" Z) D7 _* u
  52.         lludivv7m.o" G- E  v, P# P7 A0 v3 m
  53.         startup_stm32h750xx.o4 q8 n4 I" ]% V3 F
  54.          , P" L7 _3 x% D6 V
  55.         rt_locale_intlibspace.o  ) M# z( w. i+ }/ G0 y& `- o% t/ C
  56.         lc_numeric_c.o 8 L' y0 |% n: M6 x
  57.         lc_ctype_c.o3 [( {: X2 g$ ~, ^6 B) k+ B2 j
  58. 8 C  _3 L  N( t% q# e5 f
  59.         startup_stm32h750xx.o7 `0 E9 ^# `& j$ K! l2 u# W2 w$ j" i
  60.         system_stm32h7xx.o
    3 n9 d3 u! U- i# j
  61.         stm32h7xx_hal.o* ]2 ~& s  i, ]. e- T
  62.         stm32h7xx_hal_cortex.o2 T" M/ R1 Y/ f6 g: ]
  63.         stm32h7xx_hal_rcc.o
    0 r$ m" ?( l. d; V; L
  64.         stm32h7xx_hal_gpio.o
    % B$ z5 j2 c. S4 m" @& _
  65.         stm32h7xx_hal_msp.o! |4 l4 d9 Y5 o7 q" ~# w+ v
  66.         6 F$ ?) K+ N9 S) K) |/ O
  67.         main.o 9 ^) U) u8 O) w& \2 C3 _' A
  68.     sys.o
    $ ]8 s5 P$ s- I9 x% a* E3 _+ W
  69.         usart.o
    5 P% R4 ?, f7 f  h3 G! V( B- y. q- X
  70.         delay.o9 h9 b! F6 o5 R9 V( v
  71.   }
    4 n; W8 |" F# Y
  72.   RW_m_stmsram m_stmsram_start m_stmsram_size {                        //RW_m_stmsram运行域,起始地址为:m_stmsram_start,大小为:m_stmsram_size.; e/ w6 _& W$ n6 a  r
  73.    .ANY (+RW +ZI)                                                                                //将所有用到的RAM都放在这个区域
    * q4 U  p5 d, V* ~6 M4 T4 |
  74.   }
    % d; [) w" Z9 E" D
  75. }! V, x4 R  l6 x0 t
  76. / w; N5 F1 N7 {3 t" T  k
  77. LR_m_qspiflash m_qspiflash_start m_qspiflash_size {                //LR_m_qspiflash加载域5 H0 t9 d2 m, ?0 m- \5 r) M& g" r) L2 }
  78.    ER_m_qspiflash m_qspiflash_start m_qspiflash_size {        //ER_m_qspiflash加载域,起始地址为:m_qspiflash_start,大小为:m_qspiflash_size ' \( x7 X% l/ h) R# R% D1 t4 V- y
  79.     .ANY (+RO)                                                                                         //将只读数据(+RO)放这个域,任意分配.相当于程序就是存放在这个域的.
    $ R2 T+ ], d2 R' |; K; ~
  80.   }                                                                                                                         4 f+ Y! q3 d6 H. c4 T6 m* w( h2 u
  81. }
复制代码
- v% v  A1 ~6 ~5 B$ }9 w
以上分散加载文件,由正点原子编写,为了方便大家使用,不用频繁修改.sct 文件,特意3 r( H) H" \- y- t9 V+ J
' s0 O2 Y- l# h6 c+ O! F
将.ANY ROM 区域放在外部 SPI FLASH,这样大家在新增.c 参与编译时,默认就是存放在外部- c- |1 d, F- x

* n7 x7 B* V6 y# i5 y( uSPI FLASH 的,这样使用起来就更方便。: R: _: i  F8 a# t+ }  j

% |( e1 g3 e! f# u8 c! T; y注意:5 p% p! }1 m6 j0 y, s. x
9 {7 j' ~/ W! N' }
1, 如果你新增的代码,对速度有要求,可以将其对应的.o 添加到内部 FLASH,即放在:% \/ {+ i& _" q  n& [7 v$ @
3 q+ l0 ?. v: K3 }
ER_m_stmflash 运行域。7 k  B" ~( |. {1 P( A4 F
, x- c( {  q8 w4 N. O& ?1 M4 m
2, 如果添加新代码后,程序无法正常运行(通常表现为黑屏/不启动),可以尝试将新增+ H/ e# ^3 z2 k/ F$ t' x

, d+ H1 O2 Q7 e& l. c5 M$ X的.o 放到 ER_m_stmflash 运行域后(重新编译)再尝试。如果还不行,可以尝试将所0 p- @) y, E$ P& i/ O  i

5 L) s+ e) Y8 g+ f. W/ Q5 l有代码都放到 ER_m_stmflash 运行域后再尝试。
2 t/ S& O, |2 K4 Y+ N) w, ]9 Z4 a
20200609103620392.jpg
1 L9 d5 f. U/ V; L, B% w- F

- r3 w1 }7 O9 a! D  r, \2 ^  b. S* o- i二、通过boot程序跳转到qspi flash执行用户程序8 j3 X% O8 @9 Y+ b3 G: d
: ?  [9 ~5 h) G* H
    第二种方式就是通过在片内flash中存放boot程序,然后通过boot程序跳转到用户程序,用户程序就放在qspi flash中。
; t. o' i* k. p4 `; u+ k
4 o5 y5 V$ r+ R5 ^; \! pboot程序主要的工作就是初始化qspi,并设置成内存映射模式;禁用中断,重新配置中断向量表地址,然后进行跳转。这里分散加载文件直接使用系统自动生成的就可以了。程序起始地址0x08000000。
5 V- \" @) m0 z- N$ H8 J+ K" K8 ^* [+ U9 I, U
用户程序需要做的操作就是把程序起始地址改成0x90000000,然后添加下载算法,因为整个程序都是存放在qspi flash上的。下载完成后,用户程序就可以通过boot程序跳转执行了。
0 H6 R8 i; R7 D1 e5 U# Z7 i9 |$ p$ d$ r/ }
20200609104938687.jpg

* q* A8 Z3 d. B. V' H# X) t
: f2 l0 O: ~; i- [
20200609104944216.jpg
6 N# w" T9 t( R/ ~$ m& l; r5 O

- v* _" ?# ~1 I7 D注意,不管是第一种还是第二种方法,都是将qspi flash给设置成了内存映射模式,而此模式下qspi flash是只读的,所以这个时候就没办法用来作为存储器来存储数据了。不过网上也有人说内存映射模式下也是可以写数据的,至于真假,还没验证过。) u+ B0 ~1 C$ \! D1 @. `- i
1 k" j  A2 s9 _. _6 T

9 P0 t! |* J, Q/ o
收藏 评论0 发布时间:2021-12-28 22:13

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版