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

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

[复制链接]
STMCU小助手 发布时间:2021-12-28 22:13
根据ST的参考手册描述,h750的片内flash只有128kb,在实际的项目应用中,128kb的容量有点太小了,有时候光光移植好lwip+freertos以后,flash的容量就所剩无几了,所幸可以使用QSPI FLASH来存放程序代码,可以把程序的部分或者整个程序都存放在QSPI FLASH中运行。这里介绍两种不同的方法。5 j6 Z0 J2 k# w& Y& x& g$ a6 o
: p' q. O0 U% Y- N6 a3 J
一、通过分散加载文件的方式
# y" L  W& }8 M/ R7 a& m. ]2 W9 ]) |- M. J" ~) e1 J+ Z7 r/ z8 s
    本文中使用的是正点原子北极星板子的例程,跑马灯实验。例程比较简单,主要是看分散加载文件,在最后有一个LR_m_qspiflash加载域,这个就是将代码存放到QSPI FLASH的。分散加载文件的具体细节就不在这边讨论了。
" Y4 _4 F6 ]) D5 O1 u
1 W: N3 J" [' \% ?5 H    当然,光光靠配置分散加载文件,是无法把程序下载到板子上的,因为有一部分RO是要下载到片外的flash的,因此这边还需要使用特殊的片外flash算法。在正点的资料有有提供这一算法。通过添加算法的方式,这时应该能够将程序下载到板子上了,但是,这个时候程序不一定能够跑起来,还有一个重要的步骤,那就是初始化QSPI,并设置成内存映射模式。正点的例程中是将初始化操作放在了时钟初始化函数中。至此,程序就能够正常运行了。( V# N* |0 `: J- W# X
! _1 S% o% N- G0 x
  1. #! armcc -E
    - a5 E: K( b. v: N5 ^
  2. //  
    7 X/ R: [- x5 B# b
  3. //STM32H750分散加载文件(.scf文件)  r/ ~" k9 R& c; Q  B0 F8 g
  4. //ALIENTEK STM32开发板  ! o0 M0 G+ m8 l& B9 {
  5. //正点原子@ALIENTEK% P/ G5 E8 G& _1 h& f& i+ [
  6. //技术论坛:<a href="http://www.openedv.com" target="_blank">www.openedv.com</a>
    " P. r  _0 n6 [
  7. //创建日期:2019/4/21
    + Z' R" _$ w# e; i  P4 ~
  8. //版本:V1.0: P$ ]9 F- \# s( ~' `: n
  9. //版权所有,盗版必究。
    0 l8 b" \  o8 P
  10. //Copyright(C) 广州市星翼电子科技有限公司 2014-2024
    / |' R- W6 T% |" \$ p
  11. //All rights reserved
    * z0 \( _8 y! _- A2 @, w
  12. //********************************************************************************
    6 n) y6 D2 {9 P. ~9 }7 K
  13. //修改说明
    , S# G& E# n9 W- T5 _
  14. //无, i( [# m( k: q" J
  15. //8 j4 A$ b3 l( Q# k3 ~* N

  16. 3 T  n" o& ?& F

  17. 4 s- N9 n+ O; @6 k
  18. #define m_stmflash_start                                0X08000000                //m_stmflash(STM32内部FLASH)域起始地址9 u5 L2 }" S/ ?& k0 q, v# }5 E
  19. #define m_stmflash_size                                        0X20000                        //m_stmflash(STM32内部FLASH)大小,H750是128KB' O3 S6 O7 ~) G6 G2 b

  20. ( H% e, {0 X* g
  21. #define m_qspiflash_start                                0X90000000                //m_qspiflash(外扩QSPI FLASH)域起始地址$ q2 x2 h4 B" @6 N  d
  22. #define m_qspiflash_size                                0X800000                //m_qspiflash(外扩QSPI FLASH)大小,W25Q64是8MB  E/ J* f% p2 ?$ R: ^2 H

  23. - L, o8 t* n5 z9 [% l2 O
  24. #define m_stmsram_start                                        0X24000000                //m_stmsram(STM32内部RAM)域起始地址,定义在D1,AXI SRAM- X! L. ~& @/ C" ~  Q' @' l2 ~& T
  25. #define m_stmsram_size                                        0X80000                        //m_stmsram(STM32内部RAM)大小,AXI SRAM共512KB! b3 p+ ~3 U! G4 s* [: N
  26. $ x& O" o3 ]- t( u# b
  27. 3 b5 F9 ^5 B# T# _" y

  28. ' J1 X) B9 j. a' g0 }; n3 Z' q
  29. LR_m_stmflash m_stmflash_start m_stmflash_size {                //LR_m_stmflash加载域9 Z  D4 V  r5 |# A, g$ v
  30.   ER_m_stmflash m_stmflash_start m_stmflash_size {                //ER_m_stmfalsh运行域,起始地址为:m_stmflash_start,大小为:m_stmflash_size
    0 ?4 F% T3 b& N  ^8 |2 b
  31.     *.o (RESET, +First)                                                                        //优先(+FIRST)将RESET(中断向量表)段放这个域,实际上就是把中断向量表拷贝到m_stmflash_start2 p: V/ Z/ N' ?. a7 G
  32.                                                                                                                 //RESET是一个段名,表示中断向量表(在.s文件定义);+FIRST表示时第一个要加载的.
    % X" ^2 O' m7 g9 ^  w
  33.         * (InRoot$Sections)                                                                //将所有的库段(C/C++标准库)放在root region.如__main.o,__scatter*.o等
    " G: C# P- |0 p- L/ t9 c% m, g0 ~4 r2 I
  34.         * (Veneer$Code)
    . p% z7 v, k0 W: \' |5 a. w
  35.         libinit.o
    ' M+ S* J( h6 k( ^5 Z" \7 {) e
  36.         libinit2.o2 `( r  X7 ^! t3 q: H
  37.         libshutdown.o
    / t0 F" u/ Y! C) g, f+ m
  38.         libshutdown2.o, y, [  c6 H; t+ w) L
  39.         __rtentry.o. ]5 l% k0 R5 X0 w8 [
  40.         __rtentry2.o
    5 ~6 f+ B# d2 A
  41.         __rtentry4.o
      t; {/ R0 H8 v% e
  42.         rtexit.o
    ; q. x6 t+ q/ h& T
  43.         rtexit2.o : c' L! m/ \) {% i
  44.         
    ! R" g7 X' T4 Z* D" p7 j5 N+ I
  45.         use_no_semi_2.o
    9 K* m7 g# b3 B6 `; C6 P
  46.         heapauxi.o, ], o* ~6 O: D8 V+ R6 |- `: \
  47.         use_no_semi.o2 c6 a9 `. J6 _, x4 P/ d9 l. _
  48.         sys_stackheap_outer.o" A- m2 [) E9 z- V. |8 D
  49.         exit.o1 u+ b4 f4 K7 \- k. H
  50.         libspace.o
    ( p8 k9 i  s' E0 J2 r" j
  51.         fpinit.o
      q& g" h$ A  I, w! ]
  52.         lludivv7m.o" N- W* n1 K$ n0 u
  53.         startup_stm32h750xx.o
    , x9 ]! G$ h9 y  Y) x$ A" q7 x
  54.          
    $ i- Y2 I  A: Z7 F0 n$ h: o1 I
  55.         rt_locale_intlibspace.o  % L2 K0 R9 p- e. K4 [# W9 m( F; Z
  56.         lc_numeric_c.o
    $ w2 x7 E) p+ S2 O
  57.         lc_ctype_c.o" a3 Q1 x- a  d9 U$ _
  58.   Q$ Q/ E# ~% Y# Y1 u0 d9 ^6 D" o
  59.         startup_stm32h750xx.o/ N$ H$ t8 r1 ^8 P4 H& ]% F
  60.         system_stm32h7xx.o; |  G; p3 C9 [% e! q% T$ \
  61.         stm32h7xx_hal.o1 |7 J* V* z0 `  i1 h* {
  62.         stm32h7xx_hal_cortex.o
    / c5 ~* M" p! S$ S, a
  63.         stm32h7xx_hal_rcc.o
    5 y' r, t9 T. o, o4 }: F# f
  64.         stm32h7xx_hal_gpio.o2 V4 _  c+ {. ^7 |6 O0 Q  T
  65.         stm32h7xx_hal_msp.o
    & ^: i4 }  A8 [0 y& ^
  66.         / ~. f, x; t8 ?1 d' Z
  67.         main.o
    6 F! ?+ T  C% Z0 F
  68.     sys.o , x) t$ a8 o7 A" S' A
  69.         usart.o
      h3 B# d- V1 {' \* G+ R% q
  70.         delay.o9 G( j2 T: d' ]4 x/ x8 q
  71.   } ) A; ]4 f+ _" s+ [: B# Y  P
  72.   RW_m_stmsram m_stmsram_start m_stmsram_size {                        //RW_m_stmsram运行域,起始地址为:m_stmsram_start,大小为:m_stmsram_size.$ U9 A3 _, s2 W( ]) W' N
  73.    .ANY (+RW +ZI)                                                                                //将所有用到的RAM都放在这个区域
      c- s% S) Y$ t$ p" s- _
  74.   }
    , B' E6 V0 e+ U! u) |5 _
  75. }
    0 `) `5 J* L5 Z7 L7 \# v
  76. 7 V* ]5 R+ I9 m4 E) e6 B1 A  d
  77. LR_m_qspiflash m_qspiflash_start m_qspiflash_size {                //LR_m_qspiflash加载域
    2 n4 a$ Q/ b6 l1 ?
  78.    ER_m_qspiflash m_qspiflash_start m_qspiflash_size {        //ER_m_qspiflash加载域,起始地址为:m_qspiflash_start,大小为:m_qspiflash_size
    : U8 z7 g$ b  T
  79.     .ANY (+RO)                                                                                         //将只读数据(+RO)放这个域,任意分配.相当于程序就是存放在这个域的.
    . V, M. S) c* w3 N% x8 G
  80.   }                                                                                                                         4 c& X: F4 M1 x' `1 U
  81. }
复制代码

  X5 ]/ H0 Y0 D+ r! S以上分散加载文件,由正点原子编写,为了方便大家使用,不用频繁修改.sct 文件,特意
0 o4 O: F/ ]) I7 `9 T0 v, K% `9 f' ?# t7 q" H7 o+ M$ v4 X( C
将.ANY ROM 区域放在外部 SPI FLASH,这样大家在新增.c 参与编译时,默认就是存放在外部
* n+ z9 h0 X% S  ]' F4 z  e; x( j4 k
. K( D* H  u3 H+ k. gSPI FLASH 的,这样使用起来就更方便。( f, e! i3 V9 k9 B5 l5 m2 ?
; H# K- k) J+ g2 z( d: r! [
注意:
5 g4 q6 y/ {( b. c- \: @; w
9 c6 w4 ~3 `# E1, 如果你新增的代码,对速度有要求,可以将其对应的.o 添加到内部 FLASH,即放在:
* a. z% t' m6 x% Q+ D$ S0 j% N# D% P
ER_m_stmflash 运行域。: |( [% e% h+ i$ E# z1 `

! k0 t$ N/ {+ W0 M2, 如果添加新代码后,程序无法正常运行(通常表现为黑屏/不启动),可以尝试将新增( u/ Y: K8 ]3 U6 v( ]! E
! `4 ]/ p* o5 c
的.o 放到 ER_m_stmflash 运行域后(重新编译)再尝试。如果还不行,可以尝试将所5 U4 T/ E% g  U: a+ D! I. i
6 {* d0 Z5 U, D0 |2 W
有代码都放到 ER_m_stmflash 运行域后再尝试。
' x' {, \5 E3 J; V% H/ R* k# d7 z
20200609103620392.jpg

% K" G3 }8 E  A2 V8 a3 r
' e5 z& i( u/ o/ ^. g" i' {6 o4 E' M* M二、通过boot程序跳转到qspi flash执行用户程序
+ j8 A- @! U2 N; D2 k  C' i
% f  G% H1 l8 a2 u3 m    第二种方式就是通过在片内flash中存放boot程序,然后通过boot程序跳转到用户程序,用户程序就放在qspi flash中。" m6 g% b' B" z) ?' f) T0 ~' I

% ^! l  U0 O4 H6 [  g4 H0 E; Wboot程序主要的工作就是初始化qspi,并设置成内存映射模式;禁用中断,重新配置中断向量表地址,然后进行跳转。这里分散加载文件直接使用系统自动生成的就可以了。程序起始地址0x08000000。
* D, e$ \% Z, S7 }0 x9 L2 N
, `" S& F; ^! O6 c8 V; i用户程序需要做的操作就是把程序起始地址改成0x90000000,然后添加下载算法,因为整个程序都是存放在qspi flash上的。下载完成后,用户程序就可以通过boot程序跳转执行了。
+ r: J0 k7 L) A8 J" Y# [  ~% ~. l( u! t6 j3 \& U: J
20200609104938687.jpg
. l+ B1 Y. E7 B, P

1 Z: a# M; s. n* R2 g
20200609104944216.jpg
7 C4 X+ g+ `$ b3 L4 O
* Z2 F3 H+ z& l( Z9 |5 Z
注意,不管是第一种还是第二种方法,都是将qspi flash给设置成了内存映射模式,而此模式下qspi flash是只读的,所以这个时候就没办法用来作为存储器来存储数据了。不过网上也有人说内存映射模式下也是可以写数据的,至于真假,还没验证过。/ q$ y7 m9 ?& T& x0 c4 L

; v8 @( n- u& h& O' n/ F2 x1 ]0 e& U. p( e( N9 m0 S2 t9 O
收藏 评论0 发布时间:2021-12-28 22:13

举报

0个回答

所属标签

相似分享

官网相关资源

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