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

笔记---基于HAL库的M0在应用升级IAP

[复制链接]
power568 发布时间:2019-4-17 09:44
本帖最后由 power568 于 2019-4-19 06:41 编辑
3 _) [* i  H  r, Y$ S: r2 K. k
& {  O: l$ V; j1 ~  O       虽然之前看过STM32的在应用升级IAP,但是一直没有亲自实验过,最近心血来潮准备体验一下。具体的实现原理这里就不再描述,网上的资料很多。因为M0的APP实现方式不同于M0+、M3、M4等内核的实现方式,所以在这里做个笔记。
$ @# W9 o& r/ i! a. G, Z) v1 r- [3 t& |8 {, a) Q" p3 e! G
       实验平台:
# f" K$ p! k7 a7 c       硬件: STM32F072 Nucleo开发板
9 t7 F( D3 J% _2 x# \& q3 d0 ^/ R       软件: HAL库; |; L# Q1 S- v. |
       工具: IAR7 ^. Z6 ^. w2 ]9 E4 k7 s
       参考: STSW-STM32116————官方提供的F0例程(AN4065)& f" g& v) [& L/ {0 s1 c
" D( Y7 U( L! |1 a2 T! ]4 t' p

( d' y$ q! u. z一、IAP工程功能
9 B5 Q* y; c3 H/ [       上电后执行IAP,在跳转到APP之前,使用PC6控制LED翻转5次,再检测APP跳转条件,满足后跳转到APP。. u0 ?$ _  d- E; q; d
       使用CubeMx生成工程之后。增加FLASH_If_Init函数,以初始化Flash,具体代码如下:7 {3 W* k, [" m+ C) J! A: u( G
! @1 a2 u. S, C2 _' r$ q
  1. void FLASH_If_Init(void)" o0 h% X" k- Y& ~% [6 A( d( N
  2. { 6 J: x. S& j% O6 P- H# h6 p
  3.   /* Unlock the Program memory */0 {* H" S2 K) k
  4.   HAL_FLASH_Unlock();
    8 i, s: j  q2 q; n5 H/ q3 r' y

  5. ) H1 J/ q0 r& q4 f
  6.   /* Clear all FLASH flags */  ; ?+ Z. }( K7 t1 y) l
  7.   __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP|FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR );) D& S/ D% A7 Y& e/ K# A
  8. }
复制代码
      具体main函数如下:
% K- c: a1 \# ~% P" N  [
  1. int main(void)+ i( \5 T& R% u+ i+ c+ q! }
  2. {
    $ b2 r# T: Y; b& v( y
  3.   uint8_t  num = 0;
    & s# I7 N# ?2 A
  4.   uint32_t tmp=0;
    ( w) @% m- N0 x2 H  j+ N+ y
  5.   8 M- |+ Z. l) l0 m( b
  6.   FLASH_If_Init();% O0 C7 p) b" d' d
  7.   HAL_Init();0 y- m2 u  m" o, k" g% @$ d
  8. # @: }0 K! \. w& j( G1 }' W' p& ?' u
  9.   SystemClock_Config();
    " R9 x* y8 P6 _- ^, Z* x
  10.   MX_GPIO_Init();( n: N7 n8 k, H. P
  11.   
      S% u! s: \+ m. @8 a! N& t
  12.   for ( num=0; num<5; num ++)
    & r! d+ ~$ G9 s3 k4 s% }' n
  13.   {
    0 c4 a! |; C: D2 h/ h
  14.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
    ) o' ~& k+ n9 w' t0 C7 O, T2 g8 t
  15.    
    0 T' w2 m  R  z. s% N
  16.     for (tmp=0; tmp<300000; tmp ++);, \/ n/ {# L) E# D
  17.    
    ( N0 J, a' q7 l
  18.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);6 t. \: F3 Q0 j5 K
  19.     ; q0 j! @, C; q; {0 f3 y
  20.     for (tmp=0; tmp<300000; tmp ++);. p+ A' D  y4 q& `! M/ c. q
  21.   }
    ( ^0 [0 l5 D4 ?
  22.   4 b4 U8 A( i9 q- D3 U' T0 |* D
  23.          //// 判断APP的地址处是否已经下载了APP程序# ?( n, ^0 O) x# A
  24.   if ( ((*(__IO uint32_t *)APP_ADDR)&0x2FFE0000)==0x20000000 )
    6 Q, M' b, y" H* f! ?
  25.   {
    / V! t& F/ |5 [) I. d# F
  26.     JumpAddr = *(__IO uint32_t *)(APP_ADDR + 4); //// 设置APP复位中断入口地址
    6 L, [3 v! L4 J& |1 d
  27.     JumpApp = (pFunction)JumpAddr;4 `7 E$ m3 m. x5 R2 f5 r
  28.     __set_MSP(*(__IO uint32_t *)APP_ADDR); //// 设置APP栈顶地址
    , t- d% y+ i8 r2 M' ?* o- q! q
  29.     JumpApp(); //// 跳转到APP
    3 P& U1 O6 _- q; u6 E
  30.   }! g" y0 G$ m! \8 h
  31.   # z8 Q8 K4 O! C" P
  32.   while (1);
    $ }" C7 w, Y5 e4 e* h& K
  33. }
复制代码
二、APP工程功能6 ?8 J+ L0 |( e+ L* a
       由于在网上看见之前有在验证APP时,有各种现象——外部中断、串口中断和定时器中断等不响应,所以设计的工具比较多一下,看看具体有没有问题。% r7 L) k' i" l6 K% f$ Y# ~
       功能1、外部中断——PA0上升沿触发外部中断,在中断内翻转PC9;: e! G) u$ N* U1 h' ~% f9 T- W, O
       功能2、TIM3定时中断——在中断内翻转PC7;
  S( Q) C$ b' q5 X3 J8 T: B6 b+ P% r       功能3、串口1空闲中断——接收到的数据正确后,翻转PC8;
' `) t. b* P7 G( T& [6 @       功能4、主函数循环执行以下功能——开启串口DMA接收数据、串口发送数据、PC6状态翻转、延时。
" A, X. n% b+ h/ A# x. T1 \       PC6~PC9输出控制LED灯。% ~. Y/ S7 z0 K2 g- {* L

3 @; p- x. q9 U9 Z) Y9 g7 A1 B! h1 P" j6 Y6 ^. A" H
       F0属于M0内核,不同于M0+、M3和M4等内核,没有专门的中断向量控制寄存器,中断向量的设置只能采用拷贝到SRAM方式。具体实现方式——定义一个位于SRAM首地址全局数组变量,将M0的所有中断入口地址拷贝到该变量内,再将SRAM的地址映射到地址0x00000000,发生中断后,MCU自动从地址0x00000000对应的偏移处寻找中断入口,如下:8 |6 C2 f- D- f4 O
  1. ///// 定义全局数组以存储中断向量表,M0共48个
      j! ]& |  `  U7 O0 c$ J0 Q) y$ \8 J( W" }
  2. #if (defined (__CC_ARM) ) //// for keil MDK compiler3 l# Q/ `' Q) W- E6 I7 t
  3. __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
    2 x( }, U+ \( o) E$ f2 U
  4. #elif (defined (__ICCARM__) ) //// for IAR compiler
    7 K' g1 j+ A/ G0 L( R) x
  5. #pragma location=0x200000005 u8 @6 Q8 T7 e
  6. __no_init __IO uint32_t VectorTable[48];
    2 A! x/ }, \2 a7 s* D" W9 p
  7. #elif (defined ( __GNUC__) ) //// for GNU compiler: @) F: p2 t" j7 Z. p
  8. __IO uint32_t VectorTable[48] attribute__((section(".RAMVectorTable")));, Y0 p. @% l7 I9 t
  9. #elif (defined ( __TASKING__) ) //// for TASKING compiler
    5 P1 z# @  b0 S: Q
  10. __IO uint32_t VectorTable[48] at(0x20000000);- S' t! R$ l) X2 C0 Q! v
  11. #endif
    8 z4 ]6 P6 |7 j! N. }0 H% p
  12. : G) j- d; J% s/ |; }1 E6 Q
  13. //// interrupt vector remapping# n& r" K* y/ x! H
  14. void AppVectorTblRemap(void)0 n- J4 e  Q; z& T" `) k9 @
  15. {0 M; W5 p4 F& t* M( p+ R
  16.   uint8_t     tmp;% {2 b* O8 b5 U: r* b4 v
  17.   uint32_t    tmpCfgr=0;' ?  D) h% A5 `
  18.   
    ! U2 K3 h* A) u  A) q' ~7 a; b" W
  19.         //// copy interrupt vector
    . W% L+ F- o) J3 n
  20.   for (tmp=0; 48>tmp; tmp++)3 T: ?' r' K3 \0 U4 o
  21.   {' c- r6 t0 r" p+ B
  22.                 //// because size of interrupt vector's address is 4, so tmp+=4(be equal to
    ' O( C- k4 }" i8 x6 y
  23.                 //// tmp<<=2);
    9 ]) n* y- h, ?2 m# g  V3 L
  24.     VectorTable[tmp] = *( __IO uint32_t *)(APP_FLASH_ADDR + (tmp<<2));2 m, ~6 ?9 L. B1 b3 ?3 x' e/ n0 T
  25.   }6 C: m* x9 g% @# x1 F+ C# b) K3 u
  26.   ! A% Y* n) }4 f, V( D0 \
  27.   __HAL_RCC_SYSCFG_CLK_ENABLE();) n% W( [$ M* O& X) J. D) y+ d/ K
  28.   tmpCfgr = SYSCFG->CFGR1;+ n9 ^/ ]+ w; I/ [) i+ H2 _
  29.   tmpCfgr &= (uint32_t)(~SYSCFG_CFGR1_MEM_MODE_Msk);
    # v# N4 N8 `( S
  30.   tmpCfgr |= (uint32_t)0x03; //// embedded SRAM mapped at 0x0000 00008 S0 F& m9 R; o5 c; P9 ~! Z  e  i
  31.   SYSCFG->CFGR1 = tmpCfgr;
    ) H7 h5 t, V' p4 z8 b7 k: H
  32. }
