0% found this document useful (0 votes)
84 views

Chương 6 FreeRTOS

The document discusses tasks and task scheduling in ARM programming and FreeRTOS. It defines what a task is and explains the difference between preemptive and non-preemptive tasks. It discusses task scheduling policies like round robin and discusses why preemptive tasks are used to improve response times. It then summarizes key aspects of FreeRTOS including its scheduler, concurrent processing capabilities, and how to create tasks with equal priority in an example.

Uploaded by

Fawkes Sang
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
84 views

Chương 6 FreeRTOS

The document discusses tasks and task scheduling in ARM programming and FreeRTOS. It defines what a task is and explains the difference between preemptive and non-preemptive tasks. It discusses task scheduling policies like round robin and discusses why preemptive tasks are used to improve response times. It then summarizes key aspects of FreeRTOS including its scheduler, concurrent processing capabilities, and how to create tasks with equal priority in an example.

Uploaded by

Fawkes Sang
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 90

ARM PROGRAMMING

Bùi Quốc Bảo


What’s A Task?
 A Taskis an active flow of control within a computation
 Associated with a program counter value and set of register
values
 Multiple tasks can be active concurrently
 Tasks are not supposed to interfere with other task’s register
values
 Tasks share memory space and, in particular, can interfere
with memory values
Preemptive vs. Non-Preemptive Tasks

 Non-preemptive task
 Task runs to completion, even if other tasks
want service
 Example: the ISR routines

 Preemptive task
 Task is suspended if some other task wants
service, then restarted at a later time
 Example: main program loop (preempted
by ISRs)
Preemptive vs. Non-Preemptive Tasks

 Most real systems are a combination of


both
 ISRs pre-empt non-ISR tasks, but are not
preemptable themselves
 Main tasks are preemptable
Purely Non-Preemptive Tasking

 Sometimes called “cooperative” tasking


 Cyclic executive is a degenerate case
 In general, want a pool of tasks that are
executed by a scheduler
 Only one task runs at a time

 No preemption, so no need for executive to


save state:
 1. Task saves its own state before yielding
control to scheduler
 2. Task runs to completion
Example

 Starting point – cyclic executive:


 // main program
loopfor(;;)
{ poll_uart();
do_task1();
do_task2();
}
Round Robin Cooperative Tasking Latency

 “Round Robin” = everyone takes one turn in some defined order


 For Round Robin, response time for N tasks is:
 (assume task reads inputs at start, processes, does outputs at
end)• j  N 1
R   C
i j
j 0

 The task has just started, and will need to run again for new
inputs•
 All other tasks will need to run•
 This same task will need to run again•
 Same time for all tasks ... “i” doesn’t appear on right hand side of
equation
j  N 1
Ri  C
j 0
j
Task Scheduling Policies

 Scheduler needs to have a task selection


policy –answer to question “which task
runs next?” varies:
 Round-Robin
 Earliest Deadline

 Highest Priority

 Latency depends on scheduling policy!


Why Preemptive Tasks?
 Preemptive task
 Executing task is suspended if some other
task wants service
 Suspended task is restarted at a later time

 Example: an ISR preempts the main


program loop
 Without preemption, latency is bounded
by longest single task execution
 Might even be lowest priority task that keeps
everything else blocked
General Idea Of Preemption

 Interrupts are the simplest types of


preemption
 Save main program state on stack
 Execute interrupt

 Restore main program state from stack

 Return to main program


General Idea Of Preemption

 General preemptive scheduling approach


 N tasks are running concurrently
 Have a place to store N copies of program state
– NOT on the stack – that limits order of execution
 Have a scheduler that saves and restores state:
– Stop task K
– Save state in the “task K save area”
– Restore state from the “task J save area”
– Restart task J from wherever it left off
 Simplest approach is to have K stacks
– one per task – and save states there
How Do You Know When To Preempt?

 Hardware approach
 Hardware determines something of higher
priority needs to execute
 Works OK for ISRs preempting ordinary
code
 But, tricky for ISRs preempting other ISRs!
How Do You Know When To Preempt?

 Software approach
 Software sees which task is highest priority,
and starts it running
 You need a context swap to make this
work
 “Context” = all data required to define the state of
the current task
 Simplest example: all register values
 Might include other things in more complex
computing enviroments(for example, file I/O status)
Should You Build Your Own Scheduler

 Or, put another way, should you build your


