Phân Tích Cơ Bản Về Semaphore Trong FreeRTOS

Loại Semaphore

FreeRTOS cung cấp bốn loại semaphore chính:

  • Binary semaphore: Dùng cho đồng bộ tác vụ, tương đương với cờ hiệu trong hệ thống không RTOS
  • Counting semaphore: Quản lý tài nguyên chia sẻ, giá trị đếm biểu thị số lượng tài nguyên khả dụng
  • Mutex: Bảo vệ vùng giao tiếp, giải quyết vấn đề ưu tiên đảo ngược (priority inversion)
  • Recursive mutex: Cho phép cùng tác vụ lấy lại mutex mà không cần giải phóng trước

Tạo Semaphore Đếm

/* Tạo semaphore đếm với giới hạn tối đa và giá trị khởi tạo */
SemaphoreHandle_t createCountingSemaphore(UBaseType_t maxCount, UBaseType_t initValue);

Tham số:
- maxCount: Giá trị đếm tối đa
- initValue: Giá trị khởi tạo
Trả về: Handler nếu thành công, NULL nếu thiếu bộ nhớ

Tạo Binary Semaphore

/* Tạo semaphore nhị phân */
SemaphoreHandle_t createBinarySemaphore(void);

Lưu ý: Giá trị khởi tạo là 0. Nên dùng notification message thay vì binary semaphore để tối ưu hiệu năng.

Tạo Mutex

/* Tạo mutex bảo vệ vùng giao tiếp */
SemaphoreHandle_t createMutex(void);

Lưu ý: Không dùng trong ISR, chỉ dùng trong tác vụ.

Giải Phóng Semaphore

/* Giải phóng cho semaphore đếm, nhị phân, mutex */
BaseType_t releaseSemaphore(SemaphoreHandle_t semaHandle);

/* Giải phóng trong ISR */
BaseType_t releaseSemaphoreFromISR(SemaphoreHandle_t semaHandle, BaseType_t* higherTask);

/* Giải phóng recursive mutex */
BaseType_t releaseRecursiveMutex(SemaphoreHandle_t mutexHandle);

Chú ý: Trong ISR, tham số thứ hai xác định có tác vụ ưu tiên cao hơn sẵn sàng. Nếu true, cần gọi taskYIELD() sau khi kết thúc ISR.

Lấy Semaphore

/* Lấy semaphore cho đếm, nhị phân, mutex */
BaseType_t takeSemaphore(SemaphoreHandle_t semaHandle, TickType_t waitTime);

/* Lấy trong ISR */
BaseType_t takeSemaphoreFromISR(SemaphoreHandle_t semaHandle, BaseType_t* higherTask);

/* Lấy recursive mutex */
BaseType_t takeRecursiveMutex(SemaphoreHandle_t mutexHandle, TickType_t waitTime);

Chú ý: Không dùng mutex trong ISR. Tham số waitTime xác định thời gian chờ tối đa.

Vấn Đề Ưu Tiên Đảo Ngược

Xảy ra khi dùng binary semaphore thông thường:

  1. Tác vụ HighPriority (ưu tiên cao) và LowPriority (ưu tiên thấp) chia sẻ tài nguyên
  2. LowPriority chiếm tài nguyên, sau đó HighPriority trở về trạng thái sẵn sàng
  3. MediumPriority (ưu tiên trung bình) chạy trước HighPriority dù ưu tiên thấp hơn

Giải pháp: Mutex sử dụng cơ chế kế thừa ưu tiên. Khi HighPriority chờ tài nguyên, LowPriority sẽ được nâng cấp ưu tiên bằng với HighPriority, đảm bảo LowPriority hoàn thành trước khi HighPriority chạy.

Thẻ: FreeRTOS semaphore priority_inheritance Mutex counting_semaphore

Đăng vào ngày 16 tháng 6 lúc 08:51