复制代码
      其余代码实现如下:0 @' g' U  l6 \- M
  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)' G6 M& |  K. w* @# y$ A3 Z
  2. {& X8 k, w0 S9 U- G1 D3 \7 x8 o; M
  3.   if (TIM3==htim->Instance)% p' ?# F# r1 h/ r' z
  4.   {
    + R5 z3 R  m  I. }$ V% ^5 ?
  5.     TimerBitSta ^= 1;
    $ u) U' s! I, f- `1 l- B
  6.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, (GPIO_PinState)TimerBitSta);
    6 w! t3 Z/ Y, G: N+ q4 Y) L: {: S# N! c
  7.   }9 A0 F9 B8 K; W6 @
  8. }6 {' G5 ~' E4 y6 ~) d; j

  9. 0 P" G4 X' J5 `" M
  10. void Exit0IrqCb(void)$ \2 D, }% R! ~# Q
  11. {
    1 l& \$ ]. D- A" G% P* c9 u3 |
  12.   if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0))) I$ V8 x; d0 S" H
  13.   {) n' a4 e, r: B! w- Q+ _' s* x
  14.     ExitBitSta ^= 1;9 q! a  J" W6 C3 ?" |  Q
  15.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, (GPIO_PinState)ExitBitSta);. O! o# @1 e; O/ K
  16.     __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);8 ^$ D* `6 R; F) F
  17.   }
    0 W9 P6 o  }! Z# E% G5 \
  18. }
    8 ?5 O! G" w3 s4 H/ Z$ n' d

  19. ' Q6 R# i) S; u0 A! q1 h$ k
  20. void Usart1IrqCb(void)
    , _8 Q! N1 n* `% B! n! F  O- e1 C
  21. {
    8 D+ x6 g/ W$ k- S, @
  22.   if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
    , I+ U: Z/ P" {4 k: U8 ~6 d
  23.   {
    . \6 Y4 y( L7 ]
  24.     USART1->ISR;
    2 ^+ T4 o8 z" R8 ~
  25.     USART1->RDR;  g; ?) L/ o% e, ~' W3 U9 O
  26.       
    9 I2 B0 T% c  w" |1 z8 N9 m# X
  27.     if ( (1==TestUartRcvBuf[0]) && (5==TestUartRcvBuf[4]) )
    6 c9 R% a2 c& N( W
  28.     {8 n0 u; M+ }6 z* T1 v( P
  29.       UsartBitSta ^= 1;
    - C6 }. u- W0 Y+ `! y9 m/ W
  30.       HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, (GPIO_PinState)UsartBitSta);
    : Y% r) B, Q# |6 ^
  31.       TestUartRcvBuf[0] = 0;
    8 n7 [, ]" _' k. l3 ^+ V: [
  32.       TestUartRcvBuf[4] = 0;4 N: u" _& n$ u' C2 s
  33.     }9 w% _: H% [- }( Z6 d
  34.     ' U# P! h. i3 c: `6 N% W6 R
  35.   }! Y3 W: }* Z0 ^; P6 ]0 u$ Q  L
  36.   HAL_UART_AbortReceive_IT(&huart1);
    0 i8 b. Q* a0 E' Z# F
  37.   HAL_UART_DMAStop(&huart1);7 o3 ^, E/ w2 h
  38.   __HAL_UART_CLEAR_IT(&huart1, UART_FLAG_IDLE);2 s1 `$ b7 F; J8 \3 q
  39. }
复制代码
      中断服务程序:! }2 T4 s" A& ^1 |
  1. void EXTI0_1_IRQHandler(void)9 v* d" c6 Q3 ?! w) g  O7 n6 {/ K4 X
  2. {, a9 a* K/ V, p7 [) X6 o
  3.   ( m1 H- M; q+ D
  4.   Exit0IrqCb();
    # Q( ~! t9 }# Y( s+ `" H
  5. }* o3 k3 `0 g, c6 i3 K- D1 }

  6. 5 q7 e* |- l: d" U4 v$ u. f2 t0 a

  7. 3 ?( H' l" r# H7 V
  8. , [7 k/ u6 M- M& M
  9. /**5 f+ |* g/ a3 P
  10.   * @brief This function handles TIM3 global interrupt.6 m6 \2 N! V) Z8 g3 d
  11.   */: ?! y3 E9 @1 X! E, o  A
  12. void TIM3_IRQHandler(void)
    # D' B( a* F( J0 N+ e/ d6 T
  13. {% I, v* i  C+ G+ u1 h! {' q
  14.   /* USER CODE BEGIN TIM3_IRQn 0 */
    3 }  C' e' w; f# t9 l* l# g1 c. x5 x
  15. 5 E9 \: ?% o4 T& Z( @/ o
  16.   /* USER CODE END TIM3_IRQn 0 */
    / O# u) o0 a( b+ F( M" F8 T
  17.   HAL_TIM_IRQHandler(&htim3);
    6 z7 x; \' s4 O
  18.   /* USER CODE BEGIN TIM3_IRQn 1 *// J% b; B+ R, c% H
  19. % o3 x7 I  _) @1 l
  20.   /* USER CODE END TIM3_IRQn 1 */. W$ J5 m0 N0 r6 F  \4 m
  21. }
    $ {: m" Y- ?. t/ I$ E
  22. 7 P, x3 s( x$ b* M. e

  23. " i5 o1 j7 v2 z/ {
  24. void USART1_IRQHandler(void); n6 k2 z) p2 L
  25. {
      j: L9 Q! X6 U
  26.   /* USER CODE BEGIN USART1_IRQn 0 */9 n5 q/ I, l) F- C- v
  27.   Usart1IrqCb();& ^% I4 }1 b: z: G' i
  28.   /* USER CODE END USART1_IRQn 0 */9 H- k; w# Q8 b0 Z! @* p0 D! W
  29.   HAL_UART_IRQHandler(&huart1);
    2 t+ j* ]! O$ i1 `2 F, p* P3 P# z
  30.   /* USER CODE BEGIN USART1_IRQn 1 */
    - C( Q% r! Y1 a% m1 V; _/ S: C

  31. + O' V5 h5 z7 ~
  32.   /* USER CODE END USART1_IRQn 1 */. j% P1 L. q9 O( ~& J. S" Z2 m
  33. }
复制代码
      主程序:
; {& O3 y! c. D/ K) n" t
  1. int main(void)& {2 w+ p, t$ a: @+ x  p2 @
  2. {
    5 D' ?3 c+ a/ V. M' {
  3.   /* USER CODE BEGIN 1 */" |- a/ ^0 j+ i: r( y
  4.   uint32_t tmp;: ~; M8 c. g7 D2 n
  5.   
      U( r' E' |6 o3 ~
  6.   AppVectorTblRemap();. q2 i( g( D3 w1 k* c2 M: l( T
  7.   /* USER CODE END 1 */2 s0 G1 l2 A& z: `' u. I
  8. 8 P' ]. H0 v3 Y. \
  9.   /* MCU Configuration--------------------------------------------------------*/
    # S/ B" G6 L7 M7 D0 V. s
  10. 7 r7 l2 T3 _* y: e! v, s* q) s1 T- H% [. Y
  11.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    # l# d+ t6 n  R% n/ ?' I, I( M
  12.   HAL_Init();: i! A4 r: n5 ]& T: l; X9 l

  13. * [8 U: L+ o$ |0 Q9 f
  14.   /* USER CODE BEGIN Init */
    2 s0 A9 S! G5 k) X1 O& I. G# j! P
  15. 2 U% i- d' t' A* |2 X
  16.   /* USER CODE END Init */
    : F1 c1 J& y, |: k! s7 d5 i6 V2 t4 }
  17. ) l4 i* c4 L( _. v. k
  18.   /* Configure the system clock */
    ' g, R) e  j# u6 i
  19.   SystemClock_Config();
    - v- L( W% Z4 J1 [

  20. ' x2 Y9 _$ ~$ t4 c2 S3 X" ~
  21.   /* USER CODE BEGIN SysInit */9 l+ b/ c( N% \' _) s

  22. * G% A. J, T- D
  23.   /* USER CODE END SysInit */# }9 z' p2 M: ^- U! I0 o+ Q8 P

  24. # j8 r! b3 n/ O0 _. ~# k! g
  25.   /* Initialize all configured peripherals */
    ) |+ H7 F6 _5 J1 P
  26.   MX_GPIO_Init();
    % D) V  x1 W( j( i' A. T
  27.   MX_DMA_Init();
    ; g: c6 a: y5 F1 A: i
  28.   MX_USART1_UART_Init();
    2 P! N9 {5 Q! M8 B2 @
  29.   MX_TIM3_Init();
    % D& e9 W3 d2 X" w6 S0 R  |: s- z. J
  30.   HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
    0 g5 ^7 g! @$ _+ @* L+ B
  31.   
    3 X& f1 f' @+ n8 d+ B3 @
  32.   /* USER CODE BEGIN 2 */7 W& a: z+ ~# X, H8 h9 ^6 S! M
  33.   HAL_TIM_Base_Start_IT(&htim3);
    $ E. d9 f- C. E5 i, I- @% |! N
  34.   __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
    ! Q0 _4 j2 i0 g9 j& [$ D0 G
  35.   __set_PRIMASK(0); //// close interrupt in IAP, so open : I6 Q4 ?7 t7 r, y6 A
  36.   
    : N$ s) t0 Y$ _0 U
  37.   /* USER CODE END 2 */
    ' M. ], a7 @8 M3 K% K0 }

  38. 9 m: X% `4 x: R9 ]* z, W
  39.   /* Infinite loop */
    + J9 I0 `( b3 @% m; S# m/ f
  40.   /* USER CODE BEGIN WHILE */& Y5 i5 U  Z  M
  41.   while (1)" {2 b6 W2 y  w' [. p/ z! F; S4 I) h
  42.   {
    * N& y+ Y2 v8 @  J* g& D3 }
  43.     HAL_UART_Receive_DMA(&huart1, TestUartRcvBuf ,UART_BUF_LEN);
    " v4 y8 j; g5 x# k2 W" V
  44.     HAL_UART_Transmit(&huart1, TestUartSndBuf ,UART_BUF_LEN, UART_BUF_LEN);
    - p: O9 n* l+ Z5 p
  45.    
    7 ?* @8 S3 D8 C$ w. ]
  46. ////          HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);7 L$ s: j& p) H# w3 l# O6 v
  47. ////    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET);( C3 H3 _2 t( [! M7 ]8 A6 |
  48.     7 L9 F# a' o5 h9 i/ r- d# M  k$ J
  49. ////    for (tmp=0; tmp<600000; tmp ++);0 O+ g: P& z* |
  50.     : |% I- }: @- D) k/ h/ N
  51.     ; F7 m. `7 n- d5 i- a
  52.     WhileBitSta ^= 1;
    1 i9 v2 C0 X0 j0 c, Y
  53.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, (GPIO_PinState)WhileBitSta);/ v. ~5 X% d7 x) Z: m9 w
  54.     for (tmp=0; tmp<600000; tmp ++);
    + h0 Y' L. _. ]$ ^. W" R
  55.     & d7 h3 _- Q" J1 w7 N( N
  56.     /* USER CODE END WHILE */, `  v/ ]  ~$ O; s1 E- K! V

  57. : `2 W6 r6 b6 w$ U3 w, }8 Y- m
  58.     /* USER CODE BEGIN 3 */
    , E+ A" H  [2 g
  59.   }
    % k( F, `0 s$ ]7 e8 `0 c" F
  60.   /* USER CODE END 3 */+ y/ `9 E8 N: I; Y$ k
  61. }
复制代码
5 L5 C4 y( u& A. |$ `  N+ @
' o# E9 t0 r3 M
       两个工程编译通过后,使用仿真器将执行文件烧录到MCU,程序运行正常。TIM3定时中断你控制的灯一直亮,但是亮度没有其余的灯亮,因为占空比不是100%;测试串口时,使用镊子或者金属片将串口连个引脚短接起来后,在串口中断内控制翻转控制的LED均正常没有出现网上说的中断不响应等问题。9 K! c- r1 L' W7 ^1 |7 I- m, @
       整个工程代码见附件。
; k5 D+ w$ B3 q
; r5 j3 }2 i( p! X       F072TestIap.rar (487.8 KB, 下载次数: 107)

MB1076.pdf

下载

878.24 KB, 下载次数: 26

F072 Nucleo开发板原理图

收藏 8 评论9 发布时间:2019-4-17 09:44

举报

9个回答
STMWoodData 回答时间:2019-4-17 10:07:59
提示: 作者被禁止或删除 内容自动屏蔽
STMCU-管管 回答时间:2019-4-17 10:16:45
感谢分享~
毫无性格特点的果冻 回答时间:2019-9-19 10:54:11
谢谢楼主分享!
generalcircuits 回答时间:2019-9-19 17:04:10
/ y2 I0 p: k' v+ A$ ]' |3 E
谢谢楼主分享!
wdliming-222461 回答时间:2019-11-5 10:29:29
谢谢分享~~
jeffhe1 回答时间:2019-11-5 13:23:48
學習了
wdliming-222461 回答时间:2020-8-10 22:06:50
谢谢分享
zhangjun1105 回答时间:2020-9-3 11:22:10
感谢分享
zhangjun1105 回答时间:2020-9-3 11:22:38
不错,很好的帖子
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版