own RTOS
 Short answer: probably not.
 It is really difficult to get an RTOS to be correct
 Even if you are an expert, and you do write
your own...
 What happens when you leave the company?
 Win the lottery; Get a better job; Get run over
by a beer truck;
 What happens when there is a bug found?
Should You Build Your Own Scheduler

 “Make/buy” decision advice:


 Real time operating systems should be
bought, not made
 Unless you are in a company that sells an
RTOS as a product
 In management speak, only build an RTOS
if that is a critical core competency
 If you are an embedded system company,
RTOS is probably not a core competency
(unless you actually sell an RTOS!)
FreeRTOS
 A Real Time Operating System
 Written by Richard Barry & FreeRTOS Team
 Owned by Real Time Engineers Ltd but free to
use
 Huge number of users all over the world
 6000 Download per month
 Simple but very powerful
Real-Time Operating System ?

 A type of an operating system


 It’s all about scheduler :
 multi user operating system(UNIX)- fair
amount of the processing time
 desk top operating system(Windows)-
remain responsive to its user
 ……

 RTOS scheduler focuses on predictable


execution pattern
Why using FreeRTOS

 Abstract out timing information


 Maintainability/Extensibility
 Modularity
 Cleaner interfaces
 Easier testing (in some cases)
 Code reuse
 Improved efficiency?
 Idle time
When to use FreeRTOS
License of FreeRTOS

 Modified GPL
History of FreeRTOS
 Newest version: 10.1.1

FreeRTO FreeRTO FreeRTO FreeRTO FreeRTO


S S S S S
v1.0.1 v2.0.0 v3.0.0 v4.0.0 v5.0.0

+Scalability +API +Co-routines +API Changes


+New Task Changes
API +Directory
Names
Changed
+Changes in
Kernel
Concurrent processing
Scheduler

 Scheduler là 1 phần của kernel dùng để quyết


định tác vụ nào được chạy tại mỗi thời điểm.
 Kernel có thể dừng và phục hồi hoạt động của
1 tác vụ trong khi tác vụ đang chạy.
 Một tác vụ có thể dừng chính nó bằng cách
delay (sleep) một khoảng thời gian, hoặc chờ
(block) để đợi một sự kiện (vd: keypressed)
hay 1 tài nguyên (vd: serialport)
Scheduler
Scheduler

 At (1) task 1 is executing.


 At (2) the kernel suspends task 1 ...
 and at (3) resumes task 2.
 While task 2 is executing (4), it locks a
processor peripheral for it's own
exclusive access.
 At (5) the kernel suspends task 2 ...
 ... and at (6) resumes task 3.
Scheduler
 Task 3 tries to access the same processor
peripheral, finding it locked, task 3 cannot
continue so suspends itself at (7).
 At (8) the kernel resumes task 1.
 Etc.
 The next time task 2 is executing (9) it finishes
with the processor peripheral and unlocks it.
 The next time task 3 is executing (10) it finds it
can now access the
 processor peripheral and this time executes
until suspended by the kernel.
Realtime scheduler

 Mỗi tác vụ phải đáp ứng (response)


trong thời gian qui định (deadline).
 Mỗi tác vụ có 1 mức ưu tiên riêng
 Scheduler sẽ đảm bảo tác vụ có quyền
ưu tiên cao luôn được thực thi bằng
cách tạm dừng tác vụ có quyền ưu tiên
thấp.
Realtime OS
Response time: 0-100ms

Keypad LCD
Display

Analog Input output


ADC filter control

Sample rate: 5Khz


Keypad handler
void vKeyHandlerTask( void *pvParameters )
{
// Key handling is a continuous process and as such the task
// is implemented using an infinite loop (as most real time
// tasks are).
for( ;; )
{
[Suspend waiting for a key press]
[Process the key press]
}
}
control
void vControlTask( void *pvParameters )
{
for( ;; )
{
[Suspend waiting for 0.5ms since the start of the previous
cycle]
[Sample the input]
[Filter the sampled input]
[Perform control algorithm]
[Output result]
}
}
Mức ưu tiên

 Deadline của tác vụ control thì nghiêm


ngặt hơn của tác vụ keypad.
 Hậu quả của việc trễ deadline của tác vụ
