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

【经验分享】STM32 :IAP实验 & 写入内部Flash

[复制链接]
STMCU小助手 发布时间:2022-1-31 16:00
__initial_sp是堆栈指针,它就是FLASH的0x8000000地址前面4个字节(它根据堆栈大小,由编译器自动生成)0x8000004才是复位向量,所以需要在add+4
这两天再看IAP实验,觉得很实用,最近在做一个小项目,日后也肯定需要升级的。原子的程序是写在STM32的内部Flash,内部SRAM。还可以把程序写到外部Flash或者SD卡来更新。
目前做了第一步:从串口更新,移植的正点的代码。先将IAP bootload写入ROM起始地址,这里我的ROM总共256k,我分了一半给bootload,一半给app。注意设置地址问题。
                       只更新了Flash app。用的流水灯实验。SD卡FAT目前先没用,空间节省不少啊,这个RAM,ROM占用很厉害啊。这个问题还需要去解决。
                       串口接收APP设置了10k容量。
                       流程:1,Jlink写bootload到ROM起始,与平时一样
                               2,串口发送app.bin,串口接收
                               3,将接收的app.bin写入flash的指定app位置
                               4,使用bootload中的函数跳转到flash的指定app位置,执行app。
; A& z, S% \( h1 Z" H* y3 c
  1. 1 #ifndef __IAP_H__. `; E' ?# U  i" ~8 u, L- k  h5 G& u
  2. 2 #define __IAP_H__4 n8 X- D$ W* Y, G1 ~7 @
  3. 3 #include "sys.h"  " \8 c8 m( u$ p8 t; m5 b, Z
  4. 4 //////////////////////////////////////////////////////////////////////////////////     
    " d  u8 Z, h) i% Y" k( B
  5. 5 //本程序只供学习使用,未经作者许可,不得用于其它任何用途
    ) X  t( E" S* P9 Q8 o
  6. 6 //ALIENTEK战舰STM32开发板
    ) y) O# |1 b# X8 k) k  c
  7. 7 //IAP 代码      
    ( N; `+ a' t, J/ g1 M
  8. 8 //正点原子@ALIENTEK/ E8 h# b. J: l/ F7 }
  9. 9 //技术论坛:www.openedv.com# j; W2 E* p# R
  10. 10 //修改日期:2012/9/24
    # R( o, @) d$ c8 w
  11. 11 //版本:V1.0/ Y7 Y8 ?: ~1 M; r" V
  12. 12 //版权所有,盗版必究。
    - [2 A! S3 H) _
  13. 13 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019
    # W4 d% p; ?; a' p) K; z. b
  14. 14 //All rights reserved                                      6 U1 R" W# @7 |
  15. 15 //////////////////////////////////////////////////////////////////////////////////    # N+ P5 |) y: D/ a# V
  16. 16 typedef  void (*iapfun)(void);                //定义一个函数类型的参数.- c4 j5 f: U& G, q& I4 I
  17. 17 9 x: b8 O5 O& b. A
  18. 18 #define FLASH_APP1_ADDR        0x08020000      //第一个应用程序起始地址(存放在FLASH)
    % C: s: b! G; x, e% m6 g
  19. 19                                             //保留0X08000000~0X0800FFFF的空间为IAP使用
    : ^2 J2 O. ?4 n+ p2 s6 |. _
  20. 20 . B+ \/ N$ _& O
  21. 21 void iap_load_app(u32 appxaddr);            //执行flash里面的app程序
    ( r$ v, h. }5 \8 k- i# ~
  22. 22 void iap_load_appsram(u32 appxaddr);        //执行sram里面的app程序1 j8 f  q9 R% W! B, G8 B
  23. 23 void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 applen);    //在指定地址开始,写入bin
    % r( C1 H/ _# G1 h: w$ F
  24. 24 #endif
    / q( R, @  N/ ~6 v; _# W6 I, {
复制代码
  1. 1 #include "sys.h"
    / X; F" A* T: `% M( M/ z3 W  D
  2. 2 #include "systick_config.h"
      Z, o5 _) x% y* U
  3. 3 //#include "stmflash.h"
    6 J6 Q2 [2 N( Z& I
  4. 4 #include "iap.h"; r: H: C, G; i0 |
  5. 5 //////////////////////////////////////////////////////////////////////////////////     
    $ {. o) a# O% m0 a; B
  6. 6 //本程序只供学习使用,未经作者许可,不得用于其它任何用途
    1 Q% o1 \8 k0 A1 |* |
  7. 7 //ALIENTEK战舰STM32开发板
    8 u5 Y3 G  G. X6 n% S
  8. 8 //IAP 代码      
    ; o8 b" A# e+ A2 w" x
  9. 9 //正点原子@ALIENTEK
    8 v0 G! d. p4 x7 x
  10. 10 //技术论坛:www.openedv.com. i2 ~: q0 X6 a) x$ e. U
  11. 11 //修改日期:2012/9/24
    ( `1 x: {0 ^, M4 v
  12. 12 //版本:V1.08 [7 u; q* H: N& Z/ y* p; W+ C
  13. 13 //版权所有,盗版必究。9 \: W$ K: k* a& G# h
  14. 14 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019
    - I6 _- y" b2 s4 b% B
  15. 15 //All rights reserved                                      
      P0 B0 q$ X( A# w2 Z8 [
  16. 16 //////////////////////////////////////////////////////////////////////////////////    7 h1 `9 u. V4 C. t7 k
  17. 17
    ( n/ h' K8 a1 q
  18. 18 iapfun jump2app; 4 q/ g/ [: A  y% `1 \
  19. 19 u16 iapbuf[1024];   
    ( k7 X- h' o) g, ^0 j! K7 N
  20. 20 //appxaddr:应用程序的起始地址
    ' u: E' M7 C$ X6 f% N
  21. 21 //appbuf:应用程序CODE.
    ( F5 d! H2 |6 S; z
  22. 22 //appsize:应用程序大小(字节).
    6 [9 @4 v% B/ z& I, y' g( j
  23. 23 void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
    2 }7 P2 f4 G; s/ r8 B9 k* v3 S
  24. 24 {
    ) y; r/ V; A% p0 E) ^: V; C: f+ R0 A
  25. 25     u16 t;
    ; z4 e# \7 L9 h
  26. 26     u16 i=0;
    1 \; ^5 w. k" {/ @$ h3 c
  27. 27     u16 temp;
    & b$ T! H6 u  ]
  28. 28     u32 fwaddr=appxaddr;//当前写入的地址) I% Y1 R& l) P
  29. 29     u8 *dfu=appbuf;9 ]) u! I$ j% q5 r  }# i
  30. 30     for(t=0;t<appsize;t+=2)$ S. }2 z+ T: M, L/ `6 t3 m
  31. 31     {                            ; Q0 r5 y/ i4 ~5 h0 \# T
  32. 32         temp=(u16)dfu[1]<<8;, g, E4 y% P( C9 L, R
  33. 33         temp+=(u16)dfu[0];      
    $ m; s0 Z6 N6 E0 G, l, s- a2 Z. M9 [
  34. 34         dfu+=2;//偏移2个字节1 k) J5 F- y) y9 v2 `2 G
  35. 35         iapbuf[i++]=temp;        ' q: @1 m) v, M" n3 c
  36. 36         if(i==1024)1 _" s. Y, w. A, r  ?4 a) ^
  37. 37         {$ ]; e0 C4 i! O" w3 k" B) H
  38. 38             i=0;: E9 G  X/ I' d1 U
  39. 39             STMFLASH_Write(fwaddr,iapbuf,1024);   
    6 F4 D/ I. {+ L* X' {/ m5 I
  40. 40             fwaddr+=2048;//偏移2048  16=2*8.所以要乘以2.$ e, v! A, P( H. F  E" j
  41. 41         }
    % h& Q+ E1 B) ]4 ?+ x
  42. 42     }
    7 X$ k  J4 [' r3 N+ ~+ f" B/ x* S
  43. 43     if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.  + Q( F) S0 G1 p; e' B' x
  44. 44 }
    " k) Z2 w! Z) H  {" @1 P
  45. 45
    * R$ M3 |/ k7 r7 x
  46. 46 //跳转到应用程序段: W' P5 V6 ?& C$ O/ K
  47. 47 //appxaddr:用户代码起始地址.( E/ a' X5 B6 z1 j$ r
  48. 48 void iap_load_app(u32 appxaddr)
    + c" {( b8 a  f- G4 X* {$ g+ o; Q
  49. 49 {
      I6 P' C0 W) z8 A' A, g% x
  50. 50     if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)    //检查栈顶地址是否合法.
    & B- r3 \8 r! W( C. X$ x: C
  51. 51     {
    / A- u( c& b. F$ K" o
  52. 52         jump2app=(iapfun)*(vu32*)(appxaddr+4);        //用户代码区第二个字为程序开始地址(复位地址)        
    7 r2 A6 R$ x( E  {6 b' e/ b- ^  u
  53. 53         MSR_MSP(*(vu32*)appxaddr);                    //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址): y- A: Y! e$ }  R) g% k% R
  54. 54         jump2app();                                    //跳转到APP.
    ) X# W) x  G  g- z
  55. 55     }4 ?* k6 c9 w+ L0 C4 _/ G
  56. 56 } : P0 H' S9 i/ M+ ^, E: z" y/ X  o
复制代码
  1. 1 #include "stm32f10x.h"
    & h9 U& U4 ]: S4 ~6 |/ `3 \
  2.   2 #include "stm32f10x_conf.h"
    1 k! w; ]  N$ u1 N! S4 G
  3.   3 #include "exti_interrupt.h"
    8 R8 {; [' {, z5 N
  4.   4 #include "usart_config.h" & D! u; A6 R2 Q  B6 [
  5.   5 #include "timer_config.h"  
    * e+ ~% R4 K: \
  6.   6 #include "key_config.h"      
    3 f4 r6 K) I6 {5 C1 ]
  7.   7 #include "sdspi_config.h"
    9 I4 `; {' J* N2 \
  8.   8 #include "Fatfs_config.h"' j9 R) W2 n! N- G# F
  9.   9 #include "flashspi_config.h"& M* Y: U- D& w" w5 K
  10. 10 #include "ff.h"
    1 [0 c7 E( x' }
  11. 11 #include "diskio.h"& X5 z: {/ b) _$ f  J' o8 N6 W7 x
  12. 12 #include "iap.h", ~  [1 L1 d% ]3 b! Q7 ?" i
  13. 13 #include <stdio.h>9 b  G( \- l$ E: o
  14. 14 #include <string.h>/ \; U) u: E) h" q6 e( Y
  15. 15 //#include "picture.h"
    ; `1 T* |! Z# j/ ?9 p
  16. 16 5 ]) K5 w' ~: Q% |8 z
  17. 17 //#define BmpHeadSize (54)' _: m: |& T; G$ r5 }% P, q  @* n
  18. 18 FATFS fs;! W0 u' X  }7 R% _/ p- L
  19. 19 3 {" ?6 \1 i6 T
  20. 20 #ifdef __GNUC__
    9 o% z, n+ t+ k) [5 @" A4 i# j
  21. 21 /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf  M3 D+ {1 k7 U0 g1 v
  22. 22  set to 'Yes') calls __io_putchar() */& O9 }, C+ J" ?+ z2 l3 ^! Z
  23. 23 #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    " d! |1 R1 m6 P
  24. 24 #else2 Q6 T0 T5 r1 l9 t; P) Y7 X
  25. 25   #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)$ l- l9 h" }$ n( L, ]! T
  26. 26 #endif /* __GNUC__ */
    : c6 L* V3 O( x5 D% D
  27. 27 , c) A- Q  A( c& g3 Z3 i
  28. 28 static void Delay_ARMJISHU(__IO uint32_t nCount)  u& _$ p* e: F+ c8 j3 I
  29. 29 {
    4 m0 c5 I5 B" c: y" N8 h/ Z
  30. 30   for (; nCount != 0; nCount--);
    $ }& e4 [  x5 I+ i( w7 f7 N! d
  31. 31 }
      S2 L# G" n8 i$ o
  32. 32
    0 ?% U# V2 g8 R
  33. 33 extern u8 USART_RX_BUF[];     //接收缓冲,最大USART_REC_LEN个字节.2 J8 l; D' S6 E! v, ^/ u1 J
  34. 34 extern u16 USART_RX_CNT;: Z* v9 i7 ~5 C0 m" q
  35. 35 //接收状态
    % Y8 W0 w" w; m, i' {) Z8 i" x( ^4 X
  36. 36 //bit15,    接收完成标志0 ]0 t- F2 `6 m& h
  37. 37 //bit14,    接收到0x0d5 b5 e5 ]) c) R* C6 A* }
  38. 38 //bit13~0,    接收到的有效字节数目) |0 m6 Y6 W; n
  39. 39 extern u16 USART_RX_STA;
    / @) q1 H1 \- [
  40. 40 /**
    . R. _% i8 E/ X5 t
  41. 41   * @brief  Main program.0 B' E6 U6 x) a5 g6 X
  42. 42   * @param  None
    2 ^9 [; Q# ]- [. |% n" r! U3 u
  43. 43   * @retval None
      \- H/ z' a: _+ E
  44. 44   */
    ! r4 O1 S5 L7 k! `# _
  45. 45 : u9 F% H2 k, [
  46. 46 int main(void)- {6 q; d- Q# t5 s$ t
  47. 47 {
    & M- U: U- E# z1 s
  48. 48          u8 len,t;
    2 \3 V0 \: C3 C
  49. 49          u8 key;
    1 O1 l9 Q# M1 I
  50. 50          u16 oldcount=0;    //老的串口接收数据值- u1 R' k8 d& S# t
  51. 51          u16 applenth=0;    //接收到的app代码长度
      K1 V- k  m6 D1 s' }
  52. 52          u8 clearflag=0;
    2 J( A6 y: y3 U1 ~2 T
  53. 53         
    ' o2 ~: u8 V# i/ \; l
  54. 54          /* 延时初始化 */
    / ]! m# p( I# ]9 V
  55. 55          delay_init();7 C; k: X# Z8 T" E. p6 N
  56. 56
    " i6 f) q7 `5 [) i2 y( _
  57. 57          /* 串口设置 */
    $ O) j  j$ f$ A( t
  58. 58 //         Usart1_Config();2 d# A* x! I3 U+ i* l
  59. 59          Usart2_Config();) u+ R. j( I/ F7 U' d4 h
  60. 60          USART_SendData(USART2,0x55);( c2 S3 f0 C5 Q; A9 R2 m
  61. 61          while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
    # ?, ]) w6 x' H# f
  62. 62          printf("english\r\n");' B4 ?# R% J) A& ]8 @
  63. 63          printf("中文测试\r\n");( k& q! E" y; \2 Y! y
  64. 64
    0 l" B* m0 x( O/ O
  65. 65          /* 按键中断设置设置 */
    " Y4 C9 l2 N7 U& N8 j" D+ ?
  66. 66          Key_Config();) ^! h: k* n8 G$ S  x
  67. 67 //         KEY_EXIT_Init();& t0 W3 G; D# I5 K/ p, n
  68. 68 //         Key_NVIC_Config();     
    - I1 f/ e$ z' @* ]8 D
  69. 69
    4 K7 ]/ Z8 f5 P
  70. 70   
    ( B. Z& ?1 V' ]7 ?7 T" b
  71. 71 //         disk_initialize(0);3 P0 M2 ]9 b8 X  T$ g! {/ f
  72. 72 //         printf("\n\r f_mount %d\r\n", f_mount(0, &fs));
    0 Y6 [9 Y+ C8 s- e! X
  73. 73 //         mf_scan_files("0:");5 V* V& ~" b7 ^4 ?
  74. 74
    ; g7 T( k1 D# L9 L5 q/ K5 e& }/ D' J5 _
  75. 75 //        printf("\r\n将要进入主程序while:\r\n\r\n");+ J8 A% E; X! g, L5 c
  76. 76          while(1)
    , |- i. F! v8 _, k# Y6 G
  77. 77          {     7 W" \3 X8 n9 {! g# U6 _
  78. 78 & n, |4 l  h7 D9 ?" w8 z% W
  79. 79                if(USART_RX_CNT)% N% J- l! B- p, \' T
  80. 80             {
    7 W( f0 i3 w9 w
  81. 81                 if(oldcount==USART_RX_CNT)//新周期内,没有收到任何数据,认为本次数据接收完成.
    5 U# K8 H" q6 E9 W5 z2 y( w4 L% n3 A
  82. 82                 {
    4 o" [) i' @0 Y' G0 x
  83. 83                     applenth=USART_RX_CNT;8 m6 s; B  k6 S0 ]; A& n3 f/ ?- i
  84. 84                     oldcount=0;
    ( v' g  ~1 P3 g" Q$ o" Z% M" M
  85. 85                     USART_RX_CNT=0;+ g# n+ Y* i5 ^/ |; X: n# u' \9 {
  86. 86                     printf("用户程序接收完成!\r\n");
    6 Y7 A+ @7 Y; |5 i, [0 C
  87. 87                     printf("代码长度:%dBytes\r\n",applenth);
    2 B. u6 e; B/ Q. b1 g
  88. 88                 }else oldcount=USART_RX_CNT;            
    $ A( r1 w! `- L
  89. 89             }
    $ t# v3 F+ b. h4 l) U' z  }
  90. 90 $ O' Z, @0 p' a6 a$ _  m1 g  T
  91. 91             delay_ms(10);% B- x# _1 x1 w+ `" J* p! h
  92. 92
    : x3 S& D+ G! X3 j4 E
  93. 93             key=KEY_Scan();
      b  k  L# Z* n% M4 }$ t
  94. 94             if(key==KEY1)
    ! I" c+ a9 G6 F" {7 [3 A
  95. 95             {: u+ G8 F- S: o& I2 b+ g: c  k' Q4 z
  96. 96                 printf("KEY1!!\r\n");: s6 k9 Q* e8 X4 s# g" D
  97. 97                 if(applenth)
    ( ], ]! J  T3 _& d( J
  98. 98                 {
    # g' H' q7 v  l
  99. 99                     printf("开始更新固件...\r\n");    4 ~7 |! f3 M# \, f0 ?4 A) _
  100. 100 //                    LCD_ShowString(60,210,200,16,16,"Copying APP2FLASH...");
    2 U! F1 n. q- m6 W% D
  101. 101                      if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
    . ?8 F; X* u. _9 m& m# U0 Z
  102. 102                     {     ( v' b; n8 ~& }9 i( J* g
  103. 103                         iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//更新FLASH代码   
    * I% q3 |' ?) b1 j" D6 |
  104. 104                         delay_ms(100);
    2 B& A0 h0 d7 f% i
  105. 105 //                        LCD_ShowString(60,210,200,16,16,"Copy APP Successed!!");
    - s' M& b9 E/ A2 P0 C) d
  106. 106                         printf("固件更新完成!\r\n");   
    ' y6 D; z$ E: S
  107. 107                     }else . H7 P: d# W$ ], b" B1 @
  108. 108                     {# H2 r& ?& H/ X$ F/ Z6 e- h& j/ r. o
  109. 109 //                        LCD_ShowString(60,210,200,16,16,"Illegal FLASH APP!  ");      
    + {5 F7 H2 a7 f, |) X* \
  110. 110                         printf("非FLASH应用程序!\r\n");
    % b+ e: h. b( e; n, W
  111. 111                     }
    6 ~/ F7 [+ O4 D) y* o8 X* c  @9 H% Y
  112. 112                  }
    & |0 ^" C$ E& ~* {% |
  113. 113                 else 3 g0 k  k1 j9 c4 m. V7 d1 p4 z: H7 E
  114. 114                 {
    / ]% Q; l& i4 P0 g& N
  115. 115                     printf("没有可以更新的固件!\r\n");. [3 j3 i, F# k9 F7 C9 X
  116. 116 //                    LCD_ShowString(60,210,200,16,16,"No APP!");   
    9 X% y# X6 f$ G! D  X
  117. 117                 }
    2 E6 X. Z* o( c. S  D; {
  118. 118                 clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示                                    
    ; y5 c5 A7 v& C5 _; L, A
  119. 119             }& Z% i3 M$ P( Y1 [. b
  120. 120             + u5 V9 M$ |% U& y( Y% L$ ?: n
  121. 121             if(key==KEY2)' f- b: V% o- b; I3 Y- G
  122. 122             {. l/ J3 w0 M+ b: T+ y- U
  123. 123                 printf("KEY2!!\r\n");
    ) O: Y( A. o! y' P# G) S9 O
  124. 124                 if(applenth)
    $ a! o# A8 [2 L# d# H; E( k5 e
  125. 125                 {                                                                     
    0 [9 H0 s1 K# I# _' G
  126. 126                     printf("固件清除完成!\r\n");    : ?( N8 |6 ^" s! ~; `* y5 S
  127. 127 //                    LCD_ShowString(60,210,200,16,16,"APP Erase Successed!");- A3 t+ |2 ]4 i1 ^) [) r9 z
  128. 128                     applenth=0;
    ( c5 c' m  G. e& ^5 g/ }5 V/ z, y
  129. 129                 }else 4 D% M! g6 W" j  l9 j5 J
  130. 130                 {! T# r5 A; O$ n0 z& q4 s& h; l- p
  131. 131                     printf("没有可以清除的固件!\r\n");
    " S* r' V6 m1 }8 r8 h3 T9 _" ^
  132. 132 //                    LCD_ShowString(60,210,200,16,16,"No APP!");, Y3 f8 }  k; p6 g" ?
  133. 133                 }
    5 L" f5 ^3 \* O% C
  134. 134                 clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示                                    
    / A2 k# }7 n, Q" ?6 B
  135. 135             }
    % t5 o+ h# Y! i9 c, p
  136. 136             if(key==KEY3): M9 F  _( d& i) d% Y
  137. 137             {4 i4 ~, g/ Q# H  A& p7 e
  138. 138                 printf("开始执行FLASH用户代码!!\r\n");- @5 p8 I& U2 I, J9 B5 {
  139. 139                 if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX./ E  I6 t% @' P9 V- ^
  140. 140                 {     
    ' z4 r; f) g5 e( D6 a
  141. 141                     iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码6 w; l' U0 X/ T, D7 w" o
  142. 142                 }else
    * |& ^9 ~% t/ ^5 s1 s+ V
  143. 143                 {
    " |/ x" Q0 j8 z5 `
  144. 144                     printf("非FLASH应用程序,无法执行!\r\n");% R1 g. L9 N4 I5 E$ v# i, `' e( H
  145. 145 //                    LCD_ShowString(60,210,200,16,16,"Illegal FLASH APP!");      
    + C7 [( o  B$ W- i$ G  I7 N
  146. 146                 }                                    
    $ h9 \3 _2 h" S5 f8 e$ P; Q
  147. 147                 clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示      
    , G& l1 o. u1 s7 l+ s' b' X6 L
  148. 148             }
    ) K# Q! L6 `* E+ H0 P
  149. 149             if(key==KEY4)' N' d- i! |3 {  ^6 ^& S
  150. 150             {; ]8 ?  o$ y. t, Y
  151. 151                 printf("开始执行SRAM用户代码!!\r\n");
    5 u" X6 X+ Z; t( N9 A
  152. 152                 if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x20000000)//判断是否为0X20XXXXXX.7 N5 y% {3 J$ X$ B
  153. 153                 {     6 J: P- h8 ]# ^. |8 u
  154. 154                     iap_load_app(0X20001000);//SRAM地址
    1 u5 Q, t/ k# o& V, Q$ _
  155. 155                 }else ( r5 ?, m) L8 @; H' J, @
  156. 156                 {
      z( w2 h; M/ C- z$ i9 R
  157. 157                     printf("非SRAM应用程序,无法执行!\r\n");4 t* ~' r' W' N4 i/ l
  158. 158 //                    LCD_ShowString(60,210,200,16,16,"Illegal SRAM APP!");      
    : h+ u5 f9 i0 U3 p4 D* M
  159. 159                 }                                     ' ^; L) B  c6 E4 B6 o$ Z* d
  160. 160                 clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示     0 b9 I5 F0 B' w. Q% V2 v2 T1 D: S
  161. 161             }                   " d1 v+ n) u$ `! d, M3 ^
  162. 162                  
    ) s7 F: {# v) p/ ^8 g1 e
  163. 163           }         
    ) n  d* n9 L& V# g9 }- T
  164. 164
    2 Q2 B' ?" f: N/ |* q# T' G
  165. 165 % g/ V. f; w* C9 P+ e- B! a
  166. 166         
    : ]) O) D) [5 ?! E" s
  167. 167 }. e) [* q$ X, }4 l6 X( J; v
  168. 168
    : W7 f: Z# m4 F+ f
  169. 169 /**$ M) n( P  w5 D( C
  170. 170   * @brief  Retargets the C library printf function to the USART.
    6 D, K1 G9 `9 ?& x/ M3 w
  171. 171   * @param  None$ \9 ?+ g+ ~, D# J; R6 P, P# S: \
  172. 172   * @retval None
    + K* D' }9 ?) M8 _* ~2 o; V' F
  173. 173   *// Z2 P; ]' l: Z
  174. 174 PUTCHAR_PROTOTYPE( A) P* p5 T2 v# q; S# E& ~/ \) q; Y
  175. 175 {
    1 M+ |* U& V( U3 \1 h! L& Z! ?
  176. 176   /* Place your implementation of fputc here */0 I. @! J( v% M2 m
  177. 177   /* e.g. write a character to the USART */
    ! N8 v# |' a/ t6 ~$ d1 g6 D
  178. 178 //  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)7 P- e. D9 C$ u- i& V* p
  179. 179 //  {}
    3 ~1 z0 G  b* s4 d0 K8 `+ l5 C
  180. 180 //
    : y- h* N* V& I1 {
  181. 181 //  USART_SendData(USART1, (uint8_t) ch);0 M0 x/ \7 Y, l2 U
  182. 182 ) H! w7 n# H# R( ^. ^1 ]
  183. 183   while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)9 T& P  H5 y" e- h0 ], `9 ]
  184. 184   {}/ x# ~, S9 }! Z, r6 k* b
  185. 185 ( O5 j/ ?3 D5 O3 K+ S( z" r
  186. 186   USART_SendData(USART2, (uint8_t) ch);
    3 I$ X7 V, R8 h6 B1 E' R
  187. 187 ) _* }; j7 I% G
  188. 188   /* Loop until the end of transmission */
    * [+ F$ c- W' O/ f
  189. 189 //  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
    9 M# D5 N  w' _4 \& i- f
  190. 190 //  {}
    $ O8 L3 e0 l! m; ^
  191. 191 / ~5 F! l( W6 t. I. O3 R7 f% l
  192. 192   return ch;
    - Y; N4 j+ f) Z- @# R8 [# Y8 @3 x
  193. 193 }1 u' Q3 E0 @# T
  194. 194
    1 d2 s7 g* P. }4 X" B- _  I0 O6 m& ?7 ]  U
  195. 195 0 P! m3 K! [8 e
  196. 196 #ifdef  USE_FULL_ASSERT- G/ y9 x' ^& L' Z" j7 }
  197. 197 % p* T. I2 [& U
  198. 198 /**
    - O2 u3 B5 L& e+ U  z& {  Y5 N
  199. 199   * @brief  Reports the name of the source file and the source line number
    5 s. s, A) Q# I( U
  200. 200   *   where the assert_param error has occurred.) `: r& T/ E. E, \
  201. 201   * @param  file: pointer to the source file name# Y) Z9 u' ^  o. Q* o) c: }! J
  202. 202   * @param  line: assert_param error line source number
    . h# E9 L9 l% F1 m2 I8 M* {( @/ m
  203. 203   * @retval None( \3 [5 N7 H1 f3 r
  204. 204   */- F7 J  j# N% O, \" u% Q0 i  j
  205. 205 void assert_failed(uint8_t* file, uint32_t line)
    6 B- V6 v) c  H
  206. 206 {   k' j$ m  m: M7 X* n
  207. 207   /* User can add his own implementation to report the file name and line number,
    ( {1 O1 w+ K& A# b7 g- o1 S* \
  208. 208      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    4 ]- k$ O! `* ~8 D) b  _
  209. 209 7 K3 y: q6 A7 q/ h2 ^: ^
  210. 210   /* Infinite loop */
    8 l. r# b$ ^3 G# \, E5 U
  211. 211   while (1)
    . _) N6 W6 n7 c5 |1 s7 ~
  212. 212   {
    " Y' P2 N4 u: L' Z& ^7 ^
  213. 213   }
    3 A2 A8 {% U: ]# x# D5 ?
  214. 214 }
    0 J, D1 O% s, D; `8 j. x- v
  215. 215 #endif$ `9 Y# L- P5 P
  216. 216
    ! \2 Z* t) _9 H; n
  217. 217 /**. h( x% G* S7 [7 O( F
  218. 218   * @}% e: y( H4 k; Q2 m+ x
  219. 219   */- J0 @* [: n( I4 H6 @
  220. 220 9 U; L$ x7 w, g6 o6 G% L  e" ?
  221. 221
    3 ?% N0 z1 }7 H
  222. 222 /******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/8 f2 }! R4 b+ _8 e- A" Q$ R6 c( X
复制代码
  T! z9 G0 M5 w- m7 V- V9 @5 U
我们把程序自己写入片上flash,还需要一些函数
  1. 1 #include "stm32f10x.h"
    ' T: f- i6 x& W0 b
  2.   2 #include "stm32f10x_gpio.h"
    . A- ]! d8 {0 C; L% j" g
  3.   3 #include "stm32f10x_rcc.h"
    3 Z, \( w; j* z( p" L8 p
  4.   4 #include "stm32f10x_rtc.h"; C2 z; T4 }4 F- H* O$ M
  5.   5 #include "stmflash_config.h"
    , I% }7 ~& m$ H, p5 U: X( m- d: d
  6.   6 #include "systick_config.h"( ]1 K: d. h( r7 ^, @' Y* l* I! _4 V& @
  7.   7
    5 t3 w. I: r* {# S; m- z
  8.   8 //读取指定地址的半字(16位数据)9 o) e- J! Z0 d; {" }+ s- F
  9.   9 //faddr:读地址(此地址必须为2的倍数!!)
    + z, x% r/ s, U4 z: z2 T3 o
  10. 10 //返回值:对应数据." E7 u# M5 B. Y3 {. t# ^) C  D1 H* w
  11. 11 u16 STMFLASH_ReadHalfWord(u32 faddr)3 H. {. P+ u( [. Q9 t0 t1 D
  12. 12 {7 L' `  c0 P6 e
  13. 13     return *(vu16*)faddr;   n% I% }! N4 k" y) y% ?
  14. 14 }
    # M$ A+ K" M$ S( @) ]8 X0 a
  15. 15 5 ^, c9 b* ?5 R9 @. r
  16. 16 #if STM32_FLASH_WREN    //如果使能了写   ; h# X! c/ N' D+ T& N6 Y2 Z/ [" ^
  17. 17 //不检查的写入
    8 D- |7 x. S) j
  18. 18 //WriteAddr:起始地址
    . s1 A5 A: m$ |
  19. 19 //pBuffer:数据指针
    3 H( ^. k6 }5 w5 V4 Y
  20. 20 //NumToWrite:半字(16位)数   , j! F, Z, A, [3 S3 X! I- K
  21. 21 void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)   
    0 O* C! c, N/ N9 C, Q/ s
  22. 22 {                       
    - N$ ~; u7 W% N( {8 \& N
  23. 23     u16 i;; w) [  d+ O6 {
  24. 24     for(i=0;i<NumToWrite;i++)4 x* j. A' f/ h/ G, }# H
  25. 25     {1 K* Q, |7 v0 `% s
  26. 26         FLASH_ProgramHalfWord(WriteAddr,pBuffer[i]);1 ]2 L4 c) h- P  K. D
  27. 27         WriteAddr+=2;//地址增加2.
    ; ~8 f1 Z/ u- M% u
  28. 28     }  
    ! @" x& j# `; Y3 n! Q3 `
  29. 29 }/ Q' @7 o- e' B  v( {) J( l
  30. 30
    ( V6 W  P; ?3 b
  31. 31 //从指定地址开始写入指定长度的数据$ R$ z$ w; S' i/ |3 g+ M1 V
  32. 32 //WriteAddr:起始地址(此地址必须为2的倍数!!)
    : i$ p3 G. z: q" q, ]* z0 |
  33. 33 //pBuffer:数据指针5 Z, D2 E; U* e, |
  34. 34 //NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
    & K7 s. ]; i4 J# O* _
  35. 35 #if STM32_FLASH_SIZE<256
    % O- o  Q) z# m; B2 b5 e+ u
  36. 36 #define STM_SECTOR_SIZE 1024 //字节# d$ b4 y! [& ]$ d( h! S2 \* K
  37. 37 #else
    1 r/ x9 Y, E% k: b3 h
  38. 38 #define STM_SECTOR_SIZE    2048$ o/ }7 \9 w; E& B. B3 F# w
  39. 39 #endif         
    ! r7 t$ H" b4 P! }; T, r
  40. 40 u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];//最多是2K字节
    6 p/ E- [; b' h9 Z4 a$ `6 H8 Z
  41. 41 void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)    * t6 R0 e: y, {/ h
  42. 42 {# }/ @+ I, i7 J$ T, ]$ F
  43. 43     u32 secpos;       //扇区地址
    ' k5 M  d0 C( `9 G1 W' j
  44. 44     u16 secoff;       //扇区内偏移地址(16位字计算)/ v" |% i; Z5 H; l, {* J
  45. 45     u16 secremain; //扇区内剩余地址(16位字计算)      
    6 \! L! M1 {0 e4 y3 t- Q. o$ j
  46. 46      u16 i;    # X' J9 \& O' V! C5 m. K
  47. 47     u32 offaddr;   //去掉0X08000000后的地址
    ' u2 ?3 |  o+ j5 C
  48. 48     if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址) i' @4 K2 p  @2 h; k
  49. 49     FLASH_Unlock();                        //解锁2 u5 L+ x" v3 _& c$ w- ~
  50. 50     offaddr=WriteAddr-STM32_FLASH_BASE;        //实际偏移地址.
    7 g& D, ^, P7 o: f. q
  51. 51     secpos=offaddr/STM_SECTOR_SIZE;            //扇区地址  0~127 for STM32F103RBT6
    2 ?4 y6 t( X2 c, B
  52. 52     secoff=(offaddr%STM_SECTOR_SIZE)/2;        //在扇区内的偏移(2个字节为基本单位.)
    $ M( f& v9 g. M4 ?9 X8 X
  53. 53     secremain=STM_SECTOR_SIZE/2-secoff;        //扇区剩余空间大小   
    ( ^' }6 @/ P5 X  H8 ^5 k. ]
  54. 54     if(NumToWrite<=secremain)secremain=NumToWrite;//不大于该扇区范围- I, l* y/ T/ J7 q9 @, H
  55. 55     while(1)
    * R/ u# c0 G: m  G# E( L
  56. 56     {   
    ! o( Q+ Z( ~  K( L, n
  57. 57         STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整个扇区的内容# ^$ n0 k, D5 ?5 u- m6 I/ a
  58. 58         for(i=0;i<secremain;i++)//校验数据6 A$ N7 [/ J; c! m2 q' m
  59. 59         {& r- [+ Q6 }  a9 Q+ u8 {
  60. 60             if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除        * u7 f/ [+ k7 D
  61. 61         }: W' i6 y# Z5 P- u  ?8 w- Z* w
  62. 62         if(i<secremain)//需要擦除4 }3 a( m# X2 j8 v
  63. 63         {# R* q1 d1 M: ~! q3 j
  64. 64             FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除这个扇区; `% w0 A) X/ z- O& G6 H7 I! N
  65. 65             for(i=0;i<secremain;i++)//复制* I, A* o0 x7 h
  66. 66             {
    5 ?6 G) C# ~( S2 q" D, ?0 C
  67. 67                 STMFLASH_BUF[i+secoff]=pBuffer[i];      $ x  N0 O0 v: V( v; \1 Q/ Y7 C
  68. 68             }
    % J" k* N% m' k2 s+ N! c6 d
  69. 69             STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//写入整个扇区  ' C5 V8 U* n6 V3 T
  70. 70         }else STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//写已经擦除了的,直接写入扇区剩余区间.                    
    9 N) R) L3 p7 {- d; h+ q& P$ S" h
  71. 71         if(NumToWrite==secremain)break;//写入结束了* s; q0 g$ H4 l( k; {* O. S
  72. 72         else//写入未结束
    6 S- J+ V, C) X1 D- |! {! A
  73. 73         {
    4 V9 N9 K- O* W1 p; C8 \
  74. 74             secpos++;                //扇区地址增13 G9 V7 ]9 w& s7 m" W9 u; q# ?, h
  75. 75             secoff=0;                //偏移位置为0      
    ! D: h$ S; J: ^/ {
  76. 76                pBuffer+=secremain;      //指针偏移/ H$ c6 n# M* N2 W% Z
  77. 77             WriteAddr+=secremain;    //写地址偏移      
    5 a$ q5 Z+ c! n5 a) u4 J0 \6 Q
  78. 78                NumToWrite-=secremain;    //字节(16位)数递减& R1 o8 k5 ]* K  f1 d6 \- r
  79. 79             if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一个扇区还是写不完
    6 Y: q& A. T& ?2 U( M' [
  80. 80             else secremain=NumToWrite;//下一个扇区可以写完了( g- w6 s0 F3 O: t4 a' P$ Y
  81. 81         }     / l# N" N) d7 a# s
  82. 82     };   
    8 @0 ~6 A! `: M( Y4 Z+ w$ H5 T
  83. 83     FLASH_Lock();//上锁
    0 y+ e$ [2 e' {! y
  84. 84 }$ t7 t/ h- _$ z$ l2 M
  85. 85 #endif
    * l; ]1 }. E! @/ X$ l- ~- o- X4 n
  86. 86
    ) k0 w2 _2 h+ i# U4 w: J
  87. 87 3 `- l. t+ j* N
  88. 88 //从指定地址开始读出指定长度的数据) [7 n% J( B) C+ [8 ^- s6 N0 V  M
  89. 89 //ReadAddr:起始地址* q9 A$ I' |  T+ z0 ?
  90. 90 //pBuffer:数据指针
    ' X1 j- e" V) L
  91. 91 //NumToWrite:半字(16位)数
    8 c/ J; G2 x9 \: |% B
  92. 92 void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)      
    6 W2 b6 R) b* ^; n: S" S+ E: X& e
  93. 93 {) I: i  g+ q: E- P& R
  94. 94     u16 i;
    ! L2 L1 L2 |' s7 U
  95. 95     for(i=0;i<NumToRead;i++)0 G4 j. p. m# @- X. \8 Y
  96. 96     {
    % W2 U! z8 p( f7 e
  97. 97         pBuffer[i]=STMFLASH_ReadHalfWord(ReadAddr);//读取2个字节.
    ; ]: p/ |$ d- S" o9 {) A# F
  98. 98         ReadAddr+=2;//偏移2个字节.   
    1 a- m# F) }% b4 n$ r
  99. 99     }
    # o$ _7 n+ ?& ?7 w
  100. 100 }
    , g+ y- A2 U( Y  {
复制代码
, |9 O* g- Z' q+ S. p* z
主要就是在iap里面用了void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
- N* N7 X' e* ^; k: [) N) V3 n
收藏 评论0 发布时间:2022-1-31 16:00

举报

0个回答

所属标签

相似分享

官网相关资源

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