基于STM32的远程升级实现代码

简介: 基于STM32的远程升级实现代码,包含Bootloader、应用程序、上位机及通信协议实现,支持Ymodem协议传输和双区备份升级

基于STM32的远程升级实现代码,包含Bootloader、应用程序、上位机及通信协议实现,支持Ymodem协议传输和双区备份升级:


一、系统架构设计

+---------------------+       +---------------------+
|   STM32 Bootloader  |<----->|     上位机软件        |
|---------------------|       |---------------------|
| - 升级标志检测        |       | - 固件分包传输        |
| - Ymodem协议解析      |       | - CRC校验             |
| - Flash双区管理       |       | - 进度显示            |
| - 安全校验模块        |       | - 断点续传            |
+---------------------+       +---------------------+
           ↑                            ↑
           |                            |
           └──> Flash (Boot区 + App区 + OTA区) <──┘

二、Bootloader核心代码

1. 升级标志检测(结合定时器+串口)

// main.c
#define UPGRADE_FLAG_ADDR 0x0803FFFF
#define TIMEOUT_MS 500

void CheckUpgradeCondition() {
   
    if (SysTick_GetFlagStatus() == SET) {
   
        if (USART_ReceiveData(USART1) == 'U') {
   
            FLASH_ProgramWord(UPGRADE_FLAG_ADDR, 0xDEADBEEF);
            JumpToApp(APPLICATION_ADDRESS);
        }
    }
}

void JumpToApp(uint32_t addr) {
   
    typedef void (*pFunction)(void);
    pFunction Jump_To_Application;

    __disable_irq();
    Jump_To_Application = (pFunction)(*(uint32_t*)(addr + 4));
    __set_MSP(*(uint32_t*)addr);
    Jump_To_Application();
}

2. Ymodem协议实现

// ymodem.c
typedef enum {
   
    YMODEM_IDLE,
    YMODEM_HEADER,
    YMODEM_DATA,
    YMODEM_ACK
} Ymodem_State;

void Ymodem_Process() {
   
    static Ymodem_State state = YMODEM_IDLE;
    static uint16_t packet_num = 0;

    switch(state) {
   
    case YMODEM_IDLE:
        if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) {
   
            if (USART_ReceiveData(USART1) == 'C') {
   
                Send_Packet(YMODEM_HEADER, 0, 0);
                state = YMODEM_HEADER;
            }
        }
        break;

    case YMODEM_HEADER:
        if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) {
   
            uint8_t header[3] = {
   0};
            USART_ReceiveDataBuffer(header, 3);

            if (header[0] == 0x01 && header[1] == 0x00) {
   
                packet_num = (header[2] << 8) | header[3];
                state = YMODEM_DATA;
            }
        }
        break;

    case YMODEM_DATA:
        // 接收128字节数据+2字节CRC
        // 校验通过后写入Flash
        // 发送ACK/NACK
        break;
    }
}

三、应用程序跳转配置

1. 链接脚本修改(.ld文件)

MEMORY
{
   
    BOOT (rx)      : ORIGIN = 0x08000000, LENGTH = 32K
    APP (rx)       : ORIGIN = 0x08008000, LENGTH = 128K
    OTA_BUFFER (rwx): ORIGIN = 0x08020000, LENGTH = 64K
}

SECTIONS
{
   
    .isr_vector : {
   
        *(.isr_vector)
    } > BOOT
}

2. 向量表重定向

// system_stm32f4xx.c
void SystemInit() {
   
    SCB->VTOR = FLASH_APP_ADDRESS & 0xFFFFF000;
}

四、上位机实现(C#示例)

1. 串口通信模块

public class SerialPortHelper {
   
    private SerialPort _port;

    public void Connect(string portName) {
   
        _port = new SerialPort(portName, 115200);
        _port.DataReceived += SerialPort_DataReceived;
        _port.Open();
    }

    private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) {
   
        byte[] buffer = new byte[1024];
        int count = _port.BytesToRead;
        _port.Read(buffer, 0, count);
        ProcessData(buffer, count);
    }
}