control thì lớn hơn so với keypad
FreeRTOS realtime kernel
Example using FreeRTOS
int main( void ){
/* Create the 2 task in exactly the same way. */
xTaskCreate( vTask1, "Task 1", 1000, NULL, 1, NULL );
xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
/* Start the scheduler so our tasks start executing.
*/
vTaskStartScheduler();
/* If all is well we will never reach here as the
scheduler will now be running. If we do reach
here then it is likely that there was insufficient
heap available for the idle task to be created. */
for( ;; );
return 0;
}
Example using FreeRTOS
void vTask1( void *pvParameters )
{
const char *pcTaskName = "Task 1 is running\r\n";
volatile unsigned long ul;

/* As per most tasks, this task is implemented in an infinite


loop. */
for( ;; )
{
/* Print out the name of this task. */
vPrintString( pcTaskName );
/* Delay for a period. */
for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
{
}
}
}
Example using FreeRTOS
void vTask2( void *pvParameters )
{
const char *pcTaskName = "Task 2 is running\r\n";
volatile unsigned long ul;

/* As per most tasks, this task is implemented in an infinite


loop. */
for( ;; )
{
/* Print out the name of this task. */
vPrintString( pcTaskName );
/* Delay for a period. */
for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
{
}
}
}
The actual execution pattern of the
two tasks
FreeRTOS source code structure
freeRTOSconfig.h
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( ( unsigned long ) 50000000 )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 24000 ) )
#define configMAX_TASK_NAME_LEN ( 12 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0
#define configUSE_CO_ROUTINES 0
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configCHECK_FOR_STACK_OVERFLOW 2
freeRTOSconfig.h

#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )


#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
#define configQUEUE_REGISTRY_SIZE 10

/* Set the following definitions to 1 to include the API function, or zero


to exclude the API function. */

#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
Task management
Tác vụ là 1 hàm với một vòng lặp vô tận.
void ATaskFunction( void *pvParameters )
{
int iVariableExample = 0;

/* A task will normally be implemented as in infinite loop. */


for( ;; )
{
[suspend waiting for a key press]
[process the key]
}

vTaskDelete( NULL );
}
Task state
Tác vụ chuyển từ trạng thái dừng sang chạy gọi là “swapped in”,
“switched in”
Tác vụ chuyển từ trạng thái chạy sang dừng gọi là “swapped out”,
“switched out”
Task management function
Creation
xTaskCreate Utilities
xTaskDelete tskIDLE_PRIORITY
xTaskGetTickCount
uxTaskGetNumberOfTasks
Control vTaskList
vTaskDelay vTaskGetRunTimeStats
vTaskDelayUntil vTaskStartTrace
uxTaskPriorityGet ulTaskEndTrace
vTaskPrioritySet uxTaskGetStackHighWaterMark
vTaskSuspend vTaskSetApplicationTaskTag
vTaskResume xTaskSetApplicationTaskTag
xTaskResumeFromISR xTaskCallApplicationTaskHook
Naming convention
Naming convention
 Variables of type char are prefixed c
 Variables of type short are prefixed s
 Variables of type long are prefixed l
 Variables of type float are prefixed f
 Variables of type double are prefixed d
 Enumerated variables are prefixed e
 Other types (e.g. structs) are prefixed x
 Pointers have an additional prefixed p , for example a
pointer to a short will have prefix ps
 Unsigned variables have an additional prefixed u , for
example an unsigned short will have prefix us
Naming convention
 File private functions are prefixed with prv
 API functions are prefixed with their return
type, as per the convention defined for
variables
 Function names start with the file in which they
are defined. For example vTaskDelete is
defined in Task. c
 x is used both for structures and for RTOS
types such as portTickType (in the ARM port
this is equivalent to unsigned int)
Creating a Task, xTaskCreate

portBASE_TYPE xTaskCreate(
pdTASK_CODE pvTaskCode,
const signed portCHAR * const pcName,
unsigned portSHORT usStackDepth,
void *pvParameters,
unsignedportBASE_TYPE uxPriority,
xTaskHandle *pxCreatedTask
);
Creating a Task, xTaskCreate

 pvTaskCode: con trỏ chỉ đến tên tác vụ


 pcName: tên mô tả tác vụ (chiều dài lớn
nhất mặc định là 16)
 usStackDepth: độ rộng stack của tác vụ.
 pvParameters: con trỏ chỉ đến tham số
đưa vào tác vụ.
Creating a Task, xTaskCreate

 uxPriority: mức ưu tiên của tác vụ.


 Có giá trị từ 0 đến
(configMAX_PRIORITIES – 1)
 0 là mức ưu tiên thấp nhất

 pxCreatedTask: dùng để trả về handle


của tác vụ
Creating a Task, xTaskCreate

 Giá trị trả về:


 pdPass nếu thành công
 errCOULD_NOT_ALLOCATE_REQUIRED_
MEMORY nêú tác vụ không thể được khởi
tạo
Creating a Task, xTaskCreate
xTaskCreate( vTask1,
/* Pointer to the function that implements the task. */
"Task 1",
/* Text name for the task. This is to facilitate debugging
only. */
1000,
/* Stack depth - most small microcontrollers will use much
less stack than this. */
NULL, /* We are not using the task parameter. */
1, /* This task will run at priority 1. */
NULL ); /* We are not going to use the task handle. */
Using the task parametter
void vTaskFunction( void *pvParameters )
{
char *pcTaskName;
volatile unsigned long ul;
pcTaskName = ( char * ) pvParameters;

for( ;; )
{
vPrintString( pcTaskName );

/* Delay for a period. */


for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ ) ;
}
}
Using the task parametter
static const char *pcTextForTask1 = “Task 1 is running\r\n”;
static const char *pcTextForTask2 = “Task 2 is running\t\n”;
int main( void )
{
/* Create one of the two tasks. */
xTaskCreate( vTaskFunction, "Task 1", 1000,
(void*)pcTextForTask1,
/* Pass the text to be printed into the task
using the task parameter. */
1, NULL );
xTaskCreate( vTaskFunction, "Task 2", 1000,
(void*)pcTextForTask2, 1, NULL );
vTaskStartScheduler();
for( ;; );
}
Task priorities

 Tham số configMAX_PRIORITIES qui


định số mức ưu tiên có thể có.
 Nhiều tác vụ có thể có cùng mức ưu tiên
 Scheduler chạy sau mỗi khoảng thời
gian xác định (system tick).
 Tham số configTICK_RATE_HZ qui định
khoảng thời gian giữa 2 lần systemTick.
Task priorities

 Các API của FreeRTOS luôn dùng số


lần systemTick xảy ra để đếm thời gian
 Tham số portTICK_RATE_MS dùng để
chuyển đổi từ số lần sysTick sang thời
gian ở ms.
Task priorities
Two task with different priorities
static const char *pcTextForTask1 = “Task 1 is running\r\n”;
static const char *pcTextForTask2 = “Task 2 is running\t\n”;
int main( void )
{
/* Create one of the two tasks. */
xTaskCreate( vTaskFunction, "Task 1", 1000,
(void*)pcTextForTask1,
/* Pass the text to be printed into the task
using the task parameter. */
1, NULL );
xTaskCreate( vTaskFunction, "Task 2", 1000,
(void*)pcTextForTask2, 2, NULL );
vTaskStartScheduler();
for( ;; );
}
Continous processing

 Trong các ví dụ trên, các tác vụ luôn


chạy mà không cần đợi bất kỳ sự kiện
nào.
 Vì vậy, các tác vụ luôn ở trạng thái sẵn
sàng chuyển sang Running

Chuyện gì xảy ra khi tác vụ dạng


này có độ ưu tiên cao?
Event driven task

 Trong hệ thống nhúng, các tác vụ


thường được thiết kế theo dạng “event-
driven”
 Chúng phải chờ 1 sự kiện xảy ra để có
thể đi vào trạng thái “Running”
 Scheduler sẽ chọn tác vụ có độ ưu tiên
cao nhất mà có thể chuyển sang trạng
thái Running.
Task state
The Blocked State

 Tác vụ đi vào trạng thái Block để chờ 2 dạng


event sau:
 Thời gian:
 một khoảng thời gian delay hoặc một thời điểm xác
định kể từ khi scheduler bắt đầu chạy.
 Synchronization event: (sự kiện đồng bộ)
 Khi sự kiện được tạo từ 1 tác vụ khác hay interrupt.
 FreeRTOS queues, binary semaphores,
counting semaphores, recursive semaphores,
mutexes có thể dùng để tạo synchronization event.
The Suspended State

 Tác vụ bị trong trạng thái Suspended sẽ


