01. 概述
7 r/ M [" g' u8 [, o1 T任务挂起和恢复,当某个任务要停止运行一段时间就可以将这个任务挂起,当要重新运行这个任务的话就恢复这个任务的运行。FreeRTOS的任务挂起和恢复API函数如下表所示:! x: z& H2 [8 j" H& w* \+ n- _
/ E/ n( i4 m% J( y& h
6 E6 o% ?5 z. @4 h& ~7 x. l
; o+ A+ v: e) O8 ]02. vTaskSuspend函数
. q. K" H5 {0 r+ D) {" g- void vTaskSuspend( TaskHandle_t xTaskToSuspend )- H+ C' Y$ P$ ?/ c! o
- 功能:
5 g D" q( z' r& g0 [$ m K - 将某个任务设置为挂起状态,进入挂起状态的任务永远都不会进入运行态。退出挂起状态的唯一的方法就是调用任务恢复函数。$ [; T" l+ |1 e
% m0 _7 d* U" O1 s8 B- 参数:4 }" ^& q# y G$ x2 x
- xTaskToSuspend 要挂起的任务句柄。为NULL表示挂起当前任务。# P# B- X) t! z
- $ g g, o1 l4 O6 E
- 返回值:) K( g8 D7 g: s( L
- 无
复制代码
6 @, r( s) H/ V. {' x* S温馨提示:: U# D! A$ a: J @5 D
( u% W/ V7 J3 p$ @/ c3 K5 _5 i& `
调用vTaskSuspend函数是不会累计的:即使多次调用vTaskSuspend ()函数将一个任务挂起,也只需调用一次vTaskResume ()函数就能使挂起的任务解除挂起状态。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend必须设置成1,此函数才有效。- N9 J% `0 H, |( ]9 v7 J
: U' p! N, D( J8 }8 q应用示例:
- G$ ~2 g" w/ B
n* a. M3 k" t- void vFunction( void )" M" k9 y3 p" a- @0 H
- {
5 B1 @# v; B' c8 I$ n" ]& L - xTaskHandlexHandle;
, g @! N, A' Y* I6 h - // 创建任务,保存任务句柄.
4 ~/ N+ ]8 _6 @8 N; N - xTaskCreate( vTaskCode, "TASK_NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );3 {( `5 e3 X C9 d% m
- // ...7 `* K. A( s2 t; B4 H- j0 n% [6 ~
- // 使用句柄挂起创建的任务.
; P% V7 x* W* X+ @* z - vTaskSuspend( xHandle );
6 B3 U" M+ i( ~$ V2 a - // .... h% k- L( p7 X8 ?5 }8 H/ W
- // 任务不再运行,除非其它任务调用了vTaskResume(xHandle )
9 y9 v# \. ?3 P - //... d+ z) H1 M$ U5 Y, C
- // 挂起本任务.
- q. }4 ]9 l" F - vTaskSuspend( NULL );
. `, w0 S2 V- G7 F h - // 除非另一个任务使用handle调用了vTaskResume,否则永远不会执行到这里
* G" y! U1 c% ^5 B, O3 q ^ - }
复制代码
8 w: X( m/ t& R: _" Q$ S03. vTaskResume函数! @& X6 N. M- T% J
- void vTaskResume( TaskHandle_t xTaskToResume )9 Z2 y" G9 B( Q; D. ?3 u
- 功能:3 t8 L, l4 s1 x- L+ a1 W; @9 M) j
- 恢复挂起的任务
' ]0 o- k2 c) Y0 d0 q - 参数:! R/ {! t. k9 c# n3 j
- xTaskToResume 要恢复运行的任务句柄
1 ~+ A( o' y6 B, m0 c - 返回值:
; _& } G7 z. W- v1 x - 无
+ [, n5 K0 b0 l, E1 e P; `' F
复制代码
x& H. m3 ~+ K5 i4 i1 t9 E% x温馨提示:; U) }, `/ Q3 o t
& g ]$ k( ~) J0 {$ H, x0 \- R通过调用一次或多次vTaskSuspend()挂起的任务,可以调用一次vTaskResume ()函数来再次恢复运行。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend必须置1,此函数才有效。# u3 k, h! d- D6 \1 T
0 U3 j6 X: u; r W* k7 h! _应用示例:
2 h, ~& {! b2 R# b/ Z3 u, H% p! W
' U' k3 q4 z. h- void vFunction( void )3 h% d9 b& s7 p
- {
. r) b5 u( ^7 ~! s( u+ } - xTaskHandle xHandle;
2 }6 f1 W( b( O+ s* S' ? - // 创建任务,保存任务句柄. G( ~4 \+ ] ?, E' f& T
- xTaskCreate( vTaskCode, "TASK_NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
5 @, h& x, Y2 z7 _" H - // ...
, _5 O7 f' N8 t# R; q2 C9 e8 { - // 使用句柄挂起创建的任务3 N3 i; |" T* |4 Z4 Y# c+ B
- vTaskSuspend( xHandle );( @$ _+ I( n. h& ?, G$ z
- // ...8 ]" B5 N1 P$ r- S# V2 i
- //任务不再运行,除非其它任务调用了vTaskResume(xHandle )
$ A2 L) c& B1 X# F( M. r" [ - //... |2 u. k) r* Y- ^5 _/ R$ z5 A
- // 恢复挂起的任务.
. X$ D8 ?- c& m" v7 q3 K - vTaskResume( xHandle );
$ b p6 i& W9 C* ~7 N9 [ - // 任务再一次得到处理器时间
- a6 @& v, l3 a7 b# W/ A - // 任务优先级与之前相同
: N7 b/ E" q# s6 U - }
复制代码 7 P3 G d! ]: C- g: r' b
04. xTaskResumeFromISR函数
% y, f) c* e2 A- BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume )) \2 n/ X' F( i: U+ z2 p4 t
- 功能:
) ^/ B5 o1 F" d; K6 T( L - 用于恢复一个挂起的任务,用在ISR中
' y* v2 ]7 y3 O1 X - 参数:6 p& H/ _" o/ [$ j# R! o
- xTaskToResume 要恢复运行的任务句柄
4 w2 r& X% y3 U5 \9 { - 返回值:
/ ]/ p7 d, ?+ m) g) F& j - 如果恢复任务后需要上下文切换返回pdTRUE,否则返回pdFALSE。由ISR确定是否需要上下文切换。
复制代码
- ^3 c ^9 Q1 ]温馨提示:
9 i" f# E7 r, { l8 j+ c7 V9 N$ z9 c8 Z- Y* X! g7 ]
通过调用一次或多次vTaskSuspend()函数而挂起的任务,只需调用一次xTaskResumeFromISR()函数即可恢复运行。
3 U U7 s! Z# o6 W2 o6 o: k5 A7 l1 w6 c8 z5 H
xTaskResumeFromISR()不可用于任务和中断间的同步,如果中断恰巧在任务被挂起之前到达,这就会导致一次中断丢失(任务还没有挂起,调用xTaskResumeFromISR()函数是没有意义的,只能等下一次中断)。这种情况下,可以使用信号量作为同步机制。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 必须设置成1,此函数才有效。6 ^$ v! s/ b! h" M* b
/ P, V( i* {+ w/ f% r0 k) S应用示例:
0 K% r9 x* j6 m* g1 \5 L& E# K. C8 \2 i7 ?; O9 u; Q
- xTaskHandle xHandle; //注意这是一个全局变量
/ a' A% f3 J% \( [0 L9 s; q
8 N2 J; P' I5 r- void vAFunction( void )
- l: Z8 z1 A' M/ K8 E# n - {: C2 a* Q3 k2 J
- // 创建任务并保存任务句柄
8 _6 x6 z2 W5 D4 F/ }' X - xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
2 }4 d4 Q4 n* f ^ - 6 d' B, r9 u( X6 k& o k( b7 H
- // ... 剩余代码.
8 S% E7 ?" o* L" O - }' a$ X, p Y- t: X- h: C+ w/ ]
- m# @0 N! o) [& t+ Y
- void vTaskCode( void *pvParameters )
6 Z" ?7 b/ f4 y; h7 D' k: `3 y - {
8 L8 v G9 y" F8 X1 B; h1 w - for( ;; )
$ A) F, b* i: |/ [ k/ n - {& h, p2 v. C( J# [9 I
- // ... 在这里执行一些其它功能
4 N' P2 ^* z1 [
6 K8 u* u& r' X# y. q! `, U- // 挂起自己
2 F! L& f4 Z1 E1 g - vTaskSuspend( NULL );( \! }9 w1 K" Z: j1 h
' [7 j4 P7 o* J1 h0 V& y1 p- //直到ISR恢复它之前,任务会一直挂起8 {+ e/ C5 H5 O, M
- }
. f. l/ _. H# r - }- J; A+ h4 s; ~' b$ P
- # B# ], R- c$ g$ H: C$ Y. p4 O
- void vAnExampleISR( void )* I" V& O, g3 k# }* V. T/ x
- { X/ [, H, c6 V( r6 g
- portBASE_TYPExYieldRequired;
' m9 ?" o7 c- b- B% N2 m
) f; d* M- S6 l, I/ k# F; f- // 恢复被挂起的任务! u' ^1 T4 u6 Y: j) |
- xYieldRequired = xTaskResumeFromISR(xHandle );
# C- }: j, P7 V% M
4 w# p0 n5 }* T n' s" ?- if( xYieldRequired == pdTRUE ): `% D+ O+ A& S7 S/ W
- {9 G8 X" M. `; A
- // 我们应该进行一次上下文切换
, i8 Y: }# U: `/ O - // 注: 如何做取决于你具体使用,可查看说明文档和例程+ r! _7 e7 x. s$ j& J& y5 j7 S- m E
- portYIELD_FROM_ISR();5 L: ~7 b$ f, [* M
- }5 N, \( Z3 H" \! K) K2 X; E
- }
5 W) Z, w( V0 u; v# i! v+ _
: f% Z# j' N2 s* C7 L0 p1 d3 V
复制代码 % s/ |( r& J. S5 v/ E& A
|