即使語法正確的LuatOS-Air腳本,在LuatOS環境中也可能出現“靜默失敗”——程序無報錯但功能未執行。這類問題多與系統事件循環、模塊加載時機或硬件抽象層調用方式有關。本文通過多個真實案例,深入分析運行異常的根本原因并提出預防措施。
一、lua版本不一樣
LuatOS-Air使用的是lua5.1版本,本身不支持位移運算符。
LuatOS使用的是lua5.3版本,取消了module(..., package.seeall)這種形式的跨文件調用。
二、api不同
首先說明,core和腳本有所不同,用戶可以理解為,core是安卓/ios系統,腳本為一個又一個的app,只有core+腳本,才能支撐起完整的一個二次開發項目。
LuatOS-Air的api:
在https://doc.openluat.com/wiki/21?wiki_page_id=2068這里,又分為了5.1原生接口,提供的額外接口兩種。
在額外的接口其中,又分為了底層接口和二次封裝接口,底層接口叫做core api,二次封裝接口叫做script lib api,下面會簡稱為lib層api。
core api實現過程不可見,封裝在了core里,受限于和RDA的協議,這部分實現過程不開源,而lib層的api,實現過程可見,用戶可以自行修改。
lib層api一般是將底層提供的接口進行合并與封裝,更加的簡單與易用,也有部分lib層api是直接給core發送AT指令然后處理AT指令的返回值,并且以函數返回值的形式返回給調用該api的位置。
LuatOS的api:
在https://docs.openluat.com/osapi/這里,和LuatOS-Air一樣,分為了5.3原生接口和提供的額外接口兩種。
在額外的接口其中,又分為了核心庫接口和擴展庫接口,核心庫接口叫做core api,擴展庫接口叫做script lib api,下面會簡稱為lib層api。
core api實現過程不可見,封裝在了core里,這部分實現過程不開源,而lib層的api,實現過程可見,用戶可以自行修改。
LuatOS 核心庫是在底層實現的功能庫,調用核心庫無需代碼使用 require 操作;
LuatOS 擴展庫是用 Lua 腳本實現的功能庫,必須用 requre 調用才能夠使用擴展庫。
三、跨文件調用方式不同
LuatOS-Air跨文件調用方式
LuatOS-Air在每一個非main.lua的文件頭部,第一行可執行代碼永遠是module(..., package.seeall),主要作用是將該文件中所有的全局變量/全局函數,加入到一張名為 _G的table中方便其他.lua文件調用,在這里不做過多講解,能有轉移需求的客戶,基本都會LuatOS-Air的跨文件調用方法。
luatos跨文件調用方式
luatos跨文件調用方式有兩種,一種和LuatOS-Air類似,不過是在文件第一行,新建一個和文件名相同的table,文件結尾處return這個table,接下來舉個例子
首先封裝一個函數

我們新建一個文件叫tools.lua,把這個函數放進去,現在,整個文件如下面這樣:


現在,我們封裝的這個函數就能在其他文件(例如main.lua)里被調用了,具體代碼如下:

當調用了require接口后,Lua虛擬機會自動加載你調用的文件,執行文件的內容,然后返回你文件里return的結果。
為了更好地理解這段話,我們可以看下面兩個文件,其中main.lua是被運行的那個入口文件,




此處為第一種調用方法,簡單來說,被調用文件頭部,將module(..., package.seeall)換成文件名={},文件末尾處加return {本文件中寫的函數名=本文件中寫的函數名},有多個函數的時候,可以添加多個元素名= 元素名進table里。
第二種調用方法依舊是在文件開頭寫上文件名={},不同的是,需要被調用的函數名,可以寫成文件名.函數名的形式,最后的return不需要return一個很長的table了,只需要return 文件名,例如:
需要在main.lua 中調用test.lua的test函數,那么除了固定格式以外的main.lua可以寫成

具體可參考https://gitee.com/openLuat/LuatOS/tree/master/script/libs這里所有的demo
四、實例
以uart的demo為例,筆者將帶著用戶,將LuatOS-Air uart的demo,移植到luatos上(僅講解uart1的移植過程,其他串口通用),除去無關本次移植過程的部分,LuatOS-Air的uart1完整demo如下,是一個自發自收的測試demo,luatos完整的demo也會放在最后,方便用戶對比。
LuatOS-Air_uart.zip
開始移植
main.lua的改造

