• Ymodem协议-接收


    网上很多关于Ymodem协议的,有部分是错误的,以下是经过本人亲自编写的程序,测试可用。目前单片机作为接受端,用于IAP升级,发送还没写。另外对于终止传送也还没写,正常情况接收是完全没问题的。

    划重点:《重复发送1024字节直到收到EOT开头数据,网上的错误点就在这里,搞了我很久,网上说的是不够128凑齐发SOH包,其实不是,是凑齐1024发STX包直到发EOT。》

    平台:stm32f101v8  超级终端 keil

    传输起来,效果是这样的!一般很快 如下图 2秒就7K了

    首先超级终端中Ymodem协议是这样的,定义单片机位接受者,超级终端为发送者:

    SOH开头: 128字节的数据,总包大小128+5,SOH即0x01

    STX开头: 1024字节的数据,总包大小1024+5 ,STX即0x02

    EOT开头: 单个字节,传输完成,总包大小1 ,EOT即0x04

    /*YModem standard CMD*/
    #define YMODEM_SOH (0x01)
    #define YMODEM_STX (0x02)
    #define YMODEM_EOT (0x04)
    #define YMODEM_ACK (0x06)
    #define YMODEM_NAK (0x15)
    #define YMODEM_CAN (0x18)
    #define YMODEM_C (0x43)

    以下为交流顺序:

    接受者:发送大写字母C,等待数据

    发送者:发送ASCII中的SOH也就是01,后面是包序号00,包序号反码FF,文件名YG06_V0_1.bin,NULL,文件大小11212 bytes ,补齐111字节至128字节,CRC CRC是数据段的16位CRC校验码。总共此包是128+5=133字节。SOH

    我的第一个包收到如下: 01 00 FF "YG06_V0_1.bin"  NULL "11212" NULL[111] CRC CRC

    接受者:发送大写字母ACK,发送大写字母C,等待数据

    发送者:发送ASCII中的STX也就是02,后面是包序号01,包序号反码FE,1024字节数据,CRC CRC.总共此包是1024+5=1029字节。STX

    我的第一个包收到如下: 02 01 FE DATA[1024] CRC CRC

    接受者:ACK

    发送者:STX包

    接受者:ACK

    发送者:STX包

    .......

    接受者:ACK

    发送者:EOT

    重复发送1024字节直到收到EOT开头数据,网上的错误点就在这里,搞了我很久,网上说的是不够128凑齐发SOH包,其实不是,是凑齐1024发STX包直到发EOT。

    接受者:NAK ( 第一次收到EOT发NAK )

    发送者:EOT

    接受者:ACK C( 第二次收到EOT发ACK 和大写 C )

    发送者:SOH 00 FF NUL[128] CRC CRC (发送128字节空包)

    接受者:ACK ( 传输结束 )、

    简明如下:

     发送端                                                                             接收端

     <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    C
    SOH 00 FF "YG06_V0_1.bin"  NULL "11212" NULL[111] 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
    STX xx xx data[972]  1A[52] CRC CRC>>>>>>>>>>>>>>>>>>    补1A凑齐1024字节
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    ACK
    EOT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    NAK
    EOT>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    ACK
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    C
    SOH 00 FF NUL[128] CRC CRC >>>>>>>>>>>>>>>>>>>>>>>
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    ACK 结束
    附上程序如下:
    ymodem.h
    #ifndef _YMODEM_H_
    #define _YMODEM_H_
    #include "stm32f10x.h"
    #define MAX_LEN_TO_FLASH (1026)
    #define MAX_CACHE_LEN (135)
    typedef struct
    {
        u8 Data[MAX_CACHE_LEN];
        u16 cnt;
    }Cache_t;
    typedef struct
    {
        u8 Data[MAX_LEN_TO_FLASH];
        u16 cnt;
        u8 x;
    }WriteToFlash_t;
    //extern Cache_t Cache;
    extern WriteToFlash_t WriteToFlash;
    /*YModem standard CMD*/
    #define YMODEM_SOH (0x01)
    #define YMODEM_STX (0x02)
    #define YMODEM_EOT (0x04)
    #define YMODEM_ACK (0x06)
    #define YMODEM_NAK (0x15)
    #define YMODEM_CAN (0x18)
    #define YMODEM_C (0x43)
    /*Rcv_CMD define*/
    #define IS_NOT_FIRST_PACKET (0x00)
    #define IS_FIRST_PACKET (0x01)
    #define IS_NORMAL_FILE_128 (0X02)
    #define IS_NORMAL_FILE_1024 (0X03)
    #define IS_END_OF_TRANSMIT (0X04)
    extern s8 YmodemSendACK(u8 byte);
    extern void RcvFile(u8 PacketReturn,u8 * IsFileEnd,u16* systickmark);
    extern s8 YmodemRcvPacket(u8 *rcvbuf,u16 buflen,u8 *result);
    u16 YModemCRC(u8 * data,u16 len);
    #endif

    ymodem.c

    #include "ymodem.h"
    #include "base_conf.h"
    #include "uart_dma.h"
    #include "crypt.h"
    #include "sysflash.h"
    #include "main.h"
    Cache_t Cache;
    WriteToFlash_t WriteToFlash;
    static u8 EOT_Flag = 0;
    s8 YmodemSendACK(u8 byte)
    {
        UART_PutChar(UART_DEBUG,byte);
        //Delay_ms(100);
        return 0;
    }
    
    void RcvFile(u8 PacketReturn,u8 * IsFileEnd,u16 * systickmark)
    {
        static u8 i=0;
        switch(PacketReturn)
        {
            case IS_FIRST_PACKET:
            {
                YmodemSendACK(YMODEM_ACK);
                YmodemSendACK(YMODEM_C);
                *systickmark = GetCurrentTime();
                break;
            }
            case IS_NORMAL_FILE_128:
            {
          memcpy(&WriteToFlash.Data[i*128],Cache.Data,Cache.cnt);
                WriteToFlash.cnt += 128;
                i++;
                if(i==7)//write flash
                {
                    i=0;
                    Flash_Program_bytes(Page(WriteToFlash.x+APP_FLASH_OFFSET/1024),WriteToFlash.Data,WriteToFlash.cnt);
                    WriteToFlash.x++;
                }
                YmodemSendACK(YMODEM_ACK);
                *systickmark = GetCurrentTime();
                break;
            }
            case IS_NORMAL_FILE_1024:
            {
                Flash_Program_bytes((Page(WriteToFlash.x+APP_FLASH_OFFSET/1024)),WriteToFlash.Data,WriteToFlash.cnt);
                WriteToFlash.x++;
                memset(WriteToFlash.Data,0,WriteToFlash.cnt);
                YmodemSendACK(YMODEM_ACK);
                *systickmark = GetCurrentTime();
                break ;
            }
            case IS_END_OF_TRANSMIT:
            {
                if(EOT_Flag==1)
                {
                    //Flash_Program_bytes(Page(WriteToFlash.x+APP_FLASH_OFFSET/1024),WriteToFlash.Data,WriteToFlash.cnt);
                    YmodemSendACK(YMODEM_NAK);
                }
                if(EOT_Flag==2)
                {
                    YmodemSendACK(YMODEM_ACK);
                    YmodemSendACK(YMODEM_C);
                    
                }
                if(EOT_Flag==3)
                {
                    Delay_ms(10);
                    YmodemSendACK(YMODEM_ACK);
                    EOT_Flag=0;
                  *IsFileEnd =1;
                    
                }
                break;
            }
        }
    }
    
    s8 YmodemRcvPacket(u8 *rcvbuf,u16 buflen,u8 *result)
    {
          
          u16 crc;
          u8 debug;
          u8 debug1;
          
          
          switch(*(rcvbuf))
            {
                case YMODEM_EOT:
                {
                    EOT_Flag++;
                    *result =IS_END_OF_TRANSMIT ;
                    break;
                }
                case YMODEM_SOH:
                {
                    debug=((~(*(rcvbuf+1))));
              debug1=((*(rcvbuf+2)));
              if(debug!=debug1)return -1;
                    memset(Cache.Data,0,sizeof(Cache.Data));
                    Cache.cnt = 128;
                    memcpy(Cache.Data,(rcvbuf+3),Cache.cnt);
                    crc=*(rcvbuf+128+3)<<8 | *(rcvbuf+128+3+1);
                    if(YModemCRC(Cache.Data,Cache.cnt)!=crc)return -1;
            if(*(rcvbuf+1)==0)
                    {
                        if(strstr((const char *)(Cache.Data),"YG06_V0_1.bin")!=NULL)
                        {*result=IS_FIRST_PACKET;}
                        else{
                                 if(*result == IS_END_OF_TRANSMIT ) //end with some of file,NULL DATA
                                     {
                                         *result =IS_END_OF_TRANSMIT ;EOT_Flag++;
                                     }
                                     else
                                     {return -1;}//not the end of transmit,wrong file name
                            }
                    }    
                    else
                    {
                        
                        *result =IS_NORMAL_FILE_128 ;
                    }
                    break;
                }
                case YMODEM_STX:
                {
                    debug=((~(*(rcvbuf+1))));
              debug1=((*(rcvbuf+2)));
              if(debug!=debug1)return -1; 
                    WriteToFlash.cnt = 1024;
                    memcpy(WriteToFlash.Data,(rcvbuf+3),WriteToFlash.cnt);
                    crc=*(rcvbuf+1024+3)<<8 | *(rcvbuf+1024+3+1);
                    if(YModemCRC(WriteToFlash.Data,WriteToFlash.cnt)!=crc)return -1;
                    *result =IS_NORMAL_FILE_1024 ;
                    break;
                }
                
                default:
                {
                    break;
                }
            }
        
        return 0;
    }
    
    u16 YModemCRC(u8 * data,u16 len)
    {
        int crc =0;
        int i,j;
        for(i=0;i<len;i++)
        {
            crc=crc^(data[i]<<8);
            for(j=0;j<8;j++)
            {
                if((crc &((int)0x8000))!=0)
                {
                    crc = ((crc<<1) ^ 0x1021);
                }
                else
                {
                    crc = crc << 1;
                }
            }
        }
        return (crc&0xFFFF);
    }
  • 相关阅读:
    118. Pascal's Triangle
    172. Factorial Trailing Zeroes
    345. Reverse Vowels of a String
    58. Length of Last Word
    383. Ransom Note
    387. First Unique Character in a String
    83. Remove Duplicates from Sorted List
    关于Assembly.CreateInstance()与Activator.CreateInstance()方法
    查看占用指定端口的进程
    如何使用eclipse打开已有工程
  • 原文地址:https://www.cnblogs.com/ycpkbql/p/9117129.html
Copyright © 2020-2023  润新知