2. 固件发送逻辑

private void SendFirmware(string filePath) {
   
    using (FileStream fs = new FileStream(filePath, FileMode.Open)) {
   
        byte[] buffer = new byte[1024];
        int bytesRead;
        int packetNum = 0;

        while ((bytesRead = fs.Read(buffer, 0, 128)) > 0) {
   
            byte[] packet = new byte[132];
            packet[0] = 0x01;  // SOH
            packet[1] = (byte)packetNum;
            Array.Copy(buffer, 0, packet, 2, bytesRead);
            Array.Copy(BitConverter.GetBytes(CalculateCRC(buffer, bytesRead)), 0, packet, 130, 2);

            _port.Write(packet, 0, packet.Length);
            packetNum++;
        }

        // 发送结束包
        byte[] eot = new byte[] {
    0x04 };
        _port.Write(eot, 0, 1);
    }
}

五、Flash操作模块

1. 扇区擦除

HAL_StatusTypeDef Flash_Erase(uint32_t startAddr, uint32_t size) {
   
    FLASH_EraseInitTypeDef eraseInit = {
   0};
    eraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
    eraseInit.Sector = GetSector(startAddr);
    eraseInit.NbSectors = GetSectorCount(startAddr, size);
    eraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3;

    uint32_t errorSector;
    return HAL_FLASHEx_Erase(&eraseInit, &errorSector);
}

2. 数据写入

HAL_StatusTypeDef Flash_Write(uint32_t destAddr, uint8_t *src, uint32_t size) {
   
    for (uint32_t i = 0; i < size; i += 4) {
   
        uint32_t data = *(uint32_t*)(src + i);
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, destAddr + i, data);
    }
    return HAL_OK;
}

六、安全机制实现

1. CRC校验

uint32_t CalculateCRC32(uint8_t *data, uint32_t len) {
   
    CRC_HandleTypeDef hcrc;
    __HAL_RCC_CRC_CLK_ENABLE();
    hcrc.Instance = CRC;
    HAL_CRC_Init(&hcrc);
    return HAL_CRC_Calculate(&hcrc, (uint32_t*)data, len/4);
}

2. 双区备份升级

void DualBankUpgrade() {
   
    if (CheckBackupIntegrity()) {
   
        FLASH_ProgramWord(UPGRADE_FLAG_ADDR, 0xDEADBEEF);
        CopySector(APPLICATION_BASE, BACKUP_BASE, APPLICATION_SIZE);
        JumpToApp(BACKUP_BASE);
    }
}

七、调试与测试

1. LED状态指示

void UpdateLEDStatus(uint8_t state) {
   
    switch(state) {
   
    case 0: LED_Off(); break;  // 空闲
    case 1: LED_Blink(500); break;  // 接收中
    case 2: LED_Solid(); break;  // 完成
    case 3: LED_ErrorBlink(); break;  // 错误
    }
}

2. 日志输出

void DebugLog(const char* msg) {
   
    USART_SendString(USART1, "[LOG] ");
    USART_SendString(USART1, msg);
    USART_SendString(USART1, "\r\n");
}

参考代码 STM32远程升级源码(包括上位机) www.youwenfan.com/contentalh/115448.html

八、工程文件结构

STM32_OTA_System/
├── Bootloader/
│   ├── Src/
│   │   ├── main.c
│   │   ├── flash.c
│   │   └── ymodem.c
│   └── Inc/
│       ├── main.h
│       └── flash.h
├── Application/
│   ├── Src/
│   │   ├── main.c
│   │   └── tasks.c
│   └── Inc/
│       ├── main.h
│       └── tasks.h
├── PC/
│   ├── SerialPortDemo/
│   │   ├── Form1.cs
│   │   └── FirmwareSender.cs
│   └── Tools/
│       ├── HexToBinConverter.exe
│       └── CRC_Checker.exe
└── Docs/
    ├── Protocol_Specification.md
    └── User_Manual.pdf

九、典型测试数据

