到物聯(lián)網(wǎng)網(wǎng)關(guān):嵌入式工程師的ARM64與RISC-V進(jìn)階路線)
1. 從20萬(wàn)億美元這個(gè)數(shù)字說(shuō)起物聯(lián)網(wǎng)產(chǎn)業(yè)到底在發(fā)生什么第一次看到超20萬(wàn)億美元的產(chǎn)業(yè)這個(gè)說(shuō)法很多做嵌入式的朋友第一反應(yīng)是又在畫(huà)餅。我當(dāng)初也這么想直到把幾個(gè)數(shù)字?jǐn)[在一起看全球物聯(lián)網(wǎng)連接設(shè)備數(shù)量早已突破百億級(jí)別從智能電表、車(chē)載終端、工業(yè)網(wǎng)關(guān)到農(nóng)業(yè)傳感器每一個(gè)連接節(jié)點(diǎn)背后都是一顆MCU、一顆SoC、一套嵌入式Linux或者RTOS再加上云平臺(tái)、邊緣計(jì)算、數(shù)據(jù)服務(wù)。硬件、軟件、連接、平臺(tái)、服務(wù)這幾層疊加起來(lái)才湊出了這個(gè)量級(jí)。它不是某一家公司的營(yíng)收而是整個(gè)產(chǎn)業(yè)鏈的總體量。那問(wèn)題來(lái)了產(chǎn)業(yè)這么大為什么很多做嵌入式的人感覺(jué)自己沒(méi)進(jìn)去我觀察下來(lái)卡點(diǎn)通常不在技術(shù)難度而在方向選擇和信息差。有人一直在裸機(jī)STM32上打轉(zhuǎn)沒(méi)碰過(guò)嵌入式Linux有人會(huì)寫(xiě)驅(qū)動(dòng)但不懂網(wǎng)絡(luò)協(xié)議棧有人做得了網(wǎng)關(guān)硬件卻搞不定根文件系統(tǒng)掛載。這些斷層恰好就是產(chǎn)業(yè)里最缺人的位置。這篇內(nèi)容我想聊的不是物聯(lián)網(wǎng)有多好而是一個(gè)嵌入式從業(yè)者怎么從自己現(xiàn)在的位置一步步走到這個(gè)產(chǎn)業(yè)真正需要人的崗位上去。涉及的關(guān)鍵詞包括物聯(lián)網(wǎng)、嵌入式、ARM64、Linux、RISC-V也會(huì)順帶把無(wú)源物聯(lián)網(wǎng)、物聯(lián)網(wǎng)網(wǎng)關(guān)、嵌入式AI測(cè)試這些熱詞背后的實(shí)際工作內(nèi)容講清楚。不管你是剛學(xué)完51單片機(jī)還是已經(jīng)能獨(dú)立bringup一塊板子都能在里面找到下一步該補(bǔ)什么。2. 物聯(lián)網(wǎng)產(chǎn)業(yè)鏈里嵌入式到底站在哪個(gè)位置2.1 四層結(jié)構(gòu)感知、連接、平臺(tái)、應(yīng)用把物聯(lián)網(wǎng)拆開(kāi)看其實(shí)就四層每一層對(duì)嵌入式的需求完全不同。感知層傳感器、執(zhí)行器、計(jì)量芯片。這一層大量用MCUSTM32、GD32、國(guó)產(chǎn)RISC-V MCU都在這里。特點(diǎn)是資源緊張、實(shí)時(shí)性要求高、功耗敏感。FreeRTOS在這層是絕對(duì)主力很多物聯(lián)網(wǎng)網(wǎng)關(guān)的采集子模塊就是STM32跑FreeRTOS。連接層網(wǎng)關(guān)、路由器、交換機(jī)、模組。這一層是嵌入式Linux的主場(chǎng)。網(wǎng)關(guān)要做協(xié)議轉(zhuǎn)換Modbus轉(zhuǎn)MQTT、CAN轉(zhuǎn)TCP、要做邊緣預(yù)處理、要管理下掛的幾十上百個(gè)節(jié)點(diǎn)。ARM64的應(yīng)用處理器比如各種國(guó)產(chǎn)SoC跑Linux是當(dāng)前最主流的方案。平臺(tái)層物聯(lián)網(wǎng)平臺(tái)比如開(kāi)源的ThingsBoard、國(guó)內(nèi)常見(jiàn)的ThingsLinks這類(lèi)平臺(tái)。這一層偏后端和云但嵌入式工程師需要懂它的數(shù)據(jù)模型否則設(shè)備端上報(bào)的數(shù)據(jù)結(jié)構(gòu)對(duì)不上聯(lián)調(diào)時(shí)能把你耗死。應(yīng)用層具體行業(yè)方案電力、水務(wù)、工業(yè)、農(nóng)業(yè)、車(chē)載。提示很多人以為做物聯(lián)網(wǎng)就是做平臺(tái)其實(shí)平臺(tái)崗位數(shù)量遠(yuǎn)少于設(shè)備端崗位。真正大量缺人的是連接層和感知層的嵌入式開(kāi)發(fā)。2.2 為什么網(wǎng)關(guān)是嵌入式的黃金位置網(wǎng)關(guān)這個(gè)位置很特殊它上接平臺(tái)要懂MQTT、HTTP、JSON下接傳感器要懂串口、Modbus、CAN、LoRa中間還要跑一個(gè)完整的Linux系統(tǒng)要懂內(nèi)核、根文件系統(tǒng)、網(wǎng)絡(luò)配置。一個(gè)能獨(dú)立搞定網(wǎng)關(guān)的工程師等于同時(shí)具備驅(qū)動(dòng)、系統(tǒng)、網(wǎng)絡(luò)、應(yīng)用四方面能力這種人在市場(chǎng)上非常搶手。我見(jiàn)過(guò)不少物聯(lián)網(wǎng)畢業(yè)設(shè)計(jì)就是做一個(gè)STM32網(wǎng)關(guān)采集溫濕度通過(guò)ESP8266上報(bào)。這個(gè)作為入門(mén)可以但離產(chǎn)業(yè)需求還有距離。產(chǎn)業(yè)里的網(wǎng)關(guān)要處理的是多協(xié)議接入、斷網(wǎng)緩存、遠(yuǎn)程升級(jí)、設(shè)備認(rèn)證、邊緣規(guī)則引擎。這些才是真正值錢(qián)的部分。2.3 無(wú)源物聯(lián)網(wǎng)下一個(gè)增量在哪最近無(wú)源物聯(lián)網(wǎng)這個(gè)詞很熱。簡(jiǎn)單說(shuō)就是設(shè)備不帶電池靠射頻能量收集、背散射通信來(lái)工作。它的價(jià)值在于物流、倉(cāng)儲(chǔ)、資產(chǎn)管理這些場(chǎng)景貼一個(gè)標(biāo)簽就能用幾年甚至十幾年不用換電池。這對(duì)嵌入式的挑戰(zhàn)是全新的——超低功耗設(shè)計(jì)、能量收集電路、極簡(jiǎn)協(xié)議棧?,F(xiàn)在這個(gè)方向還在早期但增量空間很大提前布局的人會(huì)有先發(fā)優(yōu)勢(shì)。3. 嵌入式Linux繞不過(guò)去的那道坎3.1 從裸機(jī)到Linux思維要換三次我?guī)Я藥讉€(gè)從STM32轉(zhuǎn)Linux的同事發(fā)現(xiàn)卡點(diǎn)都集中在三個(gè)思維轉(zhuǎn)換上。第一從我控制一切到我和內(nèi)核協(xié)作。裸機(jī)時(shí)代你寫(xiě)個(gè)while(1)就是全部Linux下你的驅(qū)動(dòng)只是內(nèi)核的一個(gè)模塊要遵守內(nèi)核的框架、要處理并發(fā)、要考慮睡眠和喚醒。第二從寄存器思維到子系統(tǒng)思維。裸機(jī)上你直接操作寄存器Linux下你要掛到對(duì)應(yīng)的子系統(tǒng)上GPIO掛gpio子系統(tǒng)I2C設(shè)備掛i2c子系統(tǒng)輸入設(shè)備掛input子系統(tǒng)。不按框架來(lái)代碼能跑但沒(méi)法維護(hù)。第三從能跑就行到可復(fù)現(xiàn)、可升級(jí)。產(chǎn)品要量產(chǎn)就要考慮設(shè)備樹(shù)、根文件系統(tǒng)、OTA升級(jí)。這些在裸機(jī)上基本不存在。3.2 根文件系統(tǒng)掛載新手最容易翻車(chē)的地方熱詞里出現(xiàn)了嵌入式linux 根文件系統(tǒng)掛載 使用nfs v3這確實(shí)是高頻問(wèn)題。我把自己踩過(guò)的坑整理一下。用NFS掛載根文件系統(tǒng)做開(kāi)發(fā)是嵌入式Linux調(diào)試的常規(guī)操作。典型的內(nèi)核啟動(dòng)參數(shù)長(zhǎng)這樣# 內(nèi)核命令行參數(shù)示例 root/dev/nfs rw nfsroot192.168.1.100:/nfsroot/rootfs,v3 ip192.168.1.200:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off這里有幾個(gè)坑NFS版本老內(nèi)核默認(rèn)走v2新內(nèi)核默認(rèn)走v3或v4。如果服務(wù)端只開(kāi)了v3客戶端卻按v4去協(xié)商就會(huì)卡在掛載階段。顯式寫(xiě),v3能省很多事。網(wǎng)絡(luò)時(shí)序內(nèi)核起來(lái)時(shí)網(wǎng)卡驅(qū)動(dòng)還沒(méi)加載完NFS就超時(shí)了。解決辦法是把網(wǎng)卡驅(qū)動(dòng)編進(jìn)內(nèi)核不是模塊或者用initramfs先過(guò)渡。權(quán)限和uidNFS掛載后文件屬主可能全變成nobody導(dǎo)致系統(tǒng)服務(wù)起不來(lái)。要在服務(wù)端配置no_root_squash。注意NFS掛載只適合開(kāi)發(fā)階段。量產(chǎn)必須用flash上的根文件系統(tǒng)ext4、ubifs、squashfs等否則斷網(wǎng)就變磚。3.3 那個(gè)bad linux arm64 image magic報(bào)錯(cuò)熱詞里有個(gè)很具體的報(bào)錯(cuò)bad linux arm64 image magic! 內(nèi)核段既不是 arm64 image偏移 0x38 處無(wú) armd。這個(gè)我太熟了。ARM64的Linux內(nèi)核鏡像Image在文件頭偏移0x38處有一個(gè)魔數(shù)ARM\x640x644d5241。bootloader加載內(nèi)核時(shí)會(huì)檢查這個(gè)魔數(shù)對(duì)不上就報(bào)這個(gè)錯(cuò)。常見(jiàn)原因拿錯(cuò)了文件把vmlinuxELF格式當(dāng)成Image燒進(jìn)去了。vmlinux是帶調(diào)試信息的ELF不能直接引導(dǎo)。要用objcopy轉(zhuǎn)成Image或者用Image.gz。壓縮格式?jīng)]解壓有些bootloader不自動(dòng)解壓你給它Image.gz它不認(rèn)得給未壓縮的Image。架構(gòu)搞混把ARM32的zImage當(dāng)成ARM64的Image。兩者魔數(shù)位置和值都不同。排查方法很直接# 查看文件頭確認(rèn)是不是合法的ARM64 Image xxd -l 64 Image # 偏移0x38處應(yīng)該能看到 41 52 4d 64即 ARMd這個(gè)報(bào)錯(cuò)看著嚇人其實(shí)定位起來(lái)很快關(guān)鍵是知道魔數(shù)在哪、長(zhǎng)什么樣。4. ARM64與RISC-V兩條路線怎么選4.1 ARM64的生態(tài)優(yōu)勢(shì)短期內(nèi)無(wú)法撼動(dòng)做嵌入式LinuxARM64目前是默認(rèn)選項(xiàng)。原因很實(shí)在工具鏈成熟、內(nèi)核支持完善、芯片選擇多、社區(qū)資料全。你遇到任何問(wèn)題搜一下基本都有人踩過(guò)。qemu模擬arm64也是學(xué)習(xí)利器沒(méi)有硬件也能把整個(gè)啟動(dòng)流程跑通# 用qemu模擬arm64跑一個(gè)最小Linux qemu-system-aarch64 \ -M virt -cpu cortex-a57 -nographic \ -kernel Image \ -append consolettyAMA0 root/dev/vda rw \ -drive filerootfs.ext4,ifnone,idhd0 -device virtio-blk-device,drivehd0這套流程跑一遍你對(duì)內(nèi)核啟動(dòng)、設(shè)備樹(shù)、根文件系統(tǒng)的理解會(huì)直接上一個(gè)臺(tái)階。我建議每個(gè)學(xué)嵌入式Linux的人都用qemu完整走一遍比買(mǎi)開(kāi)發(fā)板還高效因?yàn)槟隳茈S便改、隨便試不怕搞壞。4.2 RISC-V值得現(xiàn)在就開(kāi)始了解RISC-V這兩年在嵌入式領(lǐng)域的存在感越來(lái)越強(qiáng)。它的優(yōu)勢(shì)是開(kāi)放、可裁剪、沒(méi)有授權(quán)費(fèi)特別適合做定制化的物聯(lián)網(wǎng)芯片。國(guó)內(nèi)已經(jīng)有不少RISC-V MCU和MPU在量產(chǎn)。但要說(shuō)清楚RISC-V在嵌入式Linux上還沒(méi)到ARM64的成熟度。工具鏈、內(nèi)核支持、外設(shè)驅(qū)動(dòng)、社區(qū)資料都還在完善中。我的建議是如果你現(xiàn)在要找工作、做量產(chǎn)項(xiàng)目主力還是ARM64。如果你有精力花時(shí)間了解RISC-V的指令集、工具鏈、啟動(dòng)流程這是明顯的加分項(xiàng)也是未來(lái)三五年的趨勢(shì)。兩者不是替代關(guān)系而是互補(bǔ)。很多產(chǎn)品線會(huì)同時(shí)存在ARM和RISC-V的方案選型時(shí)看成本、功耗、生態(tài)綜合決定。4.3 選型對(duì)比表維度ARM64RISC-V生態(tài)成熟度高資料豐富中快速完善中工具鏈GCC/LLVM完善GCC/LLVM基本可用內(nèi)核支持完善主線支持外設(shè)驅(qū)動(dòng)參差芯片選擇極多逐漸增多授權(quán)成本需授權(quán)開(kāi)放無(wú)授權(quán)費(fèi)適合場(chǎng)景量產(chǎn)主力、通用網(wǎng)關(guān)定制芯片、成本敏感、新項(xiàng)目預(yù)研5. 嵌入式AI測(cè)試與邊緣計(jì)算新崗位的能力要求5.1 嵌入式AI測(cè)試到底測(cè)什么熱詞里有嵌入式ai測(cè)試這個(gè)崗位這兩年需求漲得很快。它測(cè)的不是模型精度那是算法團(tuán)隊(duì)的事而是模型在真實(shí)硬件上的表現(xiàn)推理延遲單幀多少毫秒能不能滿足實(shí)時(shí)要求。內(nèi)存占用模型加載后占多少RAM峰值多少。功耗持續(xù)推理時(shí)整機(jī)功耗電池設(shè)備尤其關(guān)鍵。精度損失量化int8之后精度掉了多少能不能接受。穩(wěn)定性連續(xù)跑24小時(shí)會(huì)不會(huì)內(nèi)存泄漏、會(huì)不會(huì)熱到降頻。做這個(gè)崗位你需要懂模型部署框架TFLite、ONNX Runtime、NCNN等、懂硬件性能分析、懂測(cè)試方法論。純算法背景的人做不了純嵌入式背景的人也要補(bǔ)AI部署的知識(shí)。這是個(gè)交叉崗位競(jìng)爭(zhēng)反而沒(méi)那么激烈。5.2 邊緣計(jì)算給嵌入式帶來(lái)的變化以前嵌入式設(shè)備只管采集和上報(bào)現(xiàn)在越來(lái)越多要做邊緣側(cè)的預(yù)處理和決策。比如工業(yè)網(wǎng)關(guān)在本地就跑異常檢測(cè)只把異常數(shù)據(jù)上報(bào)省帶寬也省云成本。這對(duì)嵌入式工程師的要求是要理解數(shù)據(jù)流、要會(huì)調(diào)用推理引擎、要能做資源調(diào)度。我的經(jīng)驗(yàn)是不用一上來(lái)就啃深度學(xué)習(xí)理論。先把一個(gè)現(xiàn)成的模型部署到板子上跑通理解整個(gè)鏈路再回頭補(bǔ)理論效率高得多。6. 一條可落地的嵌入式物聯(lián)網(wǎng)學(xué)習(xí)路線6.1 分階段目標(biāo)我把路線分成四段每段都有明確的產(chǎn)出物避免學(xué)了很多但拿不出東西。第一階段MCU與RTOS1-3個(gè)月目標(biāo)能用STM32FreeRTOS做一個(gè)多任務(wù)采集節(jié)點(diǎn)。產(chǎn)出一個(gè)能采集傳感器、通過(guò)串口或無(wú)線模組上報(bào)數(shù)據(jù)的完整工程。重點(diǎn)任務(wù)調(diào)度、中斷、隊(duì)列、低功耗。第二階段嵌入式Linux基礎(chǔ)3-6個(gè)月目標(biāo)能獨(dú)立bringup一塊ARM64板子跑起Linux。產(chǎn)出自己編譯內(nèi)核、做根文件系統(tǒng)、寫(xiě)一個(gè)字符設(shè)備驅(qū)動(dòng)。重點(diǎn)設(shè)備樹(shù)、內(nèi)核裁剪、驅(qū)動(dòng)框架、qemu模擬。第三階段網(wǎng)絡(luò)與網(wǎng)關(guān)3-6個(gè)月目標(biāo)能做一個(gè)多協(xié)議網(wǎng)關(guān)。產(chǎn)出Modbus采集 MQTT上報(bào) 斷網(wǎng)緩存 OTA升級(jí)。重點(diǎn)socket編程、協(xié)議棧、MQTT、固件升級(jí)。第四階段邊緣與AI持續(xù)目標(biāo)能在網(wǎng)關(guān)上部署一個(gè)輕量模型做本地推理。產(chǎn)出一個(gè)帶異常檢測(cè)的邊緣網(wǎng)關(guān)demo。重點(diǎn)模型部署、性能測(cè)試、資源優(yōu)化。6.2 每個(gè)階段的避坑提醒第一階段別貪多把FreeRTOS的任務(wù)和隊(duì)列吃透比學(xué)十個(gè)RTOS有用。第二階段一定要用qemu先跑通再上硬件。硬件問(wèn)題會(huì)掩蓋你的理解問(wèn)題。第三階段協(xié)議別自己造輪子用成熟的開(kāi)源庫(kù)把精力放在業(yè)務(wù)邏輯上。第四階段先跑通再優(yōu)化別一上來(lái)就追求極致性能。7. 那些沒(méi)人告訴你但很重要的實(shí)操經(jīng)驗(yàn)7.1 關(guān)于開(kāi)發(fā)環(huán)境熱詞里有一堆linux鏡像安裝免費(fèi)linux網(wǎng)站大全永久免費(fèi)網(wǎng)頁(yè)版linux之類(lèi)的搜索說(shuō)明很多人在環(huán)境上就卡住了。我的建議很直接本地裝一個(gè)Ubuntu LTS用虛擬機(jī)或雙系統(tǒng)都行別折騰網(wǎng)頁(yè)版。嵌入式開(kāi)發(fā)要接硬件、要用串口、要跑qemu網(wǎng)頁(yè)環(huán)境根本不夠用。環(huán)境越簡(jiǎn)單越穩(wěn)定越好把時(shí)間花在真正的技術(shù)上。7.2 關(guān)于調(diào)試手段嵌入式調(diào)試串口打印是永遠(yuǎn)的神。但很多人只會(huì)printf不會(huì)分級(jí)。我的做法是定義日志級(jí)別ERROR/WARN/INFO/DEBUG發(fā)布版本只留ERROR調(diào)試版本全開(kāi)。這樣既不影響性能又能快速定位問(wèn)題。另外adb shell在安卓設(shè)備調(diào)試時(shí)很有用但純Linux設(shè)備上更常用的是串口ssh。設(shè)備起來(lái)后配好網(wǎng)絡(luò)ssh上去操作比串口舒服得多。7.3 關(guān)于面試熱詞里linux面試題嵌入式面試題出現(xiàn)多次。我面過(guò)不少人發(fā)現(xiàn)一個(gè)規(guī)律能講清楚一個(gè)完整項(xiàng)目的人比背了一堆知識(shí)點(diǎn)的人更受歡迎。面試時(shí)別背概念講你做過(guò)什么、遇到什么問(wèn)題、怎么解決的。比如你講清楚根文件系統(tǒng)掛載失敗怎么排查的比背十條Linux命令有用得多。7.4 關(guān)于國(guó)產(chǎn)化linux國(guó)產(chǎn)國(guó)產(chǎn)linux這些詞熱度高背后是真實(shí)的產(chǎn)業(yè)需求。國(guó)產(chǎn)芯片國(guó)產(chǎn)操作系統(tǒng)的組合越來(lái)越多這對(duì)嵌入式工程師是機(jī)會(huì)。我的建議是保持對(duì)國(guó)產(chǎn)芯片包括RISC-V方案的關(guān)注有機(jī)會(huì)就上手試試。生態(tài)早期進(jìn)入的人往往能吃到紅利。8. 我個(gè)人的一些體會(huì)做嵌入式這行十幾年我最大的感受是這個(gè)行業(yè)不缺人缺的是能打通全鏈路的人。會(huì)點(diǎn)燈的人一抓一大把能從傳感器一直做到云平臺(tái)、能獨(dú)立bringup系統(tǒng)、能排查內(nèi)核啟動(dòng)問(wèn)題的人永遠(yuǎn)稀缺。物聯(lián)網(wǎng)這個(gè)20萬(wàn)億美元的產(chǎn)業(yè)落到每個(gè)工程師身上其實(shí)就是一個(gè)個(gè)具體的問(wèn)題這塊板子怎么啟動(dòng)、這個(gè)驅(qū)動(dòng)怎么寫(xiě)、這個(gè)協(xié)議怎么轉(zhuǎn)、這個(gè)模型怎么部署。把這些問(wèn)題一個(gè)個(gè)解決掉你自然就進(jìn)入了這個(gè)產(chǎn)業(yè)而不是站在門(mén)外看那個(gè)嚇人的數(shù)字。如果你現(xiàn)在還在糾結(jié)學(xué)ARM64還是RISC-V、學(xué)Linux還是RTOS我的建議是先動(dòng)手用qemu跑一個(gè)ARM64 Linux起來(lái)再拿一塊STM32做個(gè)FreeRTOS節(jié)點(diǎn)兩個(gè)都摸一遍你就知道自己更適合哪個(gè)方向了。紙上比較一百次不如動(dòng)手做一次。