初级会员 
  
	- 积分
 - 112
 
        - 金钱
 - 112 
 
       - 注册时间
 - 2019-2-16
 
      - 在线时间
 - 18 小时
 
 
 
 | 
 
 
 楼主 |
发表于 2020-6-29 19:52:11
|
显示全部楼层
 
 
 
Stm32F777单片机下: 
Ymodem.h 
#define PACKET_HEADER_SIZE      ((uint32_t)3) 
#define PACKET_DATA_INDEX       ((uint32_t)4) 
#define PACKET_START_INDEX      ((uint32_t)1) 
#define PACKET_NUMBER_INDEX     ((uint32_t)2) 
#define PACKET_CNUMBER_INDEX    ((uint32_t)3) 
#define PACKET_TRAILER_SIZE     ((uint32_t)2) 
#define PACKET_OVERHEAD_SIZE    (PACKET_HEADER_SIZE + PACKET_TRAILER_SIZE - 1) 
#define PACKET_SIZE             ((uint32_t)128) 
#define PACKET_1K_SIZE          ((uint32_t)1024) 
#define FILE_NAME_LENGTH        ((uint32_t)64) 
#define FILE_SIZE_LENGTH        ((uint32_t)16) 
 
#define SOH                     ((uint8_t)0x01)  /* start of 128-byte data packet */ 
#define STX                     ((uint8_t)0x02)  /* start of 1024-byte data packet */ 
#define EOT                     ((uint8_t)0x04)  /* end of transmission */ 
#define ACK                     ((uint8_t)0x06)  /* acknowledge */ 
#define NAK                     ((uint8_t)0x15)  /* negative acknowledge */ 
#define CA                      ((uint32_t)0x18) /* two of these in succession aborts transfer */ 
#define CRC16                   ((uint8_t)0x43)  /* 'C' == 0x43, request 16-bit CRC */ 
#define NEGATIVE_BYTE           ((uint8_t)0xFF) 
 
#define ABORT1                  ((uint8_t)0x41)  /* 'A' == 0x41, abort by user */ 
#define ABORT2                  ((uint8_t)0x61)  /* 'a' == 0x61, abort by user */ 
 
#define NAK_TIMEOUT             ((uint32_t)0x100000) 
#define DOWNLOAD_TIMEOUT        ((uint32_t)1000) /* One second retry delay */ 
#define MAX_ERRORS              ((uint32_t)5) 
Ymodem.c 
 
HAL_StatusTypeDef Serial_PutByte( uint8_t param ) 
{ 
  return HAL_UART_Transmit(&huart1, ¶m, 1, TX_TIMEOUT); 
 
} 
 
