Xmodem和Ymodem通信协议
Xmodem和Ymodem通信协议
协议格式
Figure 1. XMODEM-1k Blocks
SENDER RECEIVER
"s -k foo.bar"
"foo.bar open x.x minutes"
C
STX 01 FE Data[1024] CRC CRC
ACK
STX 02 FD Data[1024] CRC CRC
ACK
STX 03 FC Data[1000] CPMEOF[24] CRC CRC
ACK
EOT
ACK
Figure 2. Mixed 1024 and 128 byte Blocks
SENDER RECEIVER
"s -k foo.bar"
"foo.bar open x.x minutes"
C
STX 01 FE Data[1024] CRC CRC
ACK
STX 02 FD Data[1024] CRC CRC
ACK
SOH 03 FC Data[128] CRC CRC
ACK
SOH 04 FB Data[100] CPMEOF[28] CRC CRC
ACK
EOT
ACK
Figure 3. YMODEM Batch Transmission Session
SENDER RECEIVER
"sb foo.*<CR>"
"sending in batch mode etc."
C (command:rb)
SOH 00 FF foo.c NUL[123] CRC CRC
ACK
C
SOH 01 FE Data[128] CRC CRC
ACK
SOH 03 FC Data[128] CRC CRC
ACK
SOH 04 FB Data[100] CPMEOF[28] CRC CRC
ACK
EOT
NAK
EOT
ACK
C
SOH 00 FF NUL[128] CRC CRC
ACK
Figure 4. YMODEM Batch Transmission Session-1k Blocks
SENDER RECEIVER
"sb -k foo.*<CR>"
"sending in batch mode etc."
C (command:rb)
SOH 00 FF foo.c NUL[123] CRC CRC
ACK
C
STX 02 FD Data[1024] CRC CRC
ACK
SOH 03 FC Data[128] CRC CRC
ACK
SOH 04 FB Data[100] CPMEOF[28] CRC CRC
ACK
EOT
NAK
EOT
ACK
C
SOH 00 FF NUL[128] CRC CRC
ACK
Figure 3. YMODEM Batch Transmission Session
SENDER RECEIVER
"sb foo.*<CR>"
"sending in batch mode etc."
C (command:rb)
SOH 00 FF foo.c NUL[123] CRC CRC
ACK
C
SOH 01 FE Data[128] CRC CRC
ACK
SOH 03 FC Data[128] CRC CRC
ACK
SOH 04 FB Data[100] CPMEOF[28] CRC CRC
ACK
EOT
NAK
EOT
ACK
C
SOH 00 FF NUL[128] CRC CRC
ACK
Figure 4. YMODEM Batch Transmission Session-1k Blocks
SENDER RECEIVER
"sb -k foo.*<CR>"
"sending in batch mode etc."
C (command:rb)
SOH 00 FF foo.c NUL[123] CRC CRC
ACK
C
STX 02 FD Data[1024] CRC CRC
ACK
SOH 03 FC Data[128] CRC CRC
ACK
SOH 04 FB Data[100] CPMEOF[28] CRC CRC
ACK
EOT
NAK
EOT
ACK
C
SOH 00 FF NUL[128] CRC CRC
ACK
程序
#define SOH 0x01
#define STX 0x02
#define EOT 0x04
#define ACK 0x06
#define NAK 0x15
#define CAN 0x18
#define ESC 0x1b
#define PACKET_128 128
#define PACKET_1K 1024
char putPacket(void)
{
int c, i,j;
int crc;
crc = 0;
if (xip.packet_size== PACKET_128)
Uart_SendByte_bin(SOH);
else
Uart_SendByte_bin(STX);
Uart_SendByte_bin(xip.packet_sno);
Uart_SendByte_bin(255-xip.packet_sno);
if (xip.crc_flags & USECRC)
{
for(i=0;i<xip.packet_size;i++)
{
Uart_SendByte_bin(xip.file_addr[xip.database]);
crc = crc ^ (int) xip.file_addr[xip.database]<< 8;
for (j = 0; j < 8; j++)
if (crc & 0x8000)
crc = crc << 1 ^ 0x1021;
else
crc = crc << 1;
xip.database++;
}
Uart_SendByte_bin((crc >> 8) & 0xff);
Uart_SendByte_bin(crc & 0xff);
}
else {
for(i=0;i<xip.packet_size;i++)
{
Uart_SendByte_bin(xip.file_addr[xip.database]);
crc
=(crc+(int)xip.file_addr[xip.database])&0xff;
xip.database++;
}
Uart_SendByte_bin(crc&0x00ff);
}
c = Uart_Getchb(2000000); /* Wait for ack */
return(c);
}
int X_Y_modem_send(unsigned char *file,char *name,int size)
{
char c;
int done,i,j;
char buff[128];
char buffa[10];
/* Startup synchronization... */
/* Wait to receive a NAK or 'C' from receiver. */
if(communicate_status)
{
if(com_crc_flig)
xip.crc_flags = USECRC;
else xip.crc_flags =NOTCRC;
xip.packet_sno=0;
goto flep;
}
xip.packet_sno=0;
file_put:
i=0;
done = 0;
while(!done)
{
c = Uart_Getchb(300);
switch(c)
{
case NAK:
done = 1;
xip.crc_flags =NOTCRC;
break;
case 'C':
xip.crc_flags = USECRC;
done = 1;
break;
case 'q':
return(0);
default: i++;if(i>1000)return (0);break;
}
}
flep:
if(xip.packet_sno==0)
{
i=0;
while(name[i]!='\0')
{
buff[i]=name[i];
i++;
if(i>128)
return(0);
}
buff[i]='\0';
sprintf(buffa,"%d",size);
i++;
j=0;
while(buffa[j]!='\0')
{
buff[i]=buffa[j];
i++;
j++;
if(i>128)
return(0);
}
buff[i]='\0';
i++;
while(i<PACKET_128)
{
buff[i]='\0';
i++;
}
xip.database=0;
xip.file_addr=(unsigned char *)buff;
xip.packet_size=PACKET_128;
c = putPacket();
switch(c)
{
case ACK: xip.packet_sno++;goto file_put;
case NAK: return(0);break;
case ESC: return(0);
case CAN: return(0);
case EOT: return(0);
default: Uart_SendByte_bin(CAN);Uart_Getchb(1000); return(0);
}
}
xip.database_bak=xip.database=0;
xip.file_size=size;
xip.file_addr=file;
if(xip.file_size>=PACKET_1K)
xip.packet_size=PACKET_1K;
else
xip.packet_size=PACKET_128;
while(1) {
c = putPacket();
switch(c)
{
case ACK:
xip.packet_sno++;
xip.database_bak=xip.database;
xip.file_size-=xip.packet_size;
if(xip.file_size>=PACKET_1K)
xip.packet_size=PACKET_1K;
else
xip.packet_size=PACKET_128;
break;
case NAK:
xip.database= xip.database_bak;
break;
case ESC: return(0);
case CAN: return(0);
case EOT: return(0);
default: Uart_SendByte_bin(CAN);Uart_Getchb(10000); return(0);
}
if (xip.file_size <= 0) {
c=0;
i=0;
do{
Uart_SendByte_bin(EOT);
c=Uart_Getchb(100000); /* Flush the NCK */
if(c==ACK)
break;
i++;
}
while(i<3);
c = Uart_Getchb(300000);
if((c=='c')|(c=='C'))
{
for(i=0;i<128;i++)
buff[i]=0;
xip.packet_sno=0;
xip.database=0;
xip.file_addr=(unsigned char *)buff;
xip.packet_size=PACKET_128;
c = putPacket();
if(c!=ACK)
return(0);
}
break;
}
}
return(0);
}