🌱 Cấu trúc freeRTOS Kernel và Porting cho Vi điều khiển STM32
Ở bài viết trước mình đã giới thiệu về freeRTOS và tầm quan trọng của nó trong hệ thống nhúng sử dụng Vi điều khiển. Như bài viết đã đề cập, thành phần quan trọng nhất của freeRTOS là Kernel, và khả năng porting cho nhiều kiến trúc vi điều khiển khác nhau.
Bài viết này sẽ đề cập đến kiến trúc Kernel và cách Porting freeRTOS Kernel cho các Vi điều khiển khác nhau, lấy ví dụ với vi điều khiển STM32.
Mục Lục
- file FreeRTOSConfig.h
- Các bước Porting freeRTOS Kernel cho Vi điều khiển
- Porting freeRTOS Kernel cho project vi điều khiển STM32
- Kết luận
Các thành phần cơ bản trong freeRTOS Kernel
Để tìm hiểu các thành phần này, cách tốt nhất là download source code của freeRTOS tại trang chủ!
Trong folder tải về, ngoài Kernel thì còn rất nhiều tiện ích khác đã được đề cập ở bài viết trước, bạn tìm đến đúng folder FreeRTOS-Kernel, folder này chứa toàn bộ source code của freeRTOS Kernel.
📄Các file source code chính của freeRTOS Kernel
File | Mô tả |
---|---|
croutine.c |
Hỗ trợ Co-routines (task nhẹ hơn task thường, ít dùng trong dự án hiện đại). |
event_groups.c |
Cung cấp Event Group, giúp nhiều task đồng bộ theo event bit. |
list.c |
Cấu trúc danh sách liên kết, dùng nội bộ để quản lý task/queue. |
queue.c |
Triển khai Queue, Semaphore, Mutex → cơ chế giao tiếp & đồng bộ giữa task. |
stream_buffer.c |
Cung cấp Stream Buffer & Message Buffer, truyền dữ liệu liên tục giữa task/ISR. |
tasks.c |
Trái tim của FreeRTOS: quản lý scheduler, vòng đời task, context switching. |
timers.c |
Hỗ trợ software timer, callback định kỳ. |
📄Folder include chứa các header file cần thiết, đặt chung folder để user dễ dàng link tới!
📄Các file code porting - folder portable - Các file source code này đóng vai trò quan trọng trong việc porting sang các platform khác nhau! Hai thành phần chính của folder này:① Platform (Compiler và Processor Architecture)
Trong folder Porting, có rất nhiều folder liên quan đến Platform, bao gồm cả Compiler-IDE (GCC, IAR, Keil, MikroC, ...) hoặc Processor Architecture (ARMv8M, Renesas, ...)
Khi Porting, cần tìm đúng vị trí 2 file trên dựa theo platform sử dụng - ở hình trên là chip lõi ARM Cortex-M4F, compiler sử dụng là GCC.- port.c - Hiện thực hàm phụ thuộc phần cứng: context switch, scheduler tick, khởi tạo stack task.
- portmacro.h - Định nghĩa macro đặc thù cho kiến trúc, ví dụ: bật/tắt ngắt, định nghĩa kiểu dữ liệu, align stack…
② Memory Management (MemMang)
Folder MemMang chứa các file Quản lý bộ nhớ động (heap). Có nhiều thuật toán quản lý khác nhau (heap_1.c … heap_5.c), ở đây chỉ chọn 1 file duy nhất.
- heap_1.c → malloc đơn giản, không có free.
- heap_2.c → malloc/free, nhiều block, coalescing.
- heap_3.c → wrapper cho malloc/free của compiler.
- heap_4.c → malloc/free, hợp nhất block tốt hơn (nâng cấp từ heap_2).
- heap_5.c → giống heap_4 nhưng hỗ trợ nhiều vùng nhớ rời rạc.
📄Ngoài các file source code, bạn có thể xem qua một số file còn lại:
CMakeLists.txt
→ Hỗ trợ build bằng CMake.README.md
,Quick_Start_Guide
→ Tài liệu hướng dẫn.LICENSE.md
→ MIT License.MISRA.md
→ Tuân thủ chuẩn MISRA C.History.txt
→ Lịch sử thay đổi phiên bản.manifest.yml
,cspell.config.yaml
,sbom.spdx
→ Metadata, kiểm tra chính tả, thông tin dependency.
Trong FreeRTOS, ngoài phần kernel (các file lõi như tasks.c, queue.c, timers.c...), thường còn có folder examples (hoặc Demo/ trong source chính thức). Đây là nơi chứa các project mẫu để bạn dễ dàng build và chạy trên từng vi điều khiển / IDE cụ thể.
file FreeRTOSConfig.h
Nếu chỉ bao gồm những source code trên thì project freeRTOS sẽ không build được do thiếu rất nhiều macro. Vì vậy, dev cần tự define các macro này, và thông thường, nên tạo một header file gồm các macro đó - tùy chỉnh cho từng project - đó là file FreeRTOSConfig.h. File này do dev tự phát triển, để lưu các cấu hình liên quan đến freeRTOS Kernel.
- Giúp tùy biến hành vi kernel mà không phải sửa trực tiếp code FreeRTOS.
- Xác định tham số hệ thống: số lượng task, kích thước heap, tick rate, ưu tiên tối đa…
- Bật/tắt tính năng: Mutex, Semaphore, Software Timer, Event Group…
- Chọn chế độ debug, assert, trace.
⚙️ Cấu hình trong FreeRTOSConfig.h
(STM32F401)
Tham số | Mô tả | Giá trị |
---|---|---|
Kernel Behaviour | ||
configCPU_CLOCK_HZ |
Tần số CPU Clock | 84.000.000(Hz) |
configUSE_PREEMPTION |
Dùng preemptive scheduler | 1 |
configUSE_TIME_SLICING |
Bật time slicing | 1 |
configTICK_RATE_HZ |
Tần số SysTick | 1000 (1ms) |
configMAX_PRIORITIES |
Số mức ưu tiên cho task | 5 |
configMAX_TASK_NAME_LEN |
Độ dài tối đa tên task | 16 |
Memory Allocation | ||
configTOTAL_HEAP_SIZE |
Kích thước heap FreeRTOS | 15*1024 (15KB) |
configMINIMAL_STACK_SIZE |
Stack tối thiểu (word) | 128 |
configSYSTEM_CALL_STACK_SIZE |
Stack cho system call (MPU) | 128 |
configSUPPORT_DYNAMIC_ALLOCATION |
Bật cấp phát động | 1 |
configSUPPORT_STATIC_ALLOCATION |
Bật cấp phát tĩnh | 0 |
Hook Functions | ||
configUSE_IDLE_HOOK |
Dùng Idle Hook | 0 |
configUSE_TICK_HOOK |
Dùng Tick Hook | 0 |
configUSE_MALLOC_FAILED_HOOK |
Dùng Malloc Failed Hook | 0 |
Task & Synchronization | ||
configUSE_MUTEXES |
Bật Mutex | 1 |
configUSE_RECURSIVE_MUTEXES |
Bật Recursive Mutex | 1 |
configUSE_COUNTING_SEMAPHORES |
Bật Counting Semaphore | 1 |
configUSE_TIMERS |
Bật Software Timer | 0 |
configQUEUE_REGISTRY_SIZE |
Số queue trong registry | 8 |
Debug & Safety | ||
configUSE_MPU |
Bật Memory Protection Unit | 1 |
configASSERT() |
Macro kiểm tra lỗi runtime | Vòng lặp vô hạn khi lỗi |
Các bước Porting freeRTOS Kernel cho Vi điều khiển
❶ Chuẩn bị Source Code
Download Source Code freeRTOS từ trang chủ, chỉ lấy folder FreeRTOS-Kernel
Link các Source cần thiết vào project
- Các file source bắt buộc của Kernel,
- File porting - portable/GCC/ARM_CM4F/port.c,
- File quản lý bộ nhớ - portable/MemMang/heap_4.c,
Link đến folder chứa các Header File:
- Folder include chung của Kernel,
- Folder chứa portmacro.h - ví dụ: portable/GCC/ARM_CM4F,
- Folder chứa FreeRTOSConfig.h
❷ Cấu hình file FreeRTOSConfig.h
❸ Xây dựng Application sử dụng freeRTOS!
Ví dụ, sử dụng 2 Task của freeRTOS, mỗi task điều khiển blinked một LED - sử dụng trên STM32f401 Nucleo Board:
- #include "stm32f4xx.h"
- #include "FreeRTOS.h"
- #include "task.h"
- #define LED1_PIN 5 // On-board LED (PA5)
- #define LED2_PIN 3 // External LED on PB3
- // Initialize GPIO for LED pins
- void GPIO_Init(void)
- {
- // Enable clock for GPIOA and GPIOB
- RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN);
- // Configure PA5 as output
- GPIOA->MODER &= ~(3UL << (LED1_PIN * 2)); // Clear mode bits
- GPIOA->MODER |= (1UL << (LED1_PIN * 2)); // Set to output mode
- // Configure PB3 as output
- GPIOB->MODER &= ~(3UL << (LED2_PIN * 2)); // Clear mode bits
- GPIOB->MODER |= (1UL << (LED2_PIN * 2)); // Set to output mode
- }
- // Task 1: Blink LED1 every 500 ms
- void vLedTask1(void *pvParameters)
- {
- (void) pvParameters;
- for (;;)
- {
- GPIOA->ODR ^= (1UL << LED1_PIN); // Toggle LED1
- vTaskDelay(pdMS_TO_TICKS(500)); // Delay 500 ms
- }
- }
- // Task 2: Blink LED2 every 1000 ms
- void vLedTask2(void *pvParameters)
- {
- (void) pvParameters;
- for (;;)
- {
- GPIOB->ODR ^= (1UL << LED2_PIN); // Toggle LED2
- vTaskDelay(pdMS_TO_TICKS(1000)); // Delay 1000 ms
- }
- }
- int main(void)
- {
- // Initialize GPIOs
- GPIO_Init();
- // Create two tasks
- xTaskCreate(vLedTask1, "LED1", 128, NULL, 1, NULL);
- xTaskCreate(vLedTask2, "LED2", 128, NULL, 1, NULL);
- // Start the FreeRTOS scheduler
- vTaskStartScheduler();
- // Program should never reach here
- while (1) {}
- }
Video - Porting freeRTOS Kernel cho project vi điều khiển STM32
↪ Video/Bài viết trước đó về STM32CubeIDE và STM32 + CMSIS
Kết luận
FreeRTOS là lựa chọn hàng đầu cho hệ thống nhúng cần đa nhiệm, thời gian thực, nhẹ, dễ mở rộng IoT và tối ưu chi phí. Phần kiến trúc của freeRTOS cũng khá đơn giản, dễ học, cũng như cách Porting cực kỳ đơn giản, sử dụng rộng rãi cho các ứng dụng sử dụng Vi điều khiển lõi ARM.
>>>>>> Follow ngay <<<<<<<
Để nhận được những bài học miễn phí mới nhất nhé 😊
Chúc các bạn học tập tốt 😊