久久亚洲成a人片熟女精品色一区二区三区|国产精品视频第一精品视频|av天堂热无码手机版|亚洲?v无码久久无遮挡|国产精品偷伦视频免费观看国产|麻豆国产自产精品丰满熟妇|av无码av不卡一区二区|久久亚洲精品中文字

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

NodeMCU 固件 Lua 開(kāi)發(fā) FAQ 深度指南:事件驅(qū)動(dòng)編程、內(nèi)存優(yōu)化與固件裁剪實(shí)戰(zhàn)

NodeMCU 固件 Lua 開(kāi)發(fā) FAQ 深度指南:事件驅(qū)動(dòng)編程、內(nèi)存優(yōu)化與固件裁剪實(shí)戰(zhàn) 物聯(lián)網(wǎng)嵌入式【免費(fèi)下載鏈接】nodemcu-firmwareLua based interactive firmware for ESP8266, ESP8285 and ESP32項(xiàng)目地址https://gitcode.com/gh_mirrors/no/nodemcu-firmware點(diǎn)擊查看免費(fèi)下載導(dǎo)讀本文基于 NodeMCU 固件倉(cāng)庫(kù)的開(kāi)發(fā)者 FAQ系統(tǒng)講解在 ESP8266 上開(kāi)發(fā) Lua 應(yīng)用的核心范式差異——事件驅(qū)動(dòng) vs 傳統(tǒng)過(guò)程式編程、任務(wù)調(diào)度模型、變量作用域與 Lua Registry 的底層機(jī)制并給出防 PANIC 重啟、內(nèi)存/SPIFFS 占用最小化、固件裁剪與 bytecode 編譯等實(shí)戰(zhàn)方案。讀完本文你將掌握 NodeMCU Lua 特有的開(kāi)發(fā)約束、內(nèi)存調(diào)試工具鏈node.heap()、luac、ChunkSpy以及一套可落地的應(yīng)用結(jié)構(gòu)設(shè)計(jì)方法。1. 這份 FAQ 是什么面向誰(shuí)這份 FAQ 的目標(biāo)讀者是已經(jīng)具備一定 Lua 功底、但第一次在 ESP8266/ESP8285 上編寫 NodeMCU 應(yīng)用的開(kāi)發(fā)者。它不教你 Lua 語(yǔ)言本身那屬于 Where to start 列出的外部資源范疇而是解答這樣一個(gè)問(wèn)題一個(gè)合格的 Lua 開(kāi)發(fā)者在 NodeMCU 固件基于 ESP8266 SoC 的各種模組、NodeMCU Devkit上開(kāi)發(fā)時(shí)會(huì)遇到哪些與標(biāo)準(zhǔn) Lua截然不同的情況FAQ 成文于 2017 年 4 月正值 NodeMCU 固件從 0.9 時(shí)代走向 2.x 時(shí)代的轉(zhuǎn)型期。當(dāng)時(shí)固件團(tuán)隊(duì)已經(jīng)完成了多項(xiàng)關(guān)鍵改進(jìn)這些改進(jìn)也決定了本文所述實(shí)踐方法的前提SDK 持續(xù) rebaseline不再長(zhǎng)期鎖死在舊 SDK 版本常量數(shù)據(jù)遷移出 RAM配合軟件異常處理與 LCD 補(bǔ)丁將大量常量數(shù)據(jù)從 RAM 移到固件地址空間典型構(gòu)建的可用 RAM 從約 15KB 提升到 40KB 以上代碼密度提升約 40%錯(cuò)誤報(bào)告修復(fù)traceback 現(xiàn)在能正確報(bào)告行號(hào)LwIP 網(wǎng)絡(luò)棧原生重實(shí)現(xiàn)基于 Espressif 開(kāi)源的 LwIP 實(shí)現(xiàn)文檔體系建立本文正是整個(gè)文檔體系的一部分參見(jiàn)倉(cāng)庫(kù) docs/ 目錄ESP32 移植啟動(dòng)由 Johny Mattsson 主導(dǎo)。注意FAQ 撰寫時(shí)固件基于Lua 5.1當(dāng)前倉(cāng)庫(kù) app/Makefile 中LUA_DIR : lua53說(shuō)明現(xiàn)代構(gòu)建已切換為L(zhǎng)ua 5.3相關(guān)文檔見(jiàn) docs/lua53.md。本文在原理層面仍以 5.1 的經(jīng)典表述為主涉及 Lua 版本差異處會(huì)標(biāo)注。2. Lua 語(yǔ)言層面NodeMCU Lua 與標(biāo)準(zhǔn) Lua 的同與異2.1 Lua 語(yǔ)言學(xué)習(xí)起點(diǎn)NodeMCU 固件在 ESP8266 SoC 上實(shí)現(xiàn) Lua 語(yǔ)言。官方 Lua 5.1 手冊(cè)Lua Language specification是語(yǔ)言規(guī)范的權(quán)威來(lái)源unofficial Lua FAQ 對(duì)把 Lua 作為第二語(yǔ)言學(xué)習(xí)的開(kāi)發(fā)者尤其有用Lua Users Wiki 提供大量示例源碼與討論其 Learning Lua 欄目是入門好去處。書籍方面Programming in Lua作者 Roberto IerusalimschyLua 創(chuàng)始人之一第一版可在線免費(fèi)閱讀PiL 在線版第三版仍可購(gòu)買其中清晰標(biāo)注了 Lua 5.1 與 5.2 的差異是性價(jià)比最高的選擇。文中以PiL n.m形式引用其章節(jié)。至于 ESP8266 硬件本身其架構(gòu)閉源但 Espressif SDK 持續(xù)更新文檔可通過(guò)搜索 Espressif IoT SDK Programming Guide 或訪問(wèn) Espressif 下載論壇獲取。2.2 NodeMCU Lua 與標(biāo)準(zhǔn) Lua 的本質(zhì)區(qū)別Lua 本質(zhì)上是嵌入式擴(kuò)展語(yǔ)言它不假設(shè)存在主程序而是被宿主應(yīng)用嵌入宿主可調(diào)用 Lua 函數(shù)執(zhí)行代碼、讀寫 Lua 變量、注冊(cè) C 函數(shù)供 Lua 調(diào)用。NodeMCU 固件正是這種模式的典型ESP8266 的官方 SDK 以二進(jìn)制庫(kù)形式閉源發(fā)布應(yīng)用開(kāi)發(fā)者只能依賴 SDK API 及其文檔ESP32 則采用 ESP-IDF 開(kāi)源方案NodeMCU Lua 固件是運(yùn)行在 SDK 之上的 ESP8266 應(yīng)用利用 Lua 的鉤子與特性無(wú)縫集成而不損失標(biāo)準(zhǔn) Lua 語(yǔ)言特性固件替換了與 SDK 結(jié)構(gòu)不兼容的標(biāo)準(zhǔn)庫(kù)io與os庫(kù)不可用由 NodeMCU 的node、file庫(kù)替代debug、math庫(kù)被裁剪以減小運(yùn)行時(shí)體積取模用%冪用^注意io.write()不會(huì)被file庫(kù)替代要與print(string)默認(rèn)輸出一致地寫串口請(qǐng)使用uart.write(0, string)。NodeMCU Lua 基于eLua——為嵌入式系統(tǒng)優(yōu)化的 Lua 5.1 完整實(shí)現(xiàn)。eLua 分支的核心創(chuàng)新是LTRLua Tiny RAM在可行處為庫(kù)模塊使用只讀表與常量典型構(gòu)建可減少約 20–25KB RAM 占用使 Lua 在 ESP8266 上可行。2.3 事件驅(qū)動(dòng)NodeMCU 應(yīng)用必須遵循的編程范式SDK 是非搶占式、事件驅(qū)動(dòng)的。應(yīng)用通過(guò) SDK API 為事件注冊(cè)回調(diào)函數(shù)事件在 SDK 內(nèi)部排隊(duì)一次只調(diào)用一個(gè)任務(wù)任務(wù)運(yùn)行完成后將控制權(quán)交還 SDK。SDK 明確警告任何任務(wù)運(yùn)行超過(guò) 15mSecWiFi 等服務(wù)就可能失敗。NodeMCU 庫(kù)本質(zhì)上是圍繞注冊(cè)的 Lua 回調(diào)函數(shù)的 C 包裝器讓這些回調(diào)成為 SDK 任務(wù)。因此你必須用事件驅(qū)動(dòng)風(fēng)格編寫 ESP8266 Lua 程序。大多數(shù)程序員習(xí)慣過(guò)程式寫法單一執(zhí)行流、同步調(diào)用系統(tǒng)服務(wù)完成網(wǎng)絡(luò) I/O但 ESP8266 不能這樣編碼。每個(gè)任務(wù)的內(nèi)部邏輯可以是過(guò)程式的但應(yīng)用的整體結(jié)構(gòu)必須是事件驅(qū)動(dòng)的。3. ESP8266 特有細(xì)節(jié)3.1 與標(biāo)準(zhǔn) Lua 相同之處這是完整的 Lua 5.1 實(shí)現(xiàn)現(xiàn)代構(gòu)建為 5.3所有標(biāo)準(zhǔn) Lua 語(yǔ)言結(jié)構(gòu)與數(shù)據(jù)類型均可用核心標(biāo)準(zhǔn)庫(kù)core、coroutine、string、table均已實(shí)現(xiàn)。3.2 與標(biāo)準(zhǔn) Lua 不同之處硬件與內(nèi)存模型。ESP8266 采用片上 RAM 片外 SPI Flash 組合代碼可從 Flash 映射地址空間直接執(zhí)行。硬件實(shí)際在 RAM 中執(zhí)行代碼Flash 映射地址通過(guò)基于 RAM 的 L1 緩存完成緩存未命中時(shí)硬件透明地將代碼從 Flash 拷貝到 RAM該訪問(wèn)以 SRAM 速度運(yùn)行比已緩存代碼慢約 13 倍。固件大部分從 Flash 運(yùn)行但 RAM 與 Flash 相對(duì)開(kāi)發(fā)者常用系統(tǒng)仍非常有限。經(jīng)過(guò)兩年優(yōu)化可用 RAM 從 0.9 版的約 15KB 提升到 2.x 版的約 45KB。早期 ESP8266 模組常配 512KB Flash全功能 Lua 構(gòu)建加可選庫(kù)后仍要留出應(yīng)用空間需謹(jǐn)慎挑選庫(kù)當(dāng)前固件可舒適地裝入 1MB Flash 并留有充足余量。文件系統(tǒng)。固件將未使用的 Flash 通過(guò)file庫(kù)暴露為SPIFFSSPI Flash File System專為嵌入式 SPI NOR Flash 設(shè)計(jì)優(yōu)化靜態(tài)磨損均衡與低 RAM 占用。SPIFFS 可用空間大小取決于構(gòu)建中包含的模塊數(shù)量。構(gòu)建裁剪。包含任何庫(kù)都會(huì)增大代碼與 RAM 體積推薦做法是自定義構(gòu)建只包含應(yīng)用與硬件變體需要的庫(kù)。不想搭建構(gòu)建環(huán)境的開(kāi)發(fā)者可使用云端構(gòu)建服務(wù)。此外還可選擇32 位整數(shù)運(yùn)算構(gòu)建而非浮點(diǎn)整數(shù)構(gòu)建 Flash 占用更小、執(zhí)行更快但存在不少陷阱一般推薦浮點(diǎn)構(gòu)建。開(kāi)發(fā)流程。與 Arduino 每次改應(yīng)用都要重新燒錄固件不同Lua 固件通常只燒錄一次之后所有應(yīng)用開(kāi)發(fā)都是更新 SPIFFS 上的文件——更像傳統(tǒng) PC 開(kāi)發(fā)。只有需要增刪硬件相關(guān)庫(kù)時(shí)才重刷固件。錯(cuò)誤處理。ESP8266 直接在裸硬件上運(yùn)行 SDK沒(méi)有操作系統(tǒng)來(lái)捕獲錯(cuò)誤、提供優(yōu)雅失敗模式系統(tǒng)錯(cuò)誤很容易觸發(fā)PANIC 導(dǎo)致重啟。為節(jié)省代碼空間錯(cuò)誤處理被刻意簡(jiǎn)化這加劇了該傾向。RAM 等系統(tǒng)資源耗盡幾乎必然導(dǎo)致混亂失敗與重啟。Lua 5.1 時(shí)代無(wú)debug庫(kù)主要為 Flash 體積考慮。因此只能用 1980 年代風(fēng)格的二分法定位錯(cuò)誤并通過(guò)系統(tǒng) UART 接口的 print 語(yǔ)句診斷。理論上未來(lái)可作為自定義構(gòu)建選項(xiàng)加入。LTR 的副作用不能像普通 Lua 那樣輕易擴(kuò)展標(biāo)準(zhǔn)庫(kù)。例如function table.pack()會(huì)因無(wú)法寫入全局table而報(bào)運(yùn)行時(shí)錯(cuò)誤??捎没?metatable 繼承的標(biāo)準(zhǔn)沙箱技術(shù)達(dá)到同樣效果但需注意其運(yùn)行時(shí)與 RAM 開(kāi)銷。交互式運(yùn)行時(shí)運(yùn)行時(shí)系統(tǒng)處于交互模式——先執(zhí)行init.lua若有然后監(jiān)聽(tīng)串口輸入的 Lua 塊語(yǔ)法完整后執(zhí)行。沒(méi)有批處理支持自動(dòng)化嵌入式處理通常通過(guò)在 init.lua 中設(shè)置事件觸發(fā)器實(shí)現(xiàn)。異步性是陷阱非 Lua 處理如網(wǎng)絡(luò)功能通常只在當(dāng)前 Lua 塊執(zhí)行完后發(fā)生。所有網(wǎng)絡(luò)調(diào)用都應(yīng)視為異步請(qǐng)求。常見(jiàn)錯(cuò)誤是假設(shè)socket:send()是同步的——兩行連續(xù)的socket:send()中第一個(gè)并非在第二個(gè)執(zhí)行前已完成。send()只是將發(fā)送任務(wù)排隊(duì)交給 SDK 調(diào)度該任務(wù)要等 Lua 代碼返回其調(diào)用的 C 函數(shù)后才能開(kāi)始。在單個(gè) Lua 任務(wù)中堆疊大量請(qǐng)求會(huì)燒掉寶貴 RAM 并可能觸發(fā) PANIC。這同樣適用于定時(shí)器、網(wǎng)絡(luò)及其他回調(diào)甚至包括請(qǐng)求系統(tǒng)重啟node.restart(); for i 1, 20 do print(not quite yet -- ,i); end這段代碼會(huì)先打印 20 行 not quite yet -- 才重啟——因?yàn)閚ode.restart()也只是排了一個(gè)任務(wù)。結(jié)論必須用事件驅(qū)動(dòng)方式實(shí)現(xiàn)應(yīng)用必須搞清楚哪些 SDK API 調(diào)度異步處理、哪些通過(guò) Lua 回調(diào)定義事件動(dòng)作。這種范式確實(shí)讓過(guò)程式結(jié)構(gòu)難以實(shí)現(xiàn)但非常適合 IoT 設(shè)備上的典型應(yīng)用。3.3 SDK 事件/任務(wù)系統(tǒng)在 Lua 中如何工作SDK 用少量 **ISR中斷服務(wù)例程**處理時(shí)間緊迫的硬件中斷處理持續(xù)時(shí)間極短可打斷運(yùn)行中的任務(wù)最長(zhǎng) 10μSec對(duì)多數(shù)開(kāi)發(fā)者而言修改或新增 ISR 不可行其他所有服務(wù)與應(yīng)用處理被拆分為任務(wù)tasks任務(wù)逐個(gè)執(zhí)行且運(yùn)行到完成沒(méi)有任務(wù)能搶占另一個(gè)任務(wù)可運(yùn)行任務(wù)進(jìn)入三個(gè)優(yōu)先級(jí)隊(duì)列之一SDK 的簡(jiǎn)單調(diào)度器按優(yōu)先級(jí) FIFO 執(zhí)行。高優(yōu)先級(jí)隊(duì)列用于硬件相關(guān)任務(wù)中優(yōu)先級(jí)用于定時(shí)器與事件驅(qū)動(dòng)任務(wù)低優(yōu)先級(jí)用于其他任務(wù)任務(wù)時(shí)長(zhǎng)控制中優(yōu)先級(jí)任務(wù)建議控制在 2mSec 內(nèi)低優(yōu)先級(jí)任務(wù)控制在 15mSec 內(nèi)。這是指導(dǎo)值——超過(guò)可能仍能穩(wěn)定運(yùn)行但也可能因 WiFi/網(wǎng)絡(luò)服務(wù)內(nèi)部超時(shí)而出現(xiàn)間歇性問(wèn)題任務(wù)超過(guò) 500mSec看門狗定時(shí)器會(huì)復(fù)位處理器。應(yīng)用層可用tmr.wdclr()復(fù)位看門狗但應(yīng)避免這樣做應(yīng)用任務(wù)可禁用中斷以保護(hù)關(guān)鍵代碼段但 SDK 建議關(guān)鍵段超過(guò) 10μSec 會(huì)導(dǎo)致系統(tǒng) ISR 超時(shí)。因此這種操作只能存在于用 C 編寫的硬件相關(guān)庫(kù)模塊中Lua 應(yīng)用層不可用SDK 提供 C API包括聲明 C 應(yīng)用函數(shù)為回調(diào)的接口將應(yīng)用任務(wù)與特定硬件/定時(shí)器事件關(guān)聯(lián)其執(zhí)行與 SDK 的 WiFi/網(wǎng)絡(luò)處理任務(wù)交錯(cuò)進(jìn)行。NodeMCU 固件的本質(zhì)一個(gè) C 應(yīng)用利用 Lua 作為嵌入式語(yǔ)言運(yùn)行時(shí)的能力在 Lua 腳本層鏡像這套結(jié)構(gòu)。SDK 與硬件的所有復(fù)雜性與接口都被封裝在固件庫(kù)中翻譯成對(duì)應(yīng)的 Lua APISDK 在啟動(dòng)時(shí)調(diào)用固件內(nèi)的啟動(dòng)鉤子初始化 Lua 環(huán)境并嘗試從 SPIFFS 執(zhí)行init.lua。該模塊可完成應(yīng)用初始化并調(diào)用定時(shí)器報(bào)警或庫(kù)調(diào)用綁定回調(diào)例程以響應(yīng)系統(tǒng)事件默認(rèn)情況下Lua 運(yùn)行時(shí)還以交互模式監(jiān)聽(tīng)UART 0串口執(zhí)行通過(guò)串口輸入的任何 Lua 命令。這是 ESP8266 上開(kāi)發(fā)調(diào)試 Lua 應(yīng)用最常用的方式Lua 庫(kù)提供聲明 Lua 回調(diào)的函數(shù)存儲(chǔ)在 Lua Registry 中見(jiàn)下文將應(yīng)用任務(wù)與硬件/定時(shí)器事件關(guān)聯(lián)。例如mytimer:alarm(interval, repeat, callback)調(diào)用tmr庫(kù)中的函數(shù)該函數(shù)用 SDK 為此報(bào)警注冊(cè)一個(gè) C 函數(shù)C 報(bào)警回調(diào)被調(diào)用時(shí)再轉(zhuǎn)而調(diào)用 Lua 回調(diào)過(guò)長(zhǎng)的 Lua 函數(shù)或交互提示符輸入的長(zhǎng)代碼塊會(huì)導(dǎo)致其他系統(tǒng)功能與服務(wù)超時(shí)或耗盡 RAM 緩沖排隊(duì)數(shù)據(jù)最終觸發(fā)看門狗或內(nèi)存耗盡導(dǎo)致系統(tǒng)重啟。FAQ 給事件驅(qū)動(dòng)范式下了三條鐵律如果不用定時(shí)器和回調(diào)你就用錯(cuò)了方法如果使用輪詢循環(huán)你就用錯(cuò)了方法如果每個(gè)回調(diào)執(zhí)行超過(guò)幾百行 Lua你就用錯(cuò)了方法。3.4 哪些 Lua 庫(kù)函數(shù)支持注冊(cè)回調(diào)Lua 模塊定義或移除回調(diào)的函數(shù)tmrregister([id,] interval, mode, function())nodetask.post([task_priority], function)、output(function(str), serial_debug)wifistartsmart(chan, function())、sta.getap(function(table))net.serversk:listen(port,[ip],function(socket))netsk:on(event, function(socket, [, data]))、sk:send(string, function(sent))、sk:dns(domain, function(socket,ip))gpiotrig(pin, type, function(level))mqttclient:m:on(event, function(conn[, topic, data])uartuart.on(event, cnt, [function(data)], [run_input])以tmr為例從 app/modules/tmr.c 源碼可見(jiàn)其回調(diào)注冊(cè)機(jī)制t:alarm()依次調(diào)用tmr_register()與tmr_start()注冊(cè)時(shí)通過(guò)luaL_ref(L, LUA_REGISTRYINDEX)將定時(shí)器 userdata 存入 Lua Registrytmr.c#L136-L137報(bào)警觸發(fā)時(shí)用lua_rawgeti(L, LUA_REGISTRYINDEX, tmr-self_ref)取回對(duì)象、以luaL_pcallx(L, 1, 0)保護(hù)性調(diào)用 Lua 回調(diào)tmr.c#L63-L74。t:unregister()則通過(guò)luaL_unref2釋放 Registry 引用并解除 os_timertmr.c#L187-L195——這就是 FAQ 強(qiáng)調(diào)用完必須 unregister否則 Registry 泄漏的底層原因。3.5 變量聲明方式NodeMCU 環(huán)境下為何尤其重要標(biāo)準(zhǔn) Lua 語(yǔ)義但在 NodeMCU 中理解它尤為重要。所有變量可分為全局global、局部local、上值upvalue。默認(rèn)情況下任何被引用且未聲明為local的變量都是全局的會(huì)一直駐留在全局表中直到被顯式刪除。查看當(dāng)前全局變量for k,v in pairs(_G) do print(k,v) end局部變量是詞法作用域的可在嵌套塊或函數(shù)內(nèi)聲明而不影響外層作用域內(nèi)層作用域也可引用外層局部變量這類變量稱為上值upvalues。Lua 變量可承載兩類數(shù)據(jù)值數(shù)字、布爾、字符串與引用函數(shù)、表、userdata。把變量a賦給b時(shí)值是簡(jiǎn)單拷貝引用則讓a、b指向同一個(gè)對(duì)象不做內(nèi)容拷貝。這會(huì)產(chǎn)生反直覺(jué)的后果。例如下面代碼退出時(shí)tmr2func已不在作用域但 alarm API 調(diào)用已把對(duì)該函數(shù)的引用存入 Lua Registry因此它與所用上值會(huì)持續(xù)存在直到被完全解除引用如tmr2:unregister()do local tmr2func function() ds.convert_T(true); tmr1:start() end tmr2:alarm(300000, tmr.ALARM_AUTO, tmr2func) end要區(qū)分函數(shù)編譯、綁定為閉包與運(yùn)行時(shí)調(diào)用三個(gè)時(shí)刻。閉包通常在編譯后立即綁定一次但不必然。以下例來(lái)自 FAQ 作者 TerryE 的 MCP23008 模塊-- Bind the read and write functions for commonly accessed registers for reg, regAddr in pairs { IODOR 0x00, GPPU 0x06, -- Pull-up resistors register for MCP23008 GPIO 0x09, OLAT 0x0A, } do dev[write .. reg] function(o, dataByte) write(MCP23008addr, regAddr, dataByte) end dev[read .. reg] function(o) return read(MCP23008addr, regAddr) end end此循環(huán)在模塊被 require 時(shí)只編譯一次讀寫函數(shù)的 opcode 向量連同記錄上值與局部變量數(shù)量的頭信息在編譯時(shí)創(chuàng)建但這兩個(gè)函數(shù)被綁定四次為不同函數(shù)如mcp23008.writeIODOR()每個(gè)閉包繼承自己的上值副本該函數(shù)的regAddr為0x00。上值列表在閉包創(chuàng)建時(shí)生成即便最初聲明它們的外層函數(shù)已離開(kāi)作用域并被 GC只要閉包存在Lua RTS 也保證其上值繼續(xù)存活。而局部變量的存儲(chǔ)每次調(diào)用該例程時(shí)分配在運(yùn)行的應(yīng)用中可能分配很多次。性能差異Lua 運(yùn)行時(shí)內(nèi)部用哈希鍵訪問(wèn)從表取鍵值局部變量與上值則存儲(chǔ)為連續(xù)向量、按下標(biāo)直接訪問(wèn)快得多。NodeMCU 對(duì)固件側(cè)表的訪問(wèn)尤其慢因此模塊開(kāi)頭常見(jiàn)如下語(yǔ)句——用局部變量與上值既快又減少字節(jié)碼指令local i2c i2c local i2c_start, i2c_stop, i2c_address, i2c_read, i2c_write, i2c_TRANSMITTER, i2c_RECEIVER i2c.start, i2c.stop, i2c.address, i2c.read, i2c.write, i2c.TRANSMITTER, i2c.RECEIVER3.6 事件任務(wù)之間如何傳遞上下文單個(gè) Lua 函數(shù)與每個(gè)事件回調(diào)任務(wù)綁定由 NodeMCU 庫(kù) C 代碼通過(guò)lua_call()執(zhí)行——連執(zhí)行dofile(init.lua)的系統(tǒng)初始化都是它的特例。函數(shù)可繼續(xù)調(diào)用其他函數(shù)但最終必須把控制權(quán)返回 C 庫(kù)代碼再由后者返回 SDK結(jié)束該任務(wù)。local變量天然只存在于執(zhí)行中的 Lua 函數(shù)上下文中退出即失去引用局部數(shù)據(jù)除非同時(shí)被別處引用的引用類型可在lua_call()之間被 GC。因此事件例程間傳遞上下文只能靠以下機(jī)制全局變量天然全局可訪問(wèn)直到顯式賦nil才解除??捎胒or k,v in pairs(_G)枚舉使用透明文件系統(tǒng)持久全局的特例原則上可用于傳上下文。但 ESP8266 文件系統(tǒng)基于 FlashSPIFFS 寫入壽命有限應(yīng)避免用于頻繁變化的內(nèi)容除非萬(wàn)不得已Lua Registry通常隱藏的表庫(kù)模塊用它存回調(diào)函數(shù)與其他 Lua 數(shù)據(jù)類型。GC 視 Registry 為在作用域內(nèi)因此其中引用的一切都不會(huì)被回收上值NodeMCU 完整實(shí)現(xiàn)的 Lua 標(biāo)準(zhǔn)特性。函數(shù)在外層函數(shù)內(nèi)聲明時(shí)外層作用域的所有局部變量對(duì)內(nèi)層函數(shù)可用。深入原理可參考 Ierusalimschy 的論文Closures in Lua。3.7 Lua Registry 如何工作為何重要所有 Lua 回調(diào)都由 NodeMCU 庫(kù)中的C 包裝函數(shù)調(diào)用這些 C 函數(shù)本身是被 SDK 因某事件激活的回調(diào)。C 包裝函數(shù)經(jīng)常需要跨調(diào)用或在包裝函數(shù)間保存狀態(tài)——Lua Registry正是為此服務(wù)的特殊 Lua 表它對(duì) Lua 直接訪問(wèn)隱藏但用標(biāo)準(zhǔn) Lua 表作為存儲(chǔ)使標(biāo)準(zhǔn) GC 算法可對(duì)其內(nèi)容操作。需要保存的內(nèi)容以唯一鍵創(chuàng)建。被全局引用或 Registry 引用的函數(shù)的上值會(huì)在事件例程間存活故這些上值也可用于傳上下文。內(nèi)存泄漏常見(jiàn)根源如果內(nèi)存耗盡很可能是沒(méi)有正確清理 Registry 條目。例如設(shè)置了定時(shí)器卻不 unregister又如以下片段on()把 socket 作為第一個(gè)參數(shù)sck傳給連接回調(diào)它是回調(diào)內(nèi)的局部變量同時(shí)與上值srv引用同一個(gè) socket功能上srv與sck可互換。那為何要傳參因?yàn)?GC socket 通常會(huì)自動(dòng) unregister 其回調(diào)但若把 socket 用作回調(diào)的上值socket 就被 Registry 引用而不會(huì)被 GC——Catch-22這是編程錯(cuò)誤而非 bugsrv:on(connection, function(sck, c) svr:send(reply) -- should be sck instead of srv end)正確的回調(diào)實(shí)現(xiàn)示例見(jiàn) net socket 文檔。檢查 Registry 是否泄漏可用for k,v in pairs(debug.getregistry()) do print (k,v) end如果它在增長(zhǎng)說(shuō)明存在泄漏。3.8 如何跟蹤全局變量參考 Unofficial Lua FAQ 的 Detecting Undefined VariablesFAQ 作者的做法除非有非常充分的理由否則避免使用全局變量。用luac -p -l XXX.lua | grep GLOBAL靜態(tài)過(guò)濾新模塊把意外產(chǎn)生的全局變量改成 local 或 upvalued local在 NodeMCU 上_G的 metatable 就是_G本身所以可以創(chuàng)建所需全局變量后關(guān)上大門_G.__newindexfunction(g,k,v) error (attempting to set global ..k.. to ..v) end此后任何創(chuàng)建新全局變量的嘗試都會(huì)拋錯(cuò)并給出 traceback 指出發(fā)生位置。3.9 理解上值實(shí)現(xiàn)為何對(duì) ESP8266 編程重要上值使用是 Lua 核心特性外層作用域定義的任何例程都可使用包括被_G全局表或 Lua Registry 直接/間接引用的例程。一個(gè)例程關(guān)聯(lián)的上值數(shù)量在編譯期算出閉包綁定時(shí)為其分配棧向量。每個(gè)上值分open開(kāi)放或 closed閉合初始都是 open即上值回指外層函數(shù)的寄存器集但上值必須能比外層例程中聲明它的局部變量存活更久。運(yùn)行時(shí) VM 通過(guò)在函數(shù)返回時(shí)增加額外檢查來(lái)實(shí)現(xiàn)掃描其作用域內(nèi)定義的任何閉包的回引分配內(nèi)存保存上值并讓其引用指向該內(nèi)存——這就是 closed upvalue。這是 Lua 5.x 運(yùn)行時(shí)成熟的部分正常應(yīng)用開(kāi)發(fā)中這些幕后魔法讓上值按程序員預(yù)期工作同時(shí)存儲(chǔ)了足夠 GC 元數(shù)據(jù)使這些隱藏值在正確解除引用時(shí)被正確回收。一個(gè)復(fù)雜化因素部分庫(kù)函數(shù)不會(huì)隱式解除已過(guò)期的回調(diào)引用導(dǎo)致其上值可能不被 GC表現(xiàn)為內(nèi)存泄漏在測(cè)試中則表現(xiàn)為更頻繁、更難診斷的 PANIC。因此 FAQ 作者的一般建議初期開(kāi)發(fā)堅(jiān)持用全局變量用完的顯式置nil解除引用。3.10 能否把發(fā)郵件這類動(dòng)作封裝成 Lua 函數(shù)想想前面的幾個(gè)答案。發(fā)一封郵件涉及與郵件服務(wù)器在 TCP 上的消息對(duì)話需要多次調(diào)用 SDK API且 Lua 代碼必須返回控制權(quán)給 C 調(diào)用庫(kù)才能調(diào)度這些請(qǐng)求否則請(qǐng)求只是排隊(duì)RAM 耗盡后應(yīng)用 PANIC。因此不可能寫一個(gè)模塊讓你這樣調(diào)用-- prepare message status mail.send(to, subject, body) -- move on to next phase of processing.但可以把它寫成事件驅(qū)動(dòng)任務(wù)并傳入完成時(shí)執(zhí)行的回調(diào)。注意因涉及大量異步處理、只有返回調(diào)用庫(kù) C 代碼后才會(huì)發(fā)生通常應(yīng)作為函數(shù)的最后一步執(zhí)行最好像這樣用尾調(diào)用tailcall[PiL 6.3]-- prepare message local ms require(mail_sender) return ms.send(to, subject, body, function(status) loadfile(process_next.lua)(status) end)FAQ 的比喻很貼切在 ESP8266 上構(gòu)建應(yīng)用如同把珍珠串成項(xiàng)鏈——每顆珍珠是一個(gè)足夠小、能在自身 RAM 資源內(nèi)運(yùn)行的事件任務(wù)串起珍珠的線是把它們連接起來(lái)的變量上下文。3.11 何時(shí)、為何避免tmr.delay()過(guò)程式編程者自然想用tmr.delay()做時(shí)序控制。但在事件驅(qū)動(dòng)范式下查看 app/modules/tmr.c 中該函數(shù)的實(shí)現(xiàn)os_delay_us()忙等循環(huán)期間還會(huì)調(diào)用system_soft_wdt_feed()喂軟看門狗它真的只適用于需要對(duì)外部硬件 I/O 做較精確時(shí)序控制的場(chǎng)合例如把 GPIO 引腳拉高 20μSec執(zhí)行期間中斷是使能的不保證延遲與請(qǐng)求完全一致Lua RTS 本身也可能注入 GC 等操作——若需要這種精度應(yīng)該寫成 C 庫(kù)在其他幾乎所有場(chǎng)景它都沒(méi)有功能意義任何其他系統(tǒng)代碼活動(dòng)都會(huì)被阻塞最壞情況是破壞應(yīng)用、制造難以診斷的超時(shí)錯(cuò)誤。因此 FAQ 將其一般用途標(biāo)記為棄用deprecated。3.12 如何避免init.lua的 PANIC 循環(huán)大多數(shù)開(kāi)發(fā)者都掉進(jìn)過(guò)這個(gè)坑init.lua有 bug導(dǎo)致系統(tǒng)反復(fù)重啟進(jìn)入重啟循環(huán)。此時(shí)唯一穩(wěn)妥的解決方案是重刷固件。避免重刷的最簡(jiǎn)辦法讓init.lua盡量簡(jiǎn)單——例如配置 WiFi 后用一次性tmr.alarm()延遲 2–3 秒再啟動(dòng)應(yīng)用。這個(gè)延遲足夠你在串口發(fā)出file.remove(init.lua)奪回控制權(quán)。另一個(gè)技巧啟動(dòng)時(shí)輪詢一個(gè)空閑的 GPIO 輸入引腳。FAQ 作者在板子上把該 GPIO 加 Vcc 接到跳線設(shè)置跳線即可進(jìn)入調(diào)試模式或重新供給軟件。另外新init.lua永遠(yuǎn)先測(cè)試再啟用先以init_test.lua命名通過(guò)串口手動(dòng)執(zhí)行dofile(init_test.lua)確認(rèn)正常后再改名。倉(cāng)庫(kù)文檔 docs/upload.md 給出了詳細(xì)的 init.lua 示例先dofile(credentials.lua)加載憑據(jù)通過(guò) WiFi 事件回調(diào)wifi_connect_event、wifi_got_ip_event、wifi_disconnect_event管理連接狀態(tài)拿到 IP 后用tmr.create():alarm(3000, tmr.ALARM_SINGLE, startup)延遲 3 秒啟動(dòng)startup()startup()內(nèi)先檢查init.lua是否被刪除/改名再dofile(application.lua)真正啟動(dòng)應(yīng)用——這正是 FAQ 建議的啟動(dòng)窗口內(nèi)可中斷模式的標(biāo)準(zhǔn)實(shí)現(xiàn)。4. 編譯與調(diào)試FAQ 建議在開(kāi)發(fā)主機(jī)上安裝 Lua 5.1不僅方便在 PC 上調(diào)試 Lua 片段還可用于編譯校驗(yàn)luac -p做語(yǔ)法驗(yàn)證。還可以在開(kāi)發(fā)主機(jī)上構(gòu)建luac.cross若本機(jī)裝有 Lua。它運(yùn)行在主機(jī)上具備標(biāo)準(zhǔn)luac的全部功能區(qū)別是輸出代碼文件可在 NodeMCU 下作為.lc文件運(yùn)行。倉(cāng)庫(kù)中相關(guān)源碼位于 app/lua/luac_cross/Windows 下也可用 msvc/luac-cross/ 工程構(gòu)建。5. 降低 RAM 與 SPIFFS 占用的實(shí)用技術(shù)5.1 如何最小化應(yīng)用范圍最基礎(chǔ)的一步是把應(yīng)用范圍搞正確。ESP8266 是 IoT 設(shè)備而非通用系統(tǒng)典型用途是把現(xiàn)實(shí)世界的監(jiān)控、控制等接入內(nèi)網(wǎng)。最安全穩(wěn)妥的 IoT 使用方式是通過(guò)同一網(wǎng)絡(luò)的專用通用系統(tǒng)控制它們——可以是低成本方案如 Raspberry Pi 服務(wù)器跑自定義代碼或開(kāi)源家庭自動(dòng)化應(yīng)用此類系統(tǒng)容量比 ESP8266 高幾個(gè)數(shù)量級(jí)例如 RPi 有 2GB RAM、SD 卡可達(dá) 32GB還能支持 USB 外設(shè)、運(yùn)行完整 Linux、有豐富的預(yù)配置應(yīng)用也有 $50 以下的諸多替代品以及貴 10–50 倍的自有 HA 系統(tǒng)。采用分層架構(gòu)所有對(duì) ESP8266 的用戶訪問(wèn)都經(jīng)過(guò)控制服務(wù)器意味著用戶界面或手機(jī)連接器及其驗(yàn)證與安全可在為容量設(shè)計(jì)的系統(tǒng)上實(shí)現(xiàn)ESP8266 應(yīng)用只需實(shí)現(xiàn)一組有限的功能——發(fā)送請(qǐng)求或響應(yīng)該系統(tǒng)的請(qǐng)求。如果你想在 ESP8266 里實(shí)現(xiàn)用戶界面或 HTTP Web 服務(wù)器那你真的在濫用它的設(shè)計(jì)目的。給 ESP8266 應(yīng)用定范圍時(shí)KISSKeep It Simple, Stupid原則真正適用。5.2 如何最小化應(yīng)用在文件系統(tǒng)上的占用Lua 可以寫得非常緊湊單位 KB 源碼的功能密度極高但這樣做會(huì)極難調(diào)試與維護(hù)好的折中方案是用LuaSrcDiet壓縮要下載到 ESP8266 的生產(chǎn)代碼在 PC 或云端版本庫(kù)如 GitHub維護(hù)主源碼倉(cāng)庫(kù)排版與注釋按易維護(hù)、易調(diào)試來(lái)組織用 ESPlorer 下載正在調(diào)試的模塊并測(cè)試代碼測(cè)試穩(wěn)定后先經(jīng) LuaSrcDiet 壓縮再下載到 ESP8266。這樣 SPIFFS 上的代碼占用可減少 2–3 倍。LuaSrcDiet 還有一種模式能達(dá)到約 95% 的壓縮效果但保留行號(hào)基于行號(hào)的錯(cuò)誤信息仍可用。標(biāo)準(zhǔn) Lua 編譯代碼包含大量調(diào)試信息幾乎使 RAM 體積翻倍。node.stripdebug() 可改變默認(rèn)設(shè)置為特定模塊增加調(diào)試信息或去掉行號(hào)信息省一點(diǎn)空間。而用node.compile()預(yù)編譯生產(chǎn)代碼會(huì)移除所有編譯信息含錯(cuò)誤行號(hào)故只推薦用于不需要行號(hào)的穩(wěn)定生產(chǎn)代碼。從 app/modules/node.c 源碼看node.stripdebug()支持 1–3 級(jí)剝離級(jí)別 3 丟棄局部變量、上值與行號(hào)調(diào)試信息可針對(duì)具體函數(shù)通過(guò)棧級(jí)指定 scope剝離并返回估計(jì)的剝離字節(jié)數(shù)。5.3 如何最小化運(yùn)行中應(yīng)用的內(nèi)存占用Lua 垃圾回收器非常激進(jìn)地掃描與回收死資源采用增量標(biāo)記-清除策略任何未被最終引用回全局表、Lua Registry 或當(dāng)前 Lua 代碼在作用域內(nèi)的局部變量的數(shù)據(jù)都會(huì)被回收。將變量置nil即解除其先前內(nèi)容的引用。引用型變量如表、字符串、函數(shù)可被多個(gè)變量引用同一對(duì)象一旦最后一個(gè)引用置nil收集器即回收其存儲(chǔ)。與 PHP 等編譯時(shí)加載語(yǔ)言不同Lua 編譯代碼在 GC 上與其他變量類型同等對(duì)待完全解除引用后即可被回收代碼空間可復(fù)用。默認(rèn) GC 模式非常激進(jìn)每次分配后都觸發(fā) GC sweep。參見(jiàn) node.egc.setmode() 調(diào)整node.egc.setmode(node.egc.ON_MEM_LIMIT, 4096)這是性能與保留足夠空閑內(nèi)存之間的良好折中。源碼中 node_egc_setmode 校驗(yàn) mode 不超過(guò)常量組合、且ON_MEM_LIMIT模式下 limit 必須非零node.egc.meminfo()node.c#L613-L620可返回totalallocated, estimatedused兩個(gè)值輔助觀察。Lua 執(zhí)行天然被劃分為事件任務(wù)、各綁定一個(gè) Lua 回調(diào)加上解除引用即強(qiáng)回收特性很容易應(yīng)用可追溯到 1950 年代的經(jīng)典技術(shù)——Overlay覆蓋。實(shí)現(xiàn)方式之一見(jiàn) DP Whittaker 的Massive memory optimization: flash functions主題。另一種是使用volatile modules易失模塊。標(biāo)準(zhǔn) Lua 模塊模板中require()會(huì)在package.loaded表里創(chuàng)建已加載模塊的引用該引用阻止模塊被 GC。要讓模塊易失需把package.loaded中對(duì)應(yīng)條目置nil來(lái)移除該引用。不能在模塊最外層這么做引用要等模塊代碼執(zhí)行返回后才創(chuàng)建但可在任何模塊函數(shù)中做通常是初始化函數(shù)local s net.createServer(net.TCP) s:listen(80, function(c) require(connector).init(c) end)connector.lua用標(biāo)準(zhǔn)模塊模式但M.init()例程必須包含local M, module {}, ...... function M.init(csocket) package.loaded[module] nil... end return M這樣保證模塊在完成后可被完全解除引用。代價(jià)是每個(gè)到 80 端口的 TCP 連接都要重載模塊但從 SPIFFS 加載編譯模塊只需幾 mSec如果這能幫你把應(yīng)用拆成 RAM 尺寸的塊這是可接受的。注意require()會(huì)自動(dòng)依次搜索connector.lc、connector.lua因此源碼與編譯變體都能工作。另外雖然慣例是模塊返回一個(gè)表但 [PiL 15.1] 指出有時(shí)返回單個(gè)函數(shù)更合適——省去額外表的開(kāi)銷local s net.createServer(net.TCP) s:listen(80, function(c) require(connector)(c) end)local module _ -- this is a situation where using an upvalue is essential! return function(csocket) package.loaded[module] nil module nil... end注意不要這樣寫監(jiān)聽(tīng)回調(diào)因?yàn)?RAM 必須同時(shí)容納創(chuàng)建服務(wù)器的模塊與 connector 邏輯... local s net.createServer(net.TCP) local connector require(connector) -- dont do this unless youve got the RAM available! s:listen(80, connector)5.4 如何減小編譯代碼的體積向 SPIFFS 保存編譯后的 Lua 有兩種方式用node.compile()編譯.lua源文件生成等價(jià)字節(jié)碼.lc文件。該方式剝離全部調(diào)試行號(hào)與變量信息先用loadfile()把源文件加載進(jìn)內(nèi)存再用string.dump()轉(zhuǎn)成內(nèi)存中的序列化加載格式寫回.lc文件。保留的調(diào)試信息量取決于 node.stripdebug() 設(shè)置。從 node_compile 源碼可見(jiàn)node.compile()校驗(yàn)文件名以.lua結(jié)尾加載源碼后以stripping 1調(diào)用lua_dump寫出.lc即默認(rèn)徹底剝離調(diào)試信息若目標(biāo)固件為整數(shù)算術(shù)構(gòu)建還可能報(bào) value too big or small for target integer type 等轉(zhuǎn)換錯(cuò)誤。體積差異方法 1 創(chuàng)建的字節(jié)碼 RAM 占用與直接執(zhí)行源文件相同方法 2 的字節(jié)碼在 stripdebug 級(jí)別 3 下比保留調(diào)試信息的 dump小約 10%在級(jí)別 1 下小約 60%——因?yàn)檎{(diào)試信息幾乎和代碼本身一樣大。選擇建議方法 2loadfilestring.dump適合希望在盡可能低 RAM 占用下運(yùn)行的穩(wěn)定生產(chǎn)代碼仍在調(diào)試階段時(shí)選方法 1 即可但調(diào)試期代碼改動(dòng)頻繁直接用.lua文件更省事。關(guān)鍵便利用require(XXX)加載代碼會(huì)自動(dòng)依次搜索XXX.lc、XXX.lua因此無(wú)需自己寫條件邏輯判斷加載字節(jié)碼版本還是源碼版本。5.5 如何感知函數(shù)占用多少內(nèi)存想用好有限資源應(yīng)對(duì) VM 模型有整體理解。必備參考資料是A No Frills Introduction to Lua 5.1 VM Instructions它解釋代碼生成器如何工作、每個(gè)表/函數(shù)/字符串的內(nèi)存開(kāi)銷。在 ESP8266 上難以直接得到字節(jié)碼清單但有兩個(gè)寬泛途徑在開(kāi)發(fā) PC 上生成字節(jié)碼清單Lua 5.1 代碼生成器在 PC 與 ESP8266 上基本一致雖非完全相同用標(biāo)準(zhǔn)luac配合-l -s選項(xiàng)即可大致了解代碼會(huì)生成什么。兩者主要差異ESP8266 的size_t是 4 字節(jié)而非現(xiàn)代 64 位 PC 的 8 字節(jié)eLua 變體對(duì) ROM 數(shù)據(jù)類型生成不同的訪問(wèn)引用。想看string.dump()版本生成什么就去掉-s保留調(diào)試信息。也可用本固件構(gòu)建luac.cross生成針對(duì) ESP 架構(gòu)的.lc代碼把.lc文件上傳到 PC 反匯編多種 Lua 反匯編器可列出應(yīng)用模塊生成的編譯代碼前提是有腳本把文件從 ESP8266 上傳到 PC。FAQ 作者用ChunkSpy但需要打補(bǔ)丁讓它理解 eLua 數(shù)據(jù)類型--- a/ChunkSpy-0.9.8/5.1/ChunkSpy.lua 2015-05-04 12:39:01.267975498 0100 b/ChunkSpy-0.9.8/5.1/ChunkSpy.lua 2015-05-04 12:35:59.623983095 0100 -2193,6 2193,9 config.AUTO_DETECT true elseif a --brief then config.DISPLAY_BRIEF true elseif a --elua then config.LUA_TNUMBER 5 config.LUA_TSTRING 6 elseif a --interact then perform ChunkSpy_Interact另一個(gè)得力工具是在代碼中經(jīng)常調(diào)用node.heap()node.c#L346 處的node_heap實(shí)現(xiàn)返回當(dāng)前空閑堆內(nèi)存字節(jié)數(shù)監(jiān)控內(nèi)存水位。用這些工具反復(fù)實(shí)驗(yàn)體會(huì)每種編碼風(fēng)格下典型代碼行生成的指令數(shù)。Lua Wiki 給出了一些通用優(yōu)化技巧但要記住那些主要針對(duì)執(zhí)行速度優(yōu)化而你要優(yōu)化的是代碼與變量空間——那才是消耗寶貴 RAM 的東西。5.6 使用函數(shù)的代價(jià)函數(shù)有固定開(kāi)銷因此把應(yīng)用代碼分組到較大的函數(shù)中總體 RAM 占用更少。主要告誡是如果開(kāi)始在函數(shù)間復(fù)制粘貼代碼就是在浪費(fèi)資源。當(dāng)然仍應(yīng)使用函數(shù)來(lái)結(jié)構(gòu)化代碼、封裝公共重復(fù)處理但要記住每個(gè)函數(shù)定義對(duì)其頭記錄與棧幀都有相對(duì)較高的開(kāi)銷。盡量別過(guò)度使用函數(shù)若函數(shù)只有十幾行左右且合理應(yīng)考慮內(nèi)聯(lián)。5.7 其他可用資源在開(kāi)發(fā) PC 上安裝lua與luacWindows/Mac/Linux 均可免費(fèi)獲得但強(qiáng)烈建議用Lua 5.1保持與 ESP8266 代碼的源碼兼容。這不僅能在豐富的開(kāi)發(fā)環(huán)境中單測(cè)部分模塊還能用luac生成字節(jié)碼清單、在下載到 ESP8266 前做新代碼語(yǔ)法校驗(yàn)并允許以同一種語(yǔ)言開(kāi)發(fā)服務(wù)端應(yīng)用與嵌入式應(yīng)用。6. 固件與 Lua 應(yīng)用開(kāi)發(fā)6.1 如何減小固件體積推薦使用定制固件構(gòu)建只包含開(kāi)發(fā) Lua 應(yīng)用所需的模塊。一旦具備制作與燒錄自定義構(gòu)建的能力還可以把時(shí)間敏感或邏輯密集的代碼移入自定義 C 模塊——C 代碼可直接從 Flash 運(yùn)行能節(jié)省大量 RAM。構(gòu)建固件的詳細(xì)方法與選項(xiàng)見(jiàn) 構(gòu)建固件文檔倉(cāng)庫(kù)內(nèi)對(duì)應(yīng) docs/compiling.md。這也呼應(yīng)了 FAQ 開(kāi)篇的團(tuán)隊(duì)實(shí)踐現(xiàn)代構(gòu)建通過(guò) LTR 等技術(shù)將常量數(shù)據(jù)移入固件地址空間才使典型構(gòu)建的空閑 RAM 從約 15KB 提升到 40KB 以上你在應(yīng)用層做的每一次裁剪模塊選擇、bytecode 編譯、易失模塊、事件驅(qū)動(dòng)的短任務(wù)都是這種資源意識(shí)的延續(xù)。7. 總結(jié)一套可復(fù)用的 NodeMCU 開(kāi)發(fā)心智模型范式優(yōu)先任何 ESP8266 Lua 應(yīng)用都應(yīng)是事件驅(qū)動(dòng)的——回調(diào)注冊(cè)、短任務(wù)、無(wú)輪詢、無(wú)長(zhǎng)時(shí)間同步阻塞含tmr.delay()與連續(xù)socket:send()的誤區(qū)資源意識(shí)從范圍KISS 分層架構(gòu)到運(yùn)行時(shí)局部變量/上值、nil解除引用、易失模塊、node.stripdebug()/node.compile()每一步都在為 45KB 級(jí) RAM 做預(yù)算上下文管理全局、Registry、上值三者各有代價(jià)——全局透明但易污染Registry 是庫(kù)回調(diào)的存儲(chǔ)基座不清理即泄漏上值優(yōu)雅但可能隱性泄漏開(kāi)發(fā)期建議先用全局并顯式nil防御性啟動(dòng)init.lua保持簡(jiǎn)單、帶 2–3 秒中斷窗口、先以init_test.lua驗(yàn)證避免 PANIC 重啟循環(huán)后被迫重刷固件工具鏈主機(jī)裝 Lua 5.1 與luac、構(gòu)建luac.cross、用node.heap()監(jiān)控、必要時(shí)用 ChunkSpy 反匯編.lc把內(nèi)存當(dāng)成可觀測(cè)、可優(yōu)化的工程指標(biāo)。贊分享物聯(lián)網(wǎng)嵌入式【免費(fèi)下載鏈接】nodemcu-firmwareLua based interactive firmware for ESP8266, ESP8285 and ESP32項(xiàng)目地址https://gitcode.com/gh_mirrors/no/nodemcu-firmware點(diǎn)擊查看免費(fèi)下載相關(guān)推薦TensorZero 網(wǎng)關(guān) OTLP 鏈路追蹤導(dǎo)出實(shí)戰(zhàn)把推理 Trace 接入 JaegerTensorZero 網(wǎng)關(guān) OTLP 鏈路追蹤導(dǎo)出實(shí)戰(zhàn)把推理 Trace 接入 Jaeger 本文以 TensorZero 倉(cāng)庫(kù)中的 examples/gui物聯(lián)網(wǎng)嵌入式NodeMCU固件深度解析ESP8266/ESP32的Lua交互固件革命NodeMCU是一款基于Lua的開(kāi)源固件專為ESP8266和ESP32 WiFi SoC設(shè)計(jì)。這個(gè)強(qiáng)大的固件讓物聯(lián)網(wǎng)開(kāi)發(fā)變得前所未有的簡(jiǎn)單通過(guò)Lua腳本語(yǔ)言物聯(lián)網(wǎng)嵌入式sherpa-onnx WebAssembly 關(guān)鍵詞識(shí)別KWS實(shí)戰(zhàn)模型下載、資源準(zhǔn)備與 WASM 構(gòu)建sherpa onnx WebAssembly 關(guān)鍵詞識(shí)別KWS實(shí)戰(zhàn)模型下載、資源準(zhǔn)備與 WASM 構(gòu)建 導(dǎo)讀 本文圍繞 sherpa onnx 倉(cāng)庫(kù)中物聯(lián)網(wǎng)嵌入式上一篇TrollInstallerX終極指南一鍵在iOS設(shè)備上安裝TrollStore的完整教程下一篇3分鐘掌握Z(yǔ)otero谷歌學(xué)術(shù)引用統(tǒng)計(jì)插件的完整使用指南創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
亚洲图片日本AⅤ欧美在线| 国产suv一区二区三区6| 熟妇女人妻呻吟久久AV| 综合色图亚洲欧美| 日本色婷婷| 亚洲视频精选| 国产成人AV麻豆| 蜜臀AV成人精品蜜臀| 精品人妻一区二区三区日产| 大香蕉碰碰| 男同专区一区二区三区在线| 日本三级大片| 日韩综合色图| 老熟女熟妇| 蜜乳视频网站| 91人人看| 亚洲成a人片在线观看中文!!!| 大香蕉99999| 婷婷五月综合激情| 特级特黄一级毛片免费| 91久久久老司机| xxx0国产在线播放| 亚州性9| 人妻精品4K4K4K4K4| 热思思免费视频| 丝袜美腿校园春色| 亚洲日本成人动漫| 日韩欧美一级特黄大片| 五月婷婷爱六月丁香色| 18禁精品网站在线看| AV色女综合| 成 人 影视 一区 二区 三区 四区| 婷婷五月丁香五月| 中文字幕欧美丝袜07资源| 大香樵伊人网| 大屁股熟女一区二区三区| 成人无码在线超碰网| 精吧天堂| 欧洲中文字幕| 又黄又爽在线观看视频| 久操网址| 中文字幕精品一区二| 加勒比色综合| 9精品久久| 色97| 丁香五月社区| 日韩,欧美,中文在线| 视频一区二区免费在线| 亚洲少妇视频| 欧美性Fer办公室秘书| 亚洲欧美激情另类色图| 97干在线| 日韩操逼性鲍| 欧美中文字幕日韩在线| 色欧美亚洲| 91 亚洲情侣偷拍 久久| 刺激性视频黄页| 九九热在线精品视频| 高潮毛片无遮挡高清免费| 97爱亚洲| 国产久久久久久| 久久久999国产精品| 欧美色图91p| 欧美97日韩精品| 极品内射| 日本三级韩三级99久久| 亚洲天堂,男人| 成人日韩欧美| 精品一区二区三区蜜桃臀赵总| 久久久性爱| 人伦四五区| 久久久久久久久久久久久久久久9| 91丨国产丨白浆秘 洗澡动漫| 丁香五月天婷婷姐| 九九久久首页| 日韩噜噜69| 91色伦综合| 精品美女久久一二三| 97亚洲欧美日韩| 91黑丝操| 欧美黑人与女人91~| 精品人妻一区二区三区-国产精品 一个人在线看的黄色电影网站 | 九九精品美女高溯喷水| 97色婷婷| 富二代亚洲精品99| 磁力99AV| 亚洲国产97在线精品一区| AV 少妇 人妻 偷拍| 欧美一级三级| 日韩偷拍一区二区三区| 亚洲成A∨人影院在线欢看| 最新欧洲欧美日本激情网站| 9热9热综合网| 亚洲中文一区二区三区视频| 久久久三区二区一区| 国产在线综合网| 亚洲日韩资源| 免费视频a级毛片免费视频| 亚洲色狠| 丁香五六月啪啪| 日本一二三免费久久| 狠狠亚洲| 亚洲熟女乱色一区二区三区久久久| 久久久久96| 清清一区二区三区四区不卡视频| 欧美裸体美女日麻屄| 嫩草 我啊~嗯~在线| 巨爆乳肉感一区二区三区竹菊影视 | 色婷婷综合久久久久中文一区二区 | 久久久久斤小| 日日干夜夜欢| 国产熟女精品区| 人妻密肉在线观看| 亚洲熟妇乱女区二区三区| 成人免费在线网站| 夜夜操二区| 920日本午夜免费| 91无人区卡一卡二卡三乱码入口最新版:能让用户有更多选择的选择-经典说说-爱 | 青青青青操国内视频在线| 欧美东京热青青草| 永久电影三级在线观看| 清纯唯美亚洲综合| 久久风骚城市人| 女人被添高潮免费视频| 亚洲精品视频在线| 91 国产丝袜在线放观看| 日本裸体久久色噜噜| 欧美性暴力猛交XXXX| 亚州色站 日韩电影| 亚洲男人的天堂AV| KK色在线影院| 人人操欧美风骚| av网站在线观看了| 五月丁香啪啪啪| 嗯嗯啊啊啊好舒服| 欧美精品庄| 俺去啦俺来也久久综合| 色欲天天综合网| 95人妻爽爽人人做人人澡| 色诱avtt| 日骚逼视频| 天堂中文日本在线观看| 操狠狠| 婷婷四五区| 欧美日韩啪啪电影| 人人摸人人干人人拍97| 人妻精品4K4K4K4K4| 青青草影视蜜久久| 久久久免费的精品| 久神马| 成人午夜高潮av猛片| 国内偷自视频区视频综合| 无码精品久久久天天影视| 欧美性爱另类综合| 久久激情四射婷婷丁香五月天| 啊啊啊用力在线观看| 91色综合色| 99久久婷婷丁香| 黑丝少妇麻豆| 97超碰人人操人人操| 久久国产精品一级二级三级| 亚洲精品黄码久久久久| 国产高清26uuu| 天天天天做夜夜夜夜做| 一起草欧美| 青青草久久一区网| 性爱Av免费| 美日韩一二三区| 做爱A级亚欧| 日韩情色AV| 国产精品久久久久久高清无码免费看| 20cm女自慰在线日韩欧美| 麻豆AV一区二区| 淫荡网址| 狠插 制服 自拍| 亚洲成人日韩小说| 欧美大色交| 肉嘟嘟www视频在线观看高清| 欧美特大黄一级片片免费| 中国熟女91| 欧美五十路熟| 超碰97在线色男人??| 一级黄色性爱A级片| 欧美激情久久久久| 亚洲天堂,男人| 极品白嫩美少妇在地板上位骑射淫水泛滥| 伊人久久综合影院| 青青草日韩免费观看高清在线| 中文久久| 91碰碰| 国产无马av| 精品欧美老熟女一二区| 我爱操| 国产高清1234区| 亚洲国产精品有声| 无遮挡一级毛片视频免费的| 欧美丝袜亚洲| 使劲用力艹少妇视频一区二区| 日韩无码极品| 久草综合视频| 天天综合~91入口| 天天日天天搞天天干| 97亚洲色图| 丰满少妇高潮无码| A V少妇特黄三级| 无码丰满熟妇一区二区浪潮AV| 超91综合网| AA级电影三区| 狠狠爱夜夜干| 激情文学小说一区二区| 97这里都是精品| 亚洲图片偷拍视频区| 奇米狠999| 看免费一级在线播放毛片| 色妺妺AⅤ| 美女91网| 久久香蕉国产线看观看亚洲女人| 人人色人人操在线| 国产一区二区精品久久99| CCYY草草影院地址入口| 美女久久久| 蜜臀久久精品久久久久视频| 国产精品不卡一区二区三区| 人妻五十路在线| 狠狠热这里都是精品| 91 国产丝袜在线放观看| 亚洲色图大香| 日韩天堂av电影在线观看| 色女99一级片在线观看| 嗯~啊~快点 死我视频免费看网站| 成人午夜视频免费播放| 丁香五月AV| 色欧美天天| 亚洲日韩av一区二区三区百合| 天天日天天搞天天干| 波多野结衣被操50分钟免费视频| 奶水 人妻 哺乳 在线| 国产精品美女视频诱惑| 一区不卡在线观看av| 国产精品一级特黄aaa大片在线观看| 九一性生活免费视频| 亚洲天天精品| 97在线免费视频| 尤物视频一区| 又黑又大又粗| 色悠久久久av| 亚欧高清| 天天干一干| 97蜜桃综合| 日日噜噜夜夜久久亚洲一区二区| 美女主播色欲91抠b在线播放| 伊人AAA| 宅男91视频在线播放| 91强在线播放| 国产精品盗摄 偷窥盗摄| 大香蕉乱伦视频网| 久久男人| 亚洲综合中文字幕有码| 伊人国产视频| 亚洲精品97| 韩国一级做A片免费的| 超碰调教97| 久久人妻一区二区三区高清| 手机在线播放国产福利| 久艹伊人精品综合在线| 国产高清自拍| 黑丝91视频| 日韩猛交| 精品 码产区一区二-1080P高清在线www-B029AV| 久久久久网站-538在线视频-欧美永久乱码| 欧美精品人妻视频| 精品性爱| 国产精品天干天干综合网麻豆 | 91狠狠综| 色噜噜人妻丝袜AV资源| 超碰免费人妻人人| 操人妻丝袜高跟| 青青青青操国内视频在线| 成人免费在线网站| 久艹99| 亚洲九月丁香| 日本精品一区二区三| 天天做日日做天天欢。| 精品人妻一区二区蜜桃视频| 国产成人久久久精品免费AV| 啊啊啊好大好深| 亚欧精品久久久久久久久久久| 欧美性战999| 亚洲 欧美 日韩 国产一区二区 | 能直接看AV的网站| 国产夫妻性生活视频| 人妻av在线| 欧美日韩在线小说 | 欧美激情总合网| 亚洲无线观看久久| 大屁股国产在线视频| 色久桃花影院在线观看| 激情啪啪视频| 日本在线一二| 中国少妇XXXX做受| 天堂性色| 少妇与黑人高潮在线| 91社操逼| 凹凸视频在线一区二区| 中字一区| 亚洲日韩av一区二区三区百合| 亚洲天天精品| 久久999久| 久操热| 综合国产影视三级| 91丝袜美女视频| 欧美综合在线91| 熟妇在线视频一区二区| 欧美日本国产日韩激情视频| 国产久久久久久| 青草视频人妻在线观看| 日本熟人妻中文字幕在线|...久久国产精品-国产精品_日本一区二区三区中文字幕 | 殴美性天天| 亚洲精品国产av天美传媒| 91日本在线观看| 日韩av电影成人在线| 久久久女人| 东京热精品97综合网| 美国美女AV在线| 九九人人操| 国产精品无码在线| 久久精品欧美一区二区三区不卡| a片 xxxx受爽视频| 99久草| 亚洲999综合| 欧美熟爽综合| 第四色色综合91| 青青草视频久久| 性爱av网站| 国产女乱淫真高清免费视频| 中文字幕日韩电影人妻| 亚洲 无码 偷拍| 国产激情视频一区区三区| 国产午夜精品一区二区三区牛牛| 日本高清久久| 婷婷大香蕉| 欧美日韩999| 91丨九色丨大屁股| 91狠婷| 日韩人妻少妇 一区二区三区| 乱理日韩中文| 无码一区二区三区四区五区六区七区八区九区十区视频 | 这里都是精品在线观看| 我爱大香蕉| 五月丁香啪啪啪| 日韩有码一区三区| 欧美一区二区在线资源| 欧美在线中M| 亚洲素人综合| 国产精品久久久| 亚洲欧美综合| av在线免费一区二区| 亚洲无码久久久久久久| 国产一区二区三区影片| 国产丝袜视频| 99re在线精品78| 五月天亚洲网| 久久专区| 成人性爱美曰韩| 91呆哥人妻| 亚洲精品蜜桃久久久一区二区三区| 国产美女销魂在线观看不卡| 亚洲制服aⅴ中文字幕| 91丨熟女丨丰满熟女| 九九热精品视频在线观看| 偷拍网站久久男女男| 是还免费视频1727我| 中文字幕欧美精品亚洲日韩蜜臀| 青青操在线亚洲视频观看欧美在线 | 国产白丝精品在线观看| 热99这里只有精品| 人妻熟妇久草在线| 亚洲高清视频在线免费观看| 五月丁香六月婷| 狠狠亚洲| AAAAAAAAA黄片| 啊啊啊用力在线观看| 欧美少妇第一页| 色噜噜狠狠色综无码久久合欧美| 超碰碰97资源站| 免费A V在线播放| 91女人的网站| 激情婷婷综合久久| 久久久精品日本一道| 亚洲激情欧美色图 | 亚洲成人av电影在线| 天天日日日射| 色综合av综合久久| 亚洲AV资源| 欧美性91| 91精品成人www| 超碰97人妻在线| 99无码| 91n处女在线观看| 黄色av一区二区在线| 久久久成人精品| 久久男人精品| 无码人妻精品一区二区三区九九| 久久久久久久六六 | 久久高清欧美国产| 亚洲综合 欧美| 亚洲天堂7777| 蜜屁av| 亚洲一区二区麻豆影院| 极品色综合| 黑丝少妇麻豆| 717影院理论午夜伦八戒| 久久中文字幕人妻熟av女蜜柚| 亚洲丝袜少妇在线| 国产久久久9999| 日韩福利综合一区| 欧美人妻另类在线| 97人人草| 亚洲国产av中文字幕久久| 久久久禁| 久操大香蕉| 欧美日韩插逼视频| 熟妇无码视频三区| 男人的天堂,欧美亚洲另类国产日韩,日本高清一区二区 | 影音先锋每日最新资源在线观看| 激情婷婷五月天| 五月天亚洲色图| 玖玖蜜臀资源网| 亚洲操人| 欧美日产国产在线成人第一区| 欧美天天插| 日韩熟女乱伦中出| 在线二区不卡| 久久是精品| 欧美狠狠弄| 九九香蕉网| 亚洲无码太久| 天天综合网91| 中文字幕精品三级久久久| 一区二区三区四区五区高清无码永久视频| 欧美色图91| 久插综合| www.天天干| 黄片免费看黄片免费看| www.色吧5.com| 国产一区二区在线看| 亚洲青色欧美| 亚洲男人的天堂一区二区| HEYZO高无码国产精品227| 欧洲性爱无码区| 亚洲最大成人a毛毛片| 另类图片欧美激情综合| 噜噜噜噜天天狠狠| 在线小说视频一区| 热热色AV| 清纯唯美激情| 天天综合网在线观看| 操一对老熟妇爽上天视频| 久久久久无码一妻区| 在线视频一区二区传媒| 国产精品 午夜福利| 亚洲天堂另类小说男人| 久久久久久久久久久六六| 日韩另类色图| 国产成人精品日本视频| 一级黄色性爱A级片| 国产精品呦一区二区三区| 亚洲91在线播放影院| 亚洲无码成人精品| 国产野战露脸在线播放| 老子午夜伦不卡影院| 久久69精品久久久久久久| 国产精品熟女九色九色蜜臀| 国产 热久久久久国产精品| 伦伦成年午夜免费视频| 色婷婷久久| 国产超碰国产97| 中文字幕久久亚州无码| 综合亚洲网| 蜜臀一区二区三区亚洲最新章节在线观看 - 高清蜜臀一区二区三区亚洲全集播放 | 精品国产精品一区二区| 超碰91在线| 国产欧美精品日韩区二区麻豆天美| 蜜臀无码视频在线观看| 婷婷丁香激情| 午夜黄色免费在线观看| 偷拍 精品 另类 四区| 国产91精品久久久久久久网曝门| www99热| 久久超碰久| 五月开心久久AV官网| 9精品久久久久| 试看日韩黄片| 国产精品老师| 欧美性爱一区二区三区四区| 欧美综合亚洲| 欧美高清无码免费视频高清版| 舔人妻中文免费视频| 啊啊啊啊免费视频| 中文字幕一区二区在线日韩精品| 久久久97| 91色色色| 天天草AV| 中文字幕在线观看永久| 大香樵伊人网| 中文久久96| 视频国产欧美在线播放| 欧美在线观看综合国产| 欧美91网站| 日韩一二三区| 欧美日韩第一页| 制服诱惑亚洲一区二区三区在线观看| 97伪v| 久久亚洲国产成人| 精品久久99| 久久久久久久久久久久久女过产乱-少妇高潮一区二区三区喷水-成人AV | 久久伊人东京热| 偷拍自拍在线视频观看| 久久熟女久| 国产家庭乱伦表演| 欧洲中文字幕| 日本操逼视频不卡直接放| 91爱综合| 78超碰| 国产激情综合五月久久| 99草精| 91无码中出人妻视频| 日本精品加勒比海一区| 熟妇在线视频一区二区| 伊人网高清| 97WW精品| 四虎午夜影院| 青娱乐手机日韩在线视频| 人妻干天天| 99色婷婷中文字幕乱色| 亚洲一区二区久久久久| 日韩丨制服丨中文|在线| 99色热国产视频精品| 国产免费一区| 午夜免费视频1000| 最新亚洲黄色免费电影| 性爱AV天堂| 天天精品| 日韩无码极品| 久久曰曰| 色综合网1| yiqicaoav| 99国产天美| 日本操逼视频不卡直接放| 日韩电影天堂视频二区三区| 粉嫩av在线一区二区| 茄子社区国产精品| 黄页18禁| 在线强奷到舒服的无码视频| 天天噜| 中文字幕av片| 蜜臀精品1区2区| 黄片直播三级黄片两女一男| 极品肉射| 日韩色图 一区二区| 麻豆性爱视频在线播放| 人妻少妇色综合| 无码高清专| 国产成人99久久亚洲综合| 欧美男人的天堂| 亚洲欧美一区二区不卡视频播放| 豆花视频操逼网址| 少妇精品久久| 国产丝袜啪啪| 神马九九九| 久草毛片电影怡| 欧美日韩国第一区| 欧美大码在线视频| www.婷婷六月天| 性爱乱伦一区| 影音先锋每日最新资源在线观看 | 一区二区三区看视频| 老熟妇一区二区三区啪啪| 69精品少妇一区二区三区蜜桃| 久久香蕉综合一本到3atv| 99热18| 久久一二三四五六七八九区区| 亚洲中文字幕噜噜噜久久久| 欧美成人色| 久操黄色视频| 亚洲操操| 97天天做| 久久綜合很很很| 麻豆影音天美视频| 青青草视频爽一爽| 97大色网| 91国产在线精品| 国产av色网| 97超碰公开| 97操b| 99999re| 亚洲日韩在线a不卡99精品| 四虎午夜影院| 乱伦色图网址是多少| 男插女青青影院| 人妻一区二区三区视频| 美女操逼A A| 国产精品视频麻豆入口| 日本熟女中文| 蜜臀久久久久久999| 在线人妻熟女一区二区三区四区五区| 国产三级多多影院2022国产AA一级毛片无码 | 亚洲精品一区二区精品| 草草影院日本第一页| 六月婷婷色综合| 99.色网| 精品国产国产AV| 欧美后入式| 精品免费囯产一区二区三区| 91免费看一区二区三区| 久久精品国产亚洲AV无码电影| 亚洲熟女综合网| 午夜福利免费福利视频| 亚洲一区二区三区久久 亚洲一区二区| 欧美日本中字另类在线| 国产原创自拍| 91N综合网在线| 97超碰超碰| 2020中文在线一区二区三区| 熟妇在线视频一区二区| 激情综合网一盗摄| 日韩啊V| 天天综合精品| 日韩丝袜人妻AV| 这里只有精品久久| 九九自拍伦理| 91网站18| 探花精品视频| 欧美一级欧美三级在线观看 | 亚洲第一狼人丝袜美女另类| 五月天激情网图片| 亚洲精品白丝| 中文字幕人妻资源在线| 国产精品自在自拍视频| 久久av网| 天天综合网91| 97香蕉碰碰人妻国产欧美| 色欲人妻一区二区在线| 好爽免费视频| 国内三级自拍小视频在线观看 | 一区超碰一区| 亚洲av无码成电影在线播放| 天天影视网综合少妇| 精品十三区| 伊人久久在线视频观看| 精品一区二区久久| 正在播放:深夜激情大战,自带黑丝袜全力输出骚穴 | 亚洲精品国产精品成人| 国产精品久久久久久久久久久久久久久久久久 | 嗯嗯啊操我| 性爱AV天堂| 久久久久密臀视频| 很很操在线| 岛国成人av在线播放网址| 国产噜噜噜噜噜久久久久久久久| 亚洲,日韩,欧美,成人播放| 欧美爱国产综合、| 伊人97色天使| 日韩999| 试看60秒 爽| 欧美一区二区三区日韩| 欧美少妇人妻| 91neishe| 国产夫妻性生活视频| 久久精品高清AV| 玖玖资源中文字幕制服丝袜| 欧美精品久久久久久久丰满| 1024亚洲中文字幕久在线看片你懂的 | 国产第二页| 中文字幕黄片在线| 欧美激情 日韩精品| 国产精品久久久啊| 91人妻视频在线| 久久性爱视频| 黑人与人妻| 亚洲欧洲综合av在线| 日本东京热大香蕉a片| 午夜福利一区二区影院| 亚洲欧洲无码97久久精品| 香伊人在线| 99在线精品视频| 黄片在线免费在线观看| 日本一久是| av无码精品久久久久| 欧美一级专区免费大片| 久久精品国产99精品亚洲蜜...| av在线免费一区二区| 国产原创自拍| 精品午夜福利导航| 色哟哟国产精品免费网址| 91免费看一区二区三区| 福利风月五月天影院| 亚洲国产成人7777| 国产精品欧美激在线| 国产一级137片内射麻豆| 伊人精品视频| 国产乱码精品一区二区三区四川| 日韩久久三区| 欧美日本成人一区二区| 亚洲人在线成线成人| 人妻干天天| 欧美午夜视频| 欧美顶级黄片AAAAA在线免费看| 亚洲另类久操网| 免费a v| 懂色AV中文| 婷婷色色五月天福利| 亚洲一本色码中文字幕| 天天天天天天天天天天干美女| 在线观看AV不卡| 色色色日本| 亚洲国产亚洲天堂| www.激情| AⅤ片水多多| 久久一本大香蕉| 大香蕉五月天| 精品国产Av无码久久久伦古装| 国产精品自产拍在线观看社区| 伊人国产视频| 人妻激情偷乱视三区频一区二区| 四季AV一区二区凹凸精品小说| 亚洲欧美色图| 成人黄页| 亚洲色吧网| 欧美亚洲国产91在线| 婷婷15月天青娱乐| 亚洲超碰在线| 99e久久国产精品| 天天综合网亚洲综合网| 久草久热| 亚欧成人中文字幕一区| 超碰97色| 日韩精品系列| 91 丝袜在线| 一级性爱aaaa| 日韩欧美操逼xxx| 超碰97综合网| 欧美性爱一区| 久热9| 国产中文字幕在线点播| 9 1果冻精品视频| 久久超碰、| 色色五月婷婷| 亚洲一区二区三区中文字幕| 亚洲丝袜诱惑| 啊啊啊啊啊好舒服视频| 欧美亚男人的天堂| 久久99亚洲精品久久99果| 亚洲无线码欧洲精品区别| 九九九精品一区二区无码| 伊色综合天堂色97| 一区二区三区视频国产免费| 成人怡红院| 玖玖资源视频一区二区三区| 国产精品网站www| 中文字幕高清20页视频| 无码国产精品久久久久| 伊人精品久久网站| 日本不卡五区| 91国产丝袜白虎| 久操大香蕉超碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰 | 久久久久久久久九九久孕交| 亚洲中文字幕av| 成人三一级一片aaa| 2023天天操夜夜操| 九色黄站| 精品无人区麻豆乱码1区2区图片| 99久久久久| 久操网址| 亚洲国产91精品一区二区久久| 美美91成人国产精品欧美精品久久久久久久| 人人操人人舒服| 日韩熟女精一区二区三区不卡| 嗯嗯啊操我| 亚洲国产欧美中日韩成人综合视频| 大香蕉宅男伊人| 91是天天| 在线 制服丝袜中出 人妻| www.色婷婷色综合| 岛国福利在线精品播放| 久热一区二区| 校园春色五月天| 老熟女阿 国产91| 限制级中的三级片中的黑粗大屌屌日人妻熟女| 青青欧美| 色网综合网| 无码人妻精品一区二区三区九九| 涩五月婷婷| 91精品丝袜在线观看| 偷看洗澡一二三区美女| 日本精品一区二区中文字幕| 操逼无码操逼| 91被操| 中文字幕国产在线天堂| 人妻精品视频一区二区三区| 色欲av国内精品久久久久久| 欧美懂色综合网| 97精品网| 超碰97护士| 少妇综合| 日本高清免费一本视频在线观看| 91美女视频直播| 欧美黑人日韩少妇色情| 加勒比色99999| 另类欧美色| 资源新线在线天堂| 91视频在线观看18| 麻豆国产精品午夜视频| gogogo免费高清看中国国语| 久久久久久久伊人精品| 综合操逼| 2024人人操人人摸| 久久草大香蕉| 亚州情色j区| 九九热精品免费视频| 青青草吊丝| 色五月婷婷在线| 2020视频1区2区3区| 91+欧美| 午夜欧美神马久久久久| 日本性一区| 天天日天天干天天摸天天操| 亚洲欧美另类图片| 亚洲高清色综合| 婷婷超| 7777奇米影视久久| 太久视频| 五月丁香网站| 国产13区| 躁躁日曰躁2020| 日韩淫色网| 欧美精品黑人猛交高潮| 欧美影院一区二区三区| 色翁荡息又大又硬又粗又爽| 黄色免费网页无码| 激情综合五月婷婷| 少妇被玩视频二三区| 亚洲天堂人人妻| 96一区二区三区| 欧美综合网| 国产欧美日韩精品中文| 色玖玖| 国产一区麻豆免费观看| 爱妻综合网| 清纯唯美综合| 一级片视频啪啪| 国产一区二区在线电影| 亚洲一区深夜| 性性欧美| 肥佬影院91| 亚洲综合另类小说色区亚洲成av人片在www| 蜜臀视频网站| 思思热久久成人| 五月婷婷综合在线| 伊人久久大香线蕉亚洲五月天,青草青草欧美日本一区二区,欧美日产欧美日产国产 | 国产精品一级毛片不卡视| 无码粉嫩白虎一线天b区| 亚州操操穴网| 一级做a爰片久久毛片图片| 日本精品五区| www国产天美久久久| 黄视频免费| www.男人的天堂| 俄罗斯一区二区视频在线观看| 欧美线天码中字| 偷拍精品一区二区三区| 做爱A级亚欧| 六月丁丁香| 欧美天堂第二区| 国产白丝av| 久久性爱城| 大香蕉在线视频重口味毛片在线| 97超碰逼| 偷拍亚洲情色| 免费AV中文网在线观看| 操比国产| 国产成自自拍在线观看| 亚洲欧美另类图片| 日韩一级免费性爱| 99色日| 9久精品| 国产自偷自拍一区| 一区,二区,三区视频| 欧美天天干| 久热在线精品免费观看| 麻豆久久视频在线地址| 久久久久久久9最新免费视频观看| 超碰伊人在线| 国语对白露脸XXXXXX| 亚洲 日本 一 二 三| 男人的亚洲天堂| 牛牛AV人人夜夜澡人人爽| 国产刺激视频| 欧美精品,四区。五区| 无码一区免费在线不卡| 一区二区 韩日AV| 麻豆区久久久久亚| 特级毛片特黄久久免费看| 99爱爱| 1.igao73.com 加入收藏 免费专区 国产精品 中文字幕 日韩精品 欧美精品 精彩 | 久久av色| 欧亚日韩一区在线| 九九热精品| 九九久精品| 乱伦av国产| 日韩美女高潮喷水视频| 国产白丝精品在线观看| 人妻少妇视频在线播放| 超碰吊日色| 91人妻尻屄视频| 久久九操在线观看| 欧美aa一级片| 国厂麻豆77q4| 91深夜夜| 97国产色图| 国产日逼视频| 天天天天天天天天综合| 伊人精品久久网站| 97久久久精品| 欧美黄色片在线播放| 精品免费1| 无码国产精品96久久久久孕妇| 久久亚洲AV成人精品无码| 色娱乐色呦呦夜夜夜夜av| 2017人人操,人人摸| 欧美熟妇操操视频| 91综合色噜噜| 在线天堂999| 可乐操亚洲蜜911| 五月婷婷性爱| 综合色91| 久久精品欧美一区蜜桃| 天天草天天日| 精彩国产视频播放1区2区| 日韩福利综合一区| 日日噜噜夜夜久久亚洲一区二区| 欧美色图亚洲色| 夂久色| 97狠狠| 99精品丰满人妻无| 亚洲男人天堂Av| 中文字幕97色| 少妇高潮一区二区三区在线| 黄色在线网站| 日韩青久久| 国产欧美一区激情交| 欧美性爱精品七区| 91啪啪| 亚洲精品 大香蕉| 一本一首道人妻少妇免费久久| 色爽——AV| 337p大胆噜噜噜噜噜91Av| 97青青操视频| 欧美偷拍区| 另类综合另类| 香蕉人人操tv| 欧美人妻少妇| 九色 蝌蚪 熟女自 | 黄色成年| 免費人妻夜夜爽天天爽爽一区| 亚州Av天美传媒| 欧美综合骚| 色婷婷狠狠18禁| 欧美18 在线观看| 日日夜夜国产综合| 黄色电影观看久久9| 91老司机在线| 午夜精品久久久| 亚洲无码久久久久久久| 欧美精品三级黄片| 九九九久千久久激情蜜桃在线看| 欧美激情亚洲情色| 殴美大黄片| 蜜桃久久一区二区| 麻豆一区二区三区精品| 亚洲精品日韩国产欧美| 综合网色| 国产精品免费视频人成| 乱伦av麻豆| 极品尤物自安慰| 日韩精品中文字幕人妻| 九九九九九九精品| 性欧美| 99re视频这里只有精品| 欧美巨大性舒爽顶到了| av东京热男人的天堂| 婷婷激情综合网| 国产精品久久久久久高清无码免费看| 一区二区三区视频| 2024年最新色情网站在线观看| 精品国产乱码久久久久久久久1 | 97中文字幕一区| 日韩二级| 国产精品岛国片在线观看| 亚洲欧美日韩偷拍色图| 欧美综合网站999| 激情AV| 97在线视频观看网站| 精品九九九九九| 9997se| 一区二区不卡| 天天射影院| 欧美日韩 强奸乱伦| 久久久新亚洲AV| 欧美一级专区免费大片| 黑操B| 秋霞曰韩R级| 亚洲日韩精品久久久久一区壹牛| 午夜福利在线视频1000| 免费观看有码高清视频| 91小视频| 国产精品九九九| 欧亚 另类 久| 高树玛利亚无码流出| 午夜男女爽爽爽在线视频| 亚洲电影中字一区二区| 超碰地址久久| 国产av高清版| 日本加勒比无码专区| 福利视频一区二区微拍| 大香蕉综合网| 好看的久久不射无码影视影院| 亚洲高清视频在线免费观看| 亚洲91射| 中文字幕在线观看第二页| 操一区| 8050无码八戒| 国产精品黄色三级av| 色综合V| 综合久久少妇中文字幕| 91黄站| 亚洲干B| 蜜臀久久久国产| 国产肏屁眼视频| 欧美亚综合色图| AV天天综合| 婷婷五月天_亚洲小说欧美激情另类_精品久久国产字幕 | 69国产对白刺激| 麻豆天美一区二区| 熟女少妇视频| 青娱乐黄色录像| 欧美日韩制服| 欧姜老司机| 91熟女丨老女人| 人人妻人人爽| 天天网综合| 天天做天天爱| 日韩福利电影网| 91白虎| 久久久青青草| 台湾佬大香蕉| 97美日韩视频| 2019天天干| 色欲Av人妻精品一区二| 女性91网站| 成人五月天丁香激情综合| 综合网欧美| 日韩av性爱在线播放| 1级黄色夫妻对换性交免费看| 少妇高潮一区二区三区在线| julia ann久久| 亚洲干B| 亚洲国产综合图区中文字幕| 色姑娘综合网| 日本孕妇一区二区视频操逼免费看| 97超碰中文字幕| 日本亚欧爱爱| 国产免费内射视频| 亚洲色图欧美一区二区不卡| 久久日本熟妇熟色一区| 免费精品无码一级毛片牛牛影视 | 亚洲少妇免费视频\| 9ⅰ久久久天天| 日韩BBN| 久久天堂网| 东京太热男人的天堂久久久| 男人亚洲天堂| 日韩三A大片在线观看| 一本大道不卡一二三区| 91精品啪在线观看国产城中村| 韩国免费播放一级毛片| 国产无码精品成人| 日韩操p| 国产精品一级毛片不卡视| 日本久久女同性恋视频| 超碰天天去日穴| 九久精品| 人妻丰满熟妇一区二区三| 欧美亚洲中文字幕| 长长久久88视频| 青青草在线视频欧美| 亚洲综合 欧美| 九九九九九九九九九国产精品| 亚洲资源网| 青青操日韩| AV女资源| 青青草好吊色| av网站免费线看| 强奸乱伦av电影| 偷拍伦理视频| 成人欧美日超碰| 阿姨一区二区免费视频-高清正片西瓜视频下载app-T450AV | 欧美日韩中文亚洲v在线综合| 国产91精品在线免费| 中文精品一区二去| 欧美人人AAA| 强奸少妇AV导航网| 懂色av中文字幕一区二区三区天美 | 黑人在线91| 亚洲熟女乱色一区二区三区| 十八禁成人网站在线观看| 大香蕉亚洲中文| 999 久久久| 欧美色人| 免费精品中文字幕| 婷婷丁香久久| 欧美夜夜骑视频| 外国免费性情大片| 伊人精品久久网站| 欧美综合站| 熟女熟妇伦久久影院毛片一区二区| 97在线亚洲| 六月婷婷色综合| 青青草日本中文字幕| 极品人妻少妇综合| 人人操人人操人人人操| 六月丁丁香| 欧美老妇女内射网址| 国产白丝网站| 91老司机在线| 精品日韩产品在线,日韩在线不卡视频,欧美日韩免费专区/久, | 精品一区二区人妖| 男人的天堂,欧美亚洲另类国产日韩,日本高清一区二区 | 九九热免费视频| AV色图| 乱伦一二三区| 丁香五月激情综合国产| 91大神电影天堂| 综合欧美色图| 亚洲一欧洲中文字幕在线| 91九九九馒头| 超碰97久| 午夜国产成人福利视频| 青青操在线亚洲视频观看欧美在线| 久操网在线| 国产 日韩 欧美一区| 五月丁香六月激情综合| 亚洲熟妇综合久久久久久| 国产家庭乱伦表演| 男人的天堂啪啪| 亚洲高清男人天堂| 性爱视频啪啪啪啪| 无码一区二区三区四区五区六区七区八区九区十区视频 | 视频不卡中文字幕| 51一区二区三区|