串行通信的文件传输协议主要有:Xmodem、Ymodem、Zmodem和KERMIT等。
Xmodem协议一般支持128字节数据包,并且一般支持校验和、CRC两种校验方式,在出现数据包错误的情况下支持多次重传(一般为10次)。Xmodem协议传输有接收程序和发送程序完成,先由接收程序发送协商字符,协商校验方式,协商通过之后发送程序就开始发送数据包,接收程序接收到完整的一个数据包之后按照协商的方式对数据包进行校验。校验通过之后发送确认字符,然后发送程序继续发送下一包;如果校验失败,则发送否认字符,发送程序重传此数据包。
定义:
SOH 01H(modem数据头)
EOT 04H(发送结束)
ACK 06H(应答)
NAK 15H(非应答)
CAN 18H(取消发送)
Xmodem数据包,包含一个标题开始字符,一个单字节包序号,一个包序号的补码,128字节数据和一个双字节的CRC校验。
1.校验和信息包:
校验和方式传输流程:
接收方要求发送方以校验和方式发送时以NAK来请求,发送方将对此做出应答。如下图:
2.CRC校验信息包
计算16位CRC校验的除数多项式为X ^ 16 + X ^ 12 + X ^ 5 + 1,信息报中的128数据字节将参加CRC校验的计算,在发送端CRC16的高字节在前,低字节在后。
传输流程:接收方要求发送方以CRC校验方式发送时以‘C’来请求,发送方将对此作出应答。
信息报中如果生于的数据不足128字节,不足的部分将以0x1A填充。
int32_t xmodem_download(uint32_t start_addr, uint32_t max_size, int *err)
{
xmodem_init();
xmodem_start();
while (1)
{
int ret = xmodem_getPacket();//从串口得到数据,并校验
switch (ret)
{
case XMODEM_DATA_OK:
sflash_write_data(start_addr, xbuf + 3, xmodem.packet_size);
start_addr += xmodem.packet_size;
xmodem.rcv_size += xmodem.packet_size;
xmodem.rcv_packet++;
if (xmodem.rcv_size > max_size)
{
xmodem_stop();
*err = -2;
goto exit;
}
xmodem_ack();
break;
case XMODEM_PKT_NUM_ERR:
xmodem_stop();
*err = -3;
goto exit;
case XMODEM_CHECK_ERR:
xmodem_nack();
break;
case XMODEM_DATA_REPEAT:
xmodem_ack();
break;
case XMODEM_EOT:
xmodem_ack();
PRINTF(("\nXMODEM info pkt: %d, size: %ld, chk: %s\n",
xmodem.packet_size,
xmodem.rcv_size,
xmodem.chk_type == XMODEM_CHECKSUM ? "CHECKSUM" : "CRC16"));
*err = 0;
goto exit;
case XMODEM_CAN:
xmodem_ack();
*err = -4;
goto exit;
case XMODEM_SOH_ERR:
xmodem_stop();
*err = -5;
goto exit;
default: break;
}
}
exit:
return xmodem.rcv_size;
}