- vừa được xem lúc

ISR Yield là gì? Làm sao để ngắt tương tác với task trong RTOS

0 0 2

Người đăng: delinux

Theo Viblo Asia

Giới thiệu nhanh

Ở bài trước, khi nói về Queue, mình có nói tới khái niệm ISR Yield. Có nhiều bạn hỏi mình rằng đó là gì và tại sao phải quan tâm tới nó khi thao tác với ngắt trong RTOS. Vì thế, để trả lời cho những câu hỏi đó, trong bài này mình sẽ cùng các bạn tìm hiểu ISR Yield là gì và tại sao các bạn cần để ý tới nó khi thao tác với ngắt trong RTOS nhé!

Nói sơ qua thì trong các hệ điều hành thời gian thực (RTOS), ngắt (Interrupt) là cơ chế thiết yếu để phản ứng tức thời với sự kiện bên ngoài. Tuy nhiên, việc tương tác giữa ngắt và các task trong hệ thống không thể được thực hiện một cách ngẫu nhiên – cần tuân thủ những nguyên tắc chặt chẽ để đảm bảo tính nhất quán và độ trễ tối thiểu. ISR Yield chính là một khái niệm then chốt giúp tối ưu luồng điều khiển giữa ngắt và scheduler trong FreeRTOS.


1. ISR Yield là gì?

ISR Yield là quá trình kích hoạt lại việc lập lịch (context switch) từ trong ngắt (ISR - Interrupt Service Routine) nếu một task có độ ưu tiên cao hơn task hiện tại đã sẵn sàng chạy ngay khi ISR kết thúc.

Trong FreeRTOS, bạn không nên gọi vTaskSwitchContext() trực tiếp trong ISR. Thay vào đó, sử dụng các hàm "FromISR", như:

BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(queueHandle, &data, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

Hàm portYIELD_FROM_ISR() sẽ chỉ yêu cầu yield nếu xHigherPriorityTaskWokenpdTRUE – nghĩa là một task có độ ưu tiên cao hơn đã sẵn sàng thực thi sau ISR.


2. Tại sao cần ISR Yield?

Giả sử bạn có:

  • Task A (ưu tiên thấp hơn)
  • Task B (ưu tiên cao hơn)

Nếu Task A đang chạy, và một ISR xuất hiện đưa Task B vào trạng thái sẵn sàng (ready), thì hệ thống phải chuyển sang chạy Task B ngay lập tức sau khi ISR kết thúc. Nếu không, Task A tiếp tục chiếm CPU, gây độ trễ không cần thiết cho Task B – điều tối kỵ trong hệ thống RTOS.


3. Cơ chế hoạt động bên trong

3.1. Tác động của xHigherPriorityTaskWoken

Hầu hết các API "FromISR" của FreeRTOS trả về xHigherPriorityTaskWoken:

  • pdTRUE: Nếu một task cao hơn được đưa vào "ready".
  • pdFALSE: Không có sự thay đổi về mức ưu tiên.

Điều này cho phép ISR quyết định có cần yield ngay hay không – tránh những lần context switch không cần thiết.

3.2. Vai trò của portYIELD_FROM_ISR

Hàm portYIELD_FROM_ISR() là macro hoặc hàm inline có trong mỗi port cụ thể (ARM Cortex-M, Xtensa cho ESP32,...). Nó sẽ:

  • Đánh dấu cần context switch ngay sau khi ISR hoàn tất.
  • Khi thoát khỏi ISR, kernel kiểm tra và nếu cần sẽ thực hiện chuyển task.

Trên Cortex-M:

#define portYIELD_FROM_ISR(x) if(x != pdFALSE) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT

Trên Xtensa (ESP32):

#define portYIELD_FROM_ISR() portYIELD()

4. Ví dụ thực tế

Mô hình: ISR kích hoạt khi có dữ liệu UART

Giả sử một thiết bị UART gửi dữ liệu, và trong ISR ta gửi dữ liệu đó vào một hàng đợi. Một task khác sẽ tiến hành xử lý chuỗi UART vừa nhận và task này có độ ưu tiên cao hơn task đang chạy.

// logic được đặt trong hàm ngắt
void uart_isr_handler(void *arg) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; char data = UART0.fifo.rw_byte; xQueueSendFromISR(uartQueue, &data, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

Khi xQueueSendFromISR() thành công và một task đang chờ nhận từ queue, task đó sẽ được đánh dấu ready. Nếu nó có độ ưu tiên cao hơn task hiện tại, portYIELD_FROM_ISR() sẽ yêu cầu lập lịch lại.

Biểu đồ thời gian

image.png


5. Sai lầm phổ biến

  • Không gọi portYIELD_FROM_ISR() sau khi dùng API FromISR: Điều này dẫn đến task có ưu tiên cao hơn không được chạy ngay lập tức.
  • Gọi vTaskDelay() trong ISR: Không hợp lệ. ISR nên càng ngắn càng tốt – mọi logic phải giao lại cho task.
  • Không kiểm tra xHigherPriorityTaskWoken: Dẫn đến yield không cần thiết hoặc không xảy ra.

6. Tối ưu hóa ISR với ISR Yield

Một số chiến lược chuyên sâu:

  • Tách ISR thành hai phần: phần "top-half" (ISR thực thi nhanh, đẩy dữ liệu vào queue), phần "bottom-half" (task xử lý).
  • Sử dụng portYIELD_FROM_ISR() có điều kiện để tránh context switch không cần thiết (chỉ khi có task ưu tiên cao sẵn sàng).
  • Kết hợp ISR Yield với Task Notification: nhanh hơn queue trong nhiều trường hợp.

7. Khi nào không cần ISR Yield?

Trong những trường hợp sau:

  • ISR chỉ báo hiệu cho task có cùng hoặc thấp hơn mức ưu tiên đang chạy.
  • Bạn muốn trì hoãn context switch đến khi ISR khác kết thúc.
  • Hệ thống có thiết lập configMAX_SYSCALL_INTERRUPT_PRIORITY giới hạn mức ISR có thể gọi API FreeRTOS.

8. Kết luận

ISR Yield là một cơ chế rất quan trọng nhưng thường bị bỏ qua trong thiết kế hệ thống RTOS. Sử dụng đúng sẽ giúp hệ thống:

  • Giảm độ trễ xử lý sự kiện.
  • Đảm bảo ưu tiên thực thi đúng.
  • Tăng tính phản ứng thời gian thực.

Trong những hệ thống nhúng phức tạp như ESP32, STM32, hay bất kỳ hệ thống nào dùng FreeRTOS, hiểu và vận dụng đúng ISR Yield chính là dấu hiệu phân biệt giữa một kỹ sư mới vào nghề và một chuyên gia dày dạn kinh nghiệm.


Bình luận

Bài viết tương tự

- vừa được xem lúc

#Yield #Python

#Yield #Python. 00:00 Đọc đề, suy nghĩ , chọn đáp án. 00:11 Xem kết quả. .

0 0 30

- vừa được xem lúc

Giải mã AUTOSAR: Kiến trúc tiêu chuẩn ngành Automotive

Giới thiệu. AUTOSAR có vẻ khá xa lạ đối với người làm về công nghệ thông tin, nhưng đối với những bạn làm về Embedded System, đặc biệt là trong lĩnh vực Automotive, thì cũng.

0 0 24

- vừa được xem lúc

Từ khoá volatile trong lập trình C

Trong lập trình nhúng chắc hẵn bạn đã từng gặp phải tình huống khi chương trình C của bạn cho ra kết quả không đúng, mặc dù mã code có vẻ đúng? Một nguyên nhân có thể gây ra vấn đề này là việc tối ưu

0 0 24

- vừa được xem lúc

Giải mã AUTOSAR: Kiến trúc để đời ngành Automotive - Phần 2

Updating. Trong bài viết này, ta cùng tìm hiểu kỹ hơn về lớp trên cùng của kiến trúc, chính là lớp Application Layer (ASW).

0 0 20

- vừa được xem lúc

Con Trỏ Hàm - C/C++

Hàm Con Trỏ (Function Pointer) là gì. . Con trỏ tới hàm (A pointer to a function): Đây là biến lưu trữ địa chỉ hàm mà sau này có thể gọi bằng con trỏ này. .

0 0 18

- vừa được xem lúc

Cơ bản về WatchDog Timer trong hệ thống nhúng (Embedded System)

Khái Niệm. Trong hệ thống nhúng, a WatchDog Timer (Bộ đếm thời gian giám sát) là một thành phần hoặc tính năng của phần cứng được thiết kế để giám sát hoạt động của hệ thống và thực hiện hành động khắ

0 0 14