🌱 Hướng Dẫn Triển Khai CMake Cho Dự Án Blink LED Trên STM32
Chào bạn! Series Cmake này mình sẽ không viết dài dòng về mặt cú pháp, các hướng dẫn về command bạn có thể search khi sử dụng tại trang chủ của Cmake. Bài viết này mình sẽ đi vào thực hành luôn với một project vi điều khiển cơ bản - cách viết file CMakeLists.txt để xây dựng một project Blink LED trên STM32, sử dụng phương pháp bare-metal (truy cập thanh ghi trực tiếp). Đây là cách tiếp cận đơn giản, nhẹ nhàng, và rất phù hợp cho người mới bắt đầu với CMake và STM32.
Mục Lục
Tại Sao Dùng CMake Cho STM32?
CMake là một công cụ mạnh mẽ để quản lý dự án lập trình, đặc biệt trong lập trình nhúng. So với Makefile truyền thống, CMake:
- Dễ đọc và bảo trì hơn.
- Hỗ trợ đa nền tảng (Windows, Linux, macOS).
- Tự động sinh file build cho các toolchain như arm-none-eabi-gcc.
Trước đó, mình đã giới thiệu về cách sử dụng makefile để build project vi điều khiển STM32.
[Video] Chương trình Makefile với Vi điều khiển
Trong bài này, chúng ta sẽ dùng CMake để tạo một dự án Blink LED trên STM32F4 NUCLEO Board, User LED được nối với chân PA5.
![]() |
STM32F4 NUCLEO Board User LED |
Code Blink LED Cơ Bản
Project GPIO Blinked LED thì mình đã đề cập trong bài viết STM32 GPIO Examples, dưới đây là code mẫu Blink LED trên chân PA5 (file main.c):
- #include "stm32f4xx.h"
- void delay(uint32_t count) {
- while(count--) {}
- }
- int main(void) {
- // Enable clock cho GPIOA
- RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
- // Configure PA5 as output
- GPIOA->MODER &= ~(GPIO_MODER_MODER5);
- GPIOA->MODER |= GPIO_MODER_MODER5_0;
- while(1) {
- GPIOA->ODR |= GPIO_ODR_OD5; // LED ON
- delay(1000000);
- GPIOA->ODR &= ~GPIO_ODR_OD5; // LED OFF
- delay(1000000);
- }
- }
Code này sử dụng bare-metal, chỉ dựa vào file header stm32f4xx.h để định nghĩa các thanh ghi.
Viết File CMakeLists.txt
Dưới đây là file CMakeLists.txt hoàn chỉnh cho dự án:
- cmake_minimum_required(VERSION 3.10)
- project(STM32_BlinkLED LANGUAGES C ASM)
- set(CMAKE_ARM_TOOLCHAIN "C:/ARM_TOOLCHAIN") # Your toolchain path
- set(CMAKE_C_COMPILER $(arm-none-eabi-gcc)
- set(CMAKE_ASM_COMPILER $(CMAKE_ARM_TOOLCHAIN)/arm-none-eabi-gcc)
- set(CMAKE_OBJCOPY $(CMAKE_ARM_TOOLCHAIN)/arm-none-eabi-objcopy)
- set(CMAKE_SIZE $(CMAKE_ARM_TOOLCHAIN)/arm-none-eabi-size)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wall -O0 -g -nostartfiles -nostdlib")
- set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/STM32F407VGTx_FLASH.ld)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T${LINKER_SCRIPT}")
- set(SOURCES
- main.c
- startup_stm32f407xx.s
- )
- add_executable(${PROJECT_NAME}.elf ${SOURCES})
- target_include_directories(${PROJECT_NAME}.elf PUBLIC ${CMAKE_SOURCE_DIR}/Inc)
- add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
- COMMAND ${CMAKE_OBJCOPY} -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
- COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
- COMMAND ${CMAKE_SIZE} ${PROJECT_NAME}.elf
- )
Giải Thích File CMake
- Toolchain: Sử dụng arm-none-eabi-gcc để biên dịch cho STM32.
- Một số compiler option: -mcpu=cortex-m4 tối ưu cho STM32F4; -nostartfiles -nostdlib để chạy bare-metal. Phần này tương tự như makefile.
- Source Code: Bao gồm main.c và startup_stm32f407xx.s (startup file).
- Linker Script: STM32F401RETx_FLASH.ld định nghĩa vùng bộ nhớ.
- Output: Tạo file .elf, .hex, .bin để nạp vào STM32.
Chuẩn Bị Dự Án
Để dự án hoạt động, bạn cần:
- Toolchain: Cài arm-none-eabi-gcc (Có thể tải từ trang chủ của ARM).
- File header: Tải stm32f4xx.h từ STM32CubeF4 và đặt vào thư mục Inc/.
- Startup file: Lấy startup_stm32f401xx.s tự viết hoặc tải trên CMSIS hoặc các project có sẵn.
- Linker script: Sử dụng STM32F401RETx_FLASH.ld tự viết hoặc tải trên CMSIS hoặc các project có sẵn.
Cấu trúc thư mục:
STM32_BlinkLED/
├── Inc/
│ └── stm32f4xx.h
├── main.c
├── startup_stm32f401xx.s
├── STM32F401RETx_FLASH.ld
└── CMakeLists.txt
Build Và Nạp Code
- Tạo thư mục build:
mkdir build && cd build
- Chạy CMake:
cmake ..
- Build project:
cmake --build .
- Nạp code: Dùng ST-Link hoặc OpenOCD hoặc bất cứ IDE/Debugger nào bạn có:
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -c "program STM32_BlinkLED.hex verify reset exit"
Kết quả: Sau khi nạp, LED trên STM32F4 Discovery (PA5) sẽ nhấp nháy!
➤ Lợi Ích Của Cách Tiếp Cận Này
- Đơn giản: Không phụ thuộc CMSIS hay HAL, dễ hiểu cách hoạt động của STM32.
- Nhẹ: Dự án chiếm ít tài nguyên, phù hợp với lập trình nhúng cơ bản.
- Học tập: Giúp bạn nắm rõ cách truy cập thanh ghi trực tiếp.
Kết Luận
Viết CMakeLists.txt cho dự án STM32 Blink LED không dùng CMSIS là một cách tốt để bắt đầu với lập trình nhúng và CMake. Hãy thử ngay trên STM32F4 của bạn và chia sẻ kết quả nhé!
Bạn muốn nâng cấp dự án này? Hãy để lại bình luận nếu bạn cần thêm hướng dẫn về debug hoặc dùng STM32 dòng khác!
>>>>>> 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 😊