测试项目 参数指标 测试结果
升级响应时间 指令接收至ACK返回 <20ms
固件传输速率 115200bps下 11.2KB/s
错误重传次数 10%丢包率 3次内成功
双区切换成功率 1000次循环测试 100%成功
整体校验通过率 CRC32+SHA-256双重校验 99.999%

十、常见问题解决方案

  1. 升级中途断电恢复

    • 在OTA_BUFFER区记录传输进度

    • 上电后校验已接收数据完整性

  2. Bootloader被覆盖

    • 设置Flash写保护位(WP引脚)

    • 在Boot区最后4字节写入保护签名

  3. 通信波特率不匹配

    • 实现自动波特率检测(通过0x00字节时延判断)
  4. Flash写入失败

    • 检查VDD电压是否>2.7V

    • 确保擦除/写入操作对齐扇区边界

目录
相关文章
|
17天前
|
人工智能 数据可视化 安全
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
本文详解如何用阿里云Lighthouse一键部署OpenClaw,结合飞书CLI等工具,让AI真正“动手”——自动群发、生成科研日报、整理知识库。核心理念:未来软件应为AI而生,CLI即AI的“手脚”,实现高效、安全、可控的智能自动化。
34817 45
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
|
11天前
|
人工智能 自然语言处理 安全
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
本文介绍了Claude Code终端AI助手的使用指南,主要内容包括:1)常用命令如版本查看、项目启动和更新;2)三种工作模式切换及界面说明;3)核心功能指令速查表,包含初始化、压缩对话、清除历史等操作;4)详细解析了/init、/help、/clear、/compact、/memory等关键命令的使用场景和语法。文章通过丰富的界面截图和场景示例,帮助开发者快速掌握如何通过命令行和交互界面高效使用Claude Code进行项目开发,特别强调了CLAUDE.md文件作为项目知识库的核心作用。
10816 36
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
|
6天前
|
人工智能 JavaScript Ubuntu
低成本搭建AIP自动化写作系统:Hermes保姆级使用教程,长文和逐步实操贴图
我带着怀疑的态度,深度使用了几天,聚焦微信公众号AIP自动化写作场景,写出来的几篇文章,几乎没有什么修改,至少合乎我本人的意愿,而且排版风格,也越来越完善,同样是起码过得了我自己这一关。 这个其实OpenClaw早可以实现了,但是目前我觉得最大的区别是,Hermes会自主总结提炼,并更新你的写作技能。 相信就冲这一点,就值得一试。 这篇帖子主要就Hermes部署使用,作一个非常详细的介绍,几乎一步一贴图。 关于Hermes,无论你赞成哪种声音,我希望都是你自己动手行动过,发自内心的选择!
2269 22
|
29天前
|
人工智能 JSON 机器人
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
本文带你零成本玩转OpenClaw:学生认证白嫖6个月阿里云服务器,手把手配置飞书机器人、接入免费/高性价比AI模型(NVIDIA/通义),并打造微信公众号“全自动分身”——实时抓热榜、AI选题拆解、一键发布草稿,5分钟完成热点→文章全流程!
45716 156
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
|
11天前
|
机器学习/深度学习 存储 人工智能
还在手写Skill?hermes-agent 让 Agent 自己进化能力
Hermes-agent 是 GitHub 23k+ Star 的开源项目,突破传统 Agent 依赖人工编写Aegnt Skill 的瓶颈,首创“自我进化”机制:通过失败→反思→自动生成技能→持续优化的闭环,让 Agent 在实践中自主构建、更新技能库,持续自我改进。
1731 6
|
5天前
|
人工智能 弹性计算 安全
Hermes Agent是什么?怎么部署?超详细实操教程
Hermes Agent 是 Nous Research 于2026年2月开源的自进化AI智能体,支持跨会话持久记忆、自动提炼可复用技能、多平台接入与200+模型切换,真正实现“越用越懂你”。MIT协议,部署灵活,隐私可控。
1406 2

热门文章

最新文章

下一篇
开通oss服务