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

STM32F1系列之复制data段和清除BSS段

[复制链接]
STMCU小助手 发布时间:2022-8-27 14:12
一、什么是BSS段(ZI段)
, o" s  O" t. g$ V* _/ Abss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。
3 W) {7 t6 Y. F0 Abss是英文Block Started by Symbol的简称。
  ~: L* }; p/ v& M  W" N9 ibss段属于静态内存分配。- ~: W/ X+ C! N1 x1 D. x) t# n

- k) O5 Q0 _" V8 }二、为什么要复制data段& \& q+ [' q1 B
这是因为对于在STM32F103这类资源紧缺的单片机芯片中,数据段只是暂时先保存在Flash上,在使用前被复制到内存里,而复制到内存这个过程是需要我们自己实现的。
1 K3 q3 q: E; L; g% Z  P
5 O1 p8 N9 c" Z2 p+ d三、未处理的结果5 Q6 N# k1 z9 Y
修改main函数如下所示:7 k* X! S# t- \7 B" A  \
! g( V0 Z. T- B5 @" w5 H0 G0 [
  1. #include "uart.h"
    9 i( R5 o: q: P6 n
  2. #include "led.h"6 t, A' D, M# ^

  3. ( K+ e  W' d) {) m* X
  4. int mydata = 0x32315;
    & A. q" x5 P# }0 M
  5. const int myconst = 0x22315;
    ' D4 w+ z: _) W2 E( r. R
  6. int myzero = 0;) s2 Y+ X# }" b8 \4 Y
  7. int my;3 @- F. z; ?* A% M
  8. 7 W0 B. l3 ]  k: e% e/ T9 v2 Q
  9. int main(void)6 {, i9 g" y2 v9 ^- h  X
  10. {
    5 b, L7 |& M9 f& U8 v3 V4 P6 N
  11.     uart_init();3 q4 J1 c8 }# g5 p
  12.     led_init();
    - J7 H( z, F% |4 A
  13.     putstring("stm32f103zet6\r\n");# X) b' {% o* S, ]6 @
  14.         putstring("mydata\t:");
    0 O: b) ^! H( `  |
  15.     puthex((unsigned int)&mydata);
    0 P6 ~9 {* `" M5 b* ~
  16.     puthex((unsigned int)mydata);
    * v  b6 a  e( T! Q7 @2 Z
  17.     putstring("\r\nmyconst\t:");
    8 Y) P8 i3 A! |& B7 t* h
  18.     puthex((unsigned int)&myconst);! U0 E2 `( o( _5 q( z
  19.     puthex((unsigned int)myconst);1 ?; |6 [2 e5 M0 s* |
  20.         putstring("\r\nmyzero\t:");3 C  F2 @& a' t- @& F8 Z5 Q
  21.     puthex((unsigned int)&myzero);
    " P! R2 h6 R* a; E0 A( x
  22.     puthex((unsigned int)myzero);
    9 `; t* N: x3 w. g1 l
  23.     putstring("\r\nmy\t:");$ R8 Q6 t. \1 o% i# k  L
  24.     puthex((unsigned int)&my);% x9 ?' b1 w4 }6 F& J$ g% s0 @
  25.     puthex((unsigned int)my);, C* {4 B8 c0 `; D! x
  26.     putstring("\r\n");
      z8 V/ q- c3 }  c. D# ~

  27. 7 o0 ?1 x. d* Z5 `' p' x! a: V
  28.     while(1)- X$ u7 C  k+ x' L0 f
  29.     {& _( y. C2 h+ V* ^2 Q
  30.                 putstring("led on\r\n");5 R: m! Q6 ]9 m; F6 n2 A3 s
  31.         led_on();
    8 ^6 d% i/ o- h, V! E9 O
  32.         delay(1000000);
    " k0 Q- ~+ I2 j. B9 V

  33. 6 k. i$ }* x( I; g% ]+ K
  34.                 putstring("led off\r\n");; z% o+ B9 \; k6 J" ?
  35.         led_off();  Y% T; C, e3 h: n  l& m# c
  36.         delay(1000000);
    ' Z1 d5 P) X% k* _4 O3 e: u
  37.     }
    & @" u- r  R& X% E2 [) ~
  38. }
    ! H0 P% I* @* r% ~. n; {; j
复制代码
! e/ h! a2 L3 q% u$ s: K4 [& X( V
编译烧录运行,可以看到,除了存在Flash的只读全局变量的值正确,其他几个变量的值都是错误的9 L' m! A2 x9 I! N
. Y2 c( y2 x  p
20210125214800328.png ! U7 r$ d2 r: {' E$ D' _) w3 t

& ?  c- P' B3 V: b0 z% m四、修改链接文件
5 S4 @9 Q2 ~  Q4 S' H既然要复制data段和清除BSS段,那么就需要知道如下几个数据
9 B% C) u4 R; C: _  W, t& r7 k; T" K/ C! ^+ _" M7 m7 B
  1. 1、数据段的加载地址,即数据段存放在Flash的哪个位置
    . P7 L* B; H4 D1 ?  T2 i
  2. 2、数据段的链接地址,即数据段应该复制到在RAM的哪个位置1 l  T" S' m- p' d) c- C) p, Q
  3. 3、数据段的长度,应该复制多长的数据从Flash到RAM' b# P3 H- \, s. o# P2 q( M8 s
  4. 4、BSS段的链接地址,即BSS段应该从何处开始清除
    8 M& f' J3 H7 C' D; k- D8 h% M
  5. 5、ZI段的长度,应该清除多长的BSS段
复制代码
4 `7 S3 x: s$ }% n
我们将链接文件修改为如下所示,得到data段的起始加载地址、起始链接地址和结束链接地址,以及bss段的起始链接地址和结束链接地址。其中>RAM AT > FLASH 表示存放时使用RAM地址,存放时使用FLASH地址。% {2 e) W, E! Z

" x  p* M) P- M! o# \3 f
  1. /* 指定内存区域 */, h2 u6 k- D; ?; b
  2. MEMORY  l, O( R+ j8 d+ M$ @. l
  3. {& D8 ^) J) a& }, P
  4.     FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 512K
    8 b, d+ ]4 I. Y- H. \; P! O
  5.     RAM (xrw)   : ORIGIN = 0x20000000, LENGTH = 64K8 T/ {; B% @. l8 T9 W
  6. }+ c7 Q7 W4 z8 j: L7 V7 Q
  7. # R# N2 u( V( p. e6 C7 J
  8. SECTIONS {
      T0 j) l5 d5 N' R
  9. % b. A+ |4 o- I; w' O
  10.     .text      :
    2 o! U4 C) ]/ X% d# V- X% s* B# \
  11.     {
    & M+ K8 j7 a6 m7 U3 [
  12.         . = ALIGN(4);
    5 w; P1 A7 a' H% s+ o$ v* k, Q% \
  13.         *start.o (.text)
    4 A$ w9 N4 M8 [/ \& t) m3 t1 o
  14.         *main.o (.text)
    2 q! O) j' f2 _6 U7 F1 s* s! m) U
  15.         *(.text)
    " X) G" T7 \7 o# U9 I5 e) f! ]% r# \
  16.     } > FLASH
    + {. I& `$ A  n. e, [, y
  17. 1 R  H$ F/ U& m) F% U
  18.     .rodata :
    0 Y- Y) p7 a1 h* E6 {/ P
  19.     {
    3 r6 T# A. s- l* Y  Q/ b* x/ M$ ]
  20.         . = ALIGN(4);# k% g) R, t1 f
  21.         *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    ) x* }( g: h" z
  22.         *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    # T" e2 I1 t" L5 I
  23.         . = ALIGN(4);; K, [- {' v( w
  24.     } >FLASH# e5 [4 e# k9 F# ~8 l- j

  25. 3 s8 S+ j- k  L9 P# d9 U' F3 Q4 Q& H
  26.     _sidata = LOADADDR(.data);  /* 获取data段的起始加载地址 */
    6 G: T) Q( a, I% r& w/ v
  27.     .data :
    7 Q: `* e/ u7 o
  28.     {- j' |, `9 C6 e' ^' Z4 R! L2 o
  29.         . = ALIGN(4);
    , k! L$ v3 P) T& x! i
  30.         _sdata = .;        /* 获取data段的起始链接地址 */
    ( ?3 C6 I- w7 W
  31.         *(.data)           /* .data sections */& R! ?$ r( q- i( K+ q! W9 {9 p; a/ f
  32.         *(.data*)          /* .data* sections */( r7 H$ U) d( d1 l, Q! i( f- H. i
  33.         . = ALIGN(4);' h" {6 [- Q4 i2 V& w0 V+ S
  34.         _edata = .;        /* 获取data段的结束链接地址 */
    % S2 {, c. d: x8 g  Q2 v
  35.     } >RAM AT > FLASH- W$ p9 N7 @" U3 m' c' }2 d. r- t

  36. 6 Z& G% W7 t3 |; E
  37.     . = ALIGN(4);
    ) b' @+ d: |5 L# b& n
  38.     .bss :% D' X) O: L# ~+ m$ N; [% M6 f
  39.     {
    " o, y8 o. p' a# G$ C; H( ?
  40.         _sbss = .;         /* 获取bss段的起始链接地址 */
    5 i& r, u2 {1 y  O
  41.         *(.bss)
    ' b; C: w5 _. i  J: x
  42.         *(.bss*)
    " L) `- E$ l0 F% b7 ^! n
  43.         *(COMMON)' [" u8 L0 D# |! n! N( ]
  44. 4 W2 P/ S2 w% E# h- z! ^
  45.         . = ALIGN(4);
    ( V3 q6 X; ~- o* w7 H
  46.         _ebss = .;         /* 获取bss段的结束链接地址 */
    - f4 F3 u1 X- a7 d, K) w  X1 Z
  47.     } >RAM+ r9 X: B3 Y& ^8 H! k- d% B7 C% }
  48. }
复制代码

0 V: h) [' i6 T7 E6 R/ }) p, V五、修改汇编文件. F5 Z! G6 ~+ |) D+ y
在start.s中加入如下代码复制data段和清除bss段的代码,其中data段的起始加载地址_sidata、起始链接地址_sdata和结束链接地址_edata,以及bss段的起始链接地址_sbss和结束链接地址_ebss,都是从链接脚本中获取的。* Z$ |* k2 O7 w0 A, X

  1. 4 y- F' ]) K! ^% {
  2.   .syntax unified                   /* 指明当前汇编文件的指令是ARM和THUMB通用格式 */
    , {+ g5 R) [' ^+ e5 G4 q/ d
  3.   .cpu cortex-m3                    /* 指明cpu核为cortex-m3 */5 l7 U5 q+ d" y6 u# P
  4.   .fpu softvfp                      /* 软浮点 */
    5 q6 l! L- r( S- }) U7 k; u( ?
  5.   .thumb                            /* thumb指令 */
    : M" m: O; e  c8 d5 i. ]9 f

  6. 3 \% I, N7 {3 U1 C
  7. .global  _start                     /* .global表示Reset_Handler是一个全局符号 */* L  G) E9 l6 D2 U* m) }- }' g

  8. % b" A+ x: L) v2 i
  9. .word 0x00000000                    /* 当前地址写入一个字(32bit)数据,值为0x00000000,实际上应为栈顶地址 */
    3 D9 L, q- c6 h! g& C3 W9 D9 U
  10. .word _start+1                      /* 当前地址写入一个字(32bit)数据, 值为_reset标号代表的地址+1,即程序入口地址*/  g/ N8 @) \2 g8 d2 z- g4 t+ t
  11. * z' v7 X3 d3 _5 A8 K  l/ g* o8 E
  12. _start:                             /* 标签_start,汇编程序的默认入口是_start */
    / K5 Y$ E: ^+ }2 l
  13.     /* 1、设置栈 */
    & D: p0 t, e! |0 j1 k0 D
  14.     LDR SP, =(0x20000000+0x400)) u! S5 _) q7 |  U
  15. . u2 Z  r7 }3 Y7 ?9 b& ?- G( V( U% z% r
  16.     /* 2、复制data段 */; v  x' H+ B6 a  M/ }8 e
  17.         movs r1, #0                                                /* r1寄存器用来计数 */
    , ?, a+ y1 T& y) K) T8 w2 i: U! ]
  18.     b LoopCopyDataInit
    & D" R8 e8 x  C4 j* P! _! o

  19. 7 h" j' g( A% x: `1 c9 n% {" }8 r1 A
  20. CopyDataInit:) s6 ~. n6 m% ~1 T
  21.     ldr r3, =_sidata                                /* 将data段的起始加载地址存入r3寄存器 */2 k( N6 A( L+ d  o
  22.     ldr r3, [r3, r1]                                /* 从Flash取出data段的值存入r3寄存器 */. [) R4 y" P! {
  23.     str r3, [r0, r1]                                /* 将r3寄存器的值存入RAM中 */
    1 m  a0 H1 T4 V. b7 Z
  24.     adds r1, r1, #4                                        /* 每次复制4个字节的data段数据 */
    . k- P  H% ]6 ~+ C0 s5 s
  25. ; o; @4 C% A# M" }* ^
  26. LoopCopyDataInit:
    9 d# i% N. a" g) E  f5 T3 i
  27.     ldr r0, =_sdata                                        /* 将data段的起始链接地址存入r0寄存器 */1 ^3 ?" x# j4 H4 `+ E
  28.     ldr r3, =_edata                                        /* 将data段的结束链接地址存入r0寄存器 */
    1 k7 F7 I' T% U# {( D+ e  |
  29.     adds r2, r0, r1                                        /* 起始链接地址加上计数,即当前复制地址存入r2寄存器 */
    ! W. B, K% A/ O( l
  30.     cmp r2, r3                                                /* 当前复制地址和结束链接地址相比较 */
    5 ~* H) Y1 \* j4 I# F
  31.     bcc CopyDataInit                                /* 如果r2小于等于r3跳转到CopyDataInit标签处,如果大于则往下执行 */
    # q# n  A, E; |$ {2 A. U. }, n
  32. 9 y4 }" m. K! h4 o! S3 [# ]
  33.     /* 3、清除bss段 */$ V( @# [3 X+ H/ C: k; ?3 h/ u
  34.         ldr r2, =_sbss                                        /* 将bss段的起始链接地址存入r2寄存器 */
    ) {  U! I1 t  P9 F
  35.         b LoopFillZerobss, z3 u; ^" W& K, h
  36. 2 L' b. |' U& g
  37. FillZerobss:! y$ f% B; N9 B9 @5 ^8 j1 u
  38.         movs r3, #0                                                /* 将0存入r3寄存器 */1 G9 I; b' V/ N
  39.         str r3, [r2], #4                                /* 将r3中的值存到r2中的值所指向的地址中, 同时r2中的值加4 */
    " f* o) ]8 E- W4 `) ^5 N
  40. % k2 f* A* ^; u2 a& F1 K) R6 F
  41. LoopFillZerobss:
    * T* @8 H/ @3 D6 [# d
  42.         ldr r3, = _ebss                                        /* 将bss段的结束链接地址存入r3寄存器 */
    * A( X% M* ?8 ?
  43.         cmp r2, r3                                                /* 比较r2和r3内的值,即当前清除地址和结束链接地址相比较 */8 Z; h- r- ?4 K8 ~
  44.           bcc FillZerobss                                        /* 如果r2小于等于r3跳转到FillZerobss标签处,如果大于则往下执行 */( j7 a, `1 m7 u, ]) l
  45. - s, C( K) v& m5 o+ i( D$ K
  46.     /* 4、跳转到led函数 */
    ; p2 f9 J% P- q1 C
  47.     BL main) I) a3 S, J, I+ B6 J
  48.     /* 5、原地循环 */
    0 s6 C: S& k( n) T/ b
  49.     B .# t4 a% }2 ]. X( b- U! L

  50. $ J! U" P4 \+ r1 J( O7 y% c
复制代码

$ j4 D5 Q6 @9 C3 O4 j' ?9 i1 _然后编译运行烧录,这样我们就可以看到变量的值正常了
& }8 `- |- ^6 i( s
- Q: N  s* f+ t" t  \9 o  o/ V 20210125223543797.png
( d; y' f8 C2 K% v* E% N6 w5 ^
" v) Z, \4 ~, c% s6 \, C, _  b3 q————————————————
# V1 U0 Q, {: X  `6 q/ @转载:Willliam_william
$ w3 Q2 K8 o! d) B( A+ h0 b" q0 }' i0 x  {3 t
收藏 评论0 发布时间:2022-8-27 14:12

举报

0个回答

所属标签

相似分享

官网相关资源

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