static HAL_StatusTypeDef ReceivePacket(uint8_t *p_data, uint32_t *p_length, uint32_t timeout) 
{ 
  uint32_t crc; 
  uint32_t packet_size = 0; 
  HAL_StatusTypeDef status; 
  uint8_t char1; 
 
  *p_length = 0; 
        status =  HAL_UART_Receive(&huart1, &char1, 1, timeout); 
 
  if (status == HAL_OK)//串口判忙 
  { 
//                printf("ReceivePacket中char1 = :%c\r\n",char1); 
    switch (char1) 
    { 
      case SOH://0x01 
                                printf("SOH\r\n"); 
        packet_size = PACKET_SIZE;    //128byte 
        break; 
      case STX://0x02 
                                printf("STX \r\n"); 
        packet_size = PACKET_1K_SIZE; //1024byte 
        break; 
      case EOT://0x04                 //结束发送标志位 
                                printf("EOT\r\n"); 
              if(EOTCN==0) 
        { 
          EOTCN=1; 
                                } 
                                else if(EOTCN==1) 
                                { 
                                        EOTCN=2; 
                                } 
        break; 
      case CA:                       //两个连续终止传输 
                                printf("CA\r\n"); 
        if ((HAL_UART_Receive(&huart1, &char1, 1, timeout) == HAL_OK) && (char1 == CA)) 
        { 
                                        packet_size = 2; 
        } 
        else 
        { 
                                        status = HAL_ERROR; 
        } 
        break; 
      case ABORT1:                   //'A' 
                                printf("ABORT1\r\n"); 
      case ABORT2:                   //'a' 
                                printf("ABORT2\r\n"); 
        status = HAL_BUSY; 
        break; 
      default: 
 
        status = HAL_ERROR; 
        break; 
    } 
    *p_data = char1; 
    if (packet_size >= PACKET_SIZE ) 
    {      
        printf("packet_size >= PACKET_SIZE\r\n"); 
     status = HAL_UART_Receive(&huart1, &p_data[PACKET_NUMBER_INDEX], packet_size + PACKET_OVERHEAD_SIZE, timeout); 
      /* Simple packet sanity check */ 
     if (status == HAL_OK ) 
     { 
        printf("reeive %02x\n",p_data[PACKET_NUMBER_INDEX]);         
        if (p_data[PACKET_NUMBER_INDEX] != ((p_data[PACKET_CNUMBER_INDEX]) ^ NEGATIVE_BYTE))                                                
       { 
           packet_size = 0; 
           status = HAL_ERROR; 
       } 
       else 
       { 
        printf("check crc\r\n"); 
        /* Check packet CRC */ 
        crc = p_data[ packet_size + PACKET_DATA_INDEX ] << 8; 
        crc += p_data[ packet_size + PACKET_DATA_INDEX + 1 ]; 
        if (Cal_CRC16(&p_data[PACKET_DATA_INDEX], packet_size) != crc ) 
        { 
        printf("Error\r\n"); 
        packet_size = 0; 
        status = HAL_ERROR; 
        } 
       } 
     } 
     else 
     { 
        printf("size = 0\r\n"); 
       packet_size = 0; 
     } 
    } 
  } 
  *p_length = packet_size; 
 
  return status; 
} 
 
 
/** 
  * @brief  Prepare the first block                                                                                    //准备起始帧 
  * @param  p_data:  output buffer                                                                                     //输出缓冲区 
        * @param  p_file_name: name of the file to be sent      //要发送的文件名 
        * @param  length: length of the file to be sent in bytes//要发送的文件长度 
  * @retval None 
  */ 
static void PrepareIntialPacket(uint8_t *p_data, const uint8_t *p_file_name, uint32_t length) 
{ 
  uint32_t i, j = 0; 
  uint8_t astring[10]; 
 
  /* first 3 bytes are constant */ 
  p_data[PACKET_START_INDEX] = SOH;                     //起始帧的首位0x01 
  p_data[PACKET_NUMBER_INDEX] = 0x00;                //起始帧的第二位,即帧序号,依次向下 
  p_data[PACKET_CNUMBER_INDEX] = 0xff;                //起始帧的第三位,帧序号取反 
 
  /* Filename written */ 
  for (i = 0; (p_file_name != '\0') && (i < FILE_NAME_LENGTH); i++) 
  { 
    p_data[i + PACKET_DATA_INDEX] = p_file_name;//从第四位开始是文件名字 
  } 
  p_data[i + PACKET_DATA_INDEX] = 0x00;            //在文件末名尾加0x00,表示文件名的结束 
 
  /* file size written */ 
  Int2Str (astring, length);                         //转换成字符 
  i = i + PACKET_DATA_INDEX + 1;                                                                         
  while (astring[j] != '\0')                       //加上0表示结束 
  { 
    p_data[i++] = astring[j++]; 
  } 
 
  /* padding with zeros */ 
        /*       用0填充      */ 
  for (j = i; j < PACKET_SIZE + PACKET_DATA_INDEX; j++)//除去文件名与文件大小占用的空间,其余的都用0填充 
  { 
    p_data[j] = 0; 
  } 
} 
 
 
 