bị scheduler bỏ qua.
 Hàm vTaskSuspend() được gọi để đưa
tác vụ vào trạng thái Suspended
 Hàm vTaskResume() hoặc
xvTaskResumeFromISR dùng để đưa
tác vụ ra khỏi trạng thái Suspended.
The Ready State

 Tác vụ sẵn sàng để chạy (vẫn nằm ở


trạng thái NotRunning) thì ở trạng thái
Ready
vTaskDelay()

void vTaskDelay( portTickType


xTicksToDelay );

 Hàm vTaskDelay() đưa tác vụ vào trạng thái


Blocked.
 Tác vụ trở lại trạng thái Ready sau
xTicksToDelay lần Systick.
Example using vTaskDelay
void vTaskFunction( void *pvParameters )
{
char *pcTaskName;
pcTaskName = ( char * ) pvParameters;

/* As per most tasks, this task is implemented in an infinite loop. */


for( ;; )
{
vPrintString( pcTaskName );

/* In this case a period of 250 milliseconds is being specified. */


vTaskDelay( 250 / portTICK_RATE_MS );
}
}
static const char *pcTextForTask1 = “Task 1 is running\r\n”;
static const char *pcTextForTask2 = “Task 2 is running\t\n”;
int main( void )
{
/* Create one of the two tasks. */
xTaskCreate( vTaskFunction, "Task 1", 1000,
(void*)pcTextForTask1,
/* Pass the text to be printed into the task
using the task parameter. */
1, NULL );
xTaskCreate( vTaskFunction, "Task 2", 1000,
(void*)pcTextForTask2, 2, NULL );
vTaskStartScheduler();
for( ;; );
}
Task transition
vTaskDelayUntil() API function

 void vTaskDelayUntil( portTickType *


pxPreviousWakeTime, portTickType
xTimeIncrement );

 vTaskDelayUntil chỉ chính xác số lần


Systick kể từ khi tác vụ chuyển sang trạng
thái Running trước đó đến lần chuyển sang
trạng thái Running kế tiếp
void vTaskFunction( void *pvParameters )
{
char *pcTaskName;
portTickType xLastWakeTime;
pcTaskName = ( char * ) pvParameters;

xLastWakeTime = xTaskGetTickCount();

/* As per most tasks, this task is implemented in an infinite loop. */


for( ;; )
{
/* Print out the name of this task. */
vPrintString( pcTaskName );
vTaskDelayUntil( &xLastWakeTime, ( 250 / portTICK_RATE_MS ) );
}
}
Blocking and unblocking task

void vContinuousProcessingTask( void *pvParameters )


{
char *pcTaskName;

pcTaskName = ( char * ) pvParameters;


for( ;; )
{
vPrintString( pcTaskName );
}
}
void vPeriodicTask( void *pvParameters )
{
portTickType xLastWakeTime;

xLastWakeTime = xTaskGetTickCount();

/* As per most tasks, this task is implemented in an infinite loop. */


for( ;; )
{
/* Print out the name of this task. */
vPrintString( "Periodic task is running\r\n" );

/* The task should execute every 10 milliseconds exactly. */


vTaskDelayUntil( &xLastWakeTime, ( 10 / portTICK_RATE_MS ) );
}
}
int main( void )
{
xTaskCreate( vContinuousProcessingTask, "Task 1", 1000,
(void*)pcTextForTask1, 1, NULL );
xTaskCreate( vContinuousProcessingTask, "Task 2", 1000,
(void*)pcTextForTask2, 1, NULL );

/* Create one instance of the periodic task at priority 2. */


xTaskCreate( vPeriodicTask, "Task 3", 1000,
(void*)pcTextForPeriodicTask, 2, NULL );

/* Start the scheduler so our tasks start executing. */


vTaskStartScheduler();

for( ;; );
return 0;
}
Periodic

Continuous 1

Continuous 2

IDLE

t1 t2 t3 t4 t5
IDLE task

 Idle task được tạo ra tự động, có độ ưu


tiên 0.
 Nó được chạy khi không có bất kỳ tác vụ
nào có mức ưu tiên cao hơn sẵn sàng
chạy.
IDLE task hook

 Idle task hook là 1 hàm được idle task


