So sánh chi tiết: Async Rust (Embassy) vs RTOS C (FreeRTOS) trên vi điều khiển nhúng
Bài viết phân tích chuyên sâu cuộc đối đầu giữa mô hình lập trình async Rust với thư viện Embassy và RTOS truyền thống FreeRTOS viết bằng C trên vi điều khiển STM32F446. Kết quả đo lường cho thấy Embassy/Rust vượt trội ở hầu hết các tiêu chí như độ trễ ngắt, thời gian xử lý, kích thước chương trình và bộ nhớ tĩnh, đồng thời mang lại trải nghiệm lập trình ergonomic hơn.

Cuộc đối đầu nghẹt thở: Async Rust (Embassy) hạ knock-out RTOS C (FreeRTOS) trên nền tảng embedded
Trong thế giới lập trình nhúng, cuộc chiến giữa Rust hiện đại và C truyền thống ngày càng trở nên gay cấn, đặc biệt khi so sánh mô hình async/await với Hệ điều hành thời gian thực (RTOS). Một bài phân tích kỹ thuật chuyên sâu vừa được thực hiện trên vi điều khiển STM32F446ZET6 ở tốc độ 180MHz, đặt lên bàn cân hai ứng dụng thực hiện cùng chức năng: một bên dùng Embassy/Rust, bên còn lại dùng FreeRTOS/C. Kết quả khiến không ít kỹ sư phần mềm nhúng phải bất ngờ.
Bài viết này sẽ mổ xẻ chi tiết kết quả đo lường, phân tích ưu nhược điểm của từng mô hình, đồng thời cung cấp góc nhìn thực tế cho cộng đồng lập trình nhúng tại Việt Nam - nơi đang có sự quan tâm ngày càng lớn đến Rust như một giải pháp thay thế an toàn cho các hệ thống nhúng.
Bối cảnh so sánh: Khi hai thế giới chạm trán
Cả hai mô hình lập trình đều có triết lý thiết kế riêng:
- Async Rust (Embassy): Sử dụng cơ chế future và state machine cho phép code chạy không đồng bộ, chuyển đổi ngữ cảnh chỉ khi gặp điểm
await(hợp tác đa nhiệm). Tuy nhiên, nó có giới hạn về phân bổ tĩnh và cần trình biên dịch nightly. - RTOS C (FreeRTOS): Chia chương trình thành các thread độc lập với đa nhiệm ưu tiên (pre-emptive), lưu trữ toàn bộ ngữ cảnh khi chuyển thread, giúp phản hồi sự kiện và ngắt theo thời gian dự đoán được.
Chương trình kiểm tra bao gồm ba tác vụ điển hình của một ứng dụng nhúng thực tế: nhấp nháy LED, xử lý nút bấm qua ngắt GPIO (có truyền thông qua biến boolean nguyên tử), và ghi chuỗi thông điệp từ hàng đợi message ra cổng serial.
Kết quả đo lường: Bảng số liệu không khoan nhượng
Sau khi bấm nút 100 lần và thu thập 200 mẫu bằng máy hiện sóng Rigol DS1054Z, kết quả trung bình và độ lệch chuẩn được thống kê như sau:
| Tiêu chí | C (FreeRTOS) | Rust (Embassy) | Chênh lệch | Phần trăm |
|---|---|---|---|---|
| Thời gian xử lý ngắt (trung bình) | 2.962µs | 1.450µs | -1.512µs | -51.0% |
| Thời gian xử lý ngắt (stddev) | 124.8ns | 4.96ns | -119.84ns | -96.0% |
| Thời gian thread (trung bình) | 16.19µs | 11.64µs | -4.55µs | -28.1% |
| Thời gian thread (stddev) | 248.2ns | 103.0ns | -145.2ns | -56.2% |
| Độ trễ xử lý ngắt (trung bình) | 4.973µs | 3.738µs | -1.235µs | -24.8% |
| Độ trễ xử lý ngắt (stddev) | 158.0ns | 45.3ns | -112.7ns | -71.3% |
| Kích thước chương trình (.text) | 20676 bytes | 14272 bytes | -6404 bytes | -31.0% |
| Bộ nhớ tĩnh (.data + .bss) | 5480 bytes | 872 bytes | -4608 bytes | -84.1% |
Kết quả rõ ràng nghiêng về Embassy/Rust ở mọi hạng mục và chúng có thể tái lập ở những ngày đo khác nhau. Điểm yếu duy nhất của FreeRTOS/C là phần context switching thuần túy (từ cuối ngắt đến khi thread bắt đầu chạy lại) nhanh hơn một chút: C mất 2.011µs trong khi Rust mất 2.288µs. Tuy nhiên, con số này không đáng kể khi so với việc thời gian xử lý ngắt của C dài gấp đôi.
Lý giải sự vượt trội của Embassy/Rust
Sự chênh lệch lớn đến từ nhiều yếu tố cộng hưởng:
Thiết kế tập trung vào ngắt
Embassy được xây dựng dựa trên cơ chế ngắt (interrupt) một cách tự nhiên. Khi một future gọi wait_for_rising_edge().await, nó cấu hình ngắt GPIO và đăng ký waker vào mảng toàn cục. Khi ngắt xảy ra, waker tương ứng được kích hoạt, đánh thức đúng task mà không cần các bước trung gian. Ngược lại, FreeRTOS phải thông qua cơ chế osThreadFlagsSet, gây thêm chi phí xử lý.
Mô hình dữ liệu an toàn và tối ưu
Trong code C, message queue phải tự quản lý bộ nhớ với cấu trúc UartMessage thủ công và dùng strnlen để kiểm tra. Trong khi đó, Rust dùng ArrayVec cung cấp ArrayString được phân bổ trên stack một cách an toàn, giảm rủi ro tràn bộ nhớ và tối ưu kích thước.
Ngoài ra, Rust biên dịch các future thành struct chỉ lưu đúng các biến tồn tại qua điểm await, không cần cấp phát toàn bộ stack size như một thread RTOS - đây là lý do giúp bộ nhớ tĩnh giảm tới 84%.
Ease of programming - Trải nghiệm lập trình
Tác giả bài kiểm tra, một kỹ sư nhúng giàu kinh nghiệm, thừa nhận:
"Async/await viết rất mượt. Một khi bạn chấp nhận ý tưởng có thể
awaitthứ mà bình thường bạn phải dùng ngắt, code trở nên rõ ràng và tích hợp hơn. Quản lý thread trong FreeRTOS không hề vui vẻ gì."
Kết luận: Ai xứng đáng là người chiến thắng?
Tác giả không ngần ngại tuyên bố Embassy/Rust là người chiến thắng thuyết phục trong kịch bản kiểm tra này, cả về con số lẫn trải nghiệm phát triển. Tuy nhiên, cần lưu ý:
- Ứng dụng thời gian thực cứng: Vì async task không bị pre-empt, trong vài kịch bản đặc thù, RTOS vẫn có lợi thế nhất định. Nhưng Embassy giải quyết được bằng cách cho phép nhiều executor chạy trong ngữ cảnh ngắt - waker sẽ kích hoạt executor có ưu tiên cao hơn để pre-empt executor mức thấp.
- Tự do kiểm soát: FreeRTOS/C cho phép can thiệp sâu vào ngắt và HAL; Embassy gói gọn các hàm này bên trong thư viện, có thể khó tùy biến hơn.
Khuyến nghị cho lập trình viên nhúng Việt Nam
Xu hướng chuyển dịch sang Rust trong lĩnh vực nhúng/IoT đang diễn ra mạnh mẽ trên toàn cầu, không ngoại trừ Việt Nam. Nếu bạn đang phát triển:
- Sản phẩm IoT tiêu thụ điện năng thấp, chạy pin: Async Rust giúp tối ưu thời gian "race to sleep", giảm chi phí phần cứng (bộ nhớ thấp hơn 84% là một lợi thế cực lớn về giá thành).
- Hệ thống xử lý nhiều tác vụ cùng lúc: Mô hình
taskcủa Embassy quản lý state rõ ràng, giảm lỗi logic khó tìm. - Dự án có yêu cầu bảo mật và an toàn cao: Bộ đảm bảo an toàn bộ nhớ (memory safety) của Rust giúp giảm thiểu lỗi nghiêm trọng ngay từ lúc biên dịch.
Hãy cân nhắc bắt đầu thử nghiệm với STM32 hoặc các dòng chip phổ biến đã có driver hỗ trợ Embassy (như nordic nRF52). Cộng đồng Rust Việt Nam cũng đang phát triển mạnh, rất thuận lợi để tìm kiếm sự hỗ trợ.
So sánh Rust và C trên nền tảng nhúng
Bài viết được tổng hợp và biên dịch trung thực từ nguồn Tweede Golf, phù hợp với bối cảnh phát triển phần mềm nhúng tại Việt Nam.