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')
相关推荐
三佛科技-134163842128 小时前
过认证72W碳化硅方案(12V6A)主控HN1562+HN36228V 典型应用电路、变压器参数分享
单片机·嵌入式硬件·物联网·智能家居·pcb工艺
Zwawa9 小时前
串口为什么会丢字节:从轮询到中断和环形缓冲区
c语言·单片机·嵌入式
Brilliantwxx10 小时前
【STM32】 内部 Flash 详解:寄存器逐位拆解 + 工作流程顺序全讲 + EEPROM再实现
stm32·单片机·嵌入式硬件·1024程序员节
木子单片机10 小时前
基于单片机的DS18B20温度传感器测温系统设计
单片机·嵌入式硬件·51单片机·keil
华清远见IT开放实验室10 小时前
实验室建设案例 | 安徽三联学院物联网实验室
stm32·单片机·嵌入式硬件·物联网·华清远见
Zw-awa11 小时前
串口为什么会丢字节:从轮询到中断和环形缓冲区
stm32
深圳光特通信豆子12 小时前
TTL 光模块在工业控制与串口通信中的应用指南(10M BIDI 单模系列)
单片机·嵌入式硬件
桀人12 小时前
SPI概念引入
stm32·单片机·嵌入式硬件
离凌寒13 小时前
一、基于stm32+freertos下LD2410D和R60ADB1两款雷达的使用效果
stm32·单片机·嵌入式硬件
国科安芯13 小时前
商业光学遥感载荷焦平面供电链的低噪声稳压器研究综述——以国科安芯ASP7A84AS型3A低压差线性稳压器为器件级参照
大数据·网络·嵌入式硬件·平面·卫星·商业航天·抗辐射