返回首页

MBR 324 字节 STM32F407VE:紧凑型引导加载程序

开发了大小为 324 字节的 STM32F407VE 最小 MBR 引导加载程序。在将控制权传递给地址 0x08060000 的二级引导加载程序之前检查向量表。出错时,PE13 上 LED 闪烁。完整代码、Makefile 和优化步骤。

带验证的 324 字节 MBR 引导加载程序 STM32F407VE
Advertisement 728x90

STM32F407VE 紧凑 MBR 引导加载器:仅 324 字节

这款针对 STM32F407VE 的主引导加载器(MBR)位于 Flash 第一个扇区 0x08000000,并将控制权交给位于 0x08060000 的二级引导加载器。在跳转前,它会验证中断向量表:栈指针在 SRAM 范围内(0x20000000–0x2001FFFF),复位处理程序地址在 Flash 内(0x08000000–0x080FFFFF)且设置了 Thumb 模式位。

如果验证失败,它会通过 PE13 引脚上的 LED 以 10 Hz 频率闪烁(周期 100 ms,占空比 50%)来指示错误。代码通过剔除标准库、外部中断,并使用 DWT 核心定时器实现延时,精简至 324 字节。

NOR Flash 布局:

Google AdInline article slot

| 扇区 | 起始地址 | 大小,KB | 内容 |

|------|--------------|----------|------------------|

| 0 | 0x08000000 | 16 | 主引导加载器 |

Google AdInline article slot

| 1–3 | 0x08004000–0x0800C000 | 16×3 | NVRAM |

| 4–6 | 0x08010000–0x08040000 | 64+128+128 | 应用 |

| 7 | 0x08060000 | 128 | 二级引导加载器 |

Google AdInline article slot

MBR 每节省一个字节,都能为 NVRAM 腾出更多空间。

优化阶段

优化过程采用 ARM-GCC 和 GNU Make 迭代进行:

  • 朴素 HAL 实现:25,192 字节。
  • -O0 无调试:12,052 字节。
  • -Os -flto:9,684 字节。
  • DeepSeek + -Os -flto:2,124 字节。
  • -nostdlib,无 libc_init:652 字节。
  • 最小向量表324 字节

关键编译器标志:

  • -nostdlib -nostartfiles -ffreestanding
  • -ffunction-sections -fdata-sections -Wl,--gc-sections
  • -Os 优化体积,-mcpu=cortex-m4 -mthumb

C 语言实现

核心代码集中在单个 main.c 文件中,直接访问寄存器,绕过 HAL:

// main.c - STM32F407VE 引导加载器
#include <stdint.h>

#define APP_BASE        0x08060000UL
#define SRAM_BASE       0x20000000UL
#define SRAM_END        0x2001FFFFUL
#define FLASH_BASE      0x08000000UL
#define FLASH_END       0x080FFFFFUL

// 外设
#define RCC_BASE        0x40023800UL
#define GPIOE_BASE      0x40021000UL
#define DWT_BASE        0xE0001000UL

#define RCC_AHB1ENR     (*((volatile uint32_t*)(RCC_BASE + 0x30)))
#define GPIOx_MODER     (*((volatile uint32_t*)(GPIOE_BASE + 0x00)))
#define GPIOx_ODR       (*((volatile uint32_t*)(GPIOE_BASE + 0x14)))
#define DWT_CYCCNT      (*((volatile uint32_t*)(DWT_BASE + 0x04)))
#define DWT_CTRL        (*((volatile uint32_t*)(DWT_BASE + 0x00)))

typedef struct {
    uint32_t stack_ptr;
    uint32_t reset_handler;
} VectorTable_t;

static inline int is_valid_sram(uint32_t addr) {
    return ((SRAM_BASE <= addr) && (addr <= SRAM_END));
}

static inline int is_valid_flash(uint32_t addr) {
    return ((FLASH_BASE <= addr) && (addr <= FLASH_END));
}

// 初始化 DWT
static void dwt_init(void) {
    *(volatile uint32_t*)0xE000EDF0 |= (1UL << 24);
    DWT_CTRL |= 1;
}

// 168 MHz 下延时约 ms
static void delay_ms(uint32_t ms) {
    uint32_t start = DWT_CYCCNT;
    uint32_t cycles = ms * 16000;
    while ((DWT_CYCCNT - start) < cycles);
}

// 10 Hz 闪烁 LED PE13
static void blink_led(void) __attribute__((noreturn));
static void blink_led(void) {
    RCC_AHB1ENR |= (1 << 4);
    GPIOx_MODER &= ~(3 << 26);
    GPIOx_MODER |= (1 << 26);
    dwt_init();
    while(1) {
        GPIOx_ODR |= (1 << 13);
        delay_ms(50);
        GPIOx_ODR &= ~(1 << 13);
        delay_ms(50);
    }
}

static int is_valid_vector_table(const VectorTable_t *app_vec) {
    if (!is_valid_sram(app_vec->stack_ptr)) return 0;
    uint32_t reset_addr = app_vec->reset_handler;
    if (!is_valid_flash(reset_addr & ~1)) return 0;
    if ((reset_addr & 1) == 0) return 0;
    return 1;
}

typedef void (*pFunction)(void);
int main(void) {
    const VectorTable_t *app_vec = (const VectorTable_t*)APP_BASE;
    if (is_valid_vector_table(app_vec)) {
        pFunction jump = (pFunction)app_vec->reset_handler;
        jump();
    }
    blink_led();
}

项目构建

带调试和打包支持的 Makefile:

CFLAGS += -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
CFLAGS += -Os -ffunction-sections -fdata-sections -nostdlib
CFLAGS += -nostartfiles -fno-builtin -ffreestanding
LDFLAGS += -T gcc_arm_mbr.ld -Wl,--gc-sections

SOURCES = main.c system_stm32f4xx.c
OBJECTS = $(SOURCES:.c=.o) startup_stm32f407xx.o

all: $(TARGET).bin

在 startup_stm32f407xx.S 中,我们移除了 bl __libc_init_array,并将向量表精简至必需项(栈、复位、NMI、HardFault)。

关键要点

  • 324 字节体积 为第一个扇区的 NVRAM 腾出 15+ KB 空间。
  • 向量表验证防止损坏代码导致死机。
  • DWT 定时器无需 SysTick 或 PLL 即可实现精确延时。
  • 直接寄存器访问将开销降至最低。
  • 完整构建:ARM-GCC + 自定义链接脚本,无标准库。

— Editorial Team

Advertisement 728x90

继续阅读