通过Ymodem 协议升级代码
Ymodem 协议详解
参考链接;
Ymodem协议解析-CSDN博客
Ymodem协议发送数据前需要接收端发起通信,发送端收到接收端发送的数据后才会开始传输数据,也就是握手信号。主要通信的时序参考文件传输过程,但需要注意的是,在接受过程中,通过同一个串口有打印数据的情况下,会导致发送端发送中断或者异常。在测试中,发送端发送的帧头一直是soh,没有出现过stx,只需要按照协议解析数据就可以了。
Ymodem握手信号
握手信号由接收方发起,在发送方开始传输文件前,接收方需发送YMODEM_C (字符C,ASII码为0x43)命令,发送方收到后,开始传输起始帧。
文件传输过程
文件的传输过程,以具体的例子说明。把foo.c,大小为4196Byte(16进制为0x1064)的文件作为传输的对象,则它的传输过程如下:
发送端----------------------------------------------------------------接收端
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< C
SOH 00 FF “foo.c” "1064’’ NUL[118] CRC CRC >>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< C
STX 01 FE data[1024] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
STX 02 FD data[1024] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
STX 03 FC data[1024] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
STX 04 FB data[1024] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
SOH 05 FA data[100] 1A[28] CRC CRC>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
EOT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< NAK
EOT>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< C
SOH 00 FF NUL[128] CRC CRC >>>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
原文链接:https://blog.csdn.net/huangdenan/article/details/103611081
数据解析:
void YModem_Parse(uint8_t data) {
static uint8_t packetBuffer[1024]; // 存放接收到的数据块
static uint16_t packetIndex = 0; // 当前数据块接收的位置
switch (ymodemState) {
case YMODEM_IDLE:
if (data == SOH || data == STX) {
// 检测到 SOH 或 STX,开始接收数据块
packetIndex = 0;
packetBuffer[packetIndex++] = data;
ymodemState = YMODEM_RECEIVING;
}
if (data == EOT) {
// 检测到 EOT,传输结束
ymodemState = YMODEM_IDLE;
// 发送 ACK 响应确认传输结束
Set_state(TO_RECEIVE_EOT2);
send_command(ACK);
send_command(CCC);
}
if (data == CAN) {
// 检测到 EOT,传输结束
ymodemState = YMODEM_IDLE;
// 发送 ACK 响应确认传输结束
Set_state(TO_stday);
}
break;
case YMODEM_RECEIVING:
packetBuffer[packetIndex++] = data;
if ((packetBuffer[0] == SOH && packetIndex == 133) || (packetBuffer[0] == STX && packetIndex == 1029)) {
YModem_ProcessDataBlock(packetBuffer, packetIndex);
LOGD("blockNumber %d",packetBuffer[1]);
ymodemState = YMODEM_IDLE;
}
break;
default:
break;
}
}
代码升级
/**
* @bieaf YModem升级
*
* @param none
* @return none
*/
void ymodem_fun(uint8_t* data,int len)
{
static unsigned char data_state = 0;
static unsigned int app2_size = 0;
if(Check_CRC(data, len)==1)///< 通过CRC16校验
{
if(data[1] == 0x00 &&data_state == 0)
Set_state(TO_START);
if(Get_state()==TO_RECEIVE_EOT2)
Set_state(TO_RECEIVE_END);
if((Get_state()==TO_START)&&(data[1] == 0x00)&&(data[2] == (unsigned char)(~data[1])))///< 开始
{
LOGD("> Receive start...\r\n");
data_state = 0x01;
Set_state(TO_RECEIVE_DATA);
/* 擦除App2 */
// Erase_page(Application_2_Addr, 30);
}
else if((Get_state()==TO_RECEIVE_END)&&(data[1] == 0x00)&&(data[2] == (unsigned char)(~data[1])))///< 结束
{
LOGD("> Receive end...\r\n");
Set_Update_Down();
Set_state(TO_stday);
send_command(ACK);
if(data[1] == 0x00)
send_command(CCC);
delay_ms(1000);
SoftReset();
}
else if((Get_state()==TO_RECEIVE_DATA)&&(data[1] == data_state)&&(data[2] == (unsigned char)(~data[1])))///< 接收数据
{
LOGD("> Receive data bag:%d byte\r\n",data_state * 128);
/* 烧录程序 */
ONCHIP_FLASH_Write_32Bit((Application_2_Addr + (data_state-1) * 128), (uint32_t *)(&data[3]), 32);
data_state++;
}
send_command(ACK);
if(data[1] == 0x00)
send_command(CCC);
}
else
{
LOGD("> Notpass crc\r\n");
}
}
源文件下载链接:https://download.csdn.net/download/qq_45234526/90294512
结语
上面代码内容均以测试实现,可放心下载。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_45234526/article/details/145283100
|