/** ****************************************************************************** * @file STM32F0xx_IAP/src/ymodem.c * @author MCD Application Team * @version V1.0.0 * @date 29-May-2012 * @brief Main program body ****************************************************************************** * @attention * *

© COPYRIGHT 2012 STMicroelectronics

* * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "ymodem.h" #include "string.h" //#include "main.h" #include "aes.h" #include "mk_flash.h" //#include "stm32f4xx_hal.h" #include "AppConfig.h" #include "mk_uart.h" #include "mk_trace.h" /** @addtogroup STM32F0xx_IAP * @{ */ #define IS_AF(c) ((c >= 'A') && (c <= 'F')) #define IS_af(c) ((c >= 'a') && (c <= 'f')) #define IS_09(c) ((c >= '0') && (c <= '9')) #define ISVALIDHEX(c) IS_AF(c) || IS_af(c) || IS_09(c) #define ISVALIDDEC(c) IS_09(c) #define CONVERTDEC(c) (c - '0') #define CONVERTHEX_alpha(c) (IS_AF(c) ? (c - 'A'+10) : (c - 'a'+10)) #define CONVERTHEX(c) (IS_09(c) ? (c - '0') : CONVERTHEX_alpha(c)) /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ extern uint8_t FileName[]; extern void Int2Str(uint8_t* str, int32_t intnum); //extern UART_HandleTypeDef huart1; /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ uint32_t Str2Int(uint8_t *inputstr, int32_t *intnum) { uint32_t i = 0, res = 0; uint32_t val = 0; if (inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X')) { if (inputstr[2] == '\0') { return 0; } for (i = 2; i < 11; i++) { if (inputstr[i] == '\0') { *intnum = val; /* return 1; */ res = 1; break; } if (ISVALIDHEX(inputstr[i])) { val = (val << 4) + CONVERTHEX(inputstr[i]); } else { /* return 0, Invalid input */ res = 0; break; } } /* over 8 digit hex --invalid */ if (i >= 11) { res = 0; } } else /* max 10-digit decimal input */ { for (i = 0;i < 11;i++) { if (inputstr[i] == '\0') { *intnum = val; /* return 1 */ res = 1; break; } else if ((inputstr[i] == 'k' || inputstr[i] == 'K') && (i > 0)) { val = val << 10; *intnum = val; res = 1; break; } else if ((inputstr[i] == 'm' || inputstr[i] == 'M') && (i > 0)) { val = val << 20; *intnum = val; res = 1; break; } else if (ISVALIDDEC(inputstr[i])) { val = val * 10 + CONVERTDEC(inputstr[i]); } else { /* return 0, Invalid input */ res = 0; break; } } /* Over 10 digit decimal --invalid */ if (i >= 11) { res = 0; } } return res; } /** * @brief Receive byte from sender * @param c: Character * @param timeout: Timeout * @retval 0: Byte received * -1: Timeout */ int32_t Receive_Byte (uint8_t *c, uint32_t timeout) { while (timeout-- > 0) { if (SerialKeyPressed(c) == 1)//Èç¹ûÊÕµ½´®¿ÚÊý¾Ý { // Serial0_PutString("½ÓÊܳɹ¦"); return 0; } } // Serial0_PutString("½ÓÊÜʧ°Ü"); return -1; } /** * @brief Send a byte * @param c: Character * @retval 0: Byte sent */ uint32_t Send_Byte (uint8_t c) { SerialPutChar(c); return 0; } /** * @brief Update CRC16 for input byte * @param CRC input value * @param input byte * @retval Updated CRC value */ uint16_t UpdateCRC16(uint16_t crcIn, uint8_t byte) { uint32_t crc = crcIn; 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 CRC value */ uint16_t Cal_CRC16(const uint8_t* data, uint32_t size) { uint32_t crc = 0; const uint8_t* dataEnd = data+size; while(data0: packet length * @retval 0: normally return * -1: timeout or packet error * 1: abort by user */ uint16_t current_seqno,flash_seqno,i2; uint8_t c; static int32_t Receive_Packet (uint8_t *data, int32_t *length, uint32_t timeout) { uint16_t packet_size, computedcrc; *length = 0; if (Receive_Byte(&c, timeout) != 0)//·µ»Ø0³É¹¦ÊÕÈ¡Êý¾Ý,-1ΪûÊÕµ½Êý¾Ý { 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;//·Åµ½1024+5×ֽڵİüÀïÃæ for (i2 = 1; i2 < (packet_size + PACKET_OVERHEAD); i2 ++) { if (Receive_Byte(data + i2, timeout) != 0)//²»¶ÏµÄ½ÓÊÕ1024×Ö½Ú·ÅÈë { return -1; } } //¼ì²âÐòºÅ²¹ÂëÊÇÊÇ·ñÕýÈ· if (data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff)) { return 1; } if(current_seqno==data[PACKET_SEQNO_INDEX]||c==SOH) { current_seqno++; }else{ return 1; } /* Compute the CRC */ computedcrc = Cal_CRC16(&data[PACKET_HEADER], (uint32_t)packet_size);//¼ÆËãCRC16Âë /* Check that received CRC match the already computed CRC value data[packet_size+3]<<8) | data[packet_size+4] contains the received CRC computedcrc contains the computed CRC value */ if (computedcrc != (uint16_t)((data[packet_size+3]<<8) | data[packet_size+4]))//¼ì²âCRC16УÑéÂë { /* CRC error */ return 1; } *length = packet_size; return 0; } /** * @brief Receive a file using the ymodem protocol * @param buf: Address of the first byte * @retval The size of the file */ extern volatile unsigned long time32_reset; uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr; //1024 + 5 uint8_t bufferOut[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t *BufferIn; int32_t i, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0; uint32_t flashdestination, ramsource,tempaddress; int32_t Ymodem_Receive (uint8_t *buf) { aesDecInit();//AES½âÃܳõʼ»¯ /* Initialize flashdestination variable */ flashdestination = APP_CONFIG_APPLICATION_ADDRESS; //APP´úÂëµÄÆðʼµØÖ·,APP_CONFIG_APPLICATION_ADDRESS = 0x8005000,¿ÉÔÚtarget½çÃæ¸ù¾ÝÇé¿öÉèÖà current_seqno=0; //ÕâЩ¶¼ÔÚymodem.hÀïÃæµÄºê½øÐÐÉèÖà flash_seqno=2; 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://³É¹¦½ÓÊÕµ½1K errors = 0; switch (packet_length) { /* Abort by sender */ case - 1: //½ÓÊÕʧ°Ü Send_Byte(ACK); //»Ø¸´ return 0; /* End of transmission */ case 0: Send_Byte(ACK);//»Ø¸´ file_done = 1; break; /* Normal packet */ default: //½ÓÊճɹ¦ if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff)) {//ÐòºÅ00(ÎļþÃû) Send_Byte(NAK); } 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 - 1));) { file_size[i++] = *file_ptr++;//Îļþ´óС } file_size[i++] = '\0'; Str2Int(file_size, &size);//Convert a string to an integer /* Test the size of the image to be sent */ /* Image size is greater than Flash size */ if (size > (APP_CONFIG_APPLICATION_SIZE + 1)) { /* End session */ Send_Byte(CA); Send_Byte(CA); return -1; } /* erase user application area */ // Flash_Init(); // Flash_Erase(APP_CONFIG_APPLICATION_ADDRESS, APP_CONFIG_APPLICATION_SIZE);MK8000 ÐÞ¸Ä flash_erase(FLASH_ID0, APP_CONFIG_APPLICATION_ADDRESS, APP_CONFIG_APPLICATION_SIZE);//²Á³ýAPP 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); /*----------------------------------------------------------------------------------------------*/ BufferIn=buf; for (j = 0; j < packet_length; j += 16) //ÿ´Î½âÃÜ16×Ö½Ú { //½âÃÜÊý¾Ý°ü aesDecrypt(BufferIn,bufferOut); //ÓÉÓÚ²ÎÊýʹÓõÄÊÇÖ¸Õë,ËùÒÔ½âÃܺóÒÀ¾É´æÔÚbufÀïÃæ BufferIn+=16; } /*----------------------------------------------------------------------------------------------*/ /* Write received data in Flash */ //Õâ¸ösize²ÎÊýÊÇ×Ô¼º¼Ó½øÈëµÄ,±ãÓÚÅжÏÎļþ´«ÊäÍê³É // if (Flash_Write(flashdestination, buf, packet_length) == 0&&(flashdestination==tempaddress||tempaddress>size)) MK8000ÐÞ¸Ä // { // flashdestination += packet_length; // //дÈëFLASH // Send_Byte(ACK); // flash_seqno++; // time32_reset = 0; // } // else /* An error occurred while writing to Flash memory */ // { // /* End session */ // Send_Byte(CA); // Send_Byte(CA); // return -2; // } ramsource = (uint32_t)buf; tempaddress=APP_CONFIG_APPLICATION_ADDRESS+(current_seqno-1)*0x400; if(flash_write_nbytes(FLASH_ID0,flashdestination, buf, packet_length)== 0&&(flashdestination==tempaddress||tempaddress>size)) { flashdestination += packet_length; //дÈëFLASH Send_Byte(ACK); flash_seqno++; time32_reset = 0; } else { /* 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; } /** * @brief check response using the ymodem protocol * @param buf: Address of the first byte * @retval The size of the file */ int32_t Ymodem_CheckResponse(uint8_t c) { return 0; } /** * @brief Prepare the first block * @param timeout * @retval None */ void Ymodem_PrepareIntialPacket(uint8_t *data, const uint8_t* fileName, uint32_t *length) { uint16_t i, j; uint8_t file_ptr[10]; /* Make first three packet */ data[0] = SOH; data[1] = 0x00; data[2] = 0xff; /* Filename packet has valid data */ for (i = 0; (fileName[i] != '\0') && (i < FILE_NAME_LENGTH);i++) { data[i + PACKET_HEADER] = fileName[i]; } data[i + PACKET_HEADER] = 0x00; Int2Str (file_ptr, *length); for (j =0, i = i + PACKET_HEADER + 1; file_ptr[j] != '\0' ; ) { data[i++] = file_ptr[j++]; } for (j = i; j < PACKET_SIZE + PACKET_HEADER; j++) { data[j] = 0; } } /** * @brief Prepare the data packet * @param timeout * @retval None */ void Ymodem_PreparePacket(uint8_t *SourceBuf, uint8_t *data, uint8_t pktNo, uint32_t sizeBlk) { uint16_t i, size, packetSize; uint8_t* file_ptr; /* Make first three packet */ packetSize = sizeBlk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE; size = sizeBlk < packetSize ? sizeBlk :packetSize; if (packetSize == PACKET_1K_SIZE) { data[0] = STX; } else { data[0] = SOH; } data[1] = pktNo; data[2] = (~pktNo); file_ptr = SourceBuf; /* Filename packet has valid data */ for (i = PACKET_HEADER; i < size + PACKET_HEADER;i++) { data[i] = *file_ptr++; } if ( size <= packetSize) { for (i = size + PACKET_HEADER; i < packetSize + PACKET_HEADER; i++) { data[i] = 0x1A; /* EOF (0x1A) or 0x00 */ } } } /** * @brief Transmit a data packet using the ymodem protocol * @param data * @param length * @retval None */ void Ymodem_SendPacket(uint8_t *data, uint16_t length) { uint16_t i; i = 0; while (i < length) { Send_Byte(data[i]); i++; } } /** * @brief Transmit a file using the ymodem protocol * @param buf: Address of the first byte * @retval The size of the file */ static struct UART_HANDLE_T uart_handle[UART_MAX_NUM] = { { .base = UART0, .irq = UART0_IRQn, .dma_rx_ch = DMA_CH4, .dma_tx_ch = DMA_CH5, }, { .base = UART1, .irq = UART1_IRQn, .dma_rx_ch = DMA_CH6, .dma_tx_ch = DMA_CH7, }, }; uint8_t Ymodem_Transmit (uint8_t *buf, const uint8_t* sendFileName, uint32_t sizeFile) { uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD]; uint8_t FileName[FILE_NAME_LENGTH]; uint8_t *buf_ptr, tempCheckSum ; uint16_t tempCRC, blkNumber; uint8_t receivedC[2], CRC16_F = 0, i; uint32_t errors = 0, ackReceived = 0, size = 0, pktSize; for (i = 0; i < (FILE_NAME_LENGTH - 1); i++) { FileName[i] = sendFileName[i]; } CRC16_F = 1; /* Prepare first block */ Ymodem_PrepareIntialPacket(&packet_data[0], FileName, &sizeFile); do { /* Send Packet */ Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER); /* Send CRC or Check Sum based on CRC16_F */ if (CRC16_F) { tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE); Send_Byte(tempCRC >> 8); Send_Byte(tempCRC & 0xFF); } else { tempCheckSum = CalChecksum (&packet_data[3], PACKET_SIZE); Send_Byte(tempCheckSum); } /* Wait for Ack and 'C' */ if (Receive_Byte(&receivedC[0], 1000000) == 0) { if (receivedC[0] == ACK) { /* Packet transfered correctly */ ackReceived = 1; } } else { errors++; } }while (!ackReceived && (errors < 0x0A));//УÑé´íÎóÖØ·¢ if (errors >= 0x0A) { return errors; } buf_ptr = buf; size = sizeFile; blkNumber = 0x01; /* Here 1024 bytes package is used to send the packets */ while (size) { /* Prepare next packet */ Ymodem_PreparePacket(buf_ptr, &packet_data[0], blkNumber, size); ackReceived = 0; receivedC[0]= 0; errors = 0; do { /* Send next packet */ if (size >= PACKET_1K_SIZE) { pktSize = PACKET_1K_SIZE; } else { pktSize = PACKET_SIZE; } Ymodem_SendPacket(packet_data, pktSize + PACKET_HEADER); /* Send CRC or Check Sum based on CRC16_F */ if (CRC16_F) { tempCRC = Cal_CRC16(&packet_data[3], pktSize); Send_Byte(tempCRC >> 8); Send_Byte(tempCRC & 0xFF); } else { tempCheckSum = CalChecksum (&packet_data[3], pktSize); Send_Byte(tempCheckSum); } /* Wait for Ack */ if (Receive_Byte(&receivedC[0], 1000000) == 0) { if (receivedC[0] == ACK) { ackReceived = 1; if (size > pktSize) { buf_ptr += pktSize; size -= pktSize; if (blkNumber == (APP_CONFIG_APPLICATION_SIZE/1024)) { return 0xFF; /* error */ } else { blkNumber++; } } else { buf_ptr += pktSize; size = 0; } } } else { errors++; } }while(!ackReceived && (errors < 0x0A)); /* Resend packet if NAK for a count of 10 else end of commuincation */ if (errors >= 0x0A) { return errors; } } ackReceived = 0; receivedC[0] = 0x00; receivedC[1] = 0x00; errors = 0; do { Send_Byte(EOT); /* Send (EOT); */ /* Wait for Ack */ //receivedC[0] = (uint16_t)(USART1->DR & (uint16_t)0x01FF); MK8000ÐÞ¸Ä receivedC[0]= (uint16_t)(uart_handle[1].base->RX_DATA&(uint16_t)0x01FF); if (receivedC[0] == ACK) { ackReceived = 1; } else { errors++; } /* Clear Overrun flag of the USART2 */ //__HAL_UART_CLEAR_OREFLAG(&huart1); MK8000ÐÞ¸Ä // USART_ClearFlag(USART1, UART_FLAG_ORE); }while (!ackReceived && (errors < 0x0A)); if (errors >= 0x0A) { return errors; } /* Last packet preparation */ ackReceived = 0; receivedC[0] = 0x00; receivedC[1] = 0x00; errors = 0; packet_data[0] = SOH; packet_data[1] = 0; packet_data [2] = 0xFF; for (i = PACKET_HEADER; i < (PACKET_SIZE + PACKET_HEADER); i++) { packet_data [i] = 0x00; } do { /* Send Packet */ Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER); /* Send CRC or Check Sum based on CRC16_F */ tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE); Send_Byte(tempCRC >> 8); Send_Byte(tempCRC & 0xFF); /* Wait for Ack and 'C' */ if (Receive_Byte(&receivedC[1], 1000000) == 0) { if (receivedC[1] == ACK) { /* Packet transfered correctly */ ackReceived = 1; } } else { errors++; } }while (!ackReceived && (errors < 0x0A)); /* Resend packet if NAK for a count of 10 else end of commuincation */ if (errors >= 0x0A) { return errors; } receivedC[0] = 0x00; do { Send_Byte(EOT); /* Send (EOT); */ /* Wait for Ack */ if ((Receive_Byte(&receivedC[0], 1000000) == 0) && receivedC[0] == ACK) { ackReceived = 1; } else { errors++; } /* Clear Overrun flag of the USART2 */ // __HAL_UART_CLEAR_OREFLAG(&huart1); MK8000ÐÞ¸Ä }while (!ackReceived && (errors < 0x0A)); if (errors >= 0x0A) { return errors; } return 0; /* file trasmitted successfully */ } /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/