📄 ymodem.c
字号:
/******************** (C) COPYRIGHT 2006 STMicroelectronics ********************
* File Name : ymodem.c
* Author : MCD Application Team
* Date First Issued : 10/25/2004
* Description : This file provides all the software functions related to
* the ymodem protocol.
********************************************************************************
* History:
* 02/01/2006 : IAP Version 2.0
* 11/24/2004 : IAP Version 1.0
********************************************************************************
THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH
CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A
RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH
SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN
IN CONNECTION WITH THEIR PRODUCTS.
********************************************************************************/
#include "common.h"
#define Flash_Offset 0x40002000 /* Flash user program offset */
char file_name[FILE_NAME_LENGTH];
u32 Flash_Destination = Flash_Offset;
u32 Ram_Source;
/*******************************************************************************
* Function Name : Receive_Byte
* Description : Receive byte from sender
* Input 1 : Character
* Input 2 : Timeout
* Return : 0 -- Byte received
* : -1 -- Timeout
*******************************************************************************/
static s32 Receive_Byte (char *c, u32 timeout)
{
while (timeout-- > 0)
{
if (SerialKeyPressed(c) == 1)
{
return 0;
}
}
return -1;
}
/*******************************************************************************
* Function Name : Send_Byte
* Description : Send a byte
* Input : Character
* Return : 0 -- Byte sent
*******************************************************************************/
static u32 Send_Byte (char c)
{
SerialPutChar(c);
return 0;
}
/*******************************************************************************
* Function Name : Receive_Packet
* Description : Receive a packet from sender
* Input 1 : Data
* Input 2 : Length
* Input 3 : Timeout
* Return : 0 -- normally return
* : -1 -- timeout or packet error
* : 1 -- abort by user
* : *length:
* : 0 -- end of transmission
* : -1 -- abort by sender
* : >0 -- packet length
*******************************************************************************/
static s32 Receive_Packet (char *data, s32 *length, u32 timeout)
{
int i, packet_size;
char c;
*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 CAN:
if ((Receive_Byte(&c, timeout) == 0) && (c == CAN))
{
*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;
}
}
if (data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff))
{
return -1;
}
*length = packet_size;
return 0;
}
/*******************************************************************************
* Function Name : Ymodem_Receive
* Description : Receive a file using the ymodem protocol
* Input : Address of the first byte
* Return : The size of the file
*******************************************************************************/
s32 Ymodem_Receive (char *buf)
{
char packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr;
s32 i, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
u32 Sector_Mask = 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)
{
case -1: /* Abort by sender */
Send_Byte(ACK);
return 0;
case 0: /* End of transmission */
Send_Byte(ACK);
file_done = 1;
break;
default: /* Normal packet */
if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
{
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);)
{
file_name[i++] = *file_ptr++;
}
file_name[i++] = '\0';
for (i = 0, file_ptr ++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH);)
{
file_size[i++] = *file_ptr++;
}
file_size[i++] = '\0';
Str2Int(file_size, &size);
/* Test the size of the image to be sent */
if (size > 0x3E000)
{
/* End session */
Send_Byte(CAN);
Send_Byte(CAN);
return -1;
}
/* Erase the needed sectors */
Sector_Mask = FLASH_SectorMask(size);
FLASH_SectorErase(Sector_Mask);
Send_Byte(ACK);
Send_Byte(CRC16);
}
else /* Filename packet is empty; end session */
{
Send_Byte(ACK);
file_done = 1;
session_done = 1;
break;
}
}
else /* Data packet */
{
memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
Ram_Source = 0x20002000;
for (j=0;(j<packet_length)&&(Flash_Destination < Flash_Offset + size);j+=4)
{
/* Program the data received into Flash */
FLASH_WordWrite(Flash_Destination,*(u32*)Ram_Source);
if(*(u32*)Flash_Destination != *(u32*)Ram_Source)
{
/* End session */
Send_Byte(CAN);
Send_Byte(CAN);
return -2;
}
Flash_Destination += 4;
Ram_Source+=4;
}
Send_Byte(ACK);
}
packets_received ++;
session_begin = 1;
}
}
break;
case 1:
Send_Byte(CAN);
Send_Byte(CAN);
return -3;
default:
if (session_begin > 0)
{
errors ++;
}
if (errors > MAX_ERRORS)
{
Send_Byte(CAN);
Send_Byte(CAN);
return 0;
}
Send_Byte(CRC16);
break;
}
if (file_done != 0)
{
break;
}
}
if (session_done != 0)
{
break;
}
}
return (s32)size;
}
/*******************(C)COPYRIGHT 2006 STMicroelectronics *****END OF FILE****/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -