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

【经验分享】STM32G0学习手册——FreeRTOS信号量

[复制链接]
STMCU小助手 发布时间:2021-11-12 01:00
二值信号量的用法示例% @6 J9 L( z6 _8 H8 N0 s
1.创建好带有printf-stdarg.c的FreeRTOS的工程
: B, A7 ?( p; n# F  g* p0 t* }- }, u( t5 @" k, h: \: ~- y
2.修改main.c文件
/ b' r: Q. A( o& K$ Y1 z& k  r
: ?! {; H  O9 {
  1. /* USER CODE BEGIN Includes */
    9 p2 ]2 z+ O) a

  2. 0 j2 q& z7 R, A; B' h2 q. S" [
  3. #include "FreeRTOS.h"
    " d7 X* L. i* A: Z, Q( u
  4. #include "task.h"
    % P* l) e' p) K: x
  5. #include "queue.h"  A) u; h8 z- |* y# i; v
  6. #include "semphr.h"1 K& |9 Q7 p3 O; J: C
  7. #include <stdio.h>
    4 T+ I4 F* w. j. i5 `( |
  8. #include <string.h>
    ) j2 G% D3 n" D* o6 F, }
  9. % ~' U4 s7 u, Z1 ?
  10. /* USER CODE END Includes */( Q  e; e# X, \, ]! p
  11. /* USER CODE BEGIN PV */
    " k9 H8 r. ~, R9 B

  12. 7 w% ?- q; |% L' A) s  I* q+ Z
  13. static TaskHandle_t AppTaskCreate_Handle = NULL;
    " A7 l/ X3 ^+ f
  14. static TaskHandle_t KeyTask_Handle = NULL;. V* a5 {( f8 U& T/ Q4 ?6 K/ ?$ _
  15. static TaskHandle_t Led1Task_Handle = NULL;
    3 S$ M+ e( B, M3 x+ g, e
  16. / I# i1 S0 f7 G6 ^
  17. /*Create a binary semaphore handle*/
    , s! g# @! I# E( S
  18. static SemaphoreHandle_t Binary_Handle = NULL;2 v) j  M+ B3 r# j, y. f3 n

  19. / d! i# G' b0 I: {  h
  20. extern int f_printf(const char *format, ...);, q, W0 r- L9 V8 `: {" w9 G- }3 h

  21. , \" s2 \/ k( R2 p  q+ B
  22. /* USER CODE END PV */
    3 l2 U4 O# `( i, Q9 e
  23. /* USER CODE BEGIN PFP */
    * e$ X  h# f" `0 ]

  24. 1 \: \8 g# D! y6 X( ^2 i" e" Q5 o
  25. /*Create a task function*/
    0 k$ P+ R! z1 ?. v" v# M
  26. static void AppTaskCreate(void);
    7 S- d, W- |: `
  27. static void KeyTaskCreate(void);
    ! s' s6 }! i( J0 c* i+ [  ?1 S
  28. static void Led1TaskCreate(void);
    " @+ }5 {6 P" N+ {; [  E. K4 I

  29. : c5 z: w# B. y7 M, `0 q
  30. /* USER CODE END PFP */# |6 {) c$ F3 n
  31. 0 c: G  n: V* k# r5 O
  32. int main()
    : v$ y' K5 I3 w& F) W: Q% u
  33. {( w2 x8 w( J3 X1 \
  34.   /*
    1 {/ k$ @7 `2 {( `( Q3 U9 p
  35.   *
    4 L! \3 a3 |3 |
  36.   */
    ) _2 J" R' f- _! t! b; K" U
  37.   /* USER CODE BEGIN WHILE */
    ' m* F1 U4 W3 T
  38.   UBaseType_t xReturn = pdPASS;# ^! [! O, p- W0 k, d5 t: m1 z' y
  39.         & {) h! X: g: v
  40.         xReturn = xTaskCreate((TaskFunction_t)AppTaskCreate,# I  Q& l# Q% Z  v
  41.                               (const char *) "APPTASKCREATE",( J8 X) i" _6 L! n: H0 L# N4 E- v
  42.                                                   (uint16_t)     128,
    " H& K3 ~( O/ t8 ^" h
  43.                                                   (void *)       NULL,
    & }' `0 ?: E9 J
  44.                                                   (UBaseType_t)  2,3 g, U9 V% u% N+ L
  45.                                                   (TaskHandle_t *)&AppTaskCreate_Handle);
    , b6 o8 @/ \0 V' I! a2 ~
  46.   if(xReturn ==pdPASS)8 P' L2 [" n. d0 L$ q
  47.         {
    3 ]* @7 H$ }3 X6 z8 z
  48.                 vTaskStartScheduler();0 g0 `# H5 Y: b9 z; ]
  49.                 f_printf("start..\r\n");
    2 V) M7 {5 I- v( W  W2 [1 p- N
  50.         }
    . _$ I" H$ b- @0 r
  51.   while (1)8 s; L3 k' {9 B9 T, M5 L6 P
  52.   {
    2 H/ A4 u1 \) y) S; a
  53.     /* USER CODE END WHILE */
    + O/ L" t1 O' ]  D! a  x
  54. # r' E% S9 j$ ^5 S9 m
  55.     /* USER CODE BEGIN 3 */! ?, k6 I( ]4 u4 m8 {
  56.   }
    ( T& B2 o+ S- u: ]8 U$ g
  57.   /* USER CODE END 3 */
    - d& c1 F: s' ^, B, A8 k. E

  58. 6 f1 j2 y, C4 Z3 e; ~( f* H8 q

  59. " t* P% p$ Y, V5 N( {
  60. }" u) f) c" n$ X* \9 M8 a& N

  61. 7 q3 y8 @2 u3 @: L3 F
  62. 5 S& U1 S; X" D& Z7 F) M, ^
  63. /* USER CODE BEGIN 4 */% W% {0 U* {/ w* F- C
  64. static void AppTaskCreate(void)
    . D. @. i$ r! Z( I* Z
  65. {  ^8 a6 r/ f1 S7 d  a- g" [
  66.   UBaseType_t xReturn = pdPASS;
    2 M) R- P0 P6 P' K7 s1 c+ {# S
  67. 4 e. I8 I+ `. ^( R
  68. : f$ j0 @' u. g2 n" _
  69.   xReturn = xTaskCreate((TaskFunction_t) KeyTaskCreate,
    8 r( f' i( K4 L4 W9 c8 ~$ e$ l
  70.                              (const char *)   "KEYTASKCREATE",  }: N- _  M4 @  M- t8 I, t
  71.                                                  (uint16_t)       128,( M. [9 A7 t9 c" T, U& l% V
  72.                                                  (void *)         NULL,
    ; X2 L+ N7 Q8 j! P9 H+ i0 T
  73.                                                  (UBaseType_t )   2,  L0 y% Q9 V1 R" Y) t: q# I
  74.                                                  (TaskHandle_t *) &KeyTask_Handle);
    # K" w# m$ S" o( i" {: L/ Y

  75. 9 F! ?) G3 W# Z6 T: v6 C% \
  76.   xReturn = xTaskCreate((TaskFunction_t) Led1TaskCreate,
    6 Z* n1 a8 e/ Z% d/ y4 h
  77.                                                 (const char *)   "LED1TASKCREATE",1 A& }1 K- c$ |; v) ~
  78.                                                 (uint16_t)       128,6 o/ Y& N7 H6 G; y/ {! k
  79.                                                 (void *)         NULL,
    7 i9 l! K& H) e' ~, x5 O/ E
  80.                                                 (UBaseType_t)    1,/ |4 T  d8 X  s* j. U0 h8 M! W6 i
  81.                                                 (TaskHandle_t *)&Led1Task_Handle);
    % Q& P  @; H/ p
  82.         
    6 R. |8 Q. W9 j# s" z* Y& V
  83.     /*Create a binary semaphore*/
    , _8 a8 T' w7 s4 k2 Y
  84.         Binary_Handle = xSemaphoreCreateBinary();
    ) b6 \8 E) T6 h$ w  _
  85.         if(Binary_Handle !=NULL)
      k' K! D4 g' G
  86.                 f_printf("Create Semph_Binary PASS.\r\n");
    6 ]' F! a4 X8 `+ j
  87.         ' A& I0 y; N7 o* }
  88.         if(xReturn == pdPASS)
    " f- _9 e5 |6 s6 ~
  89.     vTaskDelete((TaskHandle_t)AppTaskCreate_Handle);               
    , X5 h$ `. a/ H* m4 H
  90. }! n9 S6 Z1 x/ h8 c$ m

  91. # T+ r9 {/ z% A
  92. static void KeyTaskCreate(void)" f) G3 a, U: f, r
  93. {
    ; A& k3 E& M; @9 ?, ]1 m
  94.   while(1)7 h  u% O6 z: r( w- A" d6 w5 F0 `
  95.         {0 E3 G1 W! N+ s: N3 H" ?, d) N
  96.                 UBaseType_t xReturn = pdPASS;
    * \# e' c- @, C- D& i! u  R. `8 H
  97.                 if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0))
    0 n, P; q6 h) |# @2 W
  98.                 {
    ; r/ j9 u) r. l* u* g
  99.                         f_printf("KEY TASK PASS.\r\n");, \5 s, D! ]7 E  K7 [
  100.                         vTaskDelay(100);
    3 {8 e7 N5 }" _
  101.                         if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0))
    3 F# T7 @) i9 C9 T9 F8 W
  102.                         {
    - H, T2 W* @5 G- `: X8 U6 E
  103.                                 xReturn = xSemaphoreGive(Binary_Handle);
    / e' Y# _6 y! A! F) j  W% Z* [1 B
  104.                                 if(xReturn == pdPASS)) H+ k, ~5 ~9 N2 B6 m
  105.                                         f_printf("GIVE BINARY PASS.\r\n");6 B) ~3 T" D- Q4 }, ^+ V
  106.                                 else if(xReturn == errQUEUE_FULL)
    $ k- T% L1 Y2 e
  107.                                         f_printf("QUEUE IS FULL.\r\n");
    / C/ u5 Z# W- B1 ^
  108.                         }
    9 z: z$ ^  r+ e7 `9 y3 e
  109.                 }
    $ @7 S( q/ S% o, }
  110.                 8 _' x- X' g. K  z4 `: D' m. f/ G
  111.     vTaskDelay(100);
    % \3 ?% |+ k: ?6 @5 q
  112.         }
    6 U2 E+ N" n( u# B' M

  113. * [& R4 \; f% n$ @- U1 U
  114. }
    ! C% J- s' D5 ^2 g1 p, y
  115. static void Led1TaskCreate(void)
    4 O, @, o5 n9 u2 N2 i
  116. {, h) U' y8 L0 C* N. n
  117.   while(1)
    9 p3 G% J9 e3 n$ L" [
  118.         {
    8 j; ]/ m: v5 O' @7 c
  119.                 UBaseType_t xReturn = pdPASS;
    ' A5 r2 y$ C; q, Q' X
  120.                 " t' t. K/ U3 L. @7 E5 [
  121.                 xReturn = xSemaphoreTake(Binary_Handle, portMAX_DELAY);' B8 m: n7 h/ y( q2 p$ a
  122.                 if(xReturn == pdPASS)1 U5 V/ F. q* e  Y
  123.                 {8 u* v/ B& g; ?' r7 i7 Y: |. @) T
  124.                         f_printf("TAKE BINARY PASS.\r\n");6 y7 H" r8 J/ h1 g# t
  125.                         HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_2);2 m2 a0 w5 ^. p4 |7 j, j
  126.                 }0 d- C5 _, d  \5 t
  127.                 - @; f1 k* P# {/ b
  128.           vTaskDelay(100);" B( K' C8 n$ H9 b( y6 A3 x
  129.         }
    : C  X8 q; G! }$ s9 {) ~# L, U2 O
  130. }3 L# u# R! M0 s/ c
  131. ! u. [8 O% M9 K, g, j
  132. /* USER CODE END 4 */
复制代码

4 I0 l4 a. ~! p) g( N/ L' H计数信号量的用法示例
/ @3 a& {; J8 G) b! _& a1 C1.创建好带有printf-stdarg.c的FreeRTOS的工程" w8 A6 g' S! }* b1 Q

  Z- T0 |0 C0 o8 A) E2.修改main.c文件
. ]* @2 Q2 `/ E- o' g$ \* L- w
- K( V0 y" ?! ^+ L9 Y
  1. /* USER CODE BEGIN Includes */6 x) i9 p% l! Z  t: y
  2. . ~0 w( u3 c: G) X! i
  3. #include "FreeRTOS.h"
    + r, P7 W% `! @: R
  4. #include "task.h"
    8 R  c/ ]/ \. _$ n; {  U
  5. #include "queue.h"
    & w. P$ L/ ]& Z
  6. #include "semphr.h"- T" O; M, [( g& O* @; N+ g; R
  7. #include <stdio.h>
    9 }1 Q3 t( \' r* p1 o. O& }
  8. #include <string.h>
    $ y- X$ h$ E9 L  O
  9. - O4 o; T6 p* i# O' _
  10. /* USER CODE END Includes */- z4 @2 ?- S9 m: U/ m1 S
  11. /* USER CODE BEGIN PV */. M: d: m) _- g& Z) T2 N
  12. static TaskHandle_t AppTaskCreate_Handle = NULL;
    6 Y/ _  X. ~+ N: B! F  ?
  13. static TaskHandle_t KeyTask_Handle = NULL;! |9 i, k7 ?( }! v9 h
  14. static TaskHandle_t Led1_Handle = NULL;7 F9 l% F4 n7 e/ l" [* x

  15. 8 M% M) v; z  \9 y) W
  16. SemaphoreHandle_t SemaphCount_Handle = NULL;# x. \3 i( _. A0 A- Y. w, t  M/ d

  17. + f$ g) l: f, o: V% ~8 K+ z
  18. extern int f_printf(const char *format, ...);! i- y- a6 \. j. h( s$ r* t  p
  19. 6 C8 |, k4 B5 \. w. j6 Z2 r1 x. _
  20. /* USER CODE END PV */' I9 A2 A* V! O# D
  21. - B7 Z' t$ Z+ x& H
  22. /* USER CODE BEGIN PFP */
    7 ?( I: p& o  d9 F  |  t
  23. 5 ]4 N8 \4 T' C9 ~
  24. static void AppTaskCreate(void);' U9 P" u, a) m
  25. static void KeyTaskCreate(void);$ i( F8 P. R5 _8 j, ?' L1 l: g/ \
  26. static void LED1TaskCreate(void);
    ) C# x9 h. H; O+ {% p  v

  27. ) |7 `% ^0 C  w+ S1 E6 @3 d
  28. /* USER CODE END PFP */
    ' N2 j, `: m) i9 G& B6 K  z8 A) |
  29. : }  M* k( [. C% ~' B, S, D
  30. int main()) I6 b) ^" S" R+ l+ z
  31. {4 w5 f9 _! }" v7 p& t0 D
  32.   ***
    " g0 v7 a% u' j* m8 z- w9 p
  33. 6 w* I# Y. D# P
  34.   /* USER CODE BEGIN WHILE */  B# P* W" u% v2 [/ T  u% K

  35. - K' K$ b5 F3 X$ Z
  36.   UBaseType_t xReturn = xTaskCreate((TaskFunction_t)AppTaskCreate,( V; ?! v" I( e8 K3 A/ ^
  37.                                     (const char *)"APPTASKCREATE",
    ) m) q* D* c: [- _1 A" Z- s) Z
  38.                                                                         (uint16_t)    128,* Q& P, \9 h3 y6 A' R6 m1 U1 L4 e
  39.                                                                         (void *)      NULL,
    1 b8 B) u& s- h# B: q
  40.                                                                         (UBaseType_t) 2,2 O% G7 x# s& f6 s8 N4 t( u
  41.                                                                         (TaskHandle_t *)&AppTaskCreate_Handle);
    ( T+ O* t; x, m9 R
  42.         if(xReturn ==pdPASS)
    - S  w- P% ?! @5 e
  43.         {+ E/ I% p1 i5 e3 b, d4 @
  44.                 f_printf("TASK START.\r\n");
    0 U' ?) Z. Q/ [6 ^
  45.                 vTaskStartScheduler();* L. I" @. P& n! x* K  o
  46.         }
    9 j# b* D4 G3 q3 [2 B  _& I
  47.   while (1)3 f5 a% y+ g/ p& z' Q
  48.   {
      _6 t% C8 L; a, B$ y: ?# T9 @
  49.     /* USER CODE END WHILE */
    6 T: h% d% R" b$ O  z+ s# q0 k

  50. 8 L+ Z) V4 H' G4 Y  ]( E* x/ ?
  51.     /* USER CODE BEGIN 3 */
    / t4 N9 E. e1 q/ ]. @
  52.   }
    0 b  X4 a# W1 c" t2 Z; u
  53.   /* USER CODE END 3 */
    7 P4 t* l& J6 b2 U  \7 f" s
  54. }
    8 Z( p, q  |! S1 p
  55. 5 x4 c# {- U4 q/ x( i) D
  56. /* USER CODE BEGIN 4 */
    ' e$ }9 @  p# T. _, b# d$ t
  57. static void AppTaskCreate(void)
    7 c2 Z' t" Q+ y# R
  58. {. D; O8 C0 n9 \- D( @
  59. ) N+ E! y% ~4 l$ ^  ~& E
  60.   UBaseType_t xReturn ;; j/ C1 B" A: T) B
  61.         xReturn = xTaskCreate((TaskFunction_t)KeyTaskCreate,
    , U. @3 R$ Q1 \1 D
  62.                                     (const char *) "KEYTASKCREATE",$ {* l, _4 o5 E1 g
  63.                                     (uint16_t)      128,
    7 g+ L1 ]5 z$ I
  64.                                                                         (void *)       NULL,
    7 Y2 e* }$ E' [+ i% Q
  65.                                                                         (UBaseType_t)   2,/ L) N; t% n0 w. \% @8 r1 M* C$ B  P3 r# k
  66.                                                                         (TaskHandle_t*)&KeyTask_Handle);
    9 o3 }  f0 b: n9 ~2 P* p- r) I3 x' H
  67.   if(xReturn == pdPASS)/ e  ~3 E/ d3 I" v( f7 v; h8 i
  68.                 f_printf("KEY CREATE PASS.\r\n");
    7 w; l, P+ N6 i) l

  69. 9 }  ^4 X3 |! [2 o( z5 m' L
  70.   xReturn = xTaskCreate((TaskFunction_t)LED1TaskCreate,
    $ u5 I' t: w8 j7 ?1 e, Z. J
  71.                                                 (const char *)  "LED1TASKCREATE",& a- s; X! m4 z0 W# O
  72.                                                 (uint16_t)      128,$ V$ o( g" U  c$ `1 F  }' t
  73.                                                 (void *)        NULL,& u: }! E1 ^! |- N6 ]
  74.                                                 (UBaseType_t)   1,+ ]# b) o. P7 V) P7 H2 O; F
  75.                                                 (TaskHandle_t*)&Led1_Handle);
    " S( t9 a- `9 ^/ Y" E" H" f
  76. 7 z" i8 I2 k; U' k, B$ B6 u$ X
  77.         SemaphCount_Handle = xSemaphoreCreateCounting(3,0);
    , c" X- H% H5 c
  78.         if(SemaphCount_Handle != NULL)
    " r5 S! B: ]+ t* s$ [
  79.                 f_printf("SEMAPHORE COUNT CREATE PASS.\r\n");
    6 F; C; y0 a$ x4 O7 J2 F
  80.         * ^/ b3 v$ Q4 [) F
  81.   if(xReturn == pdPASS)
    ' A4 S% g0 K' x  k
  82.         {" W+ ~% ?/ W2 R
  83.                 f_printf("LED CREATE PASS.\r\n");        
    3 `: q( I; _2 z4 T1 a
  84.                 vTaskDelete((TaskHandle_t)AppTaskCreate_Handle);
    8 E  t$ A+ h. G' U5 [, ?' S8 [
  85.         }/ ?& o2 {6 `% _" m; ~4 C7 N8 q, e
  86. }
    ' k" R0 C- Y0 }" h, E' f
  87. / d# {, |2 E; X$ M; \5 J; p
  88. - l, x( W' K' j& x5 b
  89. static void KeyTaskCreate(void)
    ! k, ]0 O# u' H" x, Q
  90. {# j7 v* s* r7 l# z+ [  J
  91.   while(1)
    % j/ x, ?5 H: o. e" B# l; e
  92.         {
    % C9 F2 S; T# r
  93.                 UBaseType_t xReturn = pdPASS;" E4 N5 t6 L+ a: `% I5 K
  94.     if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0))$ N" `3 r8 i6 \9 }; W4 a/ l" z
  95.                 {( a8 f( K; D2 i! M
  96.                         vTaskDelay(100);+ j: a, X9 Q/ w* P$ a7 L2 d9 \# I
  97.                         if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0))( r1 Y0 l) {( R$ T& f, o
  98.                         {  D  W, e: D# ?. ]& s3 T
  99.                                 f_printf("KEY PRESS.\r\n");
    * U! Y; I% L+ x% T+ Z" P
  100.                                 xReturn = xSemaphoreGive(SemaphCount_Handle);1 }' z! O& ]* p
  101.                                 if(xReturn == pdPASS)( M: E" W# T# k; g* B4 S' A, Q
  102.                                         f_printf("GIVE COUNTING PASS.\r\n");
    9 k! ^! |1 r- I
  103.                                 else if(xReturn == errQUEUE_FULL)0 C: A6 d0 K0 R: X0 I
  104.                                         f_printf("QUEUE IS FULL.\r\n");4 n4 L( A0 \  o, `2 c; L
  105.                         }
    0 [& ^' H& A. d# }8 O+ R0 `$ o. j
  106.                 }                & z) m5 o# [0 W7 Y5 N8 D1 V1 o# }) H
  107.                 vTaskDelay(10);7 j0 ~4 A3 \5 q+ v. `
  108.         }
    7 y6 t0 Z: I3 c1 S/ ?* A  N' _
  109. }# I. |! T/ }1 t( j" }, }- f* K
  110. static void LED1TaskCreate(void)
    8 R  F5 H% t% j
  111. {
      h* K5 ~0 b0 r  m
  112.         while(1)* Q/ U9 G4 z* ]- ?$ x: h" T( T" f
  113.         {# S: b, x! h% E$ u  n# u+ }
  114.                 UBaseType_t xReturn = pdPASS;2 p* Z+ ^8 P0 }; n) s4 l2 g
  115.                 7 a( c: a$ Y* R- w1 }8 `" g
  116.                 xReturn = xSemaphoreTake(SemaphCount_Handle,portMAX_DELAY);
    $ q6 K) d- a9 Y: X" k5 v
  117.                 9 `) T/ V8 [* q3 k4 a( M" ?5 B! b
  118.                 if(xReturn == pdTRUE)+ I( P, s) A8 I1 X& a7 l
  119.                 {, p% Q. n$ c+ @8 D
  120.                         HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
    7 n" ]/ R( s& ]4 k
  121.                         f_printf("Counting Take PASS.\r\n");
    8 J3 ^! {# l7 `4 i# W! @! R
  122.                 }4 o' U9 T- r9 {9 \+ z
  123.                 else if(xReturn == errQUEUE_EMPTY)+ E! Q2 t8 w/ a2 k# @
  124.                         f_printf("semaphore is empty.\r\n");
    0 i0 j# B7 T8 ?
  125.                 vTaskDelay(2000);" C" `* E0 G7 H) S- K2 ~( N
  126.         }; z; ]7 {8 J' [1 @* p' G: Q' O! X
  127. }2 }! t1 U2 ~% u$ ~# U+ z
  128. /* USER CODE END 4 *// K2 h" [' }; M
  129. 7 f; h1 b* c) `; j1 z( A6 M5 O
复制代码
: k# G! W/ t* s# ~- L" m- q8 c
赞 收藏 评论0 发布时间:2021-11-12 01:00

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版