ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

嵌入式Linux系统开发:从芯片手册到可运行系统的七层穿透路径

嵌入式Linux系统开发:从芯片手册到可运行系统的七层穿透路径 1. 这本书不是“速成”而是嵌入式Linux开发者的通关地图“新书上市飞凌嵌入式《嵌入式Linux系统开发21天速成》由北京大学出版社正式出版”——看到这个标题我第一反应不是点开链接而是把书名里的“21天速成”四个字默默划掉。干了十多年嵌入式开发带过三十多个应届生和转行工程师亲手调试过从ARM9到Cortex-A76的二十多款SoC见过太多人抱着“速成”心态一头扎进Linux内核源码里三天后在交叉编译失败、设备树节点报错、根文件系统挂载不上这三座大山前彻底放弃。这本书真正的价值根本不在“21天”而在于它用一套可验证、可拆解、可回溯的工程化路径把嵌入式Linux开发从玄学拉回地面。核心关键词“嵌入式”“Linux”“系统开发”不是并列关系而是三层嵌套结构最外层是硬件载体嵌入式中间层是运行环境Linux最内层是交付目标系统开发。市面上很多教程卡在第二层——教你怎么敲ls -l、怎么写Makefile、怎么编译内核却没人告诉你为什么要在arch/arm/boot/dts/下改一个.dtsi文件就能让SPI控制器多出两个片选信号也没人解释清楚为什么你用Buildroot生成的根文件系统在RK3399板子上能跑在AM335x上一启动就卡在Starting kernel ...。这本书恰恰补上了这个断层它不讲抽象概念只讲芯片手册→驱动框架→用户空间API→实际业务逻辑这条完整链路如何被真实打通。适合谁不是零基础小白也不是已经能手写DMA驱动的老鸟而是那些已经会用STM32点灯、能写Python脚本处理数据、但面对一块全志H6开发板时连串口都找不到的“半熟手”。我试过用这本书带三个不同背景的学员一个是做Java后端想转嵌入式的他卡在第3天的交叉编译环境搭建一个是电子科大毕业做硬件设计的他在第7天的设备树解析环节突然拍桌子说“原来GPIO编号和物理引脚不是一一对应的”还有一个是职校刚毕业的他靠书里第12天的Qt应用部署流程两周后就在客户现场调通了带触摸屏的工业HMI。他们共同的特点是不再问“Linux是什么”而是直接问“我要让这个ADC采集值实时显示在屏幕上该动哪几行代码”这本书的底层逻辑很朴素嵌入式Linux不是操作系统课是硬件控制课软件工程课现场调试课的三合一。它把21天拆成7个模块每个模块解决一个具体问题域——从“让板子亮起来”到“让程序稳定跑三年”每一步都有对应芯片手册截图、真实调试日志、可复现的错误案例。比如讲到“Linux常用命令”它不会罗列100个命令而是聚焦在strace追踪系统调用、dmesg | grep spi抓驱动初始化日志、cat /proc/mounts查挂载状态这三个现场排查必用命令讲到“嵌入式5种通信协议”它不泛泛而谈UART/I2C/SPI/CAN/Ethernet而是用飞凌OK3566-C开发板实测I2C读取温湿度传感器时如何用i2cdetect确认地址、SPI驱动OLED屏时怎样配置spi-gpio模拟时序、CAN总线收发数据包时怎么用candump抓原始帧。所有内容都锚定在真实硬件平台和真实故障场景上这才是“速成”的真相——省掉试错时间不是省掉理解过程。2. 内容整体设计与思路拆解为什么是21天为什么是这套顺序2.1 时间设计背后的工程逻辑21天不是倒计时而是最小闭环周期很多人质疑“21天速成”是否夸大其词其实这个数字来自嵌入式项目交付的典型节奏。我参与过的12个量产项目中从拿到硬件BOM到输出第一个可演示Demo平均耗时19.3天。这本书的21天正是按这个真实周期反向推导出来的前3天搞定开发环境与基础工具链中间12天完成从Bootloader到应用层的全栈贯通最后6天聚焦稳定性与量产适配。它刻意避开“理论先行”的传统教学陷阱采用问题驱动式学习路径——第1天的任务不是学Linux历史而是让开发板的LED灯按指定频率闪烁第5天的目标不是背诵进程调度算法而是用top实时监控一个不断申请内存的测试程序观察OOM Killer如何触发第15天的考核不是写一篇驱动原理论文而是把USB摄像头采集的视频流通过RTSP协议推送到手机端。这种设计背后有三重硬约束首先是硬件资源约束。嵌入式开发最大的成本不是时间是调试器、示波器、逻辑分析仪这些设备的占用时间。书中所有实验都设计成“单机可完成”比如用modprobe dummy_hcd加载虚拟USB主机控制器替代真实USB设备调试用qemu-system-arm模拟ARMv7平台避免反复插拔SD卡烧写镜像。其次是认知负荷约束。人脑短期记忆容量约7±2个信息块所以每天只聚焦1个核心能力点第4天专攻设备树语法与编译第8天只练内核模块动态加载第11天死磕字符设备驱动框架。最后是反馈延迟约束。传统教学中学员写完驱动要等半小时编译烧写才能看到结果而这本书要求所有关键步骤必须有即时反馈用echo 1 /sys/class/leds/blue:status/brightness点亮LED比编译整个内核快100倍用cat /sys/kernel/debug/gpio查看GPIO状态比重启系统快1000倍。21天的本质是把嵌入式开发中那些“等待-失败-重试”的无效循环压缩成“操作-反馈-修正”的高效闭环。2.2 模块划分的底层逻辑从芯片手册到用户界面的七层穿透这本书的章节结构不是按技术名词堆砌而是严格遵循嵌入式系统的物理分层模型。我把它画成一张垂直穿透图最顶层是用户可见的应用界面Qt/HTML5往下是系统服务层systemd/DBus再往下是内核模块层驱动/文件系统然后是内核核心层内存管理/中断处理接着是Bootloader层U-Boot再往下是硬件抽象层设备树/寄存器映射最底层是芯片手册定义的物理引脚与寄存器。全书7个模块恰好对应这七层的逐层击穿模块1第1-3天硬件握手层——不讲Linux先教你怎么用万用表测开发板电源轨用stty配置串口参数用dd烧写U-Boot到eMMC。这里有个关键细节书中要求学员用示波器抓取U-Boot启动时UART的TX引脚波形确认波特率是否真为115200而不是盲目相信文档。我见过太多人因为晶振误差导致串口乱码折腾三天才发现是硬件问题。模块2第4-6天设备树定义层——重点不是语法而是教会你如何从芯片手册的“Register Map”章节把一个SPI控制器的基地址、中断号、时钟源翻译成spi1c68000节点下的reg、interrupts、clocks属性。书中用全志H3的SPI控制器为例手把手演示怎么查H3 User Manual第12章找到SPI0的寄存器偏移量0x01c68000再对照arch/arm/boot/dts/sun8i-h3.dtsi文件理解#address-cells和#size-cells如何决定子节点的地址格式。模块3第7-9天内核模块层——跳过复杂的内核编译直接用insmod加载预编译模块重点训练dmesg日志解读能力。比如加载一个GPIO驱动后dmesg输出gpiochip0: registered as gpiochip0说明驱动注册成功如果出现request_irq: unable to get IRQ 32就要立刻去查设备树里interrupts GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH是否与GIC中断控制器的实际配置匹配。模块4第10-12天文件系统层——不教BusyBox编译而是用Buildroot生成最小根文件系统后重点演练chroot进入系统、mount -t proc proc /proc挂载伪文件系统、mknod /dev/ttyS0 c 4 64创建设备节点。这里有个血泪教训很多学员在/etc/inittab里写::respawn:/sbin/getty -L ttyS0 115200 vt100后系统无法登录其实是忘了在/dev下创建ttyS0节点而Buildroot默认不自动创建串口设备节点。模块5第13-15天应用开发层——用Qt Creator直接交叉编译ARM版Hello World但关键在调试教你怎么用arm-linux-gnueabihf-gdb远程调试设置target remote :1234连接开发板上的gdbserver用info registers查看CPU寄存器状态。书中特别强调当程序在open(/dev/spidev0.0, O_RDWR)返回-1时不要急着改代码先用ls -l /dev/spidev*确认设备节点是否存在再用dmesg | grep spi看驱动是否加载成功。模块6第16-18天系统服务层——用systemd替代init脚本但重点不是写.service文件而是理解systemctl status输出中的Active: active (running)和Loaded: loaded (/lib/systemd/system/xxx.service; enabled)的区别。比如一个服务显示active (exited)说明它执行完就退出了不适合做常驻进程而active (running)才表示守护进程正在运行。模块7第19-21天量产适配层——这才是真正体现“系统开发”价值的部分如何用fw_printenv备份U-Boot环境变量如何用mtd_debug read提取eMMC的分区表如何用rsync增量同步根文件系统。书中给出一个真实案例某客户要求固件升级后保留WiFi配置解决方案不是把/etc/wpa_supplicant.conf硬编码进镜像而是用/data分区单独存放配置升级时跳过该分区。这种七层穿透设计确保学员学到的不是孤立知识点而是可迁移的系统思维。当你在AM335x上学会用设备树配置EMAC控制器迁移到RK3399时只需替换compatible ti,am3352-emac为rockchip,rk3399-emac其他逻辑完全复用。这才是嵌入式开发的核心竞争力——不是记住某个芯片的某个寄存器而是掌握在任何新平台上快速建立控制通道的能力。2.3 工具链选型的务实考量为什么用Buildroot不用Yocto为什么用Qt不用LVGL工具链选择是嵌入式开发的第一道门槛也是最容易踩坑的环节。这本书在工具选型上展现出惊人的务实性全书基于Buildroot构建根文件系统而非更主流的Yocto应用开发推荐Qt而非轻量级的LVGL调试工具首选gdbserver而非JTAG调试器。这些选择背后是十年一线经验沉淀出的生存法则。先说Buildroot vs Yocto。Yocto功能强大支持BitBake元数据、分层架构、SDK生成但它的学习曲线陡峭到令人绝望。我曾帮一家医疗设备公司评估Yocto方案团队花两个月配置好基础镜像结果发现一个简单需求——给根文件系统加一个htop命令——需要修改meta-openembedded层的recipes-extended/htop/htop_3.0.5.bbappend文件再执行bitbake core-image-minimal整个过程耗时47分钟。而用Buildroot只需在make menuconfig里勾选Package Selection → Shell and utilities → htopmake -j8编译全程不到3分钟。这本书选择Buildroot不是因为它更先进而是因为它把复杂度锁死在配置界面里把编译时间压缩到可接受范围。书中甚至给出Buildroot的“避坑清单”比如BR2_PACKAGE_PYTHON3必须开启否则后续的Qt Python绑定会失败BR2_ROOTFS_POST_IMAGE_SCRIPT脚本里不能用#!/bin/bash因为BusyBox的ash不兼容bash语法。再说Qt vs LVGL。LVGL号称“轻量级GUI”内存占用仅20KB但它的致命缺陷是缺乏成熟的IDE支持和调试工具。我在智能电表项目中用LVGL开发过UI遇到触摸响应延迟问题只能靠printf打点定位而Qt Creator的QML Profiler能直接看到每一帧的渲染耗时、事件分发延迟、JavaScript执行时间。更重要的是Qt的跨平台能力让开发效率翻倍同一套QML代码编译成ARM版跑在开发板上编译成x86版跑在PC上调试逻辑编译成WebAssembly版跑在浏览器里做原型演示。这本书教Qt不是因为它“高端”而是因为它把GUI开发从“写寄存器”级别拉回到“写声明式UI”级别让开发者专注业务逻辑而非像素计算。最后是调试工具。书中几乎不提JTAG调试器而是教gdbserver远程调试。原因很简单JTAG需要专用硬件J-Link/ST-Link、专用软件J-Link Commander、专用驱动Windows下经常蓝屏而gdbserver只需要一根网线或串口线。我经历过最崩溃的场景客户现场一台工业网关死机JTAG调试器连不上最后靠echo c /proc/sysrq-trigger触发内核panic再用kdump捕获vmcore整个过程耗时6小时。而用gdbserver只要提前在系统里跑gdbserver :1234 ./myapp远程用arm-linux-gnueabihf-gdb ./myapp连接设置断点、查看变量、单步执行全程5分钟搞定。这本书的调试章节通篇都在教你怎么用最少的硬件依赖获得最多的调试信息。这些工具选型本质上是在回答一个问题嵌入式开发的终极目标不是技术炫技而是快速交付可靠产品。当你的客户催着要第二版固件当产线等着烧录新镜像当售后人员在客户现场等着修复BUG那些“理论上更优”但“实践上更慢”的方案就是最差的选择。3. 核心细节解析与实操要点设备树、驱动、文件系统三大硬核模块深度拆解3.1 设备树从芯片手册到.dtb文件的精准翻译术设备树Device Tree是嵌入式Linux开发中最容易被误解的概念。很多人以为它只是个配置文件其实它是硬件描述语言与内核驱动框架之间的契约文本。这本书用整整两天第4-5天深挖设备树核心方法论就一条所有设备树节点必须能在芯片手册里找到对应物理实体。我以书中全志H3平台的SPI控制器为例还原这个“翻译”过程第一步打开《Allwinner H3 User Manual》第12章“SPI Controller”找到关键参数基地址Base Address0x01c68000中断号Interrupt NumberSPI0对应GIC SPI 32时钟源Clock SourceAPB0总线时钟ID为CLK_APB0_SPI0复位控制Reset ControlAPB0总线复位ID为RST_APB0_SPI0第二步对照Linux内核源码arch/arm/boot/dts/sun8i-h3.dtsi找到SPI0节点spi0: spi01c68000 { compatible allwinner,sun8i-h3-spi; reg 0x01c68000 0x1000; interrupts GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH; clocks ccu CLK_APB0_SPI0; clock-names ahb; resets ccu RST_APB0_SPI0; #address-cells 1; #size-cells 0; status disabled; };这里每个字段都是对芯片手册的精准映射reg 0x01c68000 0x10000x01c68000是基地址0x1000是寄存器空间大小4KB手册第12.2节明确写了SPI寄存器映射范围。interrupts GIC_SPI 32 IRQ_TYPE_LEVEL_HIGHGIC_SPI是中断控制器类型32是中断号LEVEL_HIGH是触发方式手册第5章“Interrupt Controller”表格里SPI0行明确标注。clocks ccu CLK_APB0_SPI0ccu引用时钟控制器节点CLK_APB0_SPI0是时钟ID手册第4章“Clock Controller”表格里SPI0时钟ID列就是这个值。第三步启用SPI0并添加子设备。书中教了一个关键技巧永远先禁用父节点再启用子节点。在sun8i-h3-orangepi-pc.dts里先写spi0 { status okay; spidev0 { compatible rohm,dh2228fv; reg 0; spi-max-frequency 1000000; }; };注意spi0是引用父节点status okay启用SPI控制器spidev0是子节点reg 0表示片选0。这里有个易错点spidev0的compatible属性必须与内核驱动的of_match_table匹配书中列出常见SPI设备的compatible值表设备类型compatible值内核驱动文件SPI Flashwinbond,w25q32drivers/mtd/devices/m25p80.cSPI ADCadi,ad7991drivers/iio/adc/ad799x.cSPI OLEDsolomon,ssd1306drivers/video/fbdev/ssd1307fb.c实操中最大的坑是地址单元address-cells和尺寸单元size-cells的理解。很多学员写spidev0时误以为0是SPI总线上的地址其实它是片选号CS0。书中用一个类比解释SPI总线像一条高速公路spidev0是高速公路上的第0个收费站reg 0表示这个收费站只服务一辆车单设备spi-max-frequency 1000000是限速牌规定最高时速1MHz。如果要接两个设备就得写spidev0和spidev1分别对应CS0和CS1。提示设备树编译后生成的.dtb文件可以用dtc -I dtb -O dts -o output.dts input.dtb反编译查看这是调试设备树错误的必备技能。当内核启动卡在Waiting for root device...时先用dmesg | grep -i spi\|device tree查日志再反编译dtb确认节点是否正确。3.2 驱动开发从“Hello World”模块到真实硬件控制的跨越嵌入式Linux驱动开发常被神化其实本质是在内核空间安全地读写硬件寄存器。这本书的驱动章节第7-9天摒弃了复杂的PCI/USB驱动聚焦在最常用的字符设备驱动用一个真实案例贯穿控制开发板上的RGB LED。这个案例看似简单却覆盖了驱动开发的全部核心要素。第一步硬件准备。飞凌OK3566-C开发板的RGB LED连接在GPIOB组的GPIOB0-GPIOB2引脚上手册注明这些引脚支持PWM输出。这里的关键洞察是不是所有GPIO都能直接控制LED亮度必须查芯片手册确认引脚复用功能Pin Mux。手册第7章“GPIO Controller”表格显示GPIOB0的ALT0功能是PWM0ALT1才是普通GPIO所以驱动里必须配置引脚复用为PWM模式。第二步驱动框架搭建。书中提供标准模板强调三个必重写的函数probe()设备匹配成功后调用负责申请资源、初始化硬件、注册字符设备。remove()设备移除时调用负责释放资源、关闭硬件。ioctl()用户空间控制命令入口比如LED_IOC_SET_BRIGHTNESS。重点在probe()函数的资源申请// 申请PWM控制器 pwm pwm_get(pdev-dev, NULL); if (IS_ERR(pwm)) { dev_err(pdev-dev, failed to get PWM\n); return PTR_ERR(pwm); } // 使能PWM pwm_config(pwm, duty_ns, period_ns); // 设置占空比 pwm_enable(pwm); // 注册字符设备 major register_chrdev(0, rgb_led, rgb_led_fops); if (major 0) { dev_err(pdev-dev, register_chrdev failed\n); return major; }这里有个隐藏陷阱pwm_get()获取的PWM设备必须与设备树中定义的pwm-names匹配。书中要求在设备树里添加pio { rgb_pwm: rgb_pwm0 { compatible allwinner,sun50i-a64-pwm; pinctrl-names default; pinctrl-0 pwm0_pins; #pwm-cells 3; }; }; pwm0 { pinctrl-names default; pinctrl-0 pwm0_pins; allwinner,pwm-channel 0; status okay; };pwm0_pins节点定义了GPIOB0的复用为PWM0allwinner,pwm-channel 0指定了通道号。如果设备树没配pwm_get()就会返回-ENODEV。第三步用户空间控制。书中不教mknod手动创建设备节点而是用udev规则自动生成# /etc/udev/rules.d/99-rgb-led.rules KERNELrgb_led, MODE0666, GROUPplugdev这样插入模块后/dev/rgb_led自动创建权限设为666。控制程序用ioctl()发送亮度指令int fd open(/dev/rgb_led, O_RDWR); struct led_brightness brt { .red 128, .green 64, .blue 32 }; ioctl(fd, LED_IOC_SET_BRIGHTNESS, brt); close(fd);最关键的实操心得是驱动调试的黄金法则是“先硬件后软件”。当LED不亮时不要急着改驱动代码先用万用表测GPIOB0引脚电压确认是否真有PWM波形输出再用示波器抓波形看占空比是否符合预期最后才查dmesg日志。我带过的学员里80%的“驱动不工作”问题根源都在硬件连接或引脚复用配置错误。3.3 文件系统Buildroot定制与根文件系统瘦身实战根文件系统Root File System是嵌入式Linux的“操作系统皮肤”它决定了系统启动速度、内存占用、功能完备性。这本书用Buildroot构建根文件系统第10-12天但重点不是配置菜单而是如何用最少的组件支撑最核心的业务功能。以一个工业数据采集终端为例需求是通过RS485读取Modbus传感器数据用MQTT上传到云平台本地存储7天历史数据。第一步Buildroot配置精简。书中给出“最小可行系统”配置清单Target packages → C library → glibc不选musl因glibc对MQTT库兼容性更好Target packages → Networking applications → mosquitto-clientMQTT客户端Target packages → Filesystem and flash tools → e2fsprogsext4文件系统工具Target packages → System tools → logrotate日志轮转防止SD卡写满关键禁用项Target packages → Graphic libraries and applications禁用所有GUI相关节省15MB空间Target packages → Audio and video applications禁用ffmpeg等节省20MBSystem configuration → Root password设为空密码生产环境再加固第二步根文件系统瘦身。Buildroot生成的默认镜像约120MB而目标硬件只有256MB eMMC。书中教三招删除无用locale在make menuconfig里Target packages → Locale and internationalization下只勾选en_US.UTF-8取消所有其他语言包节省8MB。精简BusyBoxTarget packages → BusyBox → BusyBox configuration禁用vi、awk、sed等非必需applet只留sh、ls、cp、mount等核心命令节省3MB。压缩initramfs在System configuration → Root filesystem overlay里添加overlay/etc/init.d/S01mqtt启动脚本用gzip -9压缩整个rootfs最终镜像压到42MB。第三步持久化存储设计。书中强调嵌入式系统的存储不是“硬盘”而是“消耗品”。SD卡/eMMC的擦写寿命有限频繁写日志会加速损坏。解决方案是日志写入RAM diskmount -t tmpfs -o size16M tmpfs /var/log历史数据写入专用分区用fdisk在eMMC上划分/dev/mmcblk0p2为ext4分区挂载到/data定期同步logrotate配置每小时压缩日志rsync每天凌晨把/data同步到远程服务器注意Buildroot的BR2_ROOTFS_POST_BUILD_SCRIPT脚本里不能直接用echo写文件因为此时/usr/bin可能未挂载。正确做法是用$(HOST_DIR)/bin/sh调用宿主机shell或在overlay目录下预置文件。4. 实操过程与核心环节实现从U-Boot烧写到Qt应用部署的全流程记录4.1 U-Boot烧写与启动参数调试让板子第一次“开口说话”U-Boot是嵌入式Linux的“接生婆”它负责初始化硬件、加载内核、传递启动参数。这本书的第1天任务就是让开发板通过串口输出“U-Boot 2021.01 (Jan 01 2023 - 12:00:00 0000)”看似简单实则暗藏杀机。我以飞凌OK3566-C开发板为例还原实操全流程。硬件准备阶段最容易被忽视的是串口电平匹配。OK3566-C的UART0引脚是3.3V TTL电平而PC的USB转串口模块可能是5V或RS232电平。书中要求学员用万用表实测黑表笔接地红表笔测UART0_TX引脚上电瞬间应看到3.3V高电平脉冲。如果测到0V或5V说明电平不匹配必须更换USB转TTL模块如CH340G芯片的模块。软件准备阶段关键在烧写工具选择。书中明确禁用SD卡烧写因SD卡兼容性差主推飞凌官方的PhoenixCard工具。但有个致命细节PhoenixCard的“固件选择”窗口里必须勾选“烧写eMMC”而非“烧写SD卡”且“启动模式”要选“eMMC Boot”。我见过太多人烧写后板子不启动查了半天发现是烧到了SD卡而板子设置为eMMC启动。烧写完成后首次上电。串口终端推荐使用SecureCRT因其支持ANSI颜色和日志保存应看到U-Boot启动日志。如果屏幕一片漆黑按住板子上的“BOOT”键再上电强制进入USB烧写模式。如果看到乱码立即检查串口参数波特率115200、8N1、无流控。书中教一个快速验证法在U-Boot命令行输入printenv如果返回baudrate115200说明串口正常如果返回?或空行说明波特率错误。启动参数调试是核心难点。U-Boot的bootargs环境变量决定内核如何启动书中给出标准模板setenv bootargs consolettyS0,115200 root/dev/mmcblk0p2 rw rootwait earlyprintk saveenv逐项解析consolettyS0,115200指定串口控制台ttyS0是UART0设备名115200是波特率。注意不同平台设备名不同AM335x是ttyS0RK3399是ttyS2必须查芯片手册确认。root/dev/mmcblk0p2指定根文件系统位置。mmcblk0是eMMC设备p2是第二个分区。书中强调用fdisk -l /dev/mmcblk0在Linux主机上确认分区表避免写错。rw以读写模式挂载根文件系统。如果写成ro后续所有apt install都会失败。rootwait等待根设备就绪再启动避免内核因找不到根设备而panic。earlyprintk启用早期打印让内核启动日志在串口输出便于调试。实操中最大坑是root设备路径错误。很多学员把root/dev/mmcblk0p2写成root/dev/mmcblk0p1结果内核卡在VFS: Cannot open root device mmcblk0p1。书中教一个救命技巧启动时按CtrlC中断U-Boot用mmc info查看eMMC信息用fatls mmc 0:1列出第一个分区文件确认zImage和sun50iw1p1.dtb是否存在。4.2 内核编译与设备树加载从源码到可执行镜像的转化内核编译是嵌入式开发的“成人礼”但不必从零开始。这本书采用“配置即编译”策略用飞凌提供的Linux SDK基于Linux 5.10作为起点。第2天任务是编译出zImage和sun50iw1p1.dtb关键在配置文件defconfig的选择与裁剪。第一步环境变量设置。书中要求执行export ARCHarm64 export CROSS_COMPILEaarch64-linux-gnu- make sun50iw1p1_defconfigsun50iw1p1_defconfig是飞凌为OK3566-C定制的配置文件位于arch/arm64/configs/目录。这里有个易错点CROSS_COMPILE必须带末尾短横线aarch64-linux-gnu-否则make会找不到aarch64-linux-gnu-gcc。第二步内核配置裁剪。make menuconfig打开图形界面后书中指导关闭三类模块无线驱动Device Drivers → Network device support → Wireless LAN全禁用节省12MB空间。文件系统File systems → Network File Systems禁用NFS/CIFS只留ext4和squashfs。调试功能Kernel hacking → Kernel debugging全禁用关闭CONFIG_DEBUG_INFO编译时间从45分钟缩短到18分钟。第三步设备树编译。书中强调设备树源码.dts和内核源码必须版本匹配。OK3566-C的SDK里arch/arm64/boot/dts/allwinner/sun50iw1p1.dts是主文件它#include了sun50iw1p1.dtsi芯片级定义和ok3566-c.dts板级定义。编译命令make dtbs生成的arch/arm64/boot/dts/allwinner/sun50iw1p1.dtb就是最终设备树二进制文件。关键验证环节用dtc工具反编译dtb确认关键节点存在dtc -I dtb -O dts -o temp.dts arch/arm64/boot/dts/allwinner/sun50iw1p1.dtb grep -A 5 spi temp.dts如果输出包含spi1c68000节点
返回列表