1. 搭建最小RTOS工程
任务目标
在Cortex-M处理器(以STM32F103为例)上搭建一个无RTOS的最小工程:包含启动文件、链接脚本和主程序,最终实现板载LED以约1Hz频率闪烁。该工程将作为后续章节移植RTOS的裸机基础。
所需环境与依赖
- 硬件:STM32F103C8T6最小系统板(蓝 pill),板载LED接PC13(低电平点亮)
- 工具链:arm-none-eabi-gcc(版本≥10)、OpenOCD、Make
- 调试器:ST-Link V2
工程文件结构
led_blink/
├── Makefile
├── startup_stm32f103.s
├── stm32f103.ld
└── main.c
关键完整代码
main.c — 主程序与LED控制逻辑:
#include <stdint.h>
#define RCC_APB2ENR (*(volatile uint32_t*)0x40021018)
#define GPIOC_CRH (*(volatile uint32_t*)0x40011004)
#define GPIOC_ODR (*(volatile uint32_t*)0x4001100C)
static void delay_ms(uint32_t ms) {
for (volatile uint32_t i = 0; i < ms * 4000; i++) {
__asm volatile("nop");
}
}
int main(void) {
// 使能GPIOC时钟(APB2)
RCC_APB2ENR |= (1 << 4);
// PC13配置为推挽输出,50MHz(CNF13=00, MODE13=11)
GPIOC_CRH = (GPIOC_CRH & ~(0xF << 20)) | (0x3 << 20);
while (1) {
GPIOC_ODR |= (1 << 13); // PC13高电平 → LED灭
delay_ms(500);
GPIOC_ODR &= ~(1 << 13); // PC13低电平 → LED亮
delay_ms(500);
}
}
void SystemInit(void) {
// 使用内部8MHz HSI,无需额外初始化
}
startup_stm32f103.s — 最小启动文件(向量表与复位处理):
.syntax unified
.cpu cortex-m3
.thumb
.section .isr_vector
.word _estack
.word Reset_Handler
.section .text
.thumb_func
.global Reset_Handler
Reset_Handler:
ldr r0, =_sdata
ldr r1, =_edata
ldr r2, =_sidata
copy_data:
cmp r0, r1
bge zero_bss
ldr r3, [r2], #4
str r3, [r0], #4
b copy_data
zero_bss:
ldr r0, =_sbss
ldr r1, =_ebss
movs r2, #0
bss_loop:
cmp r0, r1
bge call_main
str r2, [r0], #4
b bss_loop
call_main:
bl main
b .
stm32f103.ld — 链接脚本:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
RAM (rw) : ORIGIN = 0x20000000, LENGTH = 20K
}
_estack = ORIGIN(RAM) + LENGTH(RAM);
SECTIONS
{
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} > FLASH
.text :
{
. = ALIGN(4);
*(.text*)
*(.rodata*)
. = ALIGN(4);
_etext = .;
} > FLASH
_sidata = LOADADDR(.data);
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data*)
. = ALIGN(4);
_edata = .;
} > RAM AT> FLASH
.bss :
{
. = ALIGN(4);
_sbss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} > RAM
}
Makefile — 编译与烧录:
TARGET = led_blink
PREFIX = arm-none-eabi-
CFLAGS = -mcpu=cortex-m3 -mthumb -Wall -O2 -nostdlib -ffreestanding
LDFLAGS = -T stm32f103.ld -nostdlib
all: $(TARGET).bin
$(TARGET).elf: startup_stm32f103.s main.c stm32f103.ld
$(PREFIX)gcc $(CFLAGS) -o $@ startup_stm32f103.s main.c $(LDFLAGS)
$(TARGET).bin: $(TARGET).elf
$(PREFIX)objcopy -O binary $< $@
flash: $(TARGET).bin
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c "program $< verify reset exit"
clean:
rm -f $(TARGET).elf $(TARGET).bin
运行与验证
- 在工程目录执行
make,生成led_blink.bin。 - 连接ST-Link与开发板,执行
make flash烧录固件。 - 观察板载LED(PC13):应持续以约1Hz频率闪烁(亮500ms,灭500ms)。
通过条件:LED按预期频率闪烁即表示工程搭建成功——启动文件正确完成数据段/零初始化,链接脚本地址映射无误,GPIO寄存器配置生效。
常见问题
- LED不亮:检查GPIOC时钟使能位(RCC_APB2ENR bit4)是否正确置位;确认PC13配置的位段偏移(CRH寄存器bit20~23)。
- 编译报错“undefined reference to SystemInit”:main.c中已提供空实现,若使用其他启动文件需保留该符号。
- 烧录后无反应:确认链接脚本中FLASH起始地址为0x08000000,且向量表首两项(栈顶地址、复位处理函数)正确放置。