陳文斌,黃明鑫,劉根利,楊 志,翟 淵
(重慶科技學(xué)院 智能技術(shù)與工程學(xué)院,重慶 401331)
隨著物聯(lián)網(wǎng)技術(shù)的快速發(fā)展,程序的遠(yuǎn)程升級(jí)成了剛需。目前,多數(shù)單片機(jī)程序遠(yuǎn)程升級(jí)都是基于單片機(jī)的 IAP 技術(shù)[1]。然而,物聯(lián)網(wǎng)設(shè)備往往數(shù)量較多,升級(jí)所有設(shè)備對(duì)服務(wù)器開銷大,基于差分原理的升級(jí)方式對(duì)硬件要求又高,在硬件資源有限的微控制器MCU上使用差分算法存在局限性。因此,本文提出了一種應(yīng)用在MCU上的新型增量升級(jí)方法,將后期不需要升級(jí)和需要升級(jí)的代碼獨(dú)立開來(lái),形成固件工程和應(yīng)用工程。通過(guò)這種方法,實(shí)現(xiàn)了固件代碼和升級(jí)代碼的解耦,同時(shí)不需要復(fù)雜的差分算法支持,能降低硬件對(duì)資源的要求,提高升級(jí)效率,降低升級(jí)成本。
分散加載(scatter)文件是一種文本文件,可以用來(lái)描述連接器生成映像文件時(shí)需要的信息。通過(guò)編寫一個(gè)分散加載文件來(lái)指定ARM連接器在生成映像文件時(shí)如何分配 Code,RO-Data,RW-Data,ZI-Data等數(shù)據(jù)的存放地址[2]。有時(shí)候用戶希望將不同代碼放在不同存儲(chǔ)空間,也就是通過(guò)編譯器生成的映像文件需要包含多個(gè)域,每個(gè)域在加載和運(yùn)行時(shí)可以有不同的地址。要生成這樣的映像文件,必須通過(guò)某種方式告知編譯器相關(guān)的地址映射關(guān)系[3]。
MCU編譯后的代碼在執(zhí)行文件中是按照一定區(qū)域進(jìn)行排列的,并且函數(shù)在執(zhí)行文件中的首地址就是其函數(shù)的入口地址,因此通過(guò)地址能直接調(diào)用函數(shù)。參考單片機(jī)中斷函數(shù)向量表的形式,劃分一部分空間出來(lái)專門存放函數(shù)的入口地址,其他工程則利用這一地址,偏移之后,就可以得到函數(shù)的地址,實(shí)現(xiàn)不同工程之間函數(shù)的調(diào)用。其不同工程在單片機(jī)FLASH的存儲(chǔ)空間分配原理,如圖1所示。在每個(gè)工程中再分配一定的空間用于存儲(chǔ)函數(shù)地址,即圖中應(yīng)用程序接口(Application Programming Interface,API)部分。
圖1 存儲(chǔ)空間分配示意
為了實(shí)現(xiàn)Firmware固件層代碼與APP應(yīng)用層代碼的解耦,APP應(yīng)用層工程中不能含有Firmware固件工程中的代碼。Firmware固件層代碼應(yīng)該在正常完成調(diào)試之后,將APP應(yīng)用層會(huì)用到的函數(shù)的地址集中存放在單片機(jī)FLASH固定位置,以便APP應(yīng)用層能夠通過(guò)這一固定的位置來(lái)定位函數(shù)地址,實(shí)現(xiàn)對(duì)Firmware固件層函數(shù)的調(diào)用。根據(jù)以上原理和設(shè)計(jì)要求的考慮,軟件框架設(shè)計(jì)如圖2所示,整個(gè)框架一共包括以下3個(gè)部分:固件工程模塊、程序升級(jí)模塊、應(yīng)用工程模塊。
圖2 總體軟件框架結(jié)構(gòu)
(1)固件工程模塊。固件工程是存儲(chǔ)設(shè)備中不需要升級(jí)的代碼,例如輪椅傳感器驅(qū)動(dòng)程序、內(nèi)核程序、操作系統(tǒng)程序、輪椅控制程序等。這部分程序代碼量是最大的,且基本不需要升級(jí),因此只需要在設(shè)備投入使用之前寫入程序。同時(shí),這個(gè)模塊還為升級(jí)模塊和應(yīng)用層模塊提供必要的API接口。
(2)應(yīng)用層模塊。應(yīng)用層模塊用于存儲(chǔ)后期升級(jí)會(huì)用到的程序,如面部識(shí)別算法等。其中固件工程模塊與應(yīng)用層模塊之間函數(shù)能夠相互調(diào)用;設(shè)備投入使用后,需要對(duì)代碼進(jìn)行小修改,就可以將這些代碼放到應(yīng)用層工程中,以后修改這些函數(shù)代碼時(shí),只需要重新編譯,再通過(guò)OTA進(jìn)行升級(jí)。
(3)程序升級(jí)模塊。用于更新應(yīng)用層的代碼。這里的升級(jí)模塊可以使用固件工程中的函數(shù),例如校驗(yàn)函數(shù)、無(wú)線通信函數(shù)等,同時(shí)也可以單獨(dú)設(shè)計(jì)成一個(gè)Bootloder程序。這樣不但可以升級(jí)應(yīng)用層程序,還可以升級(jí)固件層的程序。
采用新的增量升級(jí)方法需要將代碼分為后期需要升級(jí)的部分作為應(yīng)用層工程,將后期不需要升級(jí)的部分作為固件工程。其程序的調(diào)整可以以一個(gè)函數(shù)為單位進(jìn)行調(diào)整,并根據(jù)需要為添加到應(yīng)用層工程的函數(shù)單獨(dú)創(chuàng)建一個(gè)或多個(gè)c文件和h文件,再將這些代碼添加到一個(gè)新的工程中;應(yīng)用層可以根據(jù)升級(jí)需要再分成多個(gè)工程。
程序的正常運(yùn)行需要一定的ROM和RAM空間,多個(gè)工程相互結(jié)合實(shí)現(xiàn)最終的功能,需要為每個(gè)工程劃分一片空間來(lái)保證程序的正常運(yùn)行。
現(xiàn)在雖然將原始代碼分成了多個(gè)工程,但是多個(gè)工程之間缺少相應(yīng)的函數(shù)名,是無(wú)法編譯的,接下來(lái)就需要實(shí)現(xiàn)不同工程之間的關(guān)聯(lián),保證函數(shù)能在不同工程之間實(shí)現(xiàn)相互調(diào)用。
(1)函數(shù)對(duì)外接口設(shè)計(jì)。在C語(yǔ)言函數(shù)的調(diào)用是通過(guò)函數(shù)地址進(jìn)行的,圖1中每個(gè)工程中的函數(shù)地址存儲(chǔ)在固定的地址,其他工程通過(guò)訪問(wèn)這一固定的地址來(lái)實(shí)現(xiàn)不同工程之間的函數(shù)調(diào)用。
函數(shù)對(duì)外接口的設(shè)計(jì)有多個(gè)方法。方法一:創(chuàng)建一個(gè)指針型結(jié)構(gòu)體,并將其值賦值為函數(shù)的地址,再使用編譯器的__attribute__指令,將該結(jié)構(gòu)體變量存放在固定地址;方法二:可以將變量在啟動(dòng)文件中使用DCD指令申請(qǐng)4字節(jié)的空間用于存儲(chǔ)函數(shù)指針結(jié)構(gòu)體變量。
(2)函數(shù)訪問(wèn)接口設(shè)計(jì)。其他工程需要訪問(wèn)這些函數(shù)時(shí),通過(guò)創(chuàng)建一個(gè)函數(shù)指針結(jié)構(gòu)體變量,并將其首地址指向這一固定地址。其他工程通過(guò)訪問(wèn)函數(shù)指針結(jié)構(gòu)體變量,進(jìn)而訪問(wèn)不同工程的函數(shù),實(shí)現(xiàn)不同工程之間的函數(shù)調(diào)用。
本論文通過(guò)介紹目前增量升級(jí)技術(shù)的應(yīng)用和目前基于差分原理的增量升級(jí)方式在低成本MCU上應(yīng)用的局限性,提出了一種新的增量升級(jí)方法。根據(jù)增量升級(jí)需求,希望能夠?qū)崿F(xiàn)對(duì)單個(gè)函數(shù)升級(jí)的要求,增量升級(jí)的設(shè)計(jì)過(guò)程。采用新的增量升級(jí)方法在低成本MCU上應(yīng)用具有一定的優(yōu)勢(shì)。