采用UDP协议实现PIC18F97J60 ethernet bootloader
扫描二维码
随时随地手机看文章
TCP/IP Stack
使用pic18f97j60开发过多个项目,项目中都使用了Microchip免费提供的TCP/IP Stack实现远程控制。但是每次更新程序,都需要将pic18f97j60目标板取回来重新烧录,很不方便。既然可以实现远程控制,为什么不实现远程更新呢?这就是我的ethernet bootloader的由来。Microchip的TCP/IP Stack功能很强大,我决定只用它的UDP模块来实现。为了实现远程更新,我需要写pic18f97j60单片机端UDP协议的ethernet bootloader程序--我将其命名为PhnBoot_v1.0; 同时还需要写PC端与bootloader交互的UDP通信程序--我将其命名为PhnLoader_v1.0。我还定义了PhnBoot_v1.0和PhnLoader_v1.0之间传输数据的通信协定。
通信协定
单片机端PhnBoot_v1.0和PC端PhnLoader_v1.0之间的通信数据包采用以下协定
定义如下:
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 功能
定义好了通讯协定, 接着就按照协定去实现PhnLoader_v1.0。 PhnLoader_v1.0的具体功能包括选择IP地址,端口和协议类型,目前只支持UDP协议, 创建UDP服务器,加载应用程序Hex文件,Parse 应用程序的Hex文件,一行一行解读Hex文件,一旦收到更新请求,立刻按照通讯协定采用UDP协议发送Hex记录到单片机,接收单片机发送回来的Response,发送完毕后断开UDP通信,发送期间出现问题就立马结束发送。
PhnLoader_v1.0 主要代码段
PhnLoader_v1.0是用C#实现的,是我在利用空余时间自学C#后写的,上面提到的功能都实现了。
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;}