#include "ymodem.h" #include "string.h" #include "stdlib.h" #include "flash.h" #include "usart1.h" #include "uart5.h" #include "delay.h" USART_TypeDef * IAP_Port = UART5; uint8_t FileName[FILE_NAME_LENGTH];//array to store filename of download *.bin char file_size[FILE_SIZE_LENGTH]; uint8_t buf_1k[1024] ={0}; /********************************************/ //移植的时候,由于函数定义了局部大数组,需要修改堆栈的大小。 //下面是需要移植的函数 static uint32_t SerialKeyPressed(uint8_t *key); static int32_t Receive_Byte(uint8_t *c, uint32_t timeout); int32_t Ymodem_Receive (uint8_t *buf, uint32_t appaddr); uint32_t STM_FLASH_Erase(uint32_t addrx); uint32_t STM_FLASH_Get_Block_Size(uint32_t addrx); uint32_t STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite); /********************************************/ //check if one byte rx successfully //key: variabl to store rx data //return: 1=success, 0=fail static uint32_t SerialKeyPressed(uint8_t *key) { if(IAP_Port == UART5) { return uart5_read_byte(key); } else { return usart1_read_byte(key); } } //Rx a byte from sender //c: variable to store data //timeout: read time out //return: 0=success, -1=fail static int32_t Receive_Byte (uint8_t *c, uint32_t timeout) { while (timeout-- > 0) { if (SerialKeyPressed(c) == 1) { return 0; } } return -1; } //send a byte via IAP_Port //c: byte to send //return: 0 static uint32_t Send_Byte (uint8_t c) { if(IAP_Port == UART5) { uart5_send_byte(c); } else { usart1_send_byte(c); } return 0; } /** * @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; } //Rx a packet from sender //data: pointer to store rx data //length: packet length //timeout: rx time out //return:0=normally return // -1=timeout or packet error // 1=abort by user static int32_t Receive_Packet (uint8_t *data, int32_t *length, uint32_t timeout) { uint16_t i, packet_size; uint8_t c; uint32_t crc=0; *length = 0; if (Receive_Byte(&c, timeout) != 0) { return -1; } switch (c) { case SOH: packet_size = PACKET_SIZE; break; case STX: packet_size = PACKET_1K_SIZE; break; case EOT: return 0; case CA: if ((Receive_Byte(&c, timeout) == 0) && (c == CA)) { *length = -1; return 0; } else { return -1; } case ABORT1: case ABORT2: return 1; default: return -1; } *data = c; for (i = 1; i < (packet_size + PACKET_OVERHEAD); i ++) { if (Receive_Byte(data + i, timeout) != 0) { return -1; } } crc = data[ packet_size + PACKET_HEADER ] << 8; crc += data[ packet_size + PACKET_HEADER + 1 ]; if (Cal_CRC16(&data[PACKET_HEADER], packet_size) != crc ) { packet_size = 0; return -1; } *length = packet_size; return 0; } //Receive a file using the ymodem protocol //buf: pointer for data storage //appaddr: User Application address //return: size of IAP file int32_t Ymodem_Receive (uint8_t *buf, uint32_t appaddr) { uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], *file_ptr, *buf_ptr,flag_EOT; int32_t i, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0; uint32_t flashdestination, ramsource; //Initialize flashdestination variable flashdestination = appaddr; flag_EOT = 0; for (session_done = 0, errors = 0, session_begin = 0; ;) { for (packets_received = 0, file_done = 0, buf_ptr = buf; ;) { switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT)) { case 0: errors = 0; switch (packet_length) { /* Abort by sender */ case - 1: Send_Byte(ACK); return 0; /* End of transmission */ case 0: if(flag_EOT==0) //first EOT { Send_Byte(NACK); flag_EOT = 1; } else if (flag_EOT==1) //second EOT { Send_Byte(ACK); Send_Byte('C'); file_done = 1; } break; /* Normal packet */ default: if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff)) { Send_Byte(NACK);//local data sequence number is different to rx data packet. } else { if (packets_received == 0) { /* Filename packet */ if (packet_data[PACKET_HEADER] != 0) { /* Filename packet has valid data */ for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);) { FileName[i++] = *file_ptr++; } FileName[i++] = '\0'; for (i = 0, file_ptr ++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH);) { file_size[i++] = *file_ptr++; } file_size[i++] = '\0'; size = atoi(file_size); /* Test the size of the image to be sent */ /* Image size is greater than Flash size */ if (size > (int32_t)(STM_FLASH_Get_Block_Size(flashdestination) + 1)) { /* End session */ Send_Byte(CA); Send_Byte(CA); return -1; } /* erase user application area */ STM_FLASH_Erase(flashdestination); Send_Byte(ACK); Send_Byte(CRC16); } /* Filename packet is empty, end session */ else { Send_Byte(ACK); file_done = 1; session_done = 1; break; } } /* Data packet */ else { memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length); ramsource = (uint32_t)buf_ptr; /* Write received data in Flash */ if (STMFLASH_Write(flashdestination, (uint32_t*)ramsource, (uint16_t) packet_length) == 0) { flashdestination+=packet_length; Send_Byte(ACK); } else /* An error occurred while writing to Flash memory */ { /* End session */ Send_Byte(CA); Send_Byte(CA); return -2; } } packets_received ++; session_begin = 1; } } break; case 1: Send_Byte(CA); Send_Byte(CA); return -3; default: if (session_begin > 0) { errors ++; } if (errors > MAX_ERRORS) { Send_Byte(CA); Send_Byte(CA); return 0; } Send_Byte(CRC16); break; } if (file_done != 0) { break; } } if (session_done != 0) { break; } } return (int32_t)size; }