Bài 60.832 phút đọc
Level 8: Mini RTOS
Sau bài này bạn sẽ làm được
- Cài chuyển ngữ cảnh bằng PendSV và assembly
- Viết bộ lập lịch xoay vòng theo mức ưu tiên
- Cài delay không chặn để task khác chạy được
- Phát hiện tràn ngăn xếp bằng số kỳ diệu ở đáy
Dự án cuối cùng, đỉnh của toàn khoá: viết một hệ điều hành thời gian thực nhỏ. Bạn tự cài chuyển ngữ cảnh, bộ lập lịch, và các nguyên thuỷ đồng bộ. Đây là nơi mọi thứ đã học, kể cả assembly, gặp nhau.
#Mục tiêu
API cần cài
void rtos_init(void);
int rtos_task_create(void (*fn)(void *), void *arg,
uint8_t prio, size_t stack_size);
void rtos_start(void);
void rtos_delay(uint32_t ms); /* KHONG chan: task khac chay duoc */
void rtos_yield(void);
Semaphore *sem_create(int gia_tri_dau);
void sem_wait(Semaphore *);
void sem_post(Semaphore *);
Queue *queue_create(size_t item_size, size_t n);
int queue_send(Queue *, const void *item, uint32_t timeout);
int queue_recv(Queue *, void *item, uint32_t timeout);| Thành phần | Kỹ thuật | Phần |
|---|---|---|
| Chuyển ngữ cảnh | PendSV handler, assembly | Phần 18, 12 |
| Task Control Block | Con trỏ ngăn xếp, trạng thái, ưu tiên | Phần 5, 6 |
| Bộ lập lịch | Xoay vòng theo mức ưu tiên | Phần 8 |
| Tick hệ thống | SysTick 1 mili giây | Phần 18 |
| Đồng bộ | Semaphore, mutex, hàng đợi | Phần 16 |
| Phát hiện tràn ngăn xếp | Số kỳ diệu ở đáy | Bài 60.7 |
#Chuyển ngữ cảnh
Task Control Block và ý tưởng chuyển ngữ cảnh
typedef enum { SAN_SANG, DANG_CHAY, DANG_CHO, DANG_NGU } TrangThai;
typedef struct {
uint32_t *sp; /* CON TRO NGAN XEP da luu cua task */
TrangThai trang_thai;
uint8_t uu_tien;
uint32_t thuc_day_luc; /* moc thoi gian danh thuc neu dang ngu */
uint32_t stack[STACK_CO]; /* ngan xep RIENG cua task */
} TCB;
/* Y tuong chuyen ngu canh:
1. Task A dang chay. Ngat SysTick (hoac yield) kich hoat PendSV.
2. PendSV handler LUU moi thanh ghi cua A vao NGAN XEP CUA A,
roi luu con tro ngan xep hien tai vao tcb_A->sp.
3. Bo lap lich chon task B tiep theo.
4. Nap tcb_B->sp vao con tro ngan xep, roi KHOI PHUC moi thanh
ghi tu ngan xep cua B.
5. Tra ve tu PendSV -> gio dang chay task B, tu dung cho no
da dung lai lan truoc.
Diem tinh te: moi task co NGAN XEP RIENG. "Trang thai" cua mot
task khong chay chinh la cac thanh ghi da luu tren ngan xep
cua no. Chuyen task chi la doi con tro ngan xep. */#Bộ lập lịch
Xoay vòng theo mức ưu tiên
/* Chon task tiep theo:
- task uu tien CAO chay truoc task uu tien thap
- cung muc uu tien thi XOAY VONG (round-robin) cong bang
- bo qua task dang cho hoac dang ngu */
static TCB *chon_task_tiep(void) {
/* tim muc uu tien cao nhat co task SAN SANG */
for (int p = UU_TIEN_CAO_NHAT; p >= 0; --p) {
TCB *bat_dau = con_tro_xoay[p];
TCB *t = bat_dau;
do {
if (t->trang_thai == SAN_SANG) {
con_tro_xoay[p] = t->tiep; /* lan sau bat dau tu ke tiep */
return t;
}
t = t->tiep;
} while (t != bat_dau);
}
return task_nhan_roi; /* khong task nao san sang */
}#Đồng bộ
#Yêu cầu
Tự làm thử
- Chuyển ngữ cảnh bằng
PendSVhandler, viết assembly. - TCB: con trỏ ngăn xếp, trạng thái, ưu tiên, thời điểm đánh thức.
- Bộ lập lịch xoay vòng trong cùng mức ưu tiên, ưu tiên cao chạy trước.
SysTickmột mili giây làm tick hệ thống.delaykhông chặn, task khác chạy được.- Semaphore, mutex có kế thừa ưu tiên, hàng đợi thông điệp.
- Phát hiện tràn ngăn xếp bằng số kỳ diệu ở đáy.
- Thống kê: CPU mỗi task, ngăn xếp còn lại.
Trình chấm điểm tự động sẽ được bổ sung ở giai đoạn sau. Hiện tại bạn tự chạy thử trên máy.
Tóm tắt
- Dự án cuối là viết một RTOS nhỏ: bạn tự lập lịch, tự chuyển ngữ cảnh, tự quản lý bộ nhớ.
- Chuyển ngữ cảnh phải là assembly trong
PendSVvì nó thao tác trực tiếp thanh ghi và phải nguyên tử; mỗi task có ngăn xếp riêng. delaykhông chặn là cốt lõi của đa nhiệm: task ngủ thì task khác chạy, CPU không lãng phí.- Mutex phải có kế thừa ưu tiên để tránh đảo ngược ưu tiên, lỗi từng làm treo tàu Mars Pathfinder.
- Phát hiện tràn ngăn xếp bằng số kỳ diệu là bắt buộc, và cả dự án cần tài liệu thiết kế cùng lịch sử git hợp lý.