请选择 进入手机版 | 继续访问电脑版

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

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

[复制链接]
STMCU小助手 发布时间:2021-12-28 22:13
根据ST的参考手册描述,h750的片内flash只有128kb,在实际的项目应用中,128kb的容量有点太小了,有时候光光移植好lwip+freertos以后,flash的容量就所剩无几了,所幸可以使用QSPI FLASH来存放程序代码,可以把程序的部分或者整个程序都存放在QSPI FLASH中运行。这里介绍两种不同的方法。$ J! x6 I# O0 |+ W7 Q6 j* V. ?
4 k7 v* W  y% h' @+ S
一、通过分散加载文件的方式% F/ K$ U# W% M% @" R. H; i; {" r

  v! ]/ q& h/ E' \3 m' |1 G    本文中使用的是正点原子北极星板子的例程,跑马灯实验。例程比较简单,主要是看分散加载文件,在最后有一个LR_m_qspiflash加载域,这个就是将代码存放到QSPI FLASH的。分散加载文件的具体细节就不在这边讨论了。
7 k; m9 o) Y, f- J6 {
" z  \# K7 g  F5 |    当然,光光靠配置分散加载文件,是无法把程序下载到板子上的,因为有一部分RO是要下载到片外的flash的,因此这边还需要使用特殊的片外flash算法。在正点的资料有有提供这一算法。通过添加算法的方式,这时应该能够将程序下载到板子上了,但是,这个时候程序不一定能够跑起来,还有一个重要的步骤,那就是初始化QSPI,并设置成内存映射模式。正点的例程中是将初始化操作放在了时钟初始化函数中。至此,程序就能够正常运行了。
$ }2 ]* z$ f- G) t
* J4 e1 }( y4 B; A
  1. #! armcc -E
    , q3 {5 u' }$ n
  2. //  6 B2 H2 ?; z% D7 Q. E
  3. //STM32H750分散加载文件(.scf文件)9 o8 T% I( v7 I* p
  4. //ALIENTEK STM32开发板  ! c$ l( t' Y( M! n+ a
  5. //正点原子@ALIENTEK4 G# f6 }- W6 `2 r2 y# i- U/ s
  6. //技术论坛:<a href="http://www.openedv.com" target="_blank">www.openedv.com</a>. x1 |1 e$ g* ~1 W
  7. //创建日期:2019/4/21$ ]) x5 a- W# D2 w, Z
  8. //版本:V1.0
    3 J# ]) U$ b1 p! M8 z
  9. //版权所有,盗版必究。
    8 T9 o! i! s( ~; o6 ^" Q( [0 ?
  10. //Copyright(C) 广州市星翼电子科技有限公司 2014-2024
    ( k7 V! ]; C( S. W: X' Q# Q" `
  11. //All rights reserved
    1 s. Z( ~6 d6 }2 y& |3 j
  12. //********************************************************************************. s' ]# ~, N( K/ f4 D- p" E0 R
  13. //修改说明
    . ?! G  L2 k2 r: j% `; p
  14. //无
    9 {! s, F. G9 S& V2 x6 h) W4 t
  15. //2 [% T* N" u8 x4 I

  16. & C5 D5 R, r* v  y- O

  17. ; t5 A- a6 q# o$ x
  18. #define m_stmflash_start                                0X08000000                //m_stmflash(STM32内部FLASH)域起始地址
    4 r# ?5 |+ b9 y0 J' T& ^
  19. #define m_stmflash_size                                        0X20000                        //m_stmflash(STM32内部FLASH)大小,H750是128KB
    ; X9 S0 H6 t: }1 G. v0 Z

  20. # T, h4 I- Y& i
  21. #define m_qspiflash_start                                0X90000000                //m_qspiflash(外扩QSPI FLASH)域起始地址
    - U3 Y* x0 q" x& W1 I4 e
  22. #define m_qspiflash_size                                0X800000                //m_qspiflash(外扩QSPI FLASH)大小,W25Q64是8MB) \& }+ ?5 e6 H% \4 I7 L& A
  23. " _$ C( V9 {4 c% r. w
  24. #define m_stmsram_start                                        0X24000000                //m_stmsram(STM32内部RAM)域起始地址,定义在D1,AXI SRAM
    ; Z8 \5 {" T' D6 J
  25. #define m_stmsram_size                                        0X80000                        //m_stmsram(STM32内部RAM)大小,AXI SRAM共512KB
    7 i( E( \* _& }5 B9 A  L3 @' L
  26. ' \- p9 A6 X. c7 R- @

  27. 8 W  D9 z5 V% K9 r. ^# t* w% \

  28. . R& l* E; S! P/ a3 L8 Z7 n
  29. LR_m_stmflash m_stmflash_start m_stmflash_size {                //LR_m_stmflash加载域4 w$ l+ C4 _4 N6 g' D; Y) n5 R( w
  30.   ER_m_stmflash m_stmflash_start m_stmflash_size {                //ER_m_stmfalsh运行域,起始地址为:m_stmflash_start,大小为:m_stmflash_size # r9 n; M5 m. N- R( h& r
  31.     *.o (RESET, +First)                                                                        //优先(+FIRST)将RESET(中断向量表)段放这个域,实际上就是把中断向量表拷贝到m_stmflash_start
    9 `- m* b1 N( N3 x1 J' V* D
  32.                                                                                                                 //RESET是一个段名,表示中断向量表(在.s文件定义);+FIRST表示时第一个要加载的.
    8 k; x+ q- P" W+ A5 O, V; J$ ]) _0 \
  33.         * (InRoot$Sections)                                                                //将所有的库段(C/C++标准库)放在root region.如__main.o,__scatter*.o等+ ~2 J% Y% D# n# a, Q
  34.         * (Veneer$Code) 0 T# l3 b, g& U- o5 u* K* J
  35.         libinit.o
    & K- G6 P" i; n% F
  36.         libinit2.o
    7 b9 O/ _: |' k" {
  37.         libshutdown.o
    7 D9 a, I) @5 n  e# K
  38.         libshutdown2.o% Q  }; U+ K6 _4 e9 o% D
  39.         __rtentry.o8 e) F/ M( A) {
  40.         __rtentry2.o& \. e4 o, f- Q) k  w8 n
  41.         __rtentry4.o
    + x, }5 D/ }- D
  42.         rtexit.o
    % P- x7 c0 ]# o2 K9 q$ k
  43.         rtexit2.o 0 M5 d; U* j6 D0 o# ?. ~4 Y$ ^
  44.         4 [( T! `: Q& g' P( X
  45.         use_no_semi_2.o% x- e- W6 O/ ]$ w4 D
  46.         heapauxi.o9 C6 V. L* r4 F' `: Q: ]7 O
  47.         use_no_semi.o& }& B; X8 ?6 O/ n7 G
  48.         sys_stackheap_outer.o$ A$ f  ?' s$ p- Q: b, ^4 _
  49.         exit.o9 z! `0 B/ Q. ?( w
  50.         libspace.o$ X2 J2 l' D* U" W0 s
  51.         fpinit.o. W" \8 C0 J! a' H
  52.         lludivv7m.o/ ?, {* \# V# L: n
  53.         startup_stm32h750xx.o
    9 F6 h% X" G% J0 G! U4 ^+ c1 r
  54.          . X9 F+ c9 Q5 ~" y  j
  55.         rt_locale_intlibspace.o  1 B; n+ H" m  k7 K; z9 e0 Y- Y
  56.         lc_numeric_c.o 1 v' ?% `  N/ K: X" E( X5 t1 N
  57.         lc_ctype_c.o" x9 B* g9 A2 C. \6 a. ^
  58. : z2 r0 d6 Q/ {( X( l: [, T
  59.         startup_stm32h750xx.o
    ( u. n% K7 W1 x8 L! W' y: M2 J
  60.         system_stm32h7xx.o, ]( v1 O  x: _' \& l/ g
  61.         stm32h7xx_hal.o7 X, P$ P; z! l! ~: Z9 y
  62.         stm32h7xx_hal_cortex.o# S. q+ d& Q" O
  63.         stm32h7xx_hal_rcc.o
    + e* p: O0 `* H  |/ n/ K3 B
  64.         stm32h7xx_hal_gpio.o. v0 H. A# M3 o0 j
  65.         stm32h7xx_hal_msp.o. t: x8 l, ~( X7 l' f
  66.         
    / w3 P5 h7 ]+ H7 [3 \$ w; y" ^
  67.         main.o 6 a+ c( u6 s, C/ b
  68.     sys.o
    ) a* q6 T- D6 k( g* c- s& W. W
  69.         usart.o
    ! P- R, l0 b* D$ J0 Q
  70.         delay.o' F  x* ~6 P' Q& p
  71.   } 2 A% J# Y# z) D0 l0 ?3 F
  72.   RW_m_stmsram m_stmsram_start m_stmsram_size {                        //RW_m_stmsram运行域,起始地址为:m_stmsram_start,大小为:m_stmsram_size.
    2 \" U/ ~' o% z6 |9 b: x8 ^' g7 K3 X1 z- m
  73.    .ANY (+RW +ZI)                                                                                //将所有用到的RAM都放在这个区域
    ! _$ D8 y$ M: m! `; ~
  74.   }; [* \/ r. S1 Z& t9 u' y
  75. }; b( H2 j+ P2 l6 p) K6 r4 Z

  76. 3 M; b6 O/ s1 u) p2 M- v$ ~
  77. LR_m_qspiflash m_qspiflash_start m_qspiflash_size {                //LR_m_qspiflash加载域, D. C' U! Y9 X& M# ?+ w4 E/ N
  78.    ER_m_qspiflash m_qspiflash_start m_qspiflash_size {        //ER_m_qspiflash加载域,起始地址为:m_qspiflash_start,大小为:m_qspiflash_size
    5 S# R7 Y4 m: N9 b+ m& e5 C: G) C
  79.     .ANY (+RO)                                                                                         //将只读数据(+RO)放这个域,任意分配.相当于程序就是存放在这个域的.
    * Q" P! G7 ^' v- ^
  80.   }                                                                                                                        
    # v# @( Z2 Y/ M7 g' d1 B
  81. }
复制代码
5 R- F7 `6 S7 m+ X) T/ _# z. }
以上分散加载文件,由正点原子编写,为了方便大家使用,不用频繁修改.sct 文件,特意2 u7 M9 e2 ~* w2 c
7 s. i' }/ v/ q
将.ANY ROM 区域放在外部 SPI FLASH,这样大家在新增.c 参与编译时,默认就是存放在外部0 |$ ~9 B0 }' I# R1 I8 V

7 |  A* t' j( n% }: O  I/ gSPI FLASH 的,这样使用起来就更方便。
% C$ @- s4 c4 [  O) M& z3 \& c
8 V( Z* q3 [  I. E" a注意:
7 Q" v1 C/ D: l+ Y1 C3 j9 X) {' x  @0 d3 h7 K+ d
1, 如果你新增的代码,对速度有要求,可以将其对应的.o 添加到内部 FLASH,即放在:8 `- `4 R! w- U  ~0 h* J0 P

2 Q5 K( I, Y, k2 P5 X" {ER_m_stmflash 运行域。
6 e4 W( j* W1 G2 m* ~
  `; `1 L& K4 B0 [9 Q1 j2, 如果添加新代码后,程序无法正常运行(通常表现为黑屏/不启动),可以尝试将新增# f  }0 E5 U( ]5 W1 P( F

! j2 `, M4 Q0 Y, I的.o 放到 ER_m_stmflash 运行域后(重新编译)再尝试。如果还不行,可以尝试将所
, k  g; \( t# P" l
: p7 j- v6 X; b& E6 w' y有代码都放到 ER_m_stmflash 运行域后再尝试。( B7 |$ |7 H6 R
7 F$ K6 M' T# q
20200609103620392.jpg
7 J) z" B- N( Q$ L, Z. ^2 U
- ^( E, A$ X: ]7 N4 ~
二、通过boot程序跳转到qspi flash执行用户程序
' {& Y) l7 A9 l& `. F9 E# i& v$ u5 }- }0 ?+ z' }: g) p
    第二种方式就是通过在片内flash中存放boot程序,然后通过boot程序跳转到用户程序,用户程序就放在qspi flash中。
0 t# Y3 q2 ~& x" z
+ s  L/ S0 p' J* R) v2 e/ L  uboot程序主要的工作就是初始化qspi,并设置成内存映射模式;禁用中断,重新配置中断向量表地址,然后进行跳转。这里分散加载文件直接使用系统自动生成的就可以了。程序起始地址0x08000000。
7 z! C2 \% I6 S% L+ i% k: O  S4 [& U3 N$ L
用户程序需要做的操作就是把程序起始地址改成0x90000000,然后添加下载算法,因为整个程序都是存放在qspi flash上的。下载完成后,用户程序就可以通过boot程序跳转执行了。) n0 E3 C0 S  `/ a6 _" p' J

8 ]) D( r- j" U5 i& a/ E
20200609104938687.jpg
/ L0 }& F0 k% W6 l; _* \$ S

& u) W1 Z! h. N0 `: K2 b/ d
20200609104944216.jpg

7 t' f- @# M$ z$ c3 I$ `8 s3 @
& P3 ?+ {9 e5 M注意,不管是第一种还是第二种方法,都是将qspi flash给设置成了内存映射模式,而此模式下qspi flash是只读的,所以这个时候就没办法用来作为存储器来存储数据了。不过网上也有人说内存映射模式下也是可以写数据的,至于真假,还没验证过。
5 T% w9 [3 F; m; i  M4 _6 Q7 `7 W' Q% Q5 V' h9 }
8 t% }3 e) u# c- @6 t1 i
收藏 评论0 发布时间:2021-12-28 22:13

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版