打印
[MM32生态]

MM32F103 串口 BootLoader 升级(二)

[复制链接]
471|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Zhiniaocun|  楼主 | 2025-6-10 21:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
通过Ymodem 协议升级代码

Ymodem 协议详解
参考链接;
Ymodem协议解析-CSDN博客

        Ymodem协议发送数据前需要接收端发起通信,发送端收到接收端发送的数据后才会开始传输数据,也就是握手信号。主要通信的时序参考文件传输过程,但需要注意的是,在接受过程中,通过同一个串口有打印数据的情况下,会导致发送端发送中断或者异常。在测试中,发送端发送的帧头一直是soh,没有出现过stx,只需要按照协议解析数据就可以了。

Ymodem握手信号
握手信号由接收方发起,在发送方开始传输文件前,接收方需发送YMODEM_C (字符C,ASII码为0x43)命令,发送方收到后,开始传输起始帧。

文件传输过程
文件的传输过程,以具体的例子说明。把foo.c,大小为4196Byte(16进制为0x1064)的文件作为传输的对象,则它的传输过程如下:
发送端----------------------------------------------------------------接收端

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< C

SOH 00 FF “foo.c” "1064’’ NUL[118] CRC CRC >>>>>>>>>>>>>

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< C

STX 01 FE data[1024] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>>

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK

STX 02 FD data[1024] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK

STX 03 FC data[1024] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK

STX 04 FB data[1024] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK

SOH 05 FA data[100] 1A[28] CRC CRC>>>>>>>>>>>>>>>>>>

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK

EOT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< NAK

EOT>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< C

SOH 00 FF NUL[128] CRC CRC >>>>>>>>>>>>>>>>>>>>>>>

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK                     
原文链接:https://blog.csdn.net/huangdenan/article/details/103611081

数据解析:

void YModem_Parse(uint8_t data) {
    static uint8_t packetBuffer[1024];  // 存放接收到的数据块
    static uint16_t packetIndex = 0;    // 当前数据块接收的位置
    switch (ymodemState) {
        case YMODEM_IDLE:
            if (data == SOH || data == STX) {
                // 检测到 SOH 或 STX,开始接收数据块
                packetIndex = 0;
                packetBuffer[packetIndex++] = data;
                ymodemState = YMODEM_RECEIVING;

            }
            if (data == EOT) {
                // 检测到 EOT,传输结束
                ymodemState = YMODEM_IDLE;
                // 发送 ACK 响应确认传输结束
                Set_state(TO_RECEIVE_EOT2);
                send_command(ACK);
                send_command(CCC);
            }
            if (data == CAN) {
                // 检测到 EOT,传输结束
                ymodemState = YMODEM_IDLE;
                // 发送 ACK 响应确认传输结束
                Set_state(TO_stday);

            }
            break;

        case YMODEM_RECEIVING:
                packetBuffer[packetIndex++] = data;
                if ((packetBuffer[0] == SOH && packetIndex == 133) || (packetBuffer[0] == STX && packetIndex == 1029)) {
                    YModem_ProcessDataBlock(packetBuffer, packetIndex);
                    LOGD("blockNumber %d",packetBuffer[1]);
                    ymodemState = YMODEM_IDLE;
                }
            break;
        default:
            break;
    }
}


代码升级

/**
* @bieaf YModem升级
*
* @param none
* @return none
*/
void ymodem_fun(uint8_t* data,int len)
{       
    static unsigned char data_state = 0;
    static unsigned int app2_size = 0;

    if(Check_CRC(data, len)==1)///< 通过CRC16校验
    {
       if(data[1] == 0x00 &&data_state == 0)
           Set_state(TO_START);
       if(Get_state()==TO_RECEIVE_EOT2)
           Set_state(TO_RECEIVE_END);
        if((Get_state()==TO_START)&&(data[1] == 0x00)&&(data[2] == (unsigned char)(~data[1])))///< 开始
        {
            LOGD("> Receive start...\r\n");

            data_state = 0x01;                                               
            Set_state(TO_RECEIVE_DATA);
            /* 擦除App2 */                                                       
//            Erase_page(Application_2_Addr, 30);
        }
        else if((Get_state()==TO_RECEIVE_END)&&(data[1] == 0x00)&&(data[2] == (unsigned char)(~data[1])))///< 结束
        {
            LOGD("> Receive end...\r\n");
            Set_Update_Down();                                               
            Set_state(TO_stday);
            send_command(ACK);
            if(data[1] == 0x00)
                send_command(CCC);
            delay_ms(1000);

            SoftReset();
        }
        else if((Get_state()==TO_RECEIVE_DATA)&&(data[1] == data_state)&&(data[2] == (unsigned char)(~data[1])))///< 接收数据
        {
            LOGD("> Receive data bag:%d byte\r\n",data_state * 128);

            /* 烧录程序 */
            ONCHIP_FLASH_Write_32Bit((Application_2_Addr + (data_state-1) * 128), (uint32_t *)(&data[3]), 32);
            data_state++;
        }
        send_command(ACK);
        if(data[1] == 0x00)
            send_command(CCC);

    }
    else
    {
        LOGD("> Notpass crc\r\n");
    }
}


源文件下载链接:https://download.csdn.net/download/qq_45234526/90294512

结语
上面代码内容均以测试实现,可放心下载。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/qq_45234526/article/details/145283100

使用特权

评论回复
沙发
guijial511| | 2025-6-11 08:04 | 只看该作者
YModem和XModem的区别在哪儿呢?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

42

主题

170

帖子

1

粉丝