XCOSnTh是一个开源的shell,由笔者设计
#include"XCOSnTh.h"
#include"YModem.h"
YModemRx YModemR;
/*
* XShell在YModem传输开始的时候会发送一个rb -E
* 此时需要Ymodem的接收方,回一个传输请求C(0x43)
* void (*RxInfo)(char *fileName,unsigned int fileSize)
* void (*RxSave)(unsigned char *rxBytes,int rxLength)
*/
unsigned char rxbuff[1024+5];
static int rxCount = 0;
static volatile unsigned int remainingLength;//剩余接收长度
static int calcrc(unsigned char *ptr, int count)
{
int crc, i;
crc = 0;
while (--count >= 0)
{
crc = crc ^ (int)*ptr++ << 8;
for (i = 0; i < 8; ++i)
{
if (crc & 0x8000)
{
crc = crc << 1 ^ 0x1021;//0x1021是CRC多项式
}
else
{
crc = crc << 1;
}
}
}
return (crc & 0xFFFF);
}
static int ATOI(char *string)
{
int i=0;
int rtn=0;
while(string[i]!=0)
{
rtn*=10;
rtn+=(string[i]-'0');
i++;
}
return rtn;
}
static int CMD_ymodemRx_exe(CmdObj obj, char* str, int len)
{
int rxByte;
int length=1;
int headerFlag=0;
unsigned char a;
int crc=1;
YModemRxObj ymodemObj=&YModemR;
ymodemObj->printf = obj->printf;
ymodemObj->fifo_pop=(int (*)())ShellRegisterFormFind( "Root", "CMD_FIFO_POP");//从注册表中并获取pop函数
ymodemObj->printf("YModemRxing");
//1、响应C
while (ymodemObj->fifo_pop() != 0x0D);
ymodemObj->printf("\x43");//ymodemObj->printf("C");//2种写法是一样的
//2、接收数据帧
while (1)
{
for (rxCount = 0, length=1; rxCount < length; )
{
rxByte = ymodemObj->fifo_pop();
if (rxByte >= 0)
{
rxbuff[rxCount++] = rxByte;
if (rxbuff[0] == 1)
{
if(headerFlag==0){headerFlag=1;}
length = 128 + 5;
}
else if (rxbuff[0] == 2)
{
if(headerFlag==0){headerFlag=1;}
length = 1024 + 5;
}
else if (rxbuff[0] == 4)
{//接收流程结束
if(ymodemObj->RxDatasEND)
{
ymodemObj->RxDatasEND();
}
break;
}
}
}
/
a=~rxbuff[2];
if ((rxbuff[0] == 1)&&(rxbuff[1]==a))
{
if(headerFlag==1)
{
headerFlag=2;
if(ymodemObj->RxInfo)
{//接收的文件名和大小
int i=3,j=0;
for(;;){if(rxbuff[i++]==0){break;}}
for(;;){if(rxbuff[i+j++]==0x20){break;}}
rxbuff[i+j-1]=0;
crc=calcrc(&rxbuff[3],128);//归零CRC //数据头不进行CRC校验
remainingLength=ATOI((char*)&rxbuff[i]);
ymodemObj->RxInfo((char*)&rxbuff[3],remainingLength);//首次剩余接收长度表示文件大小
}
}
else
{
if (ymodemObj->RxSave)
{
crc=calcrc(&rxbuff[3],128+2);//归零CRC
if(crc==0)
{
if(remainingLength>128)
{
ymodemObj->RxSave(&rxbuff[3],128);
remainingLength-=128;
}
else
{
ymodemObj->RxSave(&rxbuff[3],remainingLength);
}
}
}
}
}
else if ((rxbuff[0] == 2)&&(rxbuff[1]==a))
{
if(headerFlag==1)
{//接收的文件名和大小
int i=3,j=0;
for(;;){if(rxbuff[i++]==0){break;}}
for(;;){if(rxbuff[i+j++]==0x20){break;}}
rxbuff[i+j-1]=0;
ymodemObj->RxInfo((char*)&rxbuff[3],ATOI((char*)&rxbuff[i]));
}
else
{
if (ymodemObj->RxSave)
{
ymodemObj->RxSave(&rxbuff[3], 128);
}
}
}
else if (rxbuff[0] == 4)
{
break;
}
ymodemObj->printf("\x06");
}
//4、接收结束流程
ymodemObj->printf("\x15");
while (ymodemObj->fifo_pop() != 0x04);
ymodemObj->printf("\x06");
ymodemObj->printf("\x43");
while (ymodemObj->fifo_pop() != 0x01);
ymodemObj->printf("\x06");
ymodemObj->printf("\x4F");
while (ymodemObj->fifo_pop() != 0x18);
ymodemObj->printf("\r\n...");
if(ymodemObj->RxEND)
{
ymodemObj->RxEND(obj->printf);
}
ymodemObj->printf("\r\nEND");
return 0;
}
CmdDef(ymodemRx, "接收文件", CMD_ymodemRx_exe, "YModem接收文件");
#ifndef YModem_h
#define YModem_h
typedef struct
{
int (*fifo_pop)();
int(*printf)(const char* format, ...);
void (*RxInfo)(char* fileName, unsigned int fileSize);
void (*RxSave)(unsigned char* rxBytes, int rxLength);
void (*RxDatasEND)(void);//接收数据结束
void (*RxEND)(int(*printf)(const char* format, ...));//整个接收流程结束
}YModemRx, * YModemRxObj;
extern YModemRx YModemR;
#endif
标签:rxbuff,int,ymodemObj,pop,char,printf,XCOSnTh,YModem
From: https://blog.csdn.net/stars_A_B_C/article/details/145188691