采用UDP協(xié)議實(shí)現(xiàn)PIC18F97J60 ethernet bootloader
掃描二維碼
隨時(shí)隨地手機(jī)看文章
TCP/IP Stack
使用pic18f97j60開發(fā)過多個(gè)項(xiàng)目,項(xiàng)目中都使用了Microchip免費(fèi)提供的TCP/IP Stack實(shí)現(xiàn)遠(yuǎn)程控制。但是每次更新程序,都需要將pic18f97j60目標(biāo)板取回來重新燒錄,很不方便。既然可以實(shí)現(xiàn)遠(yuǎn)程控制,為什么不實(shí)現(xiàn)遠(yuǎn)程更新呢?這就是我的ethernet bootloader的由來。Microchip的TCP/IP Stack功能很強(qiáng)大,我決定只用它的UDP模塊來實(shí)現(xiàn)。為了實(shí)現(xiàn)遠(yuǎn)程更新,我需要寫pic18f97j60單片機(jī)端UDP協(xié)議的ethernet bootloader程序--我將其命名為PhnBoot_v1.0; 同時(shí)還需要寫PC端與bootloader交互的UDP通信程序--我將其命名為PhnLoader_v1.0。我還定義了PhnBoot_v1.0和PhnLoader_v1.0之間傳輸數(shù)據(jù)的通信協(xié)定。
通信協(xié)定
單片機(jī)端PhnBoot_v1.0和PC端PhnLoader_v1.0之間的通信數(shù)據(jù)包采用以下協(xié)定
定義如下:
STX - Start of packet indicator
ETX - End of packet indicator
LEN - The length of true data
DATA - General data 16 bytes, only first LEN of datas are true
CMD - Base command
ADDR - Address up to 24 bits ( ADDRL , ADDRH , ADDRH)
具體有以下Base command:
RD-VER: 0x00 -- Read Version Information (最終版本刪除了此命令)
RD_MEM: 0x01 -- Read Program Memory (最終版本刪除了此命令)
ER_MEM: 0x03 -- Erase Program Memory
WR_MEM: 0x02 -- Write Program Memory
WR_CFG: 0x04 -- Write Configuration Registers
PhnLoader_v1.0 功能
定義好了通訊協(xié)定, 接著就按照協(xié)定去實(shí)現(xiàn)PhnLoader_v1.0。 PhnLoader_v1.0的具體功能包括選擇IP地址,端口和協(xié)議類型,目前只支持UDP協(xié)議, 創(chuàng)建UDP服務(wù)器,加載應(yīng)用程序Hex文件,Parse 應(yīng)用程序的Hex文件,一行一行解讀Hex文件,一旦收到更新請(qǐng)求,立刻按照通訊協(xié)定采用UDP協(xié)議發(fā)送Hex記錄到單片機(jī),接收單片機(jī)發(fā)送回來的Response,發(fā)送完畢后斷開UDP通信,發(fā)送期間出現(xiàn)問題就立馬結(jié)束發(fā)送。
PhnLoader_v1.0 主要代碼段
PhnLoader_v1.0是用C#實(shí)現(xiàn)的,是我在利用空余時(shí)間自學(xué)C#后寫的,上面提到的功能都實(shí)現(xiàn)了。
privatevoidbtnDownload_Click(objectsender,EventArgse){btnDownload.Enabled=false;pBarLoading.Visible=false;if(!this.connect()){Debug.WriteLine("Udpserverbuildingunsuccessfully");textBoxStatus.ForeColor=Color.Red;textBoxStatus.AppendText("Udpserverbuildingunsuccessfullyrn");textBoxStatus.ForeColor=Color.Black;btnDownload.Enabled=true;return;}try{loaderReader=newStreamReader(textBoxFile.Text);}catch(Exceptionex){Debug.WriteLine("Error:"+ex.Message);textBoxStatus.ForeColor=Color.Red;textBoxStatus.AppendText("Readhexfileunsuccessfullyrn");textBoxStatus.ForeColor=Color.Black;loaderReader.Close();loaderServer.Close();btnDownload.Enabled=true;return;}loaderFrame=newSerialFrame();DateTimestartTime=DateTime.Now;IPEndPointclientPoint=newIPEndPoint(IPAddress.Any,0);if(!loaderServer.Read(readyMsg,timeSpan)){Debug.WriteLine("Error:Timeoutreceivereadymessagefrombootloader");textBoxStatus.ForeColor=Color.Red;textBoxStatus.AppendText("Timeoutreceivereadymessagefrombootloaderrn");textBoxStatus.ForeColor=Color.Black;loaderServer.Close();loaderReader.Close();btnDownload.Enabled=true;return;}if(!erase()){textBoxStatus.ForeColor=Color.Red;textBoxStatus.AppendText("Eraseunsuccessfullyrn");textBoxStatus.ForeColor=Color.Black;loaderReader.Close();loaderServer.Close();btnDownload.Enabled=true;return;}pBarLoading.Refresh();pBarLoading.Visible=true;pBarLoading.Value=0;pBarLoading.Maximum=loaderLines;pBarLoading.Step=1;stringrecordLine;Address_U=0;boolisNextLineUserID=false;boolisNextLineConfigBits=false;textBoxStatus.AppendText("rnDownloadinghexfile...rn");try{while(loaderReader.Peek()>=0){pBarLoading.PerformStep();recordLine=loaderReader.ReadLine();if(recordLine.Contains(EXTEND_TOKEN)==true){if(recordLine.Contains(USER_ID_TOKEN)==true){isNextLineUserID=true;continue;}elseif(recordLine.Contains(CONFIG_BITS_TOKEN)==true){constintADDR_U_START_INDEX=9;constintADDR_U_LENGTH=4;stringaddrU=recordLine.Substring(ADDR_U_START_INDEX,ADDR_U_LENGTH);Address_U=Convert.ToInt32(addrU,16)<<16;isNextLineConfigBits=true;continue;}else{constintADDR_U_START_INDEX=9;constintADDR_U_LENGTH=4;stringaddrU=recordLine.Substring(ADDR_U_START_INDEX,ADDR_U_LENGTH);Address_U=Convert.ToInt32(addrU,16)<<16;continue;}}elseif(((recordLine.Contains(J_TYPE_CONFIG_BITS_1)==true)||(recordLine.Contains(J_TYPE_CONFIG_BITS_2)==true)||(recordLine.Contains(J_TYPE_CONFIG_BITS_3)==true)||(recordLine.Contains(J_TYPE_CONFIG_BITS_4)==true)||(recordLine.Contains(J_TYPE_CONFIG_BITS_5)==true)||(recordLine.Contains(J_TYPE_CONFIG_BITS_6)==true)||(recordLine.Contains(J_TYPE_CONFIG_BITS_TOKEN_1)==true)||(recordLine.Contains(J_TYPE_CONFIG_BITS_TOKEN_2)==true))&&(Address_U==0x010000)){if(!DownloadConfigLine(recordLine)){Debug.WriteLine("Errorfoundduringconfigurationbitsprogramming");loaderReader.Close();loaderServer.Close();btnDownload.Enabled=true;return;}continue;}elseif(recordLine.Contains(END_OF_HEX_FILE_TOKEN)==true){break;}if(isNextLineUserID){isNextLineUserID=false;//donothing;}elseif(isNextLineConfigBits){if(!DownloadConfigLine(recordLine)){Debug.WriteLine("Errorfoundduringconfigurationbitsprogramming");loaderReader.Close();loaderServer.Close();btnDownload.Enabled=true;return;}isNextLineConfigBits=false;}else{if(!DownloadDataLine(recordLine)){Debug.WriteLine("Errorfoundduringdataprogramming");loaderReader.Close();loaderServer.Close();btnDownload.Enabled=true;return;}}}}catch(Exceptionex){Debug.WriteLine("Error:"+ex.Message);textBoxStatus.ForeColor=Color.Red;textBoxStatus.AppendText("Downloadingfailedrn");textBoxStatus.ForeColor=Color.Black;loaderServer.Close();loaderReader.Close();btnDownload.Enabled=true;return;}textBoxStatus.AppendText("Downloadingcompletedrn");if(!run()){textBoxStatus.ForeColor=Color.Red;textBoxStatus.AppendText("JumptoApplicationunsuccessfullyrn");textBoxStatus.ForeColor=Color.Black;loaderReader.Close();loaderServer.Close();btnDownload.Enabled=true;return;}loaderServer.Close();loaderReader.Close();btnDownload.Enabled=true;}