static void PreparePacket(uint8_t *p_source, uint8_t *p_packet, uint8_t pkt_nr, uint32_t size_blk) 
{ 
  uint8_t *p_record; 
  uint32_t i, size, packet_size; 
 
  /* Make first three packet */ 
  packet_size = size_blk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE; 
  size = size_blk < packet_size ? size_blk : packet_size; 
  if (packet_size == PACKET_1K_SIZE)                             //判断数据包是否为1024字节 
  { 
    p_packet[PACKET_START_INDEX] = STX;                                                                                                         
 
 //数据帧的起始0x02 
  } 
  else                                                                                                                                         
 
//否则,为起始帧的起始位 
  { 
    p_packet[PACKET_START_INDEX] = SOH; 
  } 
  p_packet[PACKET_NUMBER_INDEX] = pkt_nr; 
  p_packet[PACKET_CNUMBER_INDEX] = (~pkt_nr); 
  p_record = p_source; 
 
  /* Filename packet has valid data */ 
  for (i = PACKET_DATA_INDEX; i < size + PACKET_DATA_INDEX;i++) 
  { 
    p_packet = *p_record++; 
  } 
  if ( size  <= packet_size) 
  { 
    for (i = size + PACKET_DATA_INDEX; i < packet_size + PACKET_DATA_INDEX; i++) 
    { 
      p_packet = 0x1A; /* EOF (0x1A) or 0x00 */ 
    } 
  } 
} 
 
/** 
  * @brief  Update CRC16 for input byte 
  * @param  crc_in input value  
  * @param  input byte 
  * @retval None 
  */ 
uint16_t UpdateCRC16(uint16_t crc_in, uint8_t byte) 
{ 
  uint32_t crc = crc_in; 
  uint32_t in = byte | 0x100; 
 
  do 
  { 
    crc <<= 1; 
    in <<= 1; 
    if(in & 0x100) 
      ++crc; 
    if(crc & 0x10000) 
      crc ^= 0x1021; 
  } 
   
  while(!(in & 0x10000)); 
 
  return crc & 0xffffu; 
} 
 
/** 
  * @brief  Cal CRC16 for YModem Packet 
  * @param  data 
  * @param  length 
  * @retval None 
  */ 
uint16_t Cal_CRC16(const uint8_t* p_data, uint32_t size) 
{ 
  uint32_t crc = 0; 
  const uint8_t* dataEnd = p_data+size; 
 
  while(p_data < dataEnd) 
    crc = UpdateCRC16(crc, *p_data++); 
  
  crc = UpdateCRC16(crc, 0); 
  crc = UpdateCRC16(crc, 0); 
 
  return crc&0xffffu; 
} 
 
/** 
  * @brief  Calculate Check sum for YModem Packet 
  * @param  p_data Pointer to input data 
  * @param  size length of input data 
  * @retval uint8_t checksum value 
  */ 
uint8_t CalcChecksum(const uint8_t *p_data, uint32_t size) 
{ 
  uint32_t sum = 0; 
  const uint8_t *p_data_end = p_data + size; 
 
  while (p_data < p_data_end ) 
  { 
    sum += *p_data++; 
  } 
 
  return (sum & 0xffu); 
} 
 
/* Public functions ---------------------------------------------------------*/ 
/** 
  * @brief  Receive a file using the ymodem protocol with CRC16. 
  * @param  p_size The size of the file. 
  * @retval COM_StatusTypeDef result of reception/programming 
  */ 
