📄 ymodem.c
字号:
#include "Ymodem.h"
#include "UART.h"
#include <string.h>
/*******************************************************************************
* Function Name : Receive_Byte
* Description : Receive byte from sender
* Input 1 : Character
* Input 2 : Timeout
* Return : >=0 -- Byte received
* : -1 -- Timeout
*******************************************************************************/
static int Receive_Byte(void)
{
unsigned timeout = NAK_TIMEOUT;
do
if(UART_Query())
return UART_Getch();
while(--timeout);
return -1;
}
/*******************************************************************************
* Function Name : Send_Byte
* Description : Send a byte
* Input : Character
* Return : 0 -- Byte sent
*******************************************************************************/
static void Send_Byte(int c)
{
UART_Putch(c);
}
/*******************************************************************************
* 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 int Receive_Packet(unsigned char *data, int *length)
{
int c, i, packet_size;
*length = 0;
c = Receive_Byte();
if(c < 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() == 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++)
{
c = Receive_Byte();
if(c < 0)
return -1;
data[i] = c;
}
if(data[PACKET_SEQNO_INDEX] != (data[PACKET_SEQNO_COMP_INDEX] ^ 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
*******************************************************************************/
int Ymodem_Receive(void *buf, char *filename)
{
int size, errors = 0, session_begin = 0;
while(1)
{
int file_done = 0, packets_received = 0;
unsigned char *buf_ptr = buf;
do {
unsigned char packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];
int packet_length;
switch(Receive_Packet(packet_data, &packet_length))
{
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] != (packets_received & 0xff))
Send_Byte(NAK);
else
{
Send_Byte(ACK);
if(!packets_received) // filename packet
{
if(packet_data[PACKET_HEADER]) // filename packet has valid data
{
unsigned char *file_ptr = packet_data + PACKET_HEADER;
if(filename)
{
do
*filename++ = *file_ptr;
while(*file_ptr++);
}
else
while(*file_ptr++);
size = 0;
while(*file_ptr)
size = size * 10 + (*file_ptr++ - '0');
Send_Byte(CRC16);
}
else // filename packet is empty; end session
return size;
}
else // data packet
{
memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
buf_ptr += packet_length;
}
packets_received++;
session_begin = 1;
}
}
break;
case 1:
Send_Byte(CAN);
Send_Byte(CAN);
return -1;
default:
if(session_begin)
errors++;
if(errors > MAX_ERRORS)
{
Send_Byte(CAN);
Send_Byte(CAN);
return 0;
}
Send_Byte(CRC16);
}
} while(!file_done);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -