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

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

[复制链接]
STMCU小助手 发布时间:2021-12-28 22:13
根据ST的参考手册描述,h750的片内flash只有128kb,在实际的项目应用中,128kb的容量有点太小了,有时候光光移植好lwip+freertos以后,flash的容量就所剩无几了,所幸可以使用QSPI FLASH来存放程序代码,可以把程序的部分或者整个程序都存放在QSPI FLASH中运行。这里介绍两种不同的方法。
; i; L2 }# X( N' M$ D
  o4 U6 m% ~7 p7 B2 I一、通过分散加载文件的方式
3 ^* V$ @) Q6 Z  v
: H+ ]+ k9 |+ Z' M2 l( z6 c    本文中使用的是正点原子北极星板子的例程,跑马灯实验。例程比较简单,主要是看分散加载文件,在最后有一个LR_m_qspiflash加载域,这个就是将代码存放到QSPI FLASH的。分散加载文件的具体细节就不在这边讨论了。
7 R! C1 ~8 Z" @3 G2 D$ H# D$ ], ]# h
    当然,光光靠配置分散加载文件,是无法把程序下载到板子上的,因为有一部分RO是要下载到片外的flash的,因此这边还需要使用特殊的片外flash算法。在正点的资料有有提供这一算法。通过添加算法的方式,这时应该能够将程序下载到板子上了,但是,这个时候程序不一定能够跑起来,还有一个重要的步骤,那就是初始化QSPI,并设置成内存映射模式。正点的例程中是将初始化操作放在了时钟初始化函数中。至此,程序就能够正常运行了。0 u: j. z8 s% k) `3 B

: H1 b: x* O+ i8 T3 U
  1. #! armcc -E $ E- P5 e& q6 J' O2 o7 X# m
  2. //  ' x; {0 C* _( N; d
  3. //STM32H750分散加载文件(.scf文件): N1 s) ^1 ]) Q0 r: q# }% f
  4. //ALIENTEK STM32开发板  , p6 E; q+ i5 F6 ]
  5. //正点原子@ALIENTEK
      @0 o3 Q4 `& V( E2 ?* Z; K
  6. //技术论坛:<a href="http://www.openedv.com" target="_blank">www.openedv.com</a>0 W! Q! p8 }6 f* y' y6 \+ O! ?+ j
  7. //创建日期:2019/4/21
    6 F( L- z! D5 P  D+ g7 V" `1 f, F
  8. //版本:V1.0' F' E, v+ T- a& A/ v+ q
  9. //版权所有,盗版必究。
    , r/ e7 \' `' M8 U3 H5 e
  10. //Copyright(C) 广州市星翼电子科技有限公司 2014-2024
    $ G  a+ O) Z2 W: ^& S* L
  11. //All rights reserved
    3 w3 f$ l, J2 U# L" _% D' |
  12. //********************************************************************************
    0 |* d3 j3 B4 A2 T5 @6 c
  13. //修改说明9 {; U4 k* ^& L- V2 c) N  a  b; N  s& P
  14. //无, T+ Z" `' Q8 q+ y4 |
  15. //& s8 ~% t5 f" G/ X  T4 ^: R
  16. 1 l$ R9 F1 G# H7 Z

  17. ' U4 |; j8 i! ?7 K; Q
  18. #define m_stmflash_start                                0X08000000                //m_stmflash(STM32内部FLASH)域起始地址
    4 `, T, F% h7 g0 s: E
  19. #define m_stmflash_size                                        0X20000                        //m_stmflash(STM32内部FLASH)大小,H750是128KB/ C! M2 S7 v% A

  20. ( s9 ]( m) P7 o- ?- F8 e' q$ w( w1 p
  21. #define m_qspiflash_start                                0X90000000                //m_qspiflash(外扩QSPI FLASH)域起始地址4 r  ^1 r' M, t) K# Y
  22. #define m_qspiflash_size                                0X800000                //m_qspiflash(外扩QSPI FLASH)大小,W25Q64是8MB3 Z* x: [0 ?5 _, N" i3 F
  23. 1 a" O+ w: O5 `
  24. #define m_stmsram_start                                        0X24000000                //m_stmsram(STM32内部RAM)域起始地址,定义在D1,AXI SRAM. B0 A  I- K! X. c. [
  25. #define m_stmsram_size                                        0X80000                        //m_stmsram(STM32内部RAM)大小,AXI SRAM共512KB3 ]/ s3 ?( g" B5 T  w+ T! t
  26. 2 h+ h7 A$ a! [

  27. 6 W* j* J* u0 k. k& H, v7 }
  28. 9 x! l0 X& a: h. f( f* K* ~/ F" X
  29. LR_m_stmflash m_stmflash_start m_stmflash_size {                //LR_m_stmflash加载域2 w! g' K+ E" X- ?* a6 S7 }
  30.   ER_m_stmflash m_stmflash_start m_stmflash_size {                //ER_m_stmfalsh运行域,起始地址为:m_stmflash_start,大小为:m_stmflash_size 9 C' f1 o- L5 H6 G
  31.     *.o (RESET, +First)                                                                        //优先(+FIRST)将RESET(中断向量表)段放这个域,实际上就是把中断向量表拷贝到m_stmflash_start
    # ?' G! s2 r$ w+ F
  32.                                                                                                                 //RESET是一个段名,表示中断向量表(在.s文件定义);+FIRST表示时第一个要加载的.; e2 J- D0 X, K% \
  33.         * (InRoot$Sections)                                                                //将所有的库段(C/C++标准库)放在root region.如__main.o,__scatter*.o等
    - Y8 i" s# b4 ~/ v, C8 `+ I! V
  34.         * (Veneer$Code)
    ! r; X. f  c0 I- o. Q5 a) a6 q3 L+ w
  35.         libinit.o2 _# ~: M( ]& R
  36.         libinit2.o
    9 p- `( z0 y. r' h; w, j/ @
  37.         libshutdown.o2 \4 ^& L" B7 H+ x8 i
  38.         libshutdown2.o
    & j! n" y& f3 R/ P" t
  39.         __rtentry.o
    8 o4 f" H/ o7 x  r( E
  40.         __rtentry2.o
    + X; s# U% C7 P
  41.         __rtentry4.o
    , @, C" E  S) _$ d/ g
  42.         rtexit.o) I- \( B" B+ A- M/ m9 v
  43.         rtexit2.o 6 a; N6 g% X% C( Y2 }  R! B
  44.         " B' X$ G9 `0 w5 R9 S9 y
  45.         use_no_semi_2.o
    - f2 z$ T: B9 v: y' i5 \& r  ^
  46.         heapauxi.o
    - t7 z0 Y, ^: ]+ V! r8 d
  47.         use_no_semi.o
    / N, C  `6 \+ s  g0 E3 f
  48.         sys_stackheap_outer.o
    ' v! J) a8 w0 X: u6 K7 q: J- w
  49.         exit.o
    $ E4 D5 U( X( F+ Z
  50.         libspace.o
      C1 y$ W2 l: A; |9 ~! f! L8 r2 A
  51.         fpinit.o
    ; v: A, k+ ~3 _7 S7 v& W! }
  52.         lludivv7m.o& a' J; \; ~* c# z; d  Q% u" I0 Q
  53.         startup_stm32h750xx.o0 d; e# e+ ?* ?2 Y% Y9 {- u
  54.          2 f4 Z- n) O# Y
  55.         rt_locale_intlibspace.o  
    ! D. Z$ d' q" H- V  Z1 p4 H
  56.         lc_numeric_c.o
    : l% D9 v3 z& [% S+ [9 ]
  57.         lc_ctype_c.o
    3 ?! T$ f1 O3 L5 K+ N

  58. ' [4 z2 N& M4 E0 ^/ j
  59.         startup_stm32h750xx.o7 ]5 d  c. M0 s2 @8 p# |6 l% L) g
  60.         system_stm32h7xx.o
    & x+ w; S( G. W$ |
  61.         stm32h7xx_hal.o# u  T/ e7 |4 S/ g) P
  62.         stm32h7xx_hal_cortex.o* {/ \- u+ U/ d7 H6 z) M% r
  63.         stm32h7xx_hal_rcc.o
    ; u0 I. j/ N, W) ]7 |2 ]) @
  64.         stm32h7xx_hal_gpio.o
    7 _. L8 v1 l/ R( w
  65.         stm32h7xx_hal_msp.o( t  v4 b! H/ e1 W3 H0 J' l$ ?
  66.         2 K. R+ S4 N: F( H9 f1 o
  67.         main.o + F6 S6 N/ Y# f% Z6 _: Z( E( H
  68.     sys.o
    ) ^9 r; Q. j: P) F
  69.         usart.o
    5 G- ^) b4 W# p- g3 w
  70.         delay.o
    ; n) B  C9 K6 l: m
  71.   } ( Q1 V. o& j9 q( g
  72.   RW_m_stmsram m_stmsram_start m_stmsram_size {                        //RW_m_stmsram运行域,起始地址为:m_stmsram_start,大小为:m_stmsram_size.. S1 e9 |! O/ c  x
  73.    .ANY (+RW +ZI)                                                                                //将所有用到的RAM都放在这个区域( o; ^7 A- J) I$ g2 s# R
  74.   }
    7 A; q/ X. F, N% n, W
  75. }) }2 k. a9 E9 @
  76. 8 x' J: J" N" L# \4 W
  77. LR_m_qspiflash m_qspiflash_start m_qspiflash_size {                //LR_m_qspiflash加载域9 O/ G8 Z" q7 z1 m
  78.    ER_m_qspiflash m_qspiflash_start m_qspiflash_size {        //ER_m_qspiflash加载域,起始地址为:m_qspiflash_start,大小为:m_qspiflash_size . P. c9 U1 D' u9 r
  79.     .ANY (+RO)                                                                                         //将只读数据(+RO)放这个域,任意分配.相当于程序就是存放在这个域的.
    ' Q' {" {9 p/ J6 M
  80.   }                                                                                                                         " y" J  }4 I: _& i5 D5 W. S
  81. }
复制代码
3 D+ A' K& S- b6 {' a5 n0 _' L
以上分散加载文件,由正点原子编写,为了方便大家使用,不用频繁修改.sct 文件,特意9 W" _. T8 m7 U$ ~
: S. x4 V' p3 ~4 c7 x
将.ANY ROM 区域放在外部 SPI FLASH,这样大家在新增.c 参与编译时,默认就是存放在外部1 C" @! ~, ^& W5 ~) H. Y
9 q, @5 }+ v. ]# e; S) d# X$ l
SPI FLASH 的,这样使用起来就更方便。1 N0 W3 y7 @) o8 {  T

4 Y) w, W0 _9 k# G( j) {注意:
8 h& _, x# Y1 y! X9 Y3 X! @& L) `, a( [) e5 {) W0 O* g2 _& R! S( W3 @" l
1, 如果你新增的代码,对速度有要求,可以将其对应的.o 添加到内部 FLASH,即放在:
% S3 V2 C- {- ?
$ `% [) `& j3 B  z+ s& s4 PER_m_stmflash 运行域。
+ i* c3 @/ S* t' _+ g; w6 J% d3 V. s+ k) i  j
2, 如果添加新代码后,程序无法正常运行(通常表现为黑屏/不启动),可以尝试将新增* R8 F8 [( M; }1 E8 l) c
7 D3 w6 j/ M; @) C4 G3 X
的.o 放到 ER_m_stmflash 运行域后(重新编译)再尝试。如果还不行,可以尝试将所# y* r6 v: T1 E4 F% y' W+ H9 V+ e/ J

) U) M- m' X6 y- a: g" @( p有代码都放到 ER_m_stmflash 运行域后再尝试。
) D6 c5 j& e1 c8 {. g
1 [4 _# n, j) W% E6 g8 \$ q
20200609103620392.jpg

9 r# W$ l3 h& Z; O& }/ m4 m1 f) \7 z: p7 l$ K! ~. q
二、通过boot程序跳转到qspi flash执行用户程序# j/ t" d/ ?! f, [$ d# H+ I

% c) J  ^& ]+ W5 i0 U2 o    第二种方式就是通过在片内flash中存放boot程序,然后通过boot程序跳转到用户程序,用户程序就放在qspi flash中。/ y. l' R, h% A
8 T4 X* E( ~6 ]
boot程序主要的工作就是初始化qspi,并设置成内存映射模式;禁用中断,重新配置中断向量表地址,然后进行跳转。这里分散加载文件直接使用系统自动生成的就可以了。程序起始地址0x08000000。7 x6 d4 y! D' r8 t: ^
/ n: u9 n: Y; W! c. ~
用户程序需要做的操作就是把程序起始地址改成0x90000000,然后添加下载算法,因为整个程序都是存放在qspi flash上的。下载完成后,用户程序就可以通过boot程序跳转执行了。
1 y* m/ [+ h1 V! C7 ]1 R/ }
4 M" b$ x: ~8 b  ]7 E
20200609104938687.jpg

; F. k  I' l! u( A% T! e+ {( r+ |5 s& I4 J* e( _
20200609104944216.jpg
$ y0 ^' T7 }, m7 F3 |. z9 i/ P
! i" v  S# m) ?4 ^- {% T
注意,不管是第一种还是第二种方法,都是将qspi flash给设置成了内存映射模式,而此模式下qspi flash是只读的,所以这个时候就没办法用来作为存储器来存储数据了。不过网上也有人说内存映射模式下也是可以写数据的,至于真假,还没验证过。* c$ N* U( T& H' P# K! J; w
: h3 ?1 H, I$ u; H6 y  [
% p, e& W0 K% S/ H; b- Z
收藏 评论0 发布时间:2021-12-28 22:13

举报

0个回答

所属标签

相似分享

官网相关资源

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