STM32L051 的 串口升级

STM32L051 的 串口升级(UART Bootloader / IAP)


一、STM32L051 串口升级总体方案

1、系统架构

复制代码
Flash 布局(64 KB)
┌─────────────────────┐ 0x08000000
│ Bootloader (8 KB)    │ ← 上电首先运行
├─────────────────────┤ 0x08002000
│ Application A       │ ← 正常运行区
├─────────────────────┤ 0x0800C000
│ Application B       │ ← 备用/升级区(可选)
└─────────────────────┘ 0x08010000

推荐方案:

  • Bootloader + 单 App(覆盖升级)
  • 双分区(A/B)

二、启动流程(Bootloader 逻辑)

text 复制代码
上电复位
   ↓
Bootloader 启动
   ↓
检查升级标志(Flash / GPIO / 命令)
   ↓
是否需要升级?
   ├─ 是 → 接收串口固件 → 擦写 Flash → 跳转
   └─ 否 → 直接跳转到 App

三、Flash 分区与关键地址

区域 起始地址 大小
Bootloader 0x08000000 8 KB
Application 0x08002000 56 KB

升级标志位(放在 Flash 末尾)

c 复制代码
#define UPDATE_FLAG_ADDR  0x0800FF00
#define UPDATE_MAGIC_NUM  0x12345678

四、Bootloader 核心代码(HAL 库)

1、串口初始化(UART1)

c 复制代码
void UART_Init(void)
{
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    HAL_UART_Init(&huart1);
}

2、跳转到 APP

c 复制代码
typedef void (*pFunction)(void);
pFunction JumpToApplication;
uint32_t JumpAddress;

void Jump_To_App(uint32_t app_addr)
{
    __disable_irq();

    JumpAddress = *(__IO uint32_t*)(app_addr + 4);
    JumpToApplication = (pFunction)JumpAddress;

    __set_MSP(*(__IO uint32_t*)app_addr);
    JumpToApplication();
}

3、 Flash 擦除 & 写入

c 复制代码
void Flash_Write(uint32_t addr, uint8_t *data, uint32_t len)
{
    HAL_FLASH_Unlock();

    for (uint32_t i = 0; i < len; i += 4)
    {
        uint32_t word = data[i] |
                       (data[i+1] << 8) |
                       (data[i+2] << 16) |
                       (data[i+3] << 24);

        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr + i, word);
    }

    HAL_FLASH_Lock();
}

五、串口升级协议(简单可靠)

帧格式(推荐)

复制代码
| HEAD | CMD | LEN | DATA | CRC |
| 0xAA | 0x01|   N | ...  | CRC |
CMD 功能
0x01 开始升级
0x02 发送数据
0x03 结束升级
0x04 校验成功

接收数据示例

c 复制代码
void Receive_Firmware(void)
{
    uint8_t buf[256];
    uint32_t writeAddr = APP_START_ADDR;

    while (1)
    {
        HAL_UART_Receive(&huart1, buf, 132, HAL_MAX_DELAY);

        if (buf[0] == 0xAA && buf[1] == 0x02)
        {
            Flash_Write(writeAddr, &buf[4], 128);
            writeAddr += 128;
        }
        else if (buf[1] == 0x03)
        {
            break;
        }
    }
}

参考代码 stm32l051的串口升级程序 www.youwenfan.com/contentcsv/72126.html

六、APP 程序注意事项

1、中断向量偏移

c 复制代码
SCB->VTOR = FLASH_BASE | 0x2000;

2、Linker 修改(Keil)

复制代码
ROM: 0x08002000
Size: 0xE000

七、升级触发方式

方式 说明
串口命令 PC 下发升级指令
GPIO 按键 BOOT 引脚拉高
软件标志 写入 Flash 标志
看门狗超时 异常重启升级

八、防变砖设计

CRC 校验
升级失败自动回滚
Bootloader 不升级
写保护 Option Bytes
掉电保护(页写完成才更新标志)


九、PC 端升级工具

python 复制代码
import serial

ser = serial.Serial('COM3', 115200)

def send_bin(file):
    with open(file, 'rb') as f:
        while True:
            data = f.read(128)
            if not data:
                break
            ser.write(b'\xAA\x02\x80' + data)
    ser.write(b'\xAA\x03\x00')
相关推荐
科芯创展22 分钟前
10~120V宽压1.5A降压DC-DC XZ1830技术特性与应用解析
单片机
逐步前行31 分钟前
ESP32-S3-PCNT(脉冲计数控制器)
单片机·嵌入式硬件
咖丨喱1 小时前
【中断与收包】
单片机·嵌入式硬件
youshi66682 小时前
平衡车——PID算法优化
stm32·单片机·嵌入式硬件·算法·pid·平衡车
comyccccc2 小时前
高效降压电路布局与铺铜优化技巧学习笔记
单片机·嵌入式硬件
白搞电子2 小时前
ESP32-S31 WASM 应用开发实录:重力弹球从电脑预览到 ESP-Mosaico 实机测试
单片机·嵌入式硬件·物联网·电脑·wasm
尼喃2 小时前
集成输入反接保护的USB限流保护芯片IC反向电流阻断验证
嵌入式硬件
ye150127774552 小时前
220V降压24V700mA交转直芯片WT5110
stm32·单片机·嵌入式硬件·其他·硬件工程
BSD_HY3 小时前
薄膜开关矩阵扫描在低功耗 MCU 上的 GPIO 扩展
单片机·嵌入式硬件·矩阵
时代的凡人4 小时前
生活中的恒流源和恒压源
嵌入式硬件