CẨM NANG STM32 CĂN BẢN CẦN BIẾT – FreeRTOS – Giới thiệu

Từ đầu trong cuốn sách này, chúng ta đã chuyển sang sử dụng FreeRTOS. Nó cung cấp một số lợi thế, chủ yếu là làm cho lập trình trở nên đơn giản hơn nhiều và mang lại độ tin cậy cao hơn.

Không phải tất cả các nền tảng đều có khả năng hỗ trợ RTOS (real-time operating system: hệ điều hành thời gian thực). Mỗi tác vụ trong một hệ thống đa tác vụ yêu cầu một số không gian stack (ngăn xếp) để được cấp phát nơi các biến và địa chỉ trả về của các hàm gọi được lưu trữ. Chỉ đơn giản là không có nhiều RAM trên một ATmega328, ví dụ, chỉ với 2K. Mặt khác, STM32F103C8T6 có 20K SRAM để phân chia giữa các tác vụ hợp lý.

Chương này giới thiệu FreeRTOS, nó có nguồn mở và có sẵn miễn phí. Mã nguồn FreeRTOS được cấp phép theo Giấy phép GPL 2. Có một điều khoản đặc biệt để cho phép bạn phân phối sản phẩm được liên kết của bạn mà không yêu cầu phân phối mã nguồn độc quyền của riêng bạn. Tìm file văn bản có tên LICENSE để biết chi tiết.

=> Bài viết được trích từ sách : Cẩm nang STM32 (tập 1)

Tiện ích FreeRTOS

Điều gì làm cho một RTOS đáng mong đợi? Nó cung cấp cái gì? Hãy xem xét một số danh mục dịch vụ chính được tìm thấy trong FreeRTOS:

  • Đa nhiệm và lập lịch trình
  • Hàng đợi tin nhắn (Message queues)
  • Semaphoresvà mutex
  • Timer
  • Nhóm sự kiện (Event groups)

Thực hiện tác vụ

Trong môi trường Arduino, mọi thứ đều chạy như một tác vụ đơn, với một ngăn xếp duy nhất cho các biến và địa chỉ trả về. Kiểu lập trình này yêu cầu bạn chạy kiểm vòng lặp cho mỗi sự kiện cần thực thi. Với mỗi lần lặp, bạn có thể cần kiểm cảm biến nhiệt độ và sau đó gọi một lệnh khác như là một phần của vòng lặp để xuất kết quả đó.

Với FreeRTOS (một RTOS), các hàm logic được đặt vào các tác vụ riêng biệt chạy độc lập. Một tác vụ có thể chịu trách nhiệm đọc và tính toán nhiệt độ hiện tại. Một tác vụ khác có thể chịu trách nhiệm thể hiện nhiệt độ được tính toán cuối cùng đó. Trong thực tế, nó sẽ trở thành một hai chương trình chạy song song cùng một lúc.

Đối với các ứng dụng đơn giản, phí tổn của việc lên lịch tác vụ có thể là quá cao. Tuy nhiên, khi độ phức tạp tăng lên, lợi ích của việc phân chia vấn đề thành các tác vụ trở nên rõ rệt hơn nhiều.

FreeRTOS rất linh hoạt. Nó cung cấp hai loại lập lịch trình tác vụ:

  • Ưu tiên đa tác vụ
  • Hợp nhất đa tác vụ (coroutines)

Với tính năng đa tác vụ ưu tiên, một tác vụ sẽ chạy cho đến khi nó hết thời gian, hoặc bị chặn, hoặc cần kiểm soát rõ ràng. Bộ lập lịch trình tác vụ sẽ sắp xếp tác vụ chạy tiếp sau, có tính đến các ưu tiên. Đây là loại tác vụ đa nhiệm sẽ được sử dụng trong các dự án của cuốn sách này.

Một dạng đa nhiệm khác là coroutines. Sự khác biệt là tác vụ hiện tại chạy cho đến khi nó từ bỏ quyền kiểm soát. Không có phân chia thời gian hoặc thời gian chờ. Nếu không có hàm gọi nào chặn (như một mutex), thì một coroutine phải gọi một hàm yield để chuyển quyền kiểm soát với một tác vụ khác. Bộ lập lịch trình tác vụ sau đó sẽ quyết định tác vụ nào sẽ chuyển quyền kiểm soát sang bước tiếp theo. Hình thức lập chương trình này là cần phải có cho các ứng dụng yêu cầu an toàn cao sẽ kiểm soát chặt chẽ thời gian CPU.

Hàng đợi tin nhắn

Ngay sau khi bạn áp dụng đa tác vụ, bạn thừa hưởng một vấn đề về giao tiếp. Sử dụng ví dụ đọc nhiệt độ, tác vụ đọc nhiệt độ an toàn truyền giá trị đến tác vụ phát nhiệt độ như thế nào? Nếu nhiệt độ được lưu trữ là bốn byte, làm thế nào để bạn truyền giá trị đó mà không bị gián đoạn? Tính đa nhiệm ưu tiên có nghĩa là việc sao chép bốn byte dữ liệu đến một vị trí khác có thể bị gián đoạn một phần.

