一,Ymodem数据帧
1.数据帧格式
帧头 | 帧序号 | 帧序号反码 | 数据包 | CRC16校验 | |
STX/SOH | PN | XPN | Data[1024]/Data[128] | ||
字节数 | 1 | 1 | 1 | 1024/128 | 2 |
2.帧头区别
帧头为SOH(0x01)时,数据包为128个字节
帧头为STX时(0x02),数据包为1024个字节
3.帧序号
范围为0-255,大于255时是归零重新计算
4.开始帧数据结构
SOH+0x00+0xff+文件名+0x00+文件大小+0x00+0x00……(填充)+CRC16
5.结束帧数据结构
SOH+0x00+0xff+ NUL[128] +CRC16
结束帧同样以SOH开头,表示后面跟着128字节大小的数据;128字节的数据部分不存放任何信息,即NUL[128]全部用00填充。
6.数据包注意
当最后一帧数据包里的数据不足1024位时,会用0x1A去填充。
7.数据中特定符号的数值及含义
符号 | 数值 | 含义 |
SOH | 0x01 | (帧头)数据包长度为128 |
STX | 0x02 | (帧头)数据包长度为1024 |
EOT | 0x04 | 结束传输 |
ACK | 0x06 | 应答 |
NACK | 0x15 | 不应答 |
C | 0x43 | 请求数据包 |
CA | 0x18 | 中止 |
8.传输过程
开始时,上位机读到C指令后,第一帧帧头为SOH(0x01),帧序号为0x00,传输文件名和文件大小。大量0x00为填充数据包到128个字节的,后面两位为CRC校验。
正常传输数据包,可以看到第二帧数据,帧头为STX(0x02),帧序号0x01,然后传输1024位的数据包,读到(0x06)为应答成功,继续传输。
传输结束,先应答ACK(0x06)传输结束EOT(0x04)未应答NACK(0x15)再应答ACK(0x06),开始结束帧传输,帧头SOH(0x01),帧序号0x00,后面全是0x00
二,应用
在升级时,经常会遇到升级一半卡住或者软件闪退的问题,这样就会导致flash区刷一半然后执行,mcu直接变砖的情况,巧妙运用开始帧的数据,可以避免很多问题。
1.从开始帧可以看到文件名和文件大小,从我多次观察看,bin文件大小就是程序flash大小,我们直接获取文件大小,可以直接判断flash是否全部刷新成功。
// 检查flash最后几位
static u8 CheckFlash(Iap_INFO* IAP_info) {
u16 key[3]={0};
u32 ApplicationAddress_END;
//ApplicationAddress为主程序区起始0x8003000
ApplicationAddress_END = (IAP_info->total_size + ApplicationAddress );
printf("size:%d",IAP_info->total_size);
STMFLASH_Read(ApplicationAddress_END,key,3);
printf("ApplicationAddress_END:");
printf(key);
if(key[0] == 0xFFFF && key[1] == 0xFFFF && key[2] == 0xFFFF)
{
return 1;
}
return 0;
}
2.从我这个起始帧可以看到,文件大小是40496,我用keil5查找40496+0x8003000(0x9E30+0x8003000=0x800CE30)地址是可以刚好看到的
3.这样便能更好的解决一些问题了,可以做一些错误处理。