徐獻圣 張震

摘要:針對基于OpenCPU的NB-IoT模塊上作為兼任主處理器和數據傳輸功能時具有的內存壓力,該文設計一種嵌入式腳本Lua腳本語言實現NB-IoT模塊的內存優化方案。通過該方案,利用Lua腳本語言中自動內存管理和增量垃圾回收的特點彌補C語言的短板,從而優化內存空間,節省NB-IoT模塊資源的消耗,降低功耗。
關鍵詞:OpenCPU;嵌入式腳本;Lua;NB-IoT模塊;內存;優化
中圖分類號:TP393.409? ? ? ? 文獻標識碼:A
文章編號:1009-3044(2021)25-0051-02
為了適應物聯網的發展,滿足更多的應用場景和市場需求,傳感網中誕生了一批適合物與物之間遠距離通信的無線通信技術,統稱為低功耗廣域網,即LPWAN。NB-IoT是一種工作于授權頻譜下的LPWAN,其具有廣覆蓋、低功耗、低成本、大連接等多個優點,深受國內物聯網企業的青睞。在傳統方案中,往往會將NB-IoT外接至MCU。這種方式主要由MCU接收傳感器采集的數據,再通過UART方式將數據傳至NB-IoT模組,最后上傳至云平臺[1-2]。肖磊[3]提出將OpenCPU應用到NB-IoT模組上,讓NB-IoT模塊本身成為處理器,這樣用戶能夠在NB-IoT模塊上同時實現數據采集和數據上云,降低了MCU成本,節省了MCU功耗,提高了系統的穩定性和數據上傳的實時效率。但是,由于處理器功能的轉移,是以犧牲NB-IoT模組的內部資源作為代價,影響自身的運行效率。
針對此類問題,本文提出一種基于Lua腳本語言實現內置中移M5311模組的LM-NB-M-01模塊通信的解決方案,以TCP協議傳輸作為使用案例。此方案將外圍設備數據獲取和TCP通信任務都交由Lua虛擬機處理,根據獲取的數據,決定是否調用啟動關于TCP通信任務的Lua腳本,由此節省NB-IoT模組資源的消耗,提升運行效率。
1 Lua腳本語言簡介
Lua[4-6]是一種遵循標準C寫成的輕量級嵌入式腳本語言,其具有擴展性好、簡單小巧、與平臺無關的特點。Lua提供了易于使用的擴展接口和機制,尤其是當C/C++作為其宿主語言時,它們之間很容易完成交互,如同本身就是內置的功能一樣,因此Lua非常方便移植到基于C語言的OpenCPU中使用,不會引起硬件增大消耗的額問題?;贚ua實現TCP協議傳輸的NB-IoT通信方案,主要依靠Lua的下列特點。
(1)Lua是動態類型語言,即其變量沒有預定義的類型,值才有類型,并且函數也可以看成是一個值。Lua還提供了一種通用類型的表,用它可以實現數組,哈希表,集合。這些特點使得Lua除了支持面向過程編程和函數式編程,還支持面向對象編程,彌補了C語言在設計上的短板。
(2)Lua簡單小巧,Lua5.3.4發行版所有標準庫加起來只有640kb大小,編譯后僅一百余K,能夠有效節省系統內部資源。
(3)Lua具有自動內存管理和增量垃圾回收功能。設計者不需要擔心如何管理資源,只需要分配內存,同時這個內存由Lua管理。當程序不需要某個對象時,Lua會自動刪除這個失效的對象,節省系統內部資源。
(4)Lua提供的協同進程機制使得Lua腳本作為獨立線程,與主程序和其他線程互不影響地同時工作,提升程序的運行效率。
2 設計方案介紹
本方案圍繞基于中移M5311 NB-IoT模組的LM-NB-M-01模塊與私有云平臺實現TCP通信來進行設計,系統設計方案框架如圖1所示,系統運行流程圖如圖2所示。
啟動LM-NB-M-01模塊,主程序建立OpenCPU任務,等待注冊網絡。網絡在線后,外圍傳感器設備開始將感知到的數據通過外設接口傳入至LM-NB-M-01模塊中,接著主程序對數據進行處理,判斷是否需要將數據傳上云平臺。例如數據在所設閾值范圍內,不向云平臺執行發送行為。這種情況在監測系統[7]尤為常見。當終端模塊判斷數據超過閾值時,需要發送報警信號給云平臺,此時創建Lua虛擬機,將編寫的TCP通信的C函數注冊到Lua虛擬機中,然后讀取Flash文件中獨立于C程序的Lua腳本文件,完成TCP任務。之后關閉虛擬機,依靠Lua本身特點自動收集垃圾并清理內存,節省內存資源。
私有云服務器的設計,采用IOCP高并發架構設計,通過花生殼內網穿透軟件,實現云服務器與私有內網服務器建立連接,同時把內網端口映射到云端。
3設計方案介紹
為了節省系統內部資源和提升程序的運行效率,本設計重點不在如何實現獲取或處理傳感器數據,而是著重于采用Lua與C語言混合編程的方案如何實現NB-IoT基于TCP協議的傳輸。具體步驟如下。
(1)將Lua移植到LM-NB-M-01模塊的OpenCPU環境
將Lua5.3.4源碼包中src目錄內部除了lua.c與luac.c外的所有.c和.h加入到M5311-OPENCPU_SDK 3.3.0中。由于OpenCPU采用make-clean編譯方式,因此可以使用Visual Studio Code IDE完成此項工作。但要編譯成功,還需要注意將Lua源碼中用到的clock()、remove(filename)以及rename(fromname, toname)函數刪掉或修改,否則與原來OpenCPU的源碼有沖突。
(2)建立Lua與C交互環境
C與Lua之間通過C API進行交互,其關鍵在于構建一個虛擬的棧,通過操作棧上的值來實現API調用和C與Lua之間數據交換。
①通過以下格式創建Lua虛擬機。
lua_State *L = NULL;
L = luaL_newstate();? //創建Lua狀態機