核4.19.y定制實戰(zhàn):從交叉編譯到設(shè)備樹與驅(qū)動)
簡介面向樹莓派開發(fā)者的Linux內(nèi)核4.19.y分支完整源碼包適合需要在內(nèi)核層進(jìn)行驅(qū)動開發(fā)、性能調(diào)優(yōu)或功能定制的嵌入式愛好者、樹莓派玩家及系統(tǒng)工程師。壓縮包約193.93MB內(nèi)含數(shù)萬份內(nèi)核源文件其中C源碼超過2.6萬份、頭文件超過1.9萬份另有makefile、設(shè)備樹dts/dtsi、Kconfig、defconfig等構(gòu)建與硬件描述文件便于按框架快速定位特定驅(qū)動、總線和外設(shè)配置。目前已有598人瀏覽學(xué)習(xí)對入門者和進(jìn)階者都有參考價值。內(nèi)容涵蓋從獲取源碼、配置menuconfig、編譯內(nèi)核與模塊到更新config.txt/cmdline.txt并重啟驗證的完整思路同時涉及GPIO、I2C、GPU、SPI等樹莓派常用外設(shè)的驅(qū)動編寫與內(nèi)核裁剪要點(diǎn)。學(xué)習(xí)這份源碼既能理解Linux內(nèi)核的編譯流程也能掌握針對樹莓派的定制化改造方法為進(jìn)一步編寫硬件驅(qū)動、優(yōu)化系統(tǒng)性能以及開展嵌入式項目打下扎實基礎(chǔ)。1. 樹莓派Linux源碼4.19.y從讀代碼到改內(nèi)核這一步才是關(guān)鍵樹莓派的Linux內(nèi)核鏡像并不是什么黑匣子但很多人拿到4.19.y這份源碼包后第一個動作往往是在drivers目錄里搜驅(qū)動名搜到幾個c文件就以為自己看懂了。實際上下載這份源碼的真正價值不在“讀”而在“改”——裁剪掉用不到的功能、給某個外設(shè)重新寫驅(qū)動、調(diào)整設(shè)備樹讓系統(tǒng)認(rèn)出一塊新板子。樹莓派4B、3B、Zero W 這些板子的差異就藏在這一棵內(nèi)核樹和幾十個.dts設(shè)備樹文件里。適合兩類人一類是做嵌入式產(chǎn)品原型、需要一個干凈且私有化內(nèi)核的開發(fā)者另一類是遇到官方內(nèi)核無法驅(qū)動某個外設(shè)、只能自己上手改源碼的折騰派。2. 源碼結(jié)構(gòu)拆解BCM283x驅(qū)動、設(shè)備樹與4.19.y的目錄主線拿到源碼包后先別急著敲make花十分鐘把目錄主線過一遍后面編譯和改驅(qū)動時能少走很多彎路。4.19.y 這版源碼是標(biāo)準(zhǔn)的 Linux 內(nèi)核樹加上樹莓派官方補(bǔ)丁你既能看到上游內(nèi)核的影子也能發(fā)現(xiàn)大量只屬于樹莓派的私有代碼。2.1 頂層目錄先分清哪些是樹莓派私有、哪些是通用內(nèi)核源碼根目錄下的結(jié)構(gòu)對做過內(nèi)核編譯的人并不陌生但有幾處需要單獨(dú)圈出來。arch/arm是樹莓派4B和3B這類32位ARM板卡的內(nèi)核架構(gòu)目錄包含啟動相關(guān)代碼、系統(tǒng)調(diào)用入口和內(nèi)存管理底層drivers是驅(qū)動的大雜燴樹莓派官方新增的驅(qū)動絕大多數(shù)都掛在drivers下對應(yīng)的子系統(tǒng)里Documentation里是內(nèi)核文檔開發(fā)時遇到 Kconfig 選項拿不準(zhǔn)、設(shè)備樹 binding 寫不對先翻這里比上論壇發(fā)帖高效得多。linux-rpi-4.19.y/ ├── arch/arm/ # ARM架構(gòu)代碼樹莓派默認(rèn)32位內(nèi)核 ├── arch/arm/boot/dts/ # 設(shè)備樹源文件樹莓派各型號的硬件描述 ├── drivers/ # 驅(qū)動代碼bcm2835相關(guān)驅(qū)動散落在各子系統(tǒng) ├── include/ # 內(nèi)核頭文件寫驅(qū)動時經(jīng)常要引用的路徑 ├── kernel/ # 內(nèi)核核心代碼調(diào)度、進(jìn)程管理等 ├── scripts/ # 編譯腳本mkknlimg 就在這里面 ├── Documentation/ # 內(nèi)核文檔設(shè)備樹binding、API說明 ├── Kconfig # 頂層配置菜單入口 └── Makefile # 頂層構(gòu)建腳本注意幾個容易被當(dāng)成普通目錄的地方。arch/arm/boot/dts下不僅有bcm2711-rpi-4-b.dts這類板級文件還有一個overlays子目錄里面是幾十個.dtbo設(shè)備樹插件樹莓派的 GPIO、I2C、SPI 擴(kuò)展全靠它們改設(shè)備樹時這里幾乎是必動的。scripts/mkknlimg是樹莓派特有的內(nèi)核鏡像轉(zhuǎn)換腳本上游內(nèi)核沒有編譯完 zImage 后必須用這個腳本轉(zhuǎn)出能被 bootloader 識別的kernel7l.img。2.2 BCM283x 系芯片的內(nèi)核側(cè)代碼從 machine 目錄到驅(qū)動子系統(tǒng)樹莓派用的是博通的 BCM2835、BCM2836、BCM2837、BCM2711 這一系 SoC在 4.19.y 里這些芯片對應(yīng)的平臺代碼并不集中在一個叫“bcm283x”的大目錄里而是按職責(zé)拆開。arch/arm/mach-bcm283x/里是芯片級初始化代碼4.19 時代已經(jīng)大量讓位于設(shè)備樹這個目錄里剩的東西不多真正干活的代碼在drivers下面。// drivers/pinctrl/bcm/pinctrl-bcm2835.c 是GPIO引腳控制的驅(qū)動入口 static const struct of_device_id bcm2835_pinctrl_match[] { { .compatible brcm,bcm2835-gpio }, { .compatible brcm,bcm2711-gpio }, {} };這段代碼展示了樹莓派驅(qū)動的典型寫法通過設(shè)備樹里的compatible字符串把硬件描述和驅(qū)動綁定起來。brcm,bcm2835-gpio對應(yīng)老款芯片brcm,bcm2711-gpio對應(yīng)樹莓派4B同一個驅(qū)動文件兼容多個芯片型號靠的就是設(shè)備樹聲明。編譯內(nèi)核前打開arch/arm/boot/dts/bcm283x.dtsi看看這些節(jié)點(diǎn)是怎么寫的能幫你理解“為什么改一個引腳要動設(shè)備樹而不是動 C 代碼”。2.3 設(shè)備樹、defconfig 與配置文件三者的關(guān)系一張表說清樹莓派的內(nèi)核定制繞不開三樣?xùn)|西設(shè)備樹描述硬件、defconfig 決定內(nèi)核功能、config.txt 告訴 bootloader 啟動參數(shù)。它們之間的邊界經(jīng)常被新手搞混簡單記你能插什么外設(shè)主要由設(shè)備樹決定內(nèi)核支不支持這個外設(shè)的驅(qū)動主要由 defconfig 決定啟動時加載哪份內(nèi)核鏡像和設(shè)備樹由 boot 分區(qū)里的 config.txt 決定。表4.19.y 源碼中與樹莓派型號對應(yīng)的關(guān)鍵配置文件文件/配置對應(yīng)板卡主要作用bcm2711-rpi-4-b.dts樹莓派4B定義4B的引腳、SD卡、HDMI、PCIe等硬件節(jié)點(diǎn)bcm2837-rpi-3-b-plus.dts樹莓派3B3B的板級設(shè)備描述bcm2711_defconfig樹莓派4B默認(rèn)配置BCM2711 平臺的內(nèi)核功能開關(guān)bcmrpi3_defconfig樹莓派3B/3B3代芯片的默認(rèn)配置文件常見誤用是改完設(shè)備樹忘了重新編譯.dtb或者改完.dts直接把它拷到 boot 分區(qū)用這都不會生效。4.19.y 的編譯流程會把.dts編成.dtb而 bootloader 實際讀取的是.dtb不是源文件。這個環(huán)節(jié)后面編譯時會再驗證一遍。3. 交叉編譯實戰(zhàn)一條命令鏈生成可啟動的kernel7l.img源碼樹在手里下一步要做的是把.c文件變成樹莓派 SD 卡上能跑的kernel7l.img。在不熟悉交叉編譯的人眼里這一步玄學(xué)很多其實拆開看就三件事選對工具鏈、設(shè)對環(huán)境變量、按序執(zhí)行幾個 make 目標(biāo)。3.1 工具鏈選擇官方 tools 倉庫和發(fā)行版自帶交叉編譯器怎么取舍交叉編譯樹莓派內(nèi)核有兩個常用選擇一個是樹莓派官方tools倉庫里現(xiàn)成的arm-bcm2708-linux-gnueabihf-工具鏈另一個是 Ubuntu、Debian 上通過 apt 安裝的arm-linux-gnueabihf-gcc。兩條路都能編出可運(yùn)行的內(nèi)核但血淚經(jīng)驗是官方工具鏈和 4.19.y 的源碼配合最穩(wěn)發(fā)行版自帶編譯器版本太新編老內(nèi)核時偶爾會報一些莫名的語法警告雖然多數(shù)不影響產(chǎn)物但排查起來費(fèi)時間。# 下載官方工具鏈并解壓到工作目錄 wget https://github.com/raspberrypi/tools/archive/master.zip unzip master.zip export PATH$PATH:$PWD/tools-master/arm-bcm2708-linux-gnueabihf/bin環(huán)境變量PATH加了之后先用arm-bcm2708-linux-gnueabihf-gcc -v驗證一下能不能跑。注意這里的前綴arm-bcm2708-linux-gnueabihf-雖然帶著bcm2708字樣但工具鏈本身是支持后續(xù)芯片的這個命名是歷史遺留不影響你編譯樹莓派4B的內(nèi)核。3.2 一次完整的編譯命令鏈ARCH、CROSS_COMPILE、make 目標(biāo)逐個說清在源碼根目錄執(zhí)行下面這組命令前先想清楚兩個變量ARCH告訴內(nèi)核構(gòu)建系統(tǒng)目標(biāo)架構(gòu)是 ARMCROSS_COMPILE指定交叉編譯器的前綴。漏掉任何一個make大概率會在本地 x86 環(huán)境下試圖用gcc編譯 ARM 代碼直接報unknown architecture之類的錯誤。export ARCHarm export CROSS_COMPILEarm-bcm2708-linux-gnueabihf- make bcm2711_defconfig # 生成 .config4B 用 bcm2711_defconfig make -j4 zImage modules dtbsbcm2711_defconfig是一個默認(rèn)配置目標(biāo)執(zhí)行后會生成.config文件這個文件是后續(xù)所有內(nèi)核編譯的起點(diǎn)zImage是壓縮后的內(nèi)核鏡像最終要轉(zhuǎn)成kernel7l.img才能被樹莓派引導(dǎo)modules是把配置里標(biāo)記為m的功能編成.ko文件驅(qū)動里很多非必須功能都走這一步dtbs是把設(shè)備樹源碼.dts編譯成.dtb。-j4是并行編譯的作業(yè)數(shù)一般取 CPU 核心數(shù)加一。注意如果你的板子是 3B、3B把bcm2711_defconfig換成bcmrpi3_defconfig再執(zhí)行。4B 和 3 代的內(nèi)核配置差異不小混用雖然偶爾也能啟動但容易出現(xiàn)某個外設(shè)驅(qū)動缺失的怪問題。3.3 編譯產(chǎn)物核對kernel7l.img、modules、dtbs 各要拷到哪編譯完成后arch/arm/boot/zImage是裸內(nèi)核鏡像不能直接燒錄需要用源碼根目錄scripts/下的mkknlimg工具包裝一下。./scripts/mkknlimg arch/arm/boot/zImage kernel7l.img make modules_install INSTALL_MOD_PATH/media/pi/rootfs cp arch/arm/boot/dts/*.dtb /media/pi/boot/ cp arch/arm/boot/dts/overlays/*.dtbo /media/pi/boot/overlays/mkknlimg會在 zImage 頭部加上樹莓派 bootloader 需要的標(biāo)記信息轉(zhuǎn)換后得到kernel7l.img才該拷進(jìn) boot 分區(qū)。modules_install的關(guān)鍵參數(shù)INSTALL_MOD_PATH指向你開發(fā)板 SD 卡的根文件系統(tǒng)目錄驅(qū)動模塊會被安裝到該目錄的lib/modules/4.19.y下面。設(shè)備樹文件分兩處拷板級.dtb直接放 boot 分區(qū)overlays子目錄里的.dtbo插件文件要放進(jìn) boot 分區(qū)的同名子目錄。如果你的 SD 卡是直接插在讀卡器上boot 分區(qū)就是那個能看到config.txt的 FAT 分區(qū)rootfs 是那個能看到etc/的 ext4 分區(qū)別拷反了。4. 內(nèi)核裁剪與模塊化defconfig、menuconfig、ko文件怎么配合編譯一次內(nèi)核的時間不短每次改配置全量重編更讓人頭疼。4.19.y 給了一個折中方案核心功能編進(jìn)內(nèi)核鏡像非關(guān)鍵功能編成.ko模塊用到時再用modprobe加載。這一章把配置裁剪和模塊加載的完整鏈路串一遍。4.1 defconfig 是基線menuconfig 做微調(diào)兩者配合省時間bcm2711_defconfig生成的是樹莓派官方認(rèn)為“通常夠用”的配置它開啟了絕大多數(shù)硬件驅(qū)動但很多你用不到的功能也在里面比如藍(lán)牙、Wi-Fi、各種顯示驅(qū)動這些會拖慢編譯并讓內(nèi)核體積變大。你需要的是在官方配置基礎(chǔ)上做減法。make menuconfigmenuconfig 是終端里的圖形化配置界面按/鍵可以搜索某個配置項。比如想去掉藍(lán)牙直接搜BT找到Bluetooth subsystem support按空格把*改成保存退出后.config就被改掉了。這比手動編輯.config靠譜得多因為 menuconfig 會自動處理依賴關(guān)系避免出現(xiàn)“關(guān)了 A 但 A 的依賴項還開著”這種不一致。4.2 一個真實的裁剪場景關(guān)掉藍(lán)牙和相關(guān)模塊后重新編譯以樹莓派4B為例如果做的是工業(yè)數(shù)據(jù)采集設(shè)備藍(lán)牙基本用不上。裁剪步驟如下先make menuconfig在搜索框輸入BT逐一把Bluetooth subsystem support、RFCOMM、BNEP等從[*]改為[ ]再搜BT_HCIUART這是板載藍(lán)牙串口驅(qū)動一并關(guān)掉保存退出后重新編譯。grep CONFIG_BT .config make -j4 zImage modules dtbsgrep CONFIG_BT .config用來確認(rèn)藍(lán)牙相關(guān)的配置確實被關(guān)掉了。重新編譯后對比 zImage 體積通常會小上幾 MB對啟動速度影響不大但對內(nèi)存占用和內(nèi)核安全面有實際意義。注意裁剪時保留CONFIG_BT_HCIBTUSB這類通用 USB 藍(lán)牙驅(qū)動的m屬性因為 USB 藍(lán)牙適配器可能還在用保險起見按模塊編譯而不是徹底關(guān)掉。4.3 從配置項到.ko文件一個模塊的誕生和加載路徑內(nèi)核配置里m表示編譯成模塊y表示編進(jìn)內(nèi)核鏡像。選擇m后驅(qū)動代碼不會進(jìn)入 zImage而是被編譯成drivers/net/wireless/xxx.ko這樣的獨(dú)立文件。很多新手分不清這兩者的適用場景放在啟動時必須用到的驅(qū)動比如 SD 卡控制、串口調(diào)試口建議y偶爾插拔的外設(shè)驅(qū)動比如 USB 轉(zhuǎn)串口、Wi-Fi 網(wǎng)卡用m更靈活。make modules_install INSTALL_MOD_PATH/path/to/rootfs # 在開發(fā)板上執(zhí)行 modprobe xxx # 查看模塊是否加載成功 lsmod | grep xxx dmesg | tail -20modprobe和insmod的區(qū)別在于modprobe會自動解析模塊依賴加載前先把依賴的其他.ko一起載入insmod則只加載指定文件依賴需要你手動處理。日常開發(fā)建議用modprobe。模塊加載失敗時dmesg里通常會有具體原因比如依賴的符號找不到、設(shè)備樹節(jié)點(diǎn)沒匹配上按日志排查即可。5. 編譯燒錄避坑指南啟動失敗時按這三條線索排查樹莓派內(nèi)核編譯翻車的場景多數(shù)集中在編譯環(huán)境、鏡像轉(zhuǎn)換、分區(qū)內(nèi)容這三處。這一章把最常見的坑列出來每條都按“現(xiàn)象、原因、解決”三部分記錄都是我實際踩過的路。5.1 現(xiàn)象編譯中期報錯openssl/evp.h: No such file or directory原因4.19.y 內(nèi)核在生成某些模塊時需要 OpenSSL 頭文件宿主系統(tǒng)沒有安裝開發(fā)庫。不裝庫而反復(fù)make clean重建只是浪費(fèi)時間。 解決Debian/Ubuntu 系統(tǒng)執(zhí)行sudo apt install libssl-devFedora 系裝openssl-devel。裝完從上次失敗的目標(biāo)繼續(xù)編不用全量重來。5.2 現(xiàn)象編譯通過、燒錄后啟動到一半panic或者手動加載.ko時報version magic不匹配原因內(nèi)核鏡像和模塊不是同一套配置、同一次編譯出來的。常見場景是更新了內(nèi)核鏡像但lib/modules/里還是老模塊或者用了兩個不同的工具鏈分別編譯內(nèi)核和模塊模塊的 vermagic 信息和內(nèi)核對不上。 解決內(nèi)核和模塊必須用同一棵源碼樹、同一次make modules_install裝到 rootfs。重新安裝模塊后再執(zhí)行depmod -a重建依賴表避免加載時找不到符號。5.3 現(xiàn)象燒錄后卡在開機(jī)彩虹屏進(jìn)不了系統(tǒng)原因boot 分區(qū)里的內(nèi)核鏡像名和config.txt指定的不一致或者kernel7l.img沒有經(jīng)過mkknlimg轉(zhuǎn)換直接復(fù)制了 zImage。樹莓派 bootloader 按文件名找內(nèi)核找不到或格式不對就在彩虹屏原地轉(zhuǎn)圈。 解決檢查config.txt里kernel行指向的是kernel7l.img還是kernel.img確認(rèn)實際文件存在重新用./scripts/mkknlimg轉(zhuǎn)換后再覆蓋 boot 分區(qū)sync 后斷電再試別用熱重啟。5.4 現(xiàn)象新內(nèi)核進(jìn)去了但 Wi-Fi 或藍(lán)牙消失lsmod看不到固件加載日志原因裁剪 defconfig 時把無線網(wǎng)卡驅(qū)動相關(guān)的CONFIG_BRCMFMAC、CONFIG_BT_HCIUART關(guān)成了n或者 rootfs 的/lib/firmware/brcm固件目錄缺失。啟動時驅(qū)動在modprobe階段找不到固件文件外設(shè)就靜默失敗。 解決裁剪前先grep -E BRCM|BT_HCI .config確認(rèn)哪些是硬件必須項補(bǔ)回驅(qū)動并重新編譯后從官方根文件系統(tǒng)鏡像里把/lib/firmware/brcm整個拷過來。這類問題不會報 panic容易讓人誤以為是硬件壞了。5.5 現(xiàn)象內(nèi)核替換后卡在Waiting for root device ...或直接進(jìn)入 initramfs shell原因cmdline.txt里的root參數(shù)指向的根文件系統(tǒng)分區(qū)和實際 SD 卡分區(qū)對不上。比如原先系統(tǒng)是/dev/mmcblk0p2換了一片分區(qū)布局不同的卡內(nèi)核根據(jù)參數(shù)找不到 rootfs。 解決在啟動時按CtrlC或查看最終進(jìn)入的 shell 提示符用blkid查 rootfs 分區(qū)的 UUID然后把cmdline.txt里的root改成 UUID 形式。這是樹莓派官方系統(tǒng)支持的方式比依賴/dev/mmcblk0pN這種不穩(wěn)定命名穩(wěn)得多。6. 二次開發(fā)實踐把第一個字符驅(qū)動編進(jìn)樹莓派內(nèi)核最后落到最實際的改造動作寫一個最小字符設(shè)備驅(qū)動然后編譯進(jìn)內(nèi)核而不是作為一個外面加載的模塊。這樣可以直觀感受“改一個文件、編一次內(nèi)核、在開發(fā)板上驗證”的完整閉環(huán)。6.1 驅(qū)動代碼、Kconfig、Makefile 三個文件的聯(lián)動在內(nèi)核源碼drivers/char/下新建hello_drv.c實現(xiàn)最基本的讀寫操作和設(shè)備節(jié)點(diǎn)創(chuàng)建。注意這里用的是 4.19.y 的老接口風(fēng)格register_chrdev和class_create在該版本中仍然有效不依賴新內(nèi)核的復(fù)雜框架。#include linux/init.h #include linux/module.h #include linux/fs.h #include linux/device.h #include linux/uaccess.h #define DEVICE_NAME hello_drv static int major; static struct class *hello_class; static ssize_t hello_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { char data[] hello from kernel\n; /* 把內(nèi)核緩沖區(qū)的數(shù)據(jù)復(fù)制到用戶空間 */ if (copy_to_user(buf, data, sizeof(data))) return -EFAULT; return sizeof(data); } static ssize_t hello_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { char data[64]; /* 把用戶空間的數(shù)據(jù)復(fù)制到內(nèi)核緩沖區(qū) */ if (copy_from_user(data, buf, count)) return -EFAULT; pr_info(hello_drv: received %zu bytes\n, count); return count; } static const struct file_operations hello_fops { .owner THIS_MODULE, .read hello_read, .write hello_write, }; static int __init hello_init(void) { /* 注冊字符設(shè)備0 表示讓內(nèi)核自動分配主設(shè)備號 */ major register_chrdev(0, DEVICE_NAME, hello_fops); if (major 0) return major; hello_class class_create(THIS_MODULE, DEVICE_NAME); device_create(hello_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME); pr_info(hello_drv: registered, major%d\n, major); return 0; } static void __exit hello_exit(void) { device_destroy(hello_class, MKDEV(major, 0)); class_destroy(hello_class); unregister_chrdev(major, DEVICE_NAME); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE(GPL);代碼里major是主設(shè)備號0 表示由內(nèi)核動態(tài)分配避免了手動指定時和其他驅(qū)動沖突copy_to_user和copy_from_user是內(nèi)核態(tài)與用戶態(tài)交換數(shù)據(jù)的標(biāo)準(zhǔn)接口不能用memcpy直接拷指針跨權(quán)限域時會出問題pr_info會輸出到內(nèi)核日志驗證時用dmesg查看。要讓內(nèi)核構(gòu)建系統(tǒng)認(rèn)識這個文件需要改兩處drivers/char/Kconfig里加一段配置項drivers/char/Makefile里加一行編譯規(guī)則。這樣make menuconfig就能搜到它也可以直接在.config里手動加CONFIG_HELLO_DRVy。# drivers/char/Kconfig 追加 config HELLO_DRV tristate Hello world driver default y help A simple character device for kernel development practice. # drivers/char/Makefile 追加 obj-$(CONFIG_HELLO_DRV) hello_drv.o6.2 驗證路徑重新編譯、替換鏡像、確認(rèn)設(shè)備節(jié)點(diǎn)重新執(zhí)行交叉編譯流程make bcm2711_defconfig這步會把你手動加的配置覆蓋掉所以直接make -j4 zImage modules dtbs然后mkknlimg轉(zhuǎn)換、拷貝 boot 分區(qū)、重啟。重啟后執(zhí)行下面幾個操作驗證結(jié)果ls /dev/hello_drv # 確認(rèn)設(shè)備節(jié)點(diǎn)存在 echo test /dev/hello_drv # 觸發(fā) write 回調(diào) dmesg | grep hello_drv # 看內(nèi)核日志中的登記信息 cat /dev/hello_drv # 讀取驅(qū)動返回的字符串cat返回hello from kernel就說明整個鏈路通了。如果設(shè)備節(jié)點(diǎn)不存在先看dmesg里注冊是否報錯再確認(rèn).config里CONFIG_HELLO_DRV確實變y或m了經(jīng)常有人改了 Kconfig 但沒重新生成.config這個步驟最容易翻車。6.3 一個讓我少折騰半天的習(xí)慣每次改配置后固定走一遍驗證循環(huán)驅(qū)動能跑只是第一步后面你大概率會反復(fù)調(diào)file_operations里的函數(shù)、改設(shè)備樹引腳、調(diào)整模塊依賴。從那以后我每次改動都會強(qiáng)制自己走完一遍“備份舊鏡像 → 編譯 → mkknlimg → 拷貝 dtb 和 modules → sync → 重啟 → dmesg 驗證”的流程不做完不進(jìn)行下一個修改。這套循環(huán)雖然看起來機(jī)械但能精準(zhǔn)定位問題環(huán)節(jié)省去了“改了但不知道改沒生效”的反復(fù)猜測。希望幫到你在這棵 4.19.y 源碼樹上找到自己的節(jié)奏。本文還有配套的精品資源點(diǎn)擊獲取