PROJECT和VERSION這兩個參數不變,下載時候需要這兩個參數
require "log"這句可以刪除,底層已經寫好了log庫,并提供了和LuatOS-Air lib層api幾乎一致的core api,查看對應的 luatos log庫api https://docs.openluat.com/osapi/core/log/
后得知,幾種日志模式的常量有所不同,所以LOG_LEVEL = log.LOGLEVEL_TRACE這句,可以改成LOG_LEVEL = log.LOG_INFO,再添加一句log.setLevel(LOG_LEVEL )
因為主邏輯都在testUart1文件中,不需要在main.lua中調用,所以保持 require "testUart1" 原樣即可,為了用戶更直觀的看出跨文件調用的不同,所以我在testUart1中又寫了一個名為function_name的函數,然后在main.lua中進行循環調用。sys.init函數不需要,直接刪去即可
完成上述步驟以后,main.lua就被我們改造成了下面這樣

testUart1.lua的改造
接下來進入testUart1.lua中

module(...,package.seeall)改為 testUart1 ={},pm和utils兩個庫,utils不需要,直接刪除,pm庫底層提供了,無需require,也刪除。
接下來會先將proc、read、write、writeOk和我剛剛寫的function_name這幾個函數會加載到內存中,但是還沒有執行,接下來執行的是pm.wake("testUart"),查看luatos的pm接口(https://docs.openluat.com/osapi/core/pm/),可以看到luatos沒有wake接口,但是有不休眠模式,所以先設置下不休眠,也就是將pm.wake("testUart")換成pm.request(pm.NONE)
然后執行的是uart.on兩個注冊函數,當時串口有接收事件產生時候,會去執行read函數,當串口有發送事件產生時,會執行writeOK函數,對比luatos的注冊串口收發事件(https://docs.openluat.com/osapi/core/uart/#45-uartonid-event-func),可以看出,這兩個芯片收發事件函數一致,無需更改。
最后執行的是串口設置指令,LuatOS-Air和luatos有很大不同,LuatOS-Air的uart設置接口如下(https://doc.openluat.com/wiki/21?wiki_page_id=2250#uartsetup_id_baud_databits_parity_stopbitsmsgmodetxDoneReportflowcontrolpriority_33)
luatos的uart設置接口如下(https://docs.openluat.com/osapi/core/uart/#41-uartsetupid-baud_rate-data_bits-stop_bits-partiy-bit_order-buff_size-rs485_gpio-rs485_level-rs485_delay-debug_enable-error_drop)
這兩個接口,LuatOS-Air的和luatos最大區別就是,LuatOS-Air將485半自動收發控制分開了,單獨寫了一個uart.set_rs485_oe
而luatos將其寫在了一起,用戶在使用該接口時,一定要注意不同接口之間參數的位置。
當有串口接收事件產生時,模塊會進入read函數,在read函數里,打印了data原始數據和轉成hex以后的數據后,便進入了proc函數中,并且將串口來的數據傳入給proc函數,進行處理。
值得注意的是,read函數里有將串口來的數據通過uart.read函數賦值給data變量這個操作,但是luatos截至當前文章完成時,uart.read函數的第二個參數,只能填number,意為每次接收的字節數,也就是需要將代碼中的uart.read(UART_ID,"*l")換成uart.read(UART_ID,1024)后面這個1024,為uart.setup的第7個參數,串口緩沖區你設置的大小,未設置默認為1024字節,如果需要用戶自行設置,則最小512,最大4096
而當有串口發送事件產生時,模塊會進入writeOk函數,該函數比較簡單,就打印了下發送成功字樣。
最后一行因為有跨文件調用,所以需要return 文件名,也就是加一句return testUart1
最后整個testUart1.lua就被我們改造成了這樣

至此 整個改造過程結束,改造后的文件我也放在下面方便用戶對比
luatos_uart.zip
今天的內容就分享到這里了~
審核編輯 黃宇
-
LuatOS
+關注
關注
0文章
156瀏覽量
2692
發布評論請先 登錄
LuatOS 框架的嵌入式系統架構設計原理
輕松掌握——LuatOS socket基礎知識和應用開發
LuatOS-Air腳本移植到LuatOS版本注意事項
構建可靠USB應用:硬件設計要點與LuatOS開發技巧!
LuatOS下Air8000 AGPS輔助定位教程與實踐
Air780EPM開發板NTP對時教程:LuatOS腳本開發入門指南
嵌入式開發新選擇:LuatOS腳本框架入門教程
Task任務:LuatOS實現“任務級并發”的核心引擎
揭秘LuatOS Task:多任務管理的“智能中樞”
解碼LuatOS:短信功能的底層運作機制
血淚教訓總結:Air780EPM的LuatOS二次開發——OneWire協議調試注意事項
警惕兼容性陷阱:LuatOS-Air腳本在LuatOS中的運行異常分析
評論