为了解决模块不拆机,通过串口对STM32进行程序升级,采用Y-modem 协议进行升级。STM32内存划分为IAP段和APP段。IAP段存储使用Y-Modem协议的下位机程序,APP则为正常使用的软件。
文件传输过程
1、文件传输过程的开启:
(1)开启是由下位机开启传输,它发一个大写字母"C(0x43)"开启传输。然后进入等待(SOH)状态,如果没有回应,就会超时退出
(2)上位机开始时处于等待过程中,等待"C(0x43)"。收到"C(0x43)"以后,发送(SOH)数据包开始信号,发送序号(00),补码(FF),“文件名”,“0x00”“文件大小”“除去序号外,补满128字节(用0x00 补充)”,CRC校验两个字节。进入等待(ACK(0x06))状态。
(3)下位机收到以后,CRC校验满足,则发送ACK(0x06)。上位机接收到ACK(0x06),又进入等待“文件传输开启”信号,即重新进入等待"C(0x43)"的状态。
(4)前面下位机只是收到了一个文件名,现在正式开启文件传输,Ymodem支持128字节和1024字节一个数据包。128字节以(SOH)开始,1024字节以(STX)开始。
(5)下位机又发出一个"C(0x43)"信号,开始准备接收文件。进入等待"SOH"或者"STK"状态。
(6)上位机接收到"C(0x43)"以后,发送数据包,(STX)(01序号)(FE补码)(1024位数据)(CRC校验),等待下位机"ACK(0x06)",序号依次递增,不足1024位数据用0x00补充。
(7)文件发送完以后,上位机发EOT(0x04),第一次下位机以NAK(0x15)应答,进行二次确认。上位机收到NAK(0x15)后,重发EOT(0x04),下位机第二次收到结束符,就以ACK(0x06)应答。最后下位机再发送一个"C(0x43)",接着上位机会发出一个“全0数据包”(以SOH 开始的数据包头),下位机"ACK(0x06)"以后,本次通信正式结束。
注:只有数据部分参与CRC校验,数据包头不参与CRC校验。
2、数据包格式
2.1文件名数据包
数据包头 |
数据(SOH 128 Byte) |
CRC校验 |
|||||
|
序号 |
补码 |
文件名 |
|
文件大小 |
用0x00 补齐 |
2Byte |
SOH |
|
|
|
00 |
|
高位在前 |
文件名 例:DM105_IAP.bin 文件大小 12456
除去用0x00补齐的数据,数据包头、校验码,数据包为
44 4D 31 30 35 5F 49 41 50 2E 62 69 6E 00 31 32 34 35 36
2.2 传输数据包
数据包头 |
数据(STX1024 Byte) |
CRC校验 |
||
|
序号 |
补码 |
从 bin 文件中读取的数据(读取的数据不满足1024 Byte 用0x00补齐) |
2Byte |
STX |
|
|
高位在前 |
2.3 文件传输结束全0数据包
数据包头 |
数据(SOH 128 Byte) |
CRC校验 |
||
|
序号 |
补码 |
128Byte都是00 |
2Byte |
SOH |
00 |
FF |
高位在前 |
2.4 Ymodem协议中宏定义
SOH (0x01) //128字节数据包开始
STX (0x02) //1024字节的数据包开始
EOT (0x04) //结束传输
ACK (0x06) //回应
NAK (0x15) //没回应
C (0x43) //'C' == 0x4
注:下位机回复NACK的时候,上位机需要重新发送一次数据包
以下提供CRC校验的C语言算法
/*******************************************************************************
* @函数名称 UpdateCRC16
* @函数说明 更新输入数据的CRC校验
* @输入参数 crcIn
byte
* @输出参数 无
* @返回参数 CRC校验值
*******************************************************************************/
uint16_t UpdateCRC16(uint16_t crcIn, uint8_t byte)
{
uint32_t crc = crcIn;
uint32_t in = byte|0x100;
do
{
crc <<= 1;
in <<= 1;
if (in&0x100)
++crc;
if (crc&0x10000)
crc ^= 0x1021;
}
while (!(in&0x10000));
return crc&0xffffu;
}
/*******************************************************************************
* @函数名称 UpdateCRC16
* @函数说明 更新输入数据的CRC校验
* @输入参数 data :数据
size :长度
* @输出参数 无
* @返回参数 CRC校验值
*******************************************************************************/
uint16_t Cal_CRC16(const uint8_t* data, uint32_t size)
{
uint32_t crc = 0;
const uint8_t* dataEnd = data+size;
while (data
以下是我VS2015中C#的CRC校验,根据上面修改的
public UInt16 UpdateCRC16(UInt16 crcIn, byte data)
{
UInt32 crc = crcIn;
UInt32 indata = (UInt32)(data | 0x100);
do
{
crc <<= 1;
indata <<= 1;
if ((indata & 0x100) == 0x100)
++crc;
if ((crc & 0x10000) == 0x10000)
crc ^= 0x1021;
}
while ((indata & 0x10000) == 0);
UInt16 redata = (UInt16)(crc & 0xffff);
return redata;
}
public UInt16 Cal_CRC16(byte[] data, UInt32 size)
{
UInt16 crc = 0;
for(UInt32 i =0; i< size; i++)
{
crc = UpdateCRC16(crc, data[i]);
}
crc = UpdateCRC16(crc,0);
crc = UpdateCRC16(crc,0);
UInt16 redata = (UInt16)(crc & 0xffff);
return redata;
}
以上所有为本人自己进行数据跟踪得到,如果有错误,欢迎指出。