vTaskDelay()
Hàm này cho phép delay task theo đơn vị tick, giúp chuyển đổi tásk vào trạng thái "blocked" để CPU có thể thực hiện các task khác
#include "freertos/freeRTOS.h"
#include "freertos/task.h"
void TaskFunction(void *pvParameter){
while(1){
printf("Task is running...\n");
vTaskDelay(1000 / portTICK_PERIOD_MS); //Delay 1000ms (1s)
}
}vTaskDelayUntil()(Delay thời gian tuyệt đối)
Hàm này giúp đảm bảo khoảng thời gian giữa các lần chạy task không bị ảnh hưởng bởi độ trễ của các lệnh khác
void TaskFunction(void *pvParameter){
TickType_t xLastWakeTime = xTaskGetTickCount(); //Lay thoi gian hien tai
while(1){
printf("Task runs at a fixed interval...\n");
vTaskDelayUntil(&xLastWakeTime, 500 / portTICK_PERIOD_MS); //Delay chinh xac 500ms
}
}- Ham
vTasKDelayUntil()giúp duy trì tần suất chạy của task mà không bị lệch do các lệnh khác
Ví dụ: Nếu bạn cần chạy task mỗi 500ms, hàm này sẽ đảm bảo đúng khoảng thời gian đó.
xTaskGetTickCount()(Lấy thời gian hiện tại)
Hàm này sẽ trả về số tick kể từ khi hệ thống bắt đầu chạy
TickType_t now = xTaskGetTickCount();
printf("Current tick count: %d\n", now);- Nếu
CONFIG_FREERTOS_HZ = 1000thì mỗi tick tương ứng 1ms - Nếu
CONFIG_FREERTOS_HZ = 100thì mỗi tick tương ứng 10ms
pdMS_TO_TICKS()(Chuyển đổi từ milliseconds sang tick)
Nếu bạn muốn viết code dễ đọc hơn, thay vì dùng/ portTICK_PERIOD_MSthì có thể dùng hàm trên
vTaskDelay(pdMS_TO_TICKS(1000)); //Delay 1000ms (1s)xSemaphoreCreateMutex()(Mutual Exclusion - Loại trừ lẫn nhau)
- Khóa tài nguyên
- Dùng để bảo vệ tài nguyên chia sẻ, chỉ duy nhất 1 task có quyền truy cập tại 1 thời điểm nhất định
- Có tính năng ưu tiên (Priority Inversion Handling) - nếu một task có mức ưu tiên cao hơn đang chờ mutex, task giữ mutex có mức ưu tiên thấp hơn sẽ được nâng lên để giải phóng nhanh hơn.
- Task nào lấy mutex (take) thì phải trả lại mutex (give)
- Bảo vệ biến toàn cục, tài nguyên chung (I2C, SPI, UART,...)
- Tránh xung đột khi nhiều task truy cập cùng lúc
SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();
if(xMutex != NULL){
if(xSemaphoreTake(xMutex, portMAX_DELAY)){
//Truy cap tai nguyen an toan
xSemaphoreGive(xMutex); //Lay thi phai tra lai mutex luon
}
}xSemaphoreCreateBinary()(Binary Semaphore - Semaphore nhị phân)
- Đồng bộ hóa
- Chỉ có hai trạng thái: có sẵn (1) và không có sẵn (0)
- Không hỗ trợ ưu tiên task như mutex
- Dùng cho đồng bộ hóa (task này báo hiệu task khác)
- Task A có thể "give", Task B có thể "take"
- Đồng bộ giữa ISR (Interrupt Service Routine) và task
- Báo hiệu sự kiện giữa 2 task
SemaphoreHandle_t xBinarySemaphore = xSemaphoreCreateBinary();
if(xBinarySemaphore != NULL){
xTaskCreate(vTask1, "Task1", 2048, NULL, 2, NULL);
if(xSemaphoreTake(xBinarySemaphore, portMAX_DELAY)){
//Chay khi co tin hieu tu task khac
}
}xSemaphoreCreateCounting()(Counting semaphore - Semaphore đếm)
- Đếm tài nguyên
- Có thể đếm nhiều hơn 1 task, nghĩa là cho phép nhiều task cùng lúc take và give
- Hữu ích khi giới hạn số lượng tài nguyên
- Khi tạo cần chỉ định giá trị tối đa (
uxMaxCount) và giá trị ban đầu (uxInitialCount) - Mỗi counting semaphore yêu cần 1 lượng RAM nhỏ để giữ trạng thái của semaphore (từ heap FreeRTOS)
- Đếm sự kiện: Trình xử lý sẽ cung cấp một
semaphoremỗi khi một sự kiện xảy ra (tăng giá trị đếm semaphore). Mỗi khi có 1 task cần xử lý 1 sự kiện, nó sẽ lấy (take) 1 semaphore (giảm giá trị đếm semaphore) - Quản lý tài nguyên: Giá trị đếm cho biết số lượng tài nguyên sử dụng. Để kiểm soát 1 tài nguyên, trước tiên 1 task phải có được 1 semaphore - giảm giá trị đếm semaphore. Khi giá trị đếm đạt đến 0 thì không có tài nguyên nào rảnh. Khi một task hoàn thành, nó sẽ trả lại (give) semaphore - tăng giá trị đếm semaphore.
- Quản lý nhiều tài nguyên giống nhau (ví dụ: 3 cảm biến có thể chạy song song)
- Kiểm soát số lượng kết nối đồng thời (ví dụ: tối đa 5 client kết nối Wifi)
SemaphoreHandle_t xCountingSemaphore = xSemaphoreCreateCounting(5, 5);
if (xCountingSemaphore != NULL) {
if (xSemaphoreTake(xCountingSemaphore, portMAX_DELAY)) {
// Truy cập tài nguyên
xSemaphoreGive(xCountingSemaphore);
}
}