gọi trong mỗi vòng lặp của nó.
 Idle task hook thường dùng để:
 Thực hiện các xử lý có ưu tiên thấp
 Đo thời gian rảnh của hệ thống

 Đưa CPU vào trạng thái công suất thấp


IDLE task hook
/* Declare a variable that will be incremented by the hook
function. */
unsigned long ulIdleCycleCount = 0UL;

/* Idle hook functions MUST be called vApplicationIdleHook(),


take no parameters,
and return void. */
void vApplicationIdleHook( void )
{
/* This hook function does nothing but increment a counter.
*/
ulIdleCycleCount++;
}
IDLE task hook
void vTaskFunction( void *pvParameters )
{
char *pcTaskName;

pcTaskName = ( char * ) pvParameters;

/* As per most tasks, this task is implemented in an infinite loop. */


for( ;; )
{
vPrintStringAndNumber( pcTaskName, ulIdleCycleCount );

/* Delay for a period for 250 milliseconds. */


vTaskDelay( 250 / portTICK_RATE_MS );
}
}
IDLE task hook

 IDLE task hook không được block hoặc


suspend.
 Nếu có 1 tác vụ gọi hàm vTaskDelete(),
IDLE task hook phải quay về idle task
sau 1 khoảng thời gian vì idle task có
nhiệm vụ tổ chức lại tài nguyên của
kernel sau khi có 1 tác vụ bị xóa bỏ.
Change task priority
void vTaskPrioritySet( xTaskHandle pxTask,
unsigned portBASE_TYPE uxNewPriority );

(Tham số INCLUDE_vTaskPrioritySet phải


bằng 1 để có thể dùng được hàm này.)
 Parameters:
 pxTask: Handle của tác vụ muốn được thay đổi
mức ưu tiên. Nếu handle là NULL mức ưu tiên của
chính tác vụ đang gọi hàm này sẽ được set.
 uxNewPriority: Mức ưu tiên mới
Query the task’s priority
unsigned portBASE_TYPE uxTaskPriorityGet(
xTaskHandle pxTask );

pxTask: task handle


Nếu pxTask là NULL, giá trị trả về sẽ là mức ưu tiên
của chính tác vụ đang gọi hàm này.
void vTask1( void *pvParameters )
{
unsigned portBASE_TYPE uxPriority;
uxPriority = uxTaskPriorityGet( NULL );

for( ;; )
{
/* Print out the name of this task. */
vPrintString( "Task1 is running\r\n" );

vPrintString( "About to raise the Task2 priority\r\n" );


vTaskPrioritySet( xTask2Handle, ( uxPriority + 1 ) );
}
}
void vTask2( void *pvParameters )
{
unsigned portBASE_TYPE uxPriority;

uxPriority = uxTaskPriorityGet( NULL );

for( ;; )
{
vPrintString( "Task2 is running\r\n" );

vTaskPrioritySet( NULL, ( uxPriority - 2 ) );


}
}
/* Declare a variable that is used to hold the handle of
Task2. */
xTaskHandle xTask2Handle;

int main( void )


{
xTaskCreate( vTask1, "Task 1", 1000, NULL, 2, NULL );
xTaskCreate( vTask2, "Task 2", 1000, NULL, 1,
&xTask2Handle );
vTaskStartScheduler();

for( ;; );
}
Delete a task

void vTaskDelete( xTaskHandle


pxTaskToDelete );

Tác vụ có thể xóa 1 tác vụ khác hay


chính nó.
Ide task sẽ giải phóng vùng nhớ đã cấp
phát cho tác vụ được xóa.
void vTask1( void *pvParameters )
{
const portTickType xDelay100ms = 100 / portTICK_RATE_MS;

for( ;; )
{
/* Print out the name of this task. */
vPrintString( "Task1 is running\r\n" );

xTaskCreate( vTask2, "Task 2", 1000, NULL, 2, &xTask2Handle );


vTaskDelay( xDelay100ms );
}
}
void vTask2( void *pvParameters )
{
vPrintString( "Task2 is running and about
to delete itself\r\n" );
vTaskDelete( xTask2Handle );
}
int main( void )
{
xTaskCreate( vTask1, "Task 1", 1000, NULL, 1, NULL );

/* Start the scheduler so the tasks start executing. */


vTaskStartScheduler();

/* main() should never reach here as the scheduler


has been started. */
for( ;; );
}

You might also like