Một cách khá thô để giải quyết vấn đề này là ngăn chặn gián đoạn trong khi sao chép nhiệt độ của bạn đến một vị trí được sử dụng bởi tác vụ phát sóng. Nhưng cách tiếp cận này có thể không thể chấp nhận được nếu bạn thường xuyên bị gián đoạn. Vấn đề trở nên tồi tệ hơn khi các đối tượng được sao chép có kích thước tăng.

Hàng đợi tin nhắn trong FreeRTOS cung cấp một cách an toàn để truyền thông tin hoàn chỉnh. Hàng đợi tin nhắn đảm bảo rằng chỉ nhận được tin nhắn đầy đủ. Ngoài ra, nó giới hạn độ dài của hàng đợi sao cho tác vụ gửi không thể sử dụng hết bộ nhớ. Bằng cách sử dụng độ dài hàng đợi được xác định trước, tác vụ thêm thông báo sẽ bị chặn cho đến khi không gian có sẵn. Khi một tác vụ bị chặn, công cụ lập lịch trình tác vụ sẽ tự động chuyển sang một tác vụ khác đã sẵn sàng thực thi, thao tác này có thể xóa các tin nhắn khỏi cùng một hàng đợi đó. Độ dài cố định cho hàng đợi tin nhắn một dạng điều khiển dòng.

=> xem thêm : Lập trình Arm STM32

Semaphore và Mutex

Trong khi thực hiện một hàng đợi, có một thao tác mutex tại đó. Quá trình thêm tin nhắn có thể yêu cầu một số hướng dẫn để hoàn thành. Tuy nhiên, trong một hệ thống đa tác vụ ưu tiên, có thể một tin nhắn được thêm một nửa trước khi bị gián đoạn để thực hiện một tác vụ khác.

Trong FreeRTOS, hàng đợi được thiết kế để có các tin nhắn được thêm vào theo cách nguyên tử. Để thực hiện điều này, một số loại thiết bị mutex được sử dụng đằng sau chương trình. Mutex là một thiết bị tất cả hoặc không có gì. Bạn có khóa hay không.

Tương tự như mutex, có semaphore. Trong một số tình huống mà bạn muốn giới hạn một số yêu cầu nhất định, ví dụ, một semaphore có thể quản lý nó theo cách nguyên tử. Ví dụ, nó có thể cho phép một giá trị tối đa là ba. Sau đó, tối đa ba yêu cầu “nhận” sẽ thành công. Các yêu cầu “nhận” bổ sung sẽ chặn cho đến khi một hoặc nhiều yêu cầu “cung cấp” đã được thực hiện để trả lại khoảng trống.

Timer

Timer quan trọng đối với nhiều ứng dụng, bao gồm cả chương trình nhấp nháy. Khi bạn có nhiều tác vụ tốn thời gian CPU, một delay không chỉ không đáng tin cậy, mà nó còn lấy đi các tác vụ khác của thời gian CPU, cái có thể được sử dụng hiệu quả hơn.

Trong hệ thống RTOS, thường có một ngắt “systick” giúp quản lý thời gian. Cái ngắt systick này không chỉ theo dõi số lượng hiện tại của “ticks” được phát hành cho đến nay, mà còn được sử dụng bởi các bộ lập lịch trình tác vụ để hoán đổi các tác vụ.

Trong FreeRTOS, bạn có thể chọn delay việc thực hiện bằng một số tick được chỉ định. Điều này hoạt động bằng cách đánh dấu “thời gian đánh dấu” hiện tại và phát triển cho một tác vụ khác cho đến khi thời gian đánh dấu bắt buộc đã đến. Bằng cách này, độ chính xác của delay chỉ giới hạn trong khoảng thời gian được chọn được định cấu hình. Nó cũng cho phép các tác vụ khác thực hiện công việc thực sự cho đến khi đúng thời điểm đến.

FreeRTOS cũng có tiện ích timer “ảo” (software timer) có thể được tạo ra. Chỉ khi bộ đếm thời gian hết hạn là hàm callback được thực hiện. Cách tiếp cận này là bộ nhớ tiết kiệm bởi vì tất cả các bộ định thời gian sẽ sử dụng cùng một ngăn xếp.

Nhóm Event

Một vấn đề thường xảy ra là một tác vụ có thể cần phải theo dõi nhiều hàng đợi cùng một lúc. Ví dụ, một tác vụ có thể cần phải chặn cho đến khi một tin nhắn đến từ một trong hai hàng đợi khác nhau. FreeRTOS cung cấp cho việc tạo ra “bộ hàng đợi.” Điều này cho phép một tác vụ chặn cho đến khi một tin nhắn từ bất kỳ hàng đợi trong tập hợp có một tin nhắn.

Điều gì về các event do người dùng xác định? Các nhóm event có thể được tạo để cho phép các bit nhị phân đại diện cho một event. Khi được thiết lập, API FreeRTOS cho phép một tác vụ đợi cho đến khi một sự kiện kết hợp cụ thể xảy ra. Các sự kiện có thể được kích hoạt từ code tác vụ thông thường hoặc từ bên trong một ISR (interrupt service routine: dịch vụ ngắt).

=> Sách Arduino, ESP8266, STM32 : Sách tự động hóa