2. 串口输出启动信息
任务目标
在Bootloader启动早期初始化UART外设,通过串口输出格式化的启动日志,为后续阶段提供调试输出通道。本案例以STM32F407平台为例,实现一个最小可用的串口日志输出模块。
环境依赖
- 硬件:STM32F407开发板(USART2,PA2=TX,PA3=RX),USB转串口模块
- 工具链:arm-none-eabi-gcc + Makefile,或STM32CubeIDE
- 串口终端:115200-8-N-1
关键完整代码
// uart_log.h
#ifndef UART_LOG_H
#define UART_LOG_H
#include <stdint.h>
#include <stdarg.h>
void uart_init(void);
void uart_send_char(char c);
void log_printf(const char *fmt, ...);
#endif
// uart_log.c
#include "uart_log.h"
#include "stm32f4xx.h"
void uart_init(void) {
// 使能GPIOA和USART2时钟
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
// PA2=TX(AF7), PA3=RX(AF7)
GPIOA->MODER &= ~(GPIO_MODER_MODER2_Msk | GPIO_MODER_MODER3_Msk);
GPIOA->MODER |= (GPIO_MODER_MODER2_1 | GPIO_MODER_MODER3_1);
GPIOA->AFR[0] |= (7 << GPIO_AFRL_AFSEL2_Pos) | (7 << GPIO_AFRL_AFSEL3_Pos);
GPIOA->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR2_Msk | GPIO_OSPEEDER_OSPEEDR3_Msk);
// USART2: 115200, 8N1
USART2->BRR = 84000000 / 115200; // APB1=84MHz
USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
}
void uart_send_char(char c) {
while (!(USART2->SR & USART_SR_TXE));
USART2->DR = c;
}
static void uart_send_str(const char *s) {
while (*s) {
uart_send_char(*s++);
}
}
void log_printf(const char *fmt, ...) {
char buf[128];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
uart_send_str(buf);
}
// main.c(Bootloader入口)
#include "uart_log.h"
void bootloader_main(void) {
uart_init();
log_printf("[BOOT] UART initialized\r\n");
log_printf("[BOOT] System clock: %d MHz\r\n", 168);
log_printf("[BOOT] Jumping to app...\r\n");
while (1) {
// Bootloader主循环
}
}
编译与运行
# 使用Makefile构建
arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -O2 \
-I. uart_log.c -o uart_log.o
arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -O2 \
-I. main.c -o main.o
arm-none-eabi-ld -T bootloader.ld uart_log.o main.o -o bootloader.elf
arm-none-eabi-objcopy -O binary bootloader.elf bootloader.bin
# 烧录(以ST-Link为例)
st-flash write bootloader.bin 0x08000000
验证方法
- 将USB转串口模块的RX连接开发板PA2(TX),GND相连
- 打开串口终端,配置115200-8-N-1
- 复位开发板,观察串口输出
通过条件:串口终端依次显示以下三行日志,且无乱码:
[BOOT] UART initialized
[BOOT] System clock: 168 MHz
[BOOT] Jumping to app...
常见问题
- 输出乱码:检查BRR分频值是否与APB1时钟匹配(F407默认APB1=84MHz),以及串口终端波特率是否设置为115200
- 无输出:确认PA2/PA3复用功能配置正确(AF7),且USART2时钟已使能
- vsnprintf依赖:若使用newlib-nano,需在链接时添加
--specs=nano.specs以减小代码体积