01. 概述- z3 T+ a$ X; T, ?
FreeRTOS中创建和删除任务API函数的应用。使用静态方法创建任务,任务的堆栈、任务控制块就需要有用户来指定。
! E+ W" h3 c6 t3 ]0 n- R9 c# S
' y2 Q! A- G+ e02. 功能描述
3 `) A5 f; W M n$ @4 h L5 K设计三个任务:start_task、task1_task和task2_task,这三个任务的功能分别如下:
' s0 ~6 ?9 L2 v8 V6 e/ [
& d+ o. N* u5 u# j! |. V$ p; ystart_task: 用来创建其它两个任务。7 v+ z9 v% @) T# b! c! x5 ~
/ i4 k2 F5 ?) P; k6 b2 A) Qtask1_task: 当此任务运行5秒以后就会调用函数vTaskDelete()删除任务task2_task,该任务控制LED0的闪烁,并且周期性的输出信息到串口中。$ f7 h( Y3 g& {- C/ {$ u
/ `% W: Q( `" F+ ^task2_task:普通的应用任务,此任务控制LED1的闪烁,并且周期性的输出信息到串口中。
* R' X- \' v% o" V; @: A, S! W0 t. e* }- W0 e8 N
03. 任务设计% r+ ~8 t+ J8 M# Y
系统设置. h$ k' |: B7 X2 V% I! G8 W
# {5 u0 |, @; a9 l* i, x. u5 p* s4 ?
在FreeRTOSConfig.h文件中需要将宏configSUPPORT_STATIC_ALLOCATION设置为1.
/ q7 C' V# h8 `1 u% N6 v3 B
" \6 G* y9 }0 s6 ^- #define configSUPPORT_STATIC_ALLOCATION 1 //静态内存
复制代码
+ \" E9 P' @$ y. ?5 P# v8 E* q编译报如下错误1 E0 y$ W; Q: W$ J: \# }, w
0 j0 i, d7 Y7 h
7 \1 N1 d) @# s1 E" z/ \- C
! r) H" h. p9 ~. f1 G* T& n使用静态的方法创建任务我们需要自己实现函数vApplicationGetTimerTaskMemory()和函数vApplicationGetIdleTaskMemory()。' `3 n6 C8 Z& E9 f" A
' v) o$ D% [. O; ^7 s7 v7 e/ o- //空闲任务任务堆栈
3 L: ^! d' ~6 T) Q4 I! `, @ - static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
4 T0 i3 i3 i3 `2 F+ {9 D - //空闲任务控制块9 V: d7 B1 s) {8 W' b
- static StaticTask_t IdleTaskTCB;
+ ^6 j+ c. N5 u8 ~9 _ a' a; z. s
9 n9 j ^, D' \2 B# y. J- //定时器服务任务堆栈
& S& [- C4 x! ^3 t C- i - static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];, ?: D' w ~5 N0 R2 v
- //定时器服务任务控制块
; ^ @# x& X: h( k0 o5 ^ - static StaticTask_t TimerTaskTCB;
t0 B7 u5 y0 ]' i - $ W9 `: Q: A6 r h# s
- //ppxIdleTaskTCBBuffer:任务控制块内存
% ~& z$ f5 A& J! ?0 Y6 F( D - //ppxIdleTaskStackBuffer:任务堆栈内存
- u& R1 ^: d! A% b: p - //pulIdleTaskStackSize:任务堆栈大小8 H' f, W0 \% h' U4 J6 p( y- Y0 {
- void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, 7 w4 h5 W5 j& O: \! w$ O5 q
- StackType_t **ppxIdleTaskStackBuffer,
# E6 B. Q& j8 @% l - uint32_t *pulIdleTaskStackSize)
* V6 r5 D9 M' ? - {3 I: L. [6 T, b: ]) A" b; P6 j) n
- *ppxIdleTaskTCBBuffer=&IdleTaskTCB;4 o0 F2 E) i9 Z1 O
- *ppxIdleTaskStackBuffer=IdleTaskStack;
3 i6 u7 ? T- d9 o8 l8 x' X- S - *pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;3 }3 x9 ?3 v# m
- }+ ^4 ]& K' j; ^
- 7 x- Y i* Q( V6 P% F
- 7 T6 b, U5 {4 L) \0 d
- //获取定时器服务任务的任务堆栈和任务控制块内存7 T% ?) i# S; w' v
- //ppxTimerTaskTCBBuffer:任务控制块内存
9 o# @* K7 F( q2 R) Y0 Y0 n% P) _9 x2 Q - //ppxTimerTaskStackBuffer:任务堆栈内存9 L+ v% L$ o m7 ~
- //pulTimerTaskStackSize:任务堆栈大小
9 a5 B0 G: u, R2 z8 N# [$ J) f - void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
6 I: B/ |& K6 `0 G% A2 T - StackType_t **ppxTimerTaskStackBuffer,
. A5 w1 o* l* O0 W, r1 p" ? - uint32_t *pulTimerTaskStackSize)
/ e5 ~3 M: U! P+ l! E - {* ~8 T: V& A& G' h
- *ppxTimerTaskTCBBuffer=&TimerTaskTCB;6 x8 K2 ^$ N( _: G
- *ppxTimerTaskStackBuffer=TimerTaskStack;2 t! Y2 |% z) t4 X5 z6 F1 o( L5 u
- *pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;5 N( L+ M, v" [$ U$ q. n3 y
- }
$ k6 j* A' J" U2 B
复制代码
& K+ a j$ v' l2 D3 x任务优先级,堆栈大小,任务句柄和任务函数
- @6 t+ w9 j/ z! {; [% u+ S. R) V8 @. @% [ j
- <blockquote>7 P) [ |5 g& U
复制代码 , f( i1 ^% H; Q# H$ I; b" ~* T
start_task函数- //开始任务任务函数
7 {4 e1 Z+ l/ `+ e" } - void start_task(void *pvParameters)
0 _! _; y4 m: @5 s1 \ - {
+ A' [) n0 w d* f - taskENTER_CRITICAL(); //进入临界区
9 `% V f' A) N - //创建TASK1任务
! |; l2 J& q9 B& | - Task1Task_Handler=xTaskCreateStatic((TaskFunction_t )task1_task, . T7 d b3 N7 V" f3 d+ v* ^
- (const char* )"task1_task",
; s' }0 M& h7 _: M1 i c4 \0 w - (uint32_t )TASK1_STK_SIZE, ! B5 K% t1 V8 K( f
- (void* )NULL, , q/ `, ^. S0 K8 w0 }. n
- (UBaseType_t )TASK1_TASK_PRIO,
) ` b/ S- _* v' U8 E - (StackType_t* )Task1TaskStack,
4 k9 y$ X: ?8 @3 e - (StaticTask_t* )&Task1TaskTCB); % _ o5 ?& `% `. w8 { P$ q- Y
- //创建TASK2任务
2 Q" d- K) r7 v/ @4 | - Task2Task_Handler=xTaskCreateStatic((TaskFunction_t )task2_task, , ]/ ?' p2 v- _3 Q) l5 a$ {0 D, L
- (const char* )"task2_task",
+ Z. M- y; V1 J6 [ - (uint32_t )TASK2_STK_SIZE,
6 x7 x2 N2 M7 G" P - (void* )NULL,
; w# ~9 d1 b0 w1 O+ j" K4 j' V - (UBaseType_t )TASK2_TASK_PRIO, J2 I9 f, E' F. l0 ] Z
- (StackType_t* )Task2TaskStack,
- ^+ q( Z2 R" f - (StaticTask_t* )&Task2TaskTCB);
' z ]) U: f" R3 D$ R9 A - vTaskDelete(StartTask_Handler); //删除开始任务7 m: Y+ S1 @* k+ F& d' h2 O0 w+ D
- taskEXIT_CRITICAL(); //退出临界区
0 g( M' B1 S- _* n - }
复制代码
0 ]/ z% r( V! W$ b) dtask1_task函数
; J; e [( H% U0 ]1 {* s% E, b3 G9 |
; a1 Q/ k& i2 M' c) m0 e/ Y- //任务17 Y9 H2 Q6 E: D/ a. D; ?/ L" t
- void task1_task(void *pvParameters)" @' k! ^) h9 ^% \6 u
- {
& \3 {# ?! w+ \: J4 z - u8 task1_num = 0;
$ Z" a9 ?' t; \; v - 8 o ]% S% M3 v% T! P3 G- h/ C
- while(1)& o0 B7 B4 t4 A# S' D1 {
- {7 D* r7 w$ z: E. N) {9 G
- task1_num++;3 K. n$ J3 @3 b W, ^
- LED0 = !LED0;
7 x% v/ C: \8 L) A - printf("任务1已经运行%d次\r\n", task1_num);$ U1 G' @1 }2 ?/ }
- 9 C' s, e9 I8 D K* ^5 K g3 }
- if (5 == task1_num)
7 e" o7 \6 e! O9 X - {
. E3 {0 C. I1 O4 F0 {' ^9 Z - //任务1删除任务2
* Y# i: T8 R* @0 u - vTaskDelete(Task2Task_Handler);
P" h: \) |, c9 o( D: q - printf("任务1删除了任务2\r\n");. y: A5 j" }1 c) c {/ g% h& q9 [
- }2 i9 B4 f# U [* m, P, v
-
c/ P$ O8 R% G0 d2 w2 c; X - //延时1秒 1000个时钟节拍3 B% _5 H# I( p5 W7 L% q* B& m" Y
- vTaskDelay(1000);: p" N; t+ h! u
- }' F, |" G7 y: E4 D" Y. K& ]6 u9 ]
- }
复制代码 & w$ s) V& ]! F( P
task2_task函数5 e: {% d$ I) h+ T) P
r0 y% I, {' e' |2 g! y- //任务2' I* a7 K/ X7 n/ c+ n- \
- void task2_task(void *pvParameters)
/ w9 E8 {7 W9 ` - {
8 ?5 O0 V$ Q2 v7 N - u8 task2_num = 0;
& V& r; N: y3 g$ X# i -
( C: I2 i. @( h0 g6 m - while(1)
3 G4 L% c- P" \+ Z4 E& c/ \ - {; E" E3 }5 t/ v4 w3 D2 Z
- task2_num++;
9 P, X# J1 M9 Y) p - LED1 = !LED1;
9 ~( g0 l, H# X. f - printf("任务2已经执行了%d次\r\n", task2_num);
+ i% e; s1 R; N9 R } - ! Q6 t& I* V# ` @" v7 d# W( s5 T
- //延时1秒 1000个时钟节拍7 |4 z% \! {' f
- vTaskDelay(1000);
6 Q+ ^8 Q3 \9 N* t0 G- W - }; b5 C4 _) Z- I/ _
- }
复制代码
' U0 j N B0 K3 {4 O7 z' ^04. 程序设计
' q! c, E* k' r$ ^ A! Smain.c文件
% | X$ `: n# @0 ?: E) P4 @6 K5 X6 a& j9 G
- #include "sys.h": e& }# X& `! D* J6 P
- #include "delay.h"' b N7 N' K' U+ M5 z$ T8 A- P( h/ ~7 M
- #include "usart.h"
# y3 D: L0 E( ~ x- S5 W* \2 z - #include "led.h"
8 n; Q0 U4 ]: ?" i - #include "FreeRTOS.h"# M! t; T% y. v) z: I' ^
- #include "task.h"
- T0 P# X T0 b' y' z
& G6 g- ]( @% ~" W
- o+ o7 X8 a r; ~7 V9 X- //空闲任务任务堆栈: M4 Q% z8 s% @6 Y. D+ ~4 y6 g
- static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
( s7 m m1 ?$ D - //空闲任务控制块
& ^% s8 M5 @+ e - static StaticTask_t IdleTaskTCB;
( ~) U! V( J7 e& r4 o$ z
& [" y8 D q) ^6 L; C* a- //定时器服务任务堆栈
/ q' q2 K0 p# X - static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];. h, ]/ s) g* D+ ?5 h6 W$ `; C
- //定时器服务任务控制块; v: A& ?, Y5 ~9 X( n$ D
- static StaticTask_t TimerTaskTCB;& w8 }- k6 M# t3 l0 W1 a
6 l6 t& i* ^. F% E$ S5 n# P! d. c0 g- //任务优先级* e Y: Z2 S' a' k+ i$ A
- #define START_TASK_PRIO 1
" e. O& T$ S! \. m9 R5 j$ g' s% V - //任务堆栈大小 : W, F3 W( |+ Z2 X0 Z. c
- #define START_STK_SIZE 128 3 \9 q. E2 e- P% @! {
- //任务堆栈9 ?6 U4 c3 [4 ]" D: u% ]7 }
- StackType_t StartTaskStack[START_STK_SIZE];
2 p$ H) o7 h* ?5 Y; r - //任务控制块
! s% e9 M# \$ v4 m( F! R - StaticTask_t StartTaskTCB;
D" w; ^/ W$ k0 G- v - //任务句柄
. `& M1 V0 S# W0 T9 a0 ^% L - TaskHandle_t StartTask_Handler;% @; d1 w- y e8 s
- //任务函数5 o( y% q* z$ L7 x& B/ ~3 a a
- void start_task(void *pvParameters);2 r# u2 ]; U2 e" K& n4 g4 r$ X+ [
& ~' T3 q0 R. M4 S' W! z- //任务优先级; c% W5 ]. x6 F/ _# c
- #define TASK1_TASK_PRIO 2( |" s7 ?, S" y
- //任务堆栈大小
7 I2 b3 ^3 T4 T; D - #define TASK1_STK_SIZE 50
1 I, ^: y- H3 N* @ - //任务堆栈! D2 g/ w- M Z1 H* m3 }5 d2 X1 g
- StackType_t Task1TaskStack[TASK1_STK_SIZE];- J! P9 i3 y" t3 s: Z; P
- //任务控制块4 Q/ @5 @0 m/ s' @ K% T
- StaticTask_t Task1TaskTCB;3 y0 w$ H3 ]6 R% t3 M5 n+ H4 T
- //任务句柄
, v! D- R) O4 d1 R& p - TaskHandle_t Task1Task_Handler;7 y3 ^2 k. c' t& C
- //任务函数$ l0 W' W# H$ {8 D2 [+ k
- void task1_task(void *pvParameters);2 ?- A, B% E1 ?
$ |" R/ y; i4 [$ n: a7 J- //任务优先级
" N- J- |' {$ g# | - #define TASK2_TASK_PRIO 3
: s# w* o1 ?5 ?& A0 g, _* J. F7 e: | - //任务堆栈大小 ! o' o# R6 K4 p- s4 b
- #define TASK2_STK_SIZE 50
! j5 |, T" ~# `$ a& v6 ^ - //任务堆栈- Y# P- g& d8 C2 U% r: J1 ~
- StackType_t Task2TaskStack[TASK2_STK_SIZE];, f& Z- G0 P M' c
- //任务控制块
3 K0 f, G2 N8 q* ?8 s - StaticTask_t Task2TaskTCB;
9 v. m" H" @6 ~' q7 N- e - //任务句柄2 \5 T' `+ m5 n3 ~" N j) p% t8 V
- TaskHandle_t Task2Task_Handler;
/ n, O% f7 t b/ v - //任务函数, I c- r/ s; V o1 K# `
- void task2_task(void *pvParameters);( G; E2 [/ o- A1 t' j6 Z7 R9 E
' X! f' }- I- |( N; d y- + g! c, R2 L. y2 m$ g( P
- //ppxIdleTaskTCBBuffer:任务控制块内存
: r, ?, L. {1 x1 m4 p; P+ V0 F - //ppxIdleTaskStackBuffer:任务堆栈内存. F8 U; ~ r- i# F
- //pulIdleTaskStackSize:任务堆栈大小& J8 m3 K" w1 d- e9 o
- void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
: i: l7 Q& Z% [0 p/ k: C; @1 I( M; W% h - StackType_t **ppxIdleTaskStackBuffer, ; l6 |- N$ N! c8 x* T4 q+ ~" V
- uint32_t *pulIdleTaskStackSize). h2 ^, ~4 m8 a! z2 M* S' h. V
- {
1 p" [' }$ h$ \$ a4 S - *ppxIdleTaskTCBBuffer=&IdleTaskTCB;
, b e# i# m9 ^$ L9 U. z - *ppxIdleTaskStackBuffer=IdleTaskStack;6 z! s* `7 q( L; Y% c0 [
- *pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
+ d7 i$ K1 e9 k5 ?( M% z$ w - }% @/ c& `& l1 S; f* B
5 z: H0 h; y; I2 h* o
8 R* A' l; M V0 D8 }% Q( P- //获取定时器服务任务的任务堆栈和任务控制块内存. d6 y3 y w* Q5 g9 ?
- //ppxTimerTaskTCBBuffer:任务控制块内存: B6 ~5 s. h" Y7 h& j/ E/ F
- //ppxTimerTaskStackBuffer:任务堆栈内存$ p# h& ~2 h" V% ~$ M
- //pulTimerTaskStackSize:任务堆栈大小
; R- L1 J2 G5 ]9 O! @7 } - void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
* T/ E& X' x6 K0 \ - StackType_t **ppxTimerTaskStackBuffer, " ^4 {7 N5 }( _* ~" s; m
- uint32_t *pulTimerTaskStackSize)
% B" E1 a/ p% ` j - {; K% L+ x' I/ b
- *ppxTimerTaskTCBBuffer=&TimerTaskTCB;
1 b1 @& l" l* C- `9 b c. ~ - *ppxTimerTaskStackBuffer=TimerTaskStack;0 v" [- O% N- q, X. f Z
- *pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;9 L6 z8 ]+ |! Y, _/ T
- }
8 ]( o9 A Z9 B/ ?) X5 c
- n p( t9 n7 c: J' t" B+ {- o- //主函数# T& j! G' f8 H1 b8 G: B$ I1 E9 |
- int main(void)0 w( i! q: m% W& I9 X2 U. K
- {
6 Z* w) Q0 A( ~2 ?; w - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
1 d+ }8 k( Q4 R7 ^+ b - delay_init(168); //初始化延时函数0 o) n2 X* ]8 x# q3 w" W' c, i4 H
- uart_init(115200); //初始化串口
5 a2 G- K" P/ n, R - LED_Init(); //初始化LED端口
1 E ]: z$ E R- @' }3 A -
4 m! M) S8 y) m7 I- n$ z - //创建开始任务' J& _9 n! [( T7 |' G, w0 s8 e. K
- StartTask_Handler=xTaskCreateStatic((TaskFunction_t )start_task, //任务函数
& \. E9 ?1 y7 h5 Z" R - (const char* )"start_task", //任务名称( J- g O6 A- M# i/ h
- (uint32_t )START_STK_SIZE, //任务堆栈大小
5 A" P0 y6 x; L: {! x4 j6 F - (void* )NULL, //传递给任务函数的参数/ K; q! j0 J* v; d
- (UBaseType_t )START_TASK_PRIO, //任务优先级
K: I6 Q. N0 P - (StackType_t* )StartTaskStack, //任务堆栈: ~% T4 e4 U$ i; f _) h( a1 L
- (StaticTask_t* )&StartTaskTCB); //任务控制块 4 y- W6 g6 b* U' S
- ' i# z5 R" i8 _& P, ?
- vTaskStartScheduler(); //开启任务调度
- O! M: w. o) }! k: w - }
" V8 y" {+ A5 i- l1 [2 B
% @' S/ u. w1 |0 z- //开始任务任务函数
! Q, [" L6 w: L! y3 H- _2 P8 | - void start_task(void *pvParameters)
6 t# U, p9 H+ [& A - {1 |' z9 g! k/ V
- taskENTER_CRITICAL(); //进入临界区0 S$ R5 K* i# c4 k
- //创建TASK1任务
; G% u: I4 r! Y( Q: o7 d - Task1Task_Handler=xTaskCreateStatic((TaskFunction_t )task1_task, $ ]' b9 w: C" i( S5 X& p% P8 q
- (const char* )"task1_task", ' k/ B5 p1 w3 n$ t4 F
- (uint32_t )TASK1_STK_SIZE,
6 C9 w$ s/ D; X% I - (void* )NULL, / f1 Q5 @! j: f, u* m
- (UBaseType_t )TASK1_TASK_PRIO,
5 |+ w b7 w# V0 }* f* o1 A" k - (StackType_t* )Task1TaskStack, + d8 d9 f2 ^3 J+ L
- (StaticTask_t* )&Task1TaskTCB);
* @' W6 X& E% i5 V9 X% I3 V - //创建TASK2任务+ |$ B! [. U# l2 y6 A+ M% z
- Task2Task_Handler=xTaskCreateStatic((TaskFunction_t )task2_task, 8 k4 h' H: r& k
- (const char* )"task2_task",
" g8 h; L/ P+ w2 y5 L0 g$ E0 G - (uint32_t )TASK2_STK_SIZE,
+ |6 O0 s8 V. r! o' o4 S/ h - (void* )NULL, * k1 R- c, r7 [4 k7 m4 s4 Y# E
- (UBaseType_t )TASK2_TASK_PRIO,
$ V( e2 V* L. f+ b+ U* R. S7 h - (StackType_t* )Task2TaskStack, 8 `# f f1 ]4 K3 K- l
- (StaticTask_t* )&Task2TaskTCB);
$ C2 N: j7 f* V7 d7 J3 r7 i - vTaskDelete(StartTask_Handler); //删除开始任务
/ F! h( x" m$ E% T - taskEXIT_CRITICAL(); //退出临界区
+ m7 w+ L) h( G/ E: h - }
1 V" u& _3 F x6 ~' S# ^# M4 i - 6 J$ H3 ?$ Y5 `# _
- //任务19 |/ W2 l O1 h* ~; [! [
- void task1_task(void *pvParameters)
' K' u) G# }% V/ P7 P2 x" L1 q9 e - {6 c9 E1 b; }4 w+ G0 }8 {5 g
- u8 task1_num = 0;
% z; l( p8 \2 v1 x -
`0 N0 T; T% x1 \ - while(1)- e1 Y# b( R6 c% n' o& Z( T3 J
- {- W5 e& ~. \6 ~% B! {& }' W; V
- task1_num++;
% p' v. D0 u! n& y - LED0 = !LED0; r- D; g/ x- j; b/ s( Q
- printf("任务1已经运行%d次\r\n", task1_num);
/ b5 t# f2 w! h, Y0 w& U$ _! a - - J4 e8 A" E# @. C8 x
- if (5 == task1_num)" Z# |" j7 z+ v2 T/ @$ g/ i2 U, \
- {
" [) D; P$ d# Z" n1 Z& U9 ? - //任务1删除任务2
4 G: d. Q+ I% }" p2 o% D - vTaskDelete(Task2Task_Handler);
8 e3 s1 ~8 t ?4 |6 K- Y+ ~. N - printf("任务1删除了任务2\r\n");
( ^, y7 Q' c& K- W- p - }
( w. C6 C, f( Q% A. B+ E4 n6 p -
0 D& V% ?" M5 _- K3 Y - //延时1秒 1000个时钟节拍
0 Z$ A: b3 v3 u3 f$ o' H - vTaskDelay(1000);5 r- u, p. o9 s1 R4 l
- }0 ^8 A6 r9 t. G+ r" t% _" z; g
- }, S" z4 W. X2 j2 _
- 3 t( I( g. O. Z8 G3 Y& w& y# T
- //任务2' R6 y& v5 N* @, O/ z: g
- void task2_task(void *pvParameters)
$ o" D1 ^- K m' C( b; w5 C - {
6 p0 V$ W8 |! n( r9 w% s - u8 task2_num = 0;
' J# _9 Y( K! x7 J, J0 b, I - . M+ f2 V2 c* L
- while(1)* B' O- T- z8 R9 l3 `- a$ \6 b
- {2 W0 C! `8 O3 F3 Y% Q+ ^4 V
- task2_num++;
( c* O! l' X, Y: S - LED1 = !LED1;
, I* W* t8 x5 S' d" j - printf("任务2已经执行了%d次\r\n", task2_num);
( h9 g( |# I( X1 a -
2 Y; f0 u5 [9 O/ i - //延时1秒 1000个时钟节拍3 `, A9 G1 @$ _9 S% M5 \+ H
- vTaskDelay(1000);
$ y" m8 x, }( y: O - }) i! d. ~( p( G3 V( P# t( S6 Z, s
- }0 Y+ k4 C7 a9 ]) ]" ]- _: y
复制代码
1 J a. Q' E- @05. 结果验证+ Y, ` V2 O8 m
任务1运行5秒中之后删除了任务2,任务2被删除之后就不会被运行。最后只剩下任务1运行了。; F( x5 O( u( U
7 @4 b4 h$ e* m- \: p2 q( M \
: j2 I7 h7 [# {0 S2 ^2 t& Y; \ |