COM_StatusTypeDef Ymodem_Receive ( uint32_t *p_size ) 
{ 
  uint32_t i, packet_length, session_done = 0, file_done, errors = 0, session_begin = 0; 
  uint32_t flashdestination, filesize; 
  uint8_t *file_ptr; 
  uint8_t file_size[FILE_SIZE_LENGTH], tmp, packets_received; 
        COM_StatusTypeDef result = COM_OK; 
  /* Initialize flashdestination variable */ 
  flashdestination = APPLICATION_ADDRESS; 
  while ((session_done == 0) && (result == COM_OK)) 
  { 
        packets_received = 0; 
        file_done = 0; 
        while ((file_done == 0) && (result == COM_OK)) 
        {  
                         
        switch (ReceivePacket(aPacketData, &packet_length, DOWNLOAD_TIMEOUT)) 
        {      
                case HAL_OK: 
                printf("HAL_OK\r\n"); 
                errors = 0; 
                switch (packet_length) 
                { 
                case 2: 
            /* Abort by sender */ 
                printf("send ACK2\n"); 
                Serial_PutByte(ACK); 
                result = COM_ABORT; 
                break; 
                case 0: 
            /* End of transmission */ 
                if(EOTCN==1) 
                { 
                         printf("EOTsend NAK\n"); 
                        Serial_PutByte(NAK); 
                } 
                else 
                {         
                  printf("send ACK0\n");              
                  Serial_PutByte(ACK); 
                  file_done = 1; 
                }             
                break; 
                default: 
            /* Normal packet */ 
           // printf("num%d\n",aPacketData[PACKET_NUMBER_INDEX]); 
          //  printf("packets_received%d\n",packets_received); 
                if (aPacketData[PACKET_NUMBER_INDEX] != packets_received) 
                { 
                printf("NAK\n"); 
                Serial_PutByte(NAK); 
                } 
                else 
                { 
                if (packets_received == 0) 
                { 
                /* File name packet */ 
                if (aPacketData[PACKET_DATA_INDEX] != 0) 
                { 
                /* File name extraction */ 
                i = 0; 
                file_ptr = aPacketData + PACKET_DATA_INDEX; 
                while ( (*file_ptr != 0) && (i < FILE_NAME_LENGTH)) 
                { 
                        aFileName[i++] = *file_ptr++; 
                } 
                /* File size extraction */ 
                aFileName[i++] = '\0'; 
                i = 0; 
                file_ptr ++; 
                while ( (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH)) 
                { 
                        file_size[i++] = *file_ptr++; 
                } 
                file_size[i++] = '\0'; 
                Str2Int(file_size, &filesize); 
                /* Test the size of the image to be sent */ 
                /* Image size is greater than Flash size */ 
                if (*p_size > (USER_FLASH_SIZE + 1)) 
                { 
                  /* End session */ 
                tmp = CA; 
                HAL_UART_Transmit(&huart1, &tmp, 1, NAK_TIMEOUT); 
                HAL_UART_Transmit(&huart1, &tmp, 1, NAK_TIMEOUT); 
                result = COM_LIMIT; 
                } 
                /* erase user application area */ 
                if(SocFlashErase(APPLICATION_ADDRESS)==FLASHIF_OK) 
                { 
                      printf("erase ok\n"); 
                } 
                *p_size = filesize; 
                //printf("send ACK+C\n"); 
 
                Serial_PutByte(ACK); 
                Serial_PutByte(CRC16); 
                } 
                /* File header packet is empty, end session */ 
                else 
                { 
                EOTCN=0; 
                printf("send ACK3\n"); 
                Serial_PutByte(ACK); 
                file_done = 1; 
                session_done = 1; 
                break; 
                } 
                } 
                else /* Data packet */ 
                { 
                /* Write received data in Flash */ 
                if (SocFlashWrite(flashdestination, & aPacketData[PACKET_DATA_INDEX], packet_length/4) == FLASHIF_OK)                  
                { 
                        flashdestination += packet_length; 
                        printf("send ACK4\n"); 
                        Serial_PutByte(ACK); 
                } 
                else /* An error occurred while writing to Flash memory */ 
                { 
                /* End session */ 
                Serial_PutByte(CA); 
                Serial_PutByte(CA); 
                result = COM_DATA; 
                } 
                } 
                packets_received ++; 
                session_begin = 1; 
        } 
        break; 
        } 
        break; 
        case HAL_BUSY: /* Abort actually */ 
                Serial_PutByte(CA); 
                Serial_PutByte(CA); 
                result = COM_ABORT; 
                break; 
        default: 
                if (session_begin > 0) 
                { 
                errors ++; 
                } 
                if (errors > MAX_ERRORS) 
                { 
          /* Abort communication */ 
                Serial_PutByte(CA); 
                Serial_PutByte(CA); 
                } 
                else 
                { 
                        Serial_PutByte(CRC16); /* Ask for a packet */ 
                } 
                break; 
        } 
        } 
        } 
return result; 
} 
 |   
 
 
 
 |