對 YModem 的接觸,只是在無網絡的情況下,使用SecureCRT軟件輸入loady命令進行串口傳輸,燒寫內核和文件系統。
參看:Hi3516A開發-- 板卡串口燒寫
但你要問我 YModem 是個什么東西,我還真說不上來。
接下來,就開始對YModem的一步步剖析詳解??!
一、YModem簡介
參看:XMODEM/YMODEM PROTOCOL REFERENCE
。。。。 網上查了老半天,怎么感覺沒有一篇講的特別清楚的。
1、YMODEM最低要求
聲稱支持YMODEM的所有程序必須滿足以下最低要求
1) 發送程序應在塊0中發送路徑名(文件名)。
2) 路徑名應為空終止的ASCII字符串,如下所述。
對于那些懶得閱讀整篇文檔的人:
3) 除非特別要求,否則僅發送文件名部分。
4) 沒有發送驅動器號。
5) 不區分大小寫的系統,文件名中的字母只能以小寫形式發送路徑名。
6) 接收程序應使用此路徑名作為接收文件名稱,除非明確覆蓋。
7) 當接收程序成功接收到此塊時打開輸出文件,它應該用ACK確認該塊字符,然后繼續正常的XMODEM文件傳輸以接收器發送的“C”或NAK開頭。
8) 發送程序應使用CRC-16響應“C”路徑名nak,否則使用8位校驗和。
9) 接收程序必須接受128和1024字節的任何混合。它接收的每個文件中的塊。發送節目可能會任意切換1024和128字節塊。
10) 發送程序不得更改未確認的長度塊。
11) 在每個文件的末尾,發送程序應發送EOT最多十個直到收到ACK字符為止。 (這是其中的一部分XMODEM規范。)
12) 傳輸會話的結束應由null(空)表示pathname,此路徑名塊應與其他路徑名相同路徑名塊。
1、簡介
參看:YModem協議簡介
最常用的幾種通信傳輸協議有:XModem、YModem、ZModem等。
XModem是最早的協議之一,幾乎所有的通訊程序支持的文件傳輸協議,它傳輸128字節信息塊。
YModem協議是XModem的改進協議,它最用于調制解調器之間的文件傳輸的協議,具有快速,穩定傳輸的優點。它的傳輸速度比XModem快,這是由于它可以一次傳輸1024字節的信息塊,同時它還支持傳輸多個文件,也就是常說的批文件傳輸。
ZModem速度快于XModem和YModem,而且可以更好地斷開后恢復傳輸。
如今,XModem基本已經被淘汰,最常用的就是YModem與ZModem。為了后面YModem升級程序實現做鋪墊,下面就簡單介紹下YModem協議。
YModem分成YModem-1K與YModem-g。
YModem-1K用1024字節信息塊傳輸取代標準的128字節傳輸,數據的發送回使用CRC校驗,保證數據傳輸的正確性。它每傳輸一個信息塊數據時,就會等待接收端回應ACK信號,接收到回應后,才會繼續傳輸下一個信息塊,保證數據已經全部接收。
YModem-g傳輸形式與YModem-1K差不多,但是它去掉了數據的CRC校驗碼,同時在發送完一個數據塊信息后,它不會等待接收端的ACK信號,而直接傳輸下一個數據塊。正是它沒有涉及錯誤校驗,才使得它的傳輸速度比YModem-1K來得塊。
一般都會選擇YModem-1K傳輸,平時所說的YModem也是指的是YModem-1K。
二、YModem傳輸協議
1、起始幀的數據格式
YModem的起始幀并不直接傳輸文件的數據,而是將文件名與文件的大小放在數據幀中傳輸,它的幀長=3字節數據首部+128字節數據+2字節CRC16校驗碼=33字節。它的數據結構如下:
SOH 00 FF filename[ ] filezise[ ] NUL[ ] CRCH CRCL
其中SOH=0x01,表示這個數據幀中包含著128字節的數據部分;在SOH后面的00 FF,00表示數據幀序號,因為是起始幀,所以它的幀序為00,至于FF,它是幀序的取反,YModem特地這么做是為了給數據是否正確提供一種判斷依據,通過判斷這兩個字節是否為取反關系,就可以知道數據是否傳輸出錯;filename[ ]就是文件名,如文件名foo.c,它在數據幀中存放格式為:66 6F 6F 2E 63 00,一定要在文件名最后跟上一個00,表示文件名結束;filesize[ ]就是文件大小,如上面的foo.c的大小為1KByte,即1024Byte,需要先將它轉化成16進制,即0x400,所以它在數據幀的存放格式為:34 30 30 00,即“400”,同樣的文件大小最后需要跟上00,表示結束;NUL[ ]表示剩下的字節都用00填充,數據部分大小為128字節,除去文件名與文件大小占用的空間外,剩余的字節全部用00填充;CRCH CRCL分別表示16位CRC校驗碼的高8位與低8位。
擴展,什么是補碼?
參看:C語言再學習 – 負數
2、數據幀的數據格式
YModem的數據幀中會預留1024字節空間用來傳輸文件數據,它跟起始幀接收差不多,如下:
STX 01 FE data[1024] CRCH CRCL
其中STX=0x02,表示這幀數據幀后面包含著1024字節的數據部分;STX后面的01 FE,01表示第一幀數據幀,FE則是它的取反,當然如果是第二幀數據的話就是:01 FD;data[1024]表示存放著1024字節的文件數據;CRCH與CRCL是CRC16檢驗碼的高8位與低8位。
如果文件數據的最后剩余的數據在128~1024之前,則還是使用STX的1024字節傳輸,但是剩余空間全部用0x1A填充,如下結構:
STX [num] [~num] data[ ] 1A …1A CRCH CRCL
有一種特殊的情況:如果文件大小小于等于128字節或者文件數據最后剩余的數據小于128字節,則YModem會選擇SOH數據幀用128字節來傳輸數據,如果數據不滿128字節,剩余的數據用0x1A填充這是數據正的結構就變成了:
文件大小小于128字節:
SOH 01 FE data[ ] 1A …1A CRCH CRCL
文件最后剩余數據小于128字節:
SOH [num] [~~num] data[ ] 1A…1A CRCH CRCL
3、結束幀數據結構
YModem的結束幀數據也采用SOH的128字節數據幀,它的結構如下:
SOH 00 FF NUL[128] CRCH CRCL
結束幀同樣以SOH開頭,表示后面跟著128字節大小的數據;結束幀的幀序也認為是00 FF;結束幀的128字節的數據部分不存放任何信息,即NUL[128]全部用00填充。
4、文件傳輸過程
YMODEM批量傳輸會話(1個文件)
YMODEM批量傳輸會話(2個文件)
YMODEM批量傳輸Session-1k塊
YMODEM-g傳輸會話(擴展)
上面傳輸過程中存在許多通信信號,它們的數值與意義如下表所示:
CRC的計算:
參看:STM32開發 – CRC校驗碼
手冊CRC代碼:
/* update CRC */
unsigned short
updcrc(c, crc)
register c;
register unsigned crc;
{
register count;
for (count=8; --count>=0;) {
if (crc & 0x8000) {
crc <<= 1;
crc += (((c<<=1) & 0400) != 0);
crc ^= 0x1021;
}
else {
crc <<= 1;
crc += (((c<<=1) & 0400) != 0);
}
}
return crc;
}
傳輸過程文字描述
接收方發送信號C啟動傳輸會話,然后進入等待(SOH)狀態,如果沒有回應,就會超時退出。
發送方開始時處于等待C過程中。收到C以后,發送攜帶文件名和文件長度的起始幀(SOH)數據包開始信號。進入等待(ACK)狀態
接收方收到SOH起始幀以后,CRC校驗滿足,則發送ACK。發送方接收到ACK,又進入等待“文件傳輸開啟”信號,即重新進入等待“C”的狀態
接收方發送C,表示可以開始數據的傳輸
于是發送方發送數據幀、接收方接收到后回復ACK,如此循環進行數據接收(過程中雙方因為任何異常,如人工終端、通訊故障等都可能造成傳輸中斷).
文件傳輸完畢后,發送方發送EOT信號,接收方收到后,回應NAK
發送方再次發送EOT,接收方回應ACK。
接收方發送C,準備再次文件傳輸
如果是單次文件傳輸,發送方發送傳輸結束幀,接收方回應ACK后,整個傳輸會話結束
接收方和發送方應實現的處理策略
參看:通信協議之YMODEM
共通策略
出錯后需要重復嘗試10次
協議流程應由接收方驅動
使用CAN或ASCII的^X字符來取消傳輸
接收方策略
接收方應該有10s超時機制
只要接收到數據開始,接收方使用1s超時機制來接收每個數據,直到該數據包接收完成。
同步:1.接收到想要的那個數據包并且沒有任何錯誤后才算接收成功,并返回ACK; 2.能夠處理兩條重復的數據包(ACK丟失引起的問題); 3.因為一些特殊原因造成同步出錯應終止傳輸,發送CAN
發送方策略
等待傳輸開始的這段時間,發送方應該設置一個比較長的超時時間,也可以不設置超時時間
文件傳輸結束應該發送EOT到接收方,直到收到一條ACK響應,否則重復發送
三、C語言實現YModem傳輸協議
上面簡單的介紹了一下YModem的傳輸協議。那么問題來了,我想在STM32上用實現,代碼該怎么寫呢?
參看:ST官方代碼——YModem協議部分c代碼分析
參看:STM32F103代碼遠程升級(三)基于YModem協議串口升級程序的實現
下載工程:相關參考工程
網上相關的工程有很多的,接下來就逐一分析一下相關代碼。
1、接收數據
可恥的,直接復制了。。。該博主注釋的相當不錯。我沒什么可說的了。。。
/*******************************************************************************
* @函數名稱 Receive_Packet
* @函數說明 從發送端接收一個數據包
* @輸入參數 data :數據指針
length:長度
timeout :超時時間
* @輸出參數 無
* @返回參數 接收的結果
0: 正常返回
-1: 超時或者數據包錯誤
1: 用戶取消
*******************************************************************************/
static int32_t Receive_Packet (uint8_t *data, int32_t *length, uint32_t timeout)
{
uint16_t i, packet_size;
uint8_t c;
*length = 0;
if (Receive_Byte(&c, timeout) != 0)
{
return -1;//超時返回-1
}
switch (c) //c表示接收到的數據的第一個字節
{
case SOH: //數據包開始
packet_size = PACKET_SIZE;
break;
case STX: //正文開始
packet_size = PACKET_1K_SIZE;
break;
case EOT: //數據包結束
return 0;
case CA: //發送方中止傳輸
if ((Receive_Byte(&c, timeout) == 0) && (c == CA))
{
*length = -1;
return 0;
}
else
{
return -1; //中止傳輸返回-1
}
case ABORT1: //A
case ABORT2: //a
return 1;
default:
return -1;
}
*data = c;
for (i = 1; i < (packet_size + PACKET_OVERHEAD); i ++) //獲取剩下的數據(以字節為單位)
{
if (Receive_Byte(data + i, timeout) != 0)
{
return -1; //接收數據超時
}
}
if (data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff))
{
return -1;
}
*length = packet_size;
return 0;
}
/*******************************************************************************
* @函數名稱 Ymodem_Receive
* @函數說明 通過 ymodem協議接收一個文件
* @輸入參數 buf: 首地址指針
* @輸出參數 無
* @返回參數 文件長度
*******************************************************************************/
int32_t Ymodem_Receive (uint8_t *buf)
{
uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr;
int32_t i, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
//初始化Flash地址變量
FlashDestination = ApplicationAddress;
for (session_done = 0, errors = 0, session_begin = 0; ;)
{
for (packets_received = 0, file_done = 0, buf_ptr = buf; ;)
{
switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT))
{
case 0:
errors = 0;
switch (packet_length)
{
//發送端終止
case - 1:
Send_Byte(ACK);
return 0;
//結束傳輸
case 0: /* 數據包中序號和補碼不匹配,終止數據發送*/
Send_Byte(ACK);
file_done = 1;
break;
//正常的數據包
default:
if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
{
Send_Byte(NAK); //發送應答NAK,接收失敗要求重發
}
else
{
if (packets_received == 0) //第一包,包含文件名,文件大小
{
//文件名數據包
if (packet_data[PACKET_HEADER] != 0) //去除3個字節的首部,讀取128B的數據包
{
//文件名數據包有效數據區域
//取出文件名--32B用于存儲
上一篇:STM32開發 -- Ublox GPS之設置PUBX
下一篇:STM32開發 -- 看門狗詳解
推薦閱讀
史海拾趣
在21世紀初,隨著數字技術的興起,Horizon Electronics Enterprises Group(以下簡稱“Horizon”)由一群對電子技術充滿熱情的工程師創立。公司初期專注于研發高性能的半導體芯片,以解決當時市場上對高速、低功耗芯片的迫切需求。通過不懈努力,Horizon成功研發出了一款具有突破性的芯片產品,該產品在數據處理速度和能效比上遠超同類產品,迅速獲得了市場的認可。這一技術創新不僅為公司贏得了首批客戶,也為后續發展奠定了堅實的技術基礎。
Dino-Lite公司在發展過程中,始終注重市場拓展和合作伙伴關系的建立。公司與多家知名企業建立了長期穩定的合作關系,共同開拓市場、分享資源。通過與合作伙伴的緊密合作,Dino-Lite公司的產品得以快速進入各個行業領域,并獲得了良好的口碑和市場份額。
此外,Dino-Lite公司還積極參與國際展覽和交流活動,展示公司的最新技術和產品。這些活動不僅提高了公司的知名度,也為公司帶來了更多的商業機會和合作伙伴。
為了滿足全球客戶的需求,DRI Relays Inc公司開始實施全球化戰略。公司先后在亞洲、歐洲和美洲等地設立了分公司和研發中心,以便更好地了解當地市場需求和提供定制化服務。同時,公司還積極參與國際展覽和交流活動,加強與全球客戶的溝通和合作。這些舉措不僅提高了公司的國際知名度,還為公司贏得了更多的訂單和市場份額。
Eltek公司是一家專注于電力電子技術的公司,成立于20世紀中期。創始人王剛(化名)意識到電力電子技術對于提高能源利用效率的重要性,于是決定投身這一領域。在他的帶領下,Eltek公司不斷研發出高效、可靠的電力電子產品,如變頻器、逆變器等。隨著可再生能源技術的興起,Eltek公司抓住機遇,將電力電子技術應用于可再生能源領域,如太陽能、風能等。這一創新舉措讓Eltek公司在可再生能源領域取得了顯著的成績。
隨著技術的不斷進步和市場需求的不斷變化,AZ Displays的產品應用領域也在不斷拓展。除了傳統的消費電子領域外,公司的產品還廣泛應用于航空電子、醫療、導航系統、工業控制等多個領域。通過與各行業合作伙伴的緊密合作,AZ Displays成功打開了新的市場大門,實現了業務的快速增長。
工信部副部長奚國華6月底在北京舉行“2010中國物聯網大會”上表示,工業和信息 化部副部長奚國華在致辭時表示,對于物聯網,工信部將加強規劃指導和政策引導,加強指導協調,盡快研究解決物聯網的內涵,產業界定和產業統計的問題。同時 將超 ...… 查看全部問答∨ |
有中斷傳輸和塊傳輸,怎么寫固件? 我要做的設備 有一個中斷傳輸,3個塊傳輸(端點號:1OUT、2OUT、1IN、4IN,其中 1IN為中斷傳輸端點地址,其他為塊傳輸端點地址),要怎樣寫固件程序? 例程里面的固件程序都是2、4、6、8為端點號,而且都是塊傳 ...… 查看全部問答∨ |
我用的是PIC單片機,MC45(GSM)模塊。 硬件電路MC45的50腳直接插到單片機的50腳插槽上,我用到的MC45腳包括TXD0,RXD0,IGT。 我并不知道MC45的這幾個腳如何與單片機的RXD0,TXD0,IGT相連。 我的問題是可不可以軟件上實現單片機的RXD0和MC45的TXD ...… 查看全部問答∨ |
|
之前有了解過pt1000的測量電路,就是很不準確,求各位高人指點! file:///C:/Documents%20and%20Settings/Administrator/Application%20Data/Tencent/Users/372182098/QQ/WinTemp/GE/8C6B5CD2-B508-47B8-8B53-AEEBA13D57F7.jpg… 查看全部問答∨ |
|
一分錢逼到英雄漢,發帖清貨.................!!!!!!!!!! 本帖最后由 ddllxxrr 于 2016-1-7 16:45 編輯 吐槽下:在老家買了套房,口袋回到解放前,唉,最近又定了一批4寸的屏,現在到處借錢 ,多謝大家支持,請順便看下聲明,多謝! 申明: 1,默認發申通快遞!省內10元,外省15元! 2,有資料會寫明有 ...… 查看全部問答∨ |
BeagleBone Black設計:Qt程序編寫和桌面圖標添加! 24bit的7寸LCD屏和觸摸屏調試通過之后,Qt程序的編寫就要提上日程! 因為我用的是官方的SDK,所以其自帶了Qt4.8的庫!我需要做的只是按照官方說明編寫自己的Qt程序,然后編譯之后生成可執行文件,放入開發板當中去執行即可!! 具體搭建Qt編程環 ...… 查看全部問答∨ |
2015電子大賽題目已經出爐,分享一些資料給大家參考。祝各位取得好成績!附件中所有電路均可以免費下載,具體可聯系管理員:459888529,索要優惠碼。 … 查看全部問答∨ |
【MicroPython】Micropython PM檢測添加SD卡存儲 繼續添加功能,PM值檢測出來了,同時RTC功能也有了,接下來添加一個SD卡模塊,希望能夠實時將檢測到的數據保存下來,作為歷史數據。 在Micropython的官方文檔中有關于SD卡的例程和庫文件,拿來分析一下,就可以根據例程修改為自己的代碼使用。 本 ...… 查看全部問答∨ |