楊超 胡旭
摘 要:在嵌入式設(shè)備研發(fā)過程中,程序的更新是不可避免的問題。如果嵌入式設(shè)備數(shù)量眾多或者已經(jīng)封閉安裝,使用連線下載方式重新將全部設(shè)備更新程序,將是一項(xiàng)困難的工作。所以使用遠(yuǎn)程方式進(jìn)行程序的更新是嵌入式設(shè)備必不可少的一項(xiàng)功能。無操作系統(tǒng)嵌入式設(shè)備一般在用戶程序段之前加入一段IAP程序段,在開機(jī)之后先運(yùn)行IAP程序,如果需要升級(jí)程序進(jìn)入接收狀態(tài),最后將接收到的程序覆蓋用戶程序段完成升級(jí)。而內(nèi)嵌操作系統(tǒng)的嵌入式設(shè)備就更容易一些,只需要增加一個(gè)接收升級(jí)指令的線程,將更新后的程序替換原有文件就完成了升級(jí)。這兩種處理方式大多數(shù)都是通過以太網(wǎng)接收升級(jí)包,而文章討論的嵌入式設(shè)備底層不具備以太網(wǎng)接口,而是使用CAN總線完成整個(gè)升級(jí)過程。
關(guān)鍵詞:CAN總線;遠(yuǎn)程更新;Linux系統(tǒng)
中國飛機(jī)強(qiáng)度研究所自主研發(fā)設(shè)計(jì)生產(chǎn)的數(shù)據(jù)采集系統(tǒng),結(jié)構(gòu)如圖1所示。
客戶端使用以太網(wǎng)與通訊控制器相連接,而每一個(gè)通訊控制底下連接了數(shù)個(gè)采集模塊,每一個(gè)采集模塊都內(nèi)嵌Linux操作系統(tǒng)。通訊控制器負(fù)責(zé)接收客戶端發(fā)送的各種命令,將命令解析后,按需要將解析后的命令通過控制器局域網(wǎng)絡(luò)(Controller Area Network,CAN)總線發(fā)送給相應(yīng)對(duì)的采集模塊,采集模塊在收到命令后完成相應(yīng)的任務(wù)并通過CAN總線將數(shù)據(jù)結(jié)果返回通訊控制器。通訊控制器將數(shù)個(gè)采集模塊返回的數(shù)據(jù)包整合,按照一定的格式打包返回給客戶端,這樣就完成了整個(gè)命令下發(fā)和數(shù)據(jù)返回的過程。在實(shí)際使用中,如果每一次更新都需要把采集模塊從機(jī)箱中拆出,更新后在安裝,這樣的工作量是非常巨大的。所以在本系統(tǒng)中使用遠(yuǎn)程更新是非常必需的。由于采集模塊與通訊控制器之間只有CAN總線連接,而沒有以太網(wǎng)接口,如果需要完成遠(yuǎn)程升級(jí)的任務(wù),就無法按照以往的以太網(wǎng)方式進(jìn)行[1]。本文詳細(xì)介紹如何使用CAN總線來完成整個(gè)升級(jí)的過程。
1 軟件設(shè)計(jì)說明
采集模塊的程序遠(yuǎn)程更新的過程涉及兩部分的軟件設(shè)計(jì):通訊控制器與采集模塊。通訊控制器負(fù)責(zé)接收升級(jí)命令和升級(jí)數(shù)據(jù)包并下發(fā),這部分的遠(yuǎn)程升級(jí)使用IAP方式,由于此方式使用較為廣泛,例程較多,比較簡單不再過多闡述。采集模塊使用Freescale 的i.MX6Q處理器,內(nèi)嵌Linux操作系統(tǒng)[2]。程序流程如圖2所示。
在采集模塊中,處理正常工作所需要的執(zhí)行文件之外,增加了update可執(zhí)行文件,負(fù)責(zé)完成升級(jí)工作。在程序主線程運(yùn)行過程中,如果收到上層發(fā)來升級(jí)的命令,主線程首先關(guān)閉與AD轉(zhuǎn)換相關(guān)的副線程,關(guān)閉主線程,然后開啟軟件升級(jí)線程。在軟件升級(jí)線程中,主要工作有:判斷升級(jí)類型、建立備份升級(jí)文件、接收升級(jí)數(shù)據(jù)、寫入備份文件、校驗(yàn)文件、替換原有執(zhí)行文件。在完成了升級(jí)線程所有步驟之后,將升級(jí)結(jié)果發(fā)送主機(jī),然后板卡自動(dòng)重啟執(zhí)行更新后的程序。
在整個(gè)升級(jí)過程中需要注意以下兩個(gè)地方:(1)在開始執(zhí)行升級(jí)前需要關(guān)閉正在運(yùn)行的線程,因?yàn)樯?jí)的程序有可能就是正在執(zhí)行的程序,如果邊執(zhí)行邊進(jìn)行文件替換有可能造成文件寫入錯(cuò)誤。(2)需要建立備份文件,將所有更新的程序?qū)懭?,最后進(jìn)行更新數(shù)據(jù)的校驗(yàn),如果校驗(yàn)通過則開始替換原文件。
由于是使用CAN總線進(jìn)行數(shù)據(jù)接收,每一個(gè)CAN數(shù)據(jù)包可接收8字節(jié)數(shù)據(jù),除去命令頭、控制字節(jié)、計(jì)數(shù)字節(jié),每一個(gè)CAN數(shù)據(jù)包只能發(fā)送4個(gè)字節(jié)的升級(jí)數(shù)據(jù)。并且系統(tǒng)在正常的升級(jí)過程中一次性會(huì)同時(shí)升級(jí)多個(gè)機(jī)箱,所以本系統(tǒng)在升級(jí)過程中充分利用了雙層通訊結(jié)構(gòu),在同時(shí)升級(jí)多個(gè)機(jī)箱的情況下,首先將需要升級(jí)的可執(zhí)行文件使用以太網(wǎng)分別下發(fā)給各個(gè)通訊控制器,通訊控制器將數(shù)據(jù)暫存在本地。接下來通訊控制器將升級(jí)數(shù)據(jù)分解成多個(gè)4字節(jié)的CAN數(shù)據(jù)包依次下發(fā)給每一個(gè)采集模塊。本系統(tǒng)中CAN總線速度設(shè)置為750 kb/s,在同時(shí)升級(jí)8個(gè)板卡并且合理協(xié)調(diào)時(shí)間間隔后,在升級(jí)文件為2 M左右大小時(shí),實(shí)測整個(gè)升級(jí)過程需要幾分鐘[3]。
2 程序說明
在升級(jí)線程啟動(dòng)之后,首先進(jìn)行外部資源的初始化,關(guān)閉相關(guān)的線程,然后進(jìn)入命令接受狀態(tài),根據(jù)命令種類不同進(jìn)入不同的處理流程,隨后進(jìn)入升級(jí)開始函數(shù),首先打開備份文件,將收到的升級(jí)數(shù)據(jù)寫入備份文件,進(jìn)行數(shù)據(jù)校驗(yàn),并記錄數(shù)據(jù)總數(shù):
Data_Update_Start()
{
unsigned char write_buff[4],i;
if(first_open == 0)
{
first_open = 1;
txt_fd = open(“test_copy”, O_RDWR); //打開升級(jí)備份文件
if (-1 == txt_fd)
{
printf(“open error\n”);
}
else
{
printf(“open success,txt_fd = %d\n”, txt_fd);
}
}
for(i=0;i<4;i++)
write_buff[i] = recievedata[i+4];
ret = write(txt_fd, write_buff, recievedata[1]);
if (ret < 0)
{
printf(“write error.\n”);
update_count = -1;
}
CRC_check(); //數(shù)據(jù)校驗(yàn) 如未通過校驗(yàn),客戶端會(huì)重新發(fā)送這一段數(shù)據(jù)
update_count = update_count + recievedata[1]; //升級(jí)數(shù)據(jù)計(jì)數(shù)
}
Data_Update_Finish()
{
unsigned char i,size;
unsigned long long_size;
close(txt_fd);
first_open = 0;
for(i=0;i<8;i++)
frame.data[i] = 0;
frame.data[0] = 0xF2;
frame.data[1] = DAU_number;
long_size = update_count& 0x000000ff;
size = (char) long_size;
frame.data[7] = size;
long_size = update_count& 0x0000ff00;
long_size = long_size >> 8;
size = (char) long_size;
frame.data[6] = size;
long_size = update_count& 0x00ff0000;
long_size = long_size >> 16;
size = (char) long_size;
frame.data[5] = size;
long_size = update_count& 0xff000000;
long_size = long_size >> 24;
size = (char) long_size;
frame.data[4] = size;
frame.can_dlc = 8;
nbytes = sendto(s, &frame, sizeof(struct can_frame), 0, (struct sockaddr*)&addr, sizeof(addr));
}
最后的升級(jí)完成函數(shù)中首先判斷升級(jí)上位機(jī)發(fā)送的升級(jí)指令中,指明的需要升級(jí)的可執(zhí)行文件。然后將已經(jīng)更新完成的備份文件替換掉原可執(zhí)行文件。最后向上位機(jī)發(fā)送升級(jí)成功報(bào)告并重新啟動(dòng)采集板卡,完成整個(gè)升級(jí)過程。此部分軟件考慮到篇幅限制不在此列出。
3 結(jié)語
按照以上的遠(yuǎn)程升級(jí)軟件設(shè)計(jì),理論課可同時(shí)進(jìn)行255臺(tái)采集機(jī)箱的升級(jí)工作。由于CAN總線通訊升級(jí)部分各個(gè)機(jī)箱是并行運(yùn)行,多臺(tái)升級(jí)與單臺(tái)采集機(jī)箱升級(jí)消耗時(shí)間幾乎相同。實(shí)際測試同時(shí)升級(jí)8臺(tái)機(jī)箱,更新AD采樣計(jì)算部分程序時(shí),該部分可執(zhí)行文件大小為2.2 M,共用時(shí)5分28秒。雖然從文件傳輸角度考慮速度比較慢,但是考慮到系統(tǒng)升級(jí)對(duì)于時(shí)間要求不高且此方法的遠(yuǎn)程升級(jí)大大減少了現(xiàn)場拆裝工作量,節(jié)省了數(shù)十倍的時(shí)間,本文討論的測量系統(tǒng)的遠(yuǎn)程升級(jí)功能已經(jīng)圓滿完成了任務(wù)。
[參考文獻(xiàn)]
[1]宋寶華. Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解[M].2版.北京:人民郵電出版社,2008.
[2]MATTHEW N,STON R.Linux程序設(shè)計(jì)[M].4版.北京:人民郵電出版社,2007.
[3]斯洛斯.ARM嵌入式系統(tǒng)開發(fā):軟件設(shè)計(jì)與優(yōu)化[M].北京:北京航空航天大學(xué)出版社,2005.