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')
相关推荐
FreakStudio8 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
✎ ﹏梦醒͜ღ҉繁华落℘13 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u1521096484913 天前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd84510150013 天前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼13 天前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
牛根生同志13 天前
SPI数据收发的时候 TXE与RXNE标志位置位的时机
stm32·spi·transfer
wohoo_wangzi13 天前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
goldenrolan13 天前
学习型红外控制系统稳定性挂测工装专项总结
软件测试·python·stm32·嵌入式·红外
✎ ﹏梦醒͜ღ҉繁华落℘13 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展13 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件