久久派龙芯k平台内核交叉编译与安全升级实践

发布时间:2026/9/9 5:23:51

久久派龙芯k平台内核交叉编译与安全升级实践
上一篇把板子点亮之后后台一直有朋友催更出厂内核用着能用但总觉得不踏实想自己编译一版内核又不知道从哪下手还有人问设备树改了之后要不要重新烧整个系统这一篇就专门填这些坑。主题很明确基于手头这块龙芯k平台的久久派把交叉编译内核的完整流程走通同时把升级动作拆到“即使失败也不会变砖”的安全范围内。这篇笔记默认你已经完成了上篇的基础工作主机上能通过串口登录板子板子能正常进入LinuxTF卡或eMMC上有可用的根文件系统。如果你还在“点不亮”阶段先回头把串口和启动介质搞定否则后面的一切都没有载体。这篇文章适合两类人刚拿到久久派、想尽快进入驱动开发或外设调试的入门者以及用过其他嵌入式板子、想转到龙芯k平台上来的老手。1. 动手之前先弄明白内核升级到底在做什么1.1 为什么不能一直用出厂内核出厂内核最大的问题是“不可控”。板厂为了方便演示通常会把大量驱动编进内核配置保守、功能冗余跑起来占用高不说有些外设明明板子上没有驱动却还在加载反过来真到了你想接一个自己设计的传感器、想改一个引脚复用时出厂内核里往往没有对应的配置项或者设备树里根本没留节点。我自己的体会是拿到一块新开发板前两周用出厂内核完全没问题但第三周开始你一定会有自己编译内核的冲动。原因不外乎这几类需要开启某个内核配置但出厂内核没有打开比如某些网络协议、文件系统支持。需要修改设备树里的引脚功能、外设节点不改内核就没法生效。需要打上游补丁或做内核版本升级用新特性或修复已知问题。内核出问题时需要开调试信息、加打印快速定位是驱动问题还是硬件问题。无论是哪种逻辑上最终都会走到同一步拿到官方或板厂提供的内核源码用交叉编译工具链编出一个适合自己板子的内核然后把旧内核换掉。这一步跨过去后续所有和硬件打交道的开发都会顺畅很多。1.2 从源码到板端完整的工作流长什么样在写第一行命令之前先在脑子里把整个流程走一遍。我的经验是嵌入式开发里绝大部分“编译不过”“启动卡死”都是因为对整个链条理解不完整而不是某一条命令打错了。一次常规的内核升级完整链路可以拆成这样主机上准备交叉编译工具链确认架构和板子匹配。获取内核源码切到板级对应的分支或 tag。用默认配置或自定义配置生成 .config。用 make 交叉编译内核镜像和设备树 dtb。编译内核模块并安装到根文件系统的对应目录。把新内核镜像、dtb 备份后传到板子的启动分区。重启板子确认新内核启动成功验证外设功能。这个链路里第 1 到 5 步都在主机上做第 6 到 7 步才真正碰到开发板。换句话说哪怕内核编出来有问题在烧进去之前你都还有补救空间一旦到了第 6 步就要像拆炸弹一样小心了。我在后面的章节里会把每一步容易踩的坑单独拎出来说。1.3 版本与分支规划先想清楚再动手很多新手最容易犯的错是不管三七二十一从内核官网拉一个 latest stable 就开始编。编完才发现板子的 Bootloader 不认这个格式或者某个外设驱动在主线内核上根本没适配。龙芯k平台的内核开发和普通 ARM 板还不太一样。它虽然也走 Linux 主线但很多板级支持代码、设备树、BSP 驱动可能在厂商的维护分支上才够完整。我的建议是第一优先使用板厂/龙芯 SDK 里配套的内核源码版本。这个版本和出厂固件、Bootloader 配合最稳定。第二优先使用龙芯开源社区维护的 loongarch 内核分支但要注意看板级 defconfig 和 dts 是否覆盖你的板子。第三优先自己尝试上游主线适合想折腾新特性、有能力自己适配设备树的老手新手不推荐从这里起步。怎么确认当前板子上跑的内核版本登录板子执行uname -a cat /proc/version记下这个版本号后面选源码分支就对着它来。比如当前跑的是 5.10.x那在源码仓库里优先找 5.10 对应的分支或 tag而不是直接跳到 6.x。要记住内核升级讲究的是“稳”不是“新”。2. 编译环境补充与源码准备2.1 主机依赖缺什么补什么上篇我们已经在主机上装过一部分开发工具但内核编译对主机环境有额外要求尤其是老一点的 Ubuntu/Debian 系统很可能缺几个关键包。先执行一遍缺啥补啥省得编译到一半报错再回头装sudo apt update sudo apt install -y git make gcc flex bison bc \ libssl-dev libncurses-dev libelf-dev \ device-tree-compiler u-boot-tools逐个解释一下这些包是干嘛的flex、bison内核的 Kconfig 和 DTS 解析需要用到词法/语法分析器生成解析代码。缺了它们make menuconfig 那一步就可能直接报错。bc内核编译脚本里有用到计算器处理数值少了会报“bc: not found”。libssl-dev编译内核时需要生成签名证书相关代码老版本内核对这个依赖比较强。libncurses-devmenuconfig 的图形界面依赖它不装的话 make menuconfig 起不来。device-tree-compiler提供 dtc 工具编译设备树必须用它。u-boot-tools提供 mkimage用于制作 U-Boot 认识的镜像格式后面打包内核时会用到。这一套装完主机层面的依赖基本就齐了。如果你用的是 Fedora/Arch 这类发行版包名略有差异按对应包管理器搜一下即可。2.2 获取内核源码先对版本再谈编译获取源码的路径取决于你手上板子的 BSP 来源。常见的有三种龙芯官方或板厂提供的 SDK 压缩包解压后里面就有 kernel 目录。Git 仓库可能是龙芯开源社区的 loongarch 内核仓库也可能是板厂自己的仓库。上游 kernel.org 主线仓库但这种适合做移植新手慎选。以 Git 仓库为例拉取时可以加--depth1只拉最新提交省时间也省空间。但如果要切到某个历史 tag 或分支还是建议完整拉取否则后面切分支会遇到对象缺失的问题。git clone https://github.com/loongson/linux.git cd linux git branch -a git tag | grep 5.10 | tail看到分支列表之后选一个和你当前系统版本最接近的分支比如git checkout -b my-kernel-5.10 origin/loongarch-5.10这里必须强调一点别急着开编。先花 10 分钟确认源码目录下有arch/loongarch目录并且arch/loongarch/configs/里能找到一个可用的板级 defconfig 文件。如果这两个条件不满足说明这份源码根本不支持龙芯k平台后面全是白干。2.3 交叉编译环境变量一次性配好交叉编译和本地编译最大的区别在于需要在编译命令里告诉 make 三个关键信息目标架构是什么、编译器前缀是什么、编译器路径在哪。我习惯写成一个环境变量脚本放到自己的工作目录下每次开新终端直接 source 一下不用重复敲# 放在 env.sh 里 export ARCHloongarch export CROSS_COMPILEloongarch64-linux-gnu- export PATH/opt/loongarch64-toolchain/bin:$PATH其中ARCHloongarch告诉内核 Makefile 使用 loongarch 架构的代码目录。CROSS_COMPILEloongarch64-linux-gnu-指定交叉编译器前缀。实际编译时 make 会去找loongarch64-linux-gnu-gcc、loongarch64-linux-gnu-ld这些工具。PATH里的路径要根据你的交叉工具链实际解压位置调整我这边放在/opt/loongarch64-toolchain你按实际情况改。配好后先验证工具链可用loongarch64-linux-gnu-gcc -v如果能正常打印版本信息说明工具链没问题。这里有一个小坑我提示一下网上有些教程会让你直接export CROSS_COMPILEloongarch64-linux-gnu-但前面的PATH没配好结果系统里找不到这个命令报错还特别隐蔽。所以 verify 一步不能省。3. 内核配置从默认配置到你的裁剪清单3.1 找到适合久久派的默认配置内核源码拿到手之后不要急着 menuconfig而是先找板级的默认配置。在 ARM 平台这叫xxx_defconfig在 loongarch 平台上通常也会有一批类似文件放在arch/loongarch/configs/下面。找配置文件有个最笨也最有效的方法ls arch/loongarch/configs/ grep -ri 久久派\|2k\|龙芯k arch/loongarch/configs/ arch/loongarch/boot/dts/如果你的板厂比较讲究配置文件名里就会直接体现板子型号如果找不到也可以用出厂内核自带的配置来生成。做法是登录板子把/proc/config.gz拷出来前提是内核开启了 CONFIG_IKCONFIG然后放到源码目录下解压成.config# 板子上执行 zcat /proc/config.gz kernel.config # 把这个文件传到主机放到内核源码目录 cp kernel.config .config这个方法相当于“继承”了出厂内核的全部配置再在小范围内做调整对新手来说是最可靠的上手方式。当然前提是源码版本要和出厂内核版本接近否则旧 config 里的很多选项在新源码里可能已经被移除了。3.2 menuconfig 里应该关注哪些选项拿到初始配置后执行make menuconfig这个命令会打开一个终端图形界面本质上就是在编辑.config文件。新手进去之后容易迷失在几千个选项里我建议第一批只需要关注下面几个方向确认板级平台相关选项被正确选中。通常在 Device Drivers - Character devices 或 Platform specific devices 下面不同源码组织方式差异很大建议直接搜索关键字。文件系统。确认你根文件系统用的 ext4、squashfs、overlayfs 等都被编进内核或编译为模块。串口驱动。必须确认你调试用的串口控制器驱动被编译进去。如果编成模块内核启动早期还没有根文件系统挂载模块加载不了你就永远看不到启动日志。网络驱动。如果后面要 SSH 登录或 NFS 启动确认网卡驱动开启。initramfs/initrd 相关选项。取决于你的启动方案。在 menuconfig 里按/可以直接搜索关键字非常方便。比如想知道某个配置项在哪搜索后按数字键就能跳过去。3.3 裁剪原则模块化优于全部编译说到裁剪很多人的第一反应是“尽量把不用的都编成模块能省内存”。这个思路本身没错但在实际开发阶段我建议反过来核心启动路径上能编进内核的就不要编成模块。原因很简单模块是在根文件系统挂载之后才加载的如果根文件系统本身有问题或者模块版本和内核不匹配设备就会启动到一半就“消失”。把串口、存储控制器、根文件系统相关驱动都编进内核等于给系统留了一条最稳的保底路径。一旦系统能稳定启动再慢慢把可以模块化的部分拆出来。我在实际开发中见过太多人一上来就把驱动全模块化结果 rootfs 里的模块路径没配对板子卡在挂载根文件系统的错误上排查半天才发现是驱动没起来。这属于典型的“优化过早反受其害”。3.4 保存配置记录你的每一次变更配置改完之后menuconfig 默认保存到.config。但.config这个名字太通用不方便做版本管理。我习惯在每次确认能编译通过、能正常启动后把配置备份一份cp .config arch/loongarch/configs/my_jingjiupai_defconfig下次想重新编译或者分享给别人直接make my_jingjiupai_defconfig就能恢复到你保存的那个状态。这相当于给你的内核配置做了一个快照非常实用。因为内核的配置项有依赖关系如果哪次手滑在 menuconfig 里误删了某个选项导致依赖它的配置全部消失恢复起来会非常痛苦有快照就能一键回到稳定版本。4. 编译内核与模块产出一套能启动的组合4.1 make 命令怎么敲才省心配置确认无误后开始编译。完整的命令是make -j$(nproc) Image dtbs modules逐段解释-j$(nproc)并行编译核数越多越快。但如果你主机的内存偏小不到 8GB建议手动限制并发数比如-j4否则内存被吃满编译进程卡死甚至触发 OOM。Image生成内核镜像。在 loongarch 架构里最终产物是arch/loongarch/boot/Image这是一个未经压缩的 ELF 镜像有些场景还会生成Image.gz需要压缩时用。dtbs编译全部设备树二进制。modules把配置里标记为M的驱动编译成内核模块。先编这三个目标一次搞定。第一次编译时间会比较长我这边在普通笔记本上全速编译大概用了 10 到 15 分钟中途没有任何报错输出其实是很正常的别以为卡死了。如果中间报错不要盲目重试先看报错信息。大部分问题集中在工具链版本老不支持当前内核用到的某些语法。缺少头文件或依赖库。源码目录不干净之前编过其他架构的产物混在里面。针对最后一种情况执行一次彻底清理再重新来make mrproper make my_jingjiupai_defconfig make -j$(nproc) Image dtbs modulesmake mrproper会把之前所有编译产物和 .config 一起清掉是“从零再来”的标准动作。4.2 编译产物到底在哪各有什么用途编译完成后有一个动作很多新手会忽略先别急着部署花几分钟梳理一下产物。内核编译的产物分散在不同的目录打包时搞混很容易启动失败。主要产物及位置如下表文件路径作用内核镜像arch/loongarch/boot/Image 或 Image.gz真正被 Bootloader 引导的内核设备树文件arch/loongarch/boot/dts/ 下各厂商目录描述板级硬件信息外设初始化靠它vmlinux源码根目录带符号的未压缩内核主要用于调试内核模块drivers/ 和 sound/ 等目录下的 .ko 文件按需加载的外设驱动等Module.symvers源码根目录模块符号表外部模块编译时需要引用这里特别说一下vmlinux。如果你只打算跑板子vmlinux没用但如果你想用 kgdb 调试内核或者看 panic 栈的符号这个文件就是唯一宝贝。建议每次编译后把它保留到单独的目录别清理掉。4.3 编译 KBuild 外部模块驱动开发的前置练习编译完内核主体后再准备一个外部模块的编译环境。平时写设备驱动基本都是外部模块的方式不需要每次改一行驱动就重编一遍整个内核。先在内核源码目录下确认Module.symvers存在它是内核导出符号的列表。然后随便建一个测试模块目录// hello.c #include linux/module.h #include linux/kernel.h static int __init hello_init(void) { printk(KERN_INFO hello from jingjiupai\n); return 0; } static void __exit hello_exit(void) { printk(KERN_INFO goodbye\n); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE(GPL);配套的 Makefileobj-m : hello.o KERNEL_DIR ? /path/to/your/kernel/source PWD : $(shell pwd) all: $(MAKE) ARCHloongarch CROSS_COMPILEloongarch64-linux-gnu- -C $(KERNEL_DIR) M$(PWD) modules clean: $(MAKE) ARCHloongarch CROSS_COMPILEloongarch64-linux-gnu- -C $(KERNEL_DIR) M$(PWD) clean然后执行make如果配置正确目录下会多出hello.ko。把这个文件拷到板子上insmod hello.ko再用dmesg | tail就能看到打印。这一整套流程跑通说明你的交叉编译环境已经具备了驱动开发的基本能力。4.4 编译内核模块后怎么处理模块的部署问题内核镜像编好只是第一步如果.config里有大量模块那根文件系统里必须对应有/lib/modules/内核版本/目录否则那些动态加载的驱动都不会生效。最标准的做法是# 先安装到一个临时目录 make ARCHloongarch CROSS_COMPILEloongarch64-linux-gnu- \ INSTALL_MOD_PATH/tmp/rootfs modules_installINSTALL_MOD_PATH指定根文件系统的挂载点或目录。执行后会在/tmp/rootfs/lib/modules/下生成与内核版本同名的目录里面是modules.dep、modules.alias等文件以及所有.ko。然后把整个lib/modules/内核版本目录拷贝到板子的根文件系统对应位置scp -r /tmp/rootfs/lib/modules/内核版本 root板子IP:/lib/modules/拷贝完成后在板子上执行depmod -a这一步会重新生成模块依赖关系。很多新手跳过了 depmod直接 insmod 某些模块明明文件还在却报 module not found就是因为依赖关系文件没更新。5. 设备树修改把内核和真实硬件对齐5.1 设备树文件去哪找改哪个内核编译完之后如果板子上的某个外设没工作大概率不是内核代码的问题而是设备树节点没配好。设备树描述的是“硬件长什么样、分布在哪些地址、用哪个中断、引脚怎么复用”本质上是一份硬件配置清单。先找到板子对应的 dts 文件。常见路径是arch/loongarch/boot/dts/loongson/或类似目录。如果你不确定用搜索命令find arch/loongarch/boot/dts -name *.dts | xargs grep -l model 板级 dts 通常会 include 一个 SoC 通用的 dtsi 文件dtsi 里定义的是芯片内部外设dts 里才定义“这块板子上到底启用了哪些外设、接到了哪个引脚”。修改的原则是能改板级 dts 的就不动 SoC 的 dtsi。因为 dtsi 是公用的动了它会影响同一芯片下的所有板子。5.2 新增一个 GPIO 控制节点的实例举个例子。如果久久派上有一颗 LED 灯接在某个 GPIO 上你想在设备树里给驱动留一个节点可以在板级 dts 中追加类似内容/ { leds { compatible gpio-leds; status okay; user_led { label user-led; gpios gpio0 12 GPIO_ACTIVE_HIGH; linux,default-trigger heartbeat; }; }; };这个片段在根节点下新建了一个gpio-leds节点告诉内核第一个 GPIO 控制器的第 12 号引脚上接了 LED默认触发方式是心跳闪烁。但要注意gpios gpio0 12 GPIO_ACTIVE_HIGH里的 12 号引脚不能乱写。必须先查板子的原理图或者芯片手册确认这个 LED 到底挂在哪个控制器、哪个引脚上。我曾经踩过一个坑以为写 12 号引脚就行结果这个引脚在硬件上直接被复用成了其他功能驱动加载后不仅灯没亮还影响了另一个外设的工作。5.3 引脚复用配置最容易被忽视的细节外设要正常工作光有设备树节点还不够对应的引脚必须先被配置成正确的复用功能。大多数 SoC 都有 pinmux引脚复用机制。一个物理引脚可能有七八种功能比如既能做 GPIO也能做 UART 的 TX还能做 PWM 输出。用哪个功能需要在设备树的 pinctrl 节点里指定。比如启用某个板载串口时dtsi 里可能会有类似这样的片段uart1 { status okay; pinctrl-names default; pinctrl-0 uart1_pins; };这里pinctrl-0指向一个预设好的引脚配置组配置组里包含了引脚号、功能编号、上下拉等电气属性。如果你新接的外设恰好和某个引脚冲突就可能会导致两个设备节点争抢同一个引脚编译不会报错但运行时表现非常诡异一会儿能用一会儿不能用。所以每次改完设备树之后强烈建议用下面命令反编译生成的 dtb检查实际生效的引脚配置dtc -I dtb -O dts -o decompiled.dts arch/loongarch/boot/dts/xxx.dtb把decompiled.dts和源码里的 dts 对比一下确认改动真实落到了产物里而不是因为 include 顺序问题被覆盖了。5.4 设备树改完怎么验证先别急着上板设备树是在内核启动早期就要解析的东西如果设备树写错了轻则某个外设不工作重则内核在初始化阶段就 panic而且日志可能只闪一两行你根本来不及看。我的习惯是先用 qemu 或至少用dtbs_check这类检查工具做一次静态验证。如果环境里没有 qemu那就退而求其次在 dtc 反编译后仔细核对语法和节点路径。一个非常实用的技巧是编译完 dtb 后在板子的 U-Boot 里用命令把设备树加载到内存并打印load mmc 0:1 0x90000000 /boot/xxx.dtb fdt addr 0x90000000 fdt print /soc/gpioxxxfdt print可以确认 Bootloader 实际读入的设备树内容和你预期一致。这一步能排查掉 80% 的“改了没生效”问题。6. 内核升级的边界操作如何做到失败也不变砖6.1 备份旧内核给系统留一条退路内核升级最怕的不是编译失败而是新内核启动不了。我之前有一块板子升级完新内核后系统在启动早期 panic旧内核又没有备份最后只能拆下存储卡重新烧镜像整个环境全部推倒重来。从此之后我给自己立了一条规矩不管多自信升级前必须备份当前能用的一套内核镜像、dtb 和设备树源码。具体操作可以这样ssh root板子IP mkdir -p /boot/backup-$(date %Y%m%d) cp /boot/Image* /boot/backup-$(date %Y%m%d)/ cp -r /lib/modules/$(uname -r) /lib/modules/backup-$(uname -r)备份完之后再看你板子的启动方式。如果 Bootloader 通过固定名称加载文件比如从/boot/Image启动那用新内核替换前最好保留一个旧内核的副本并修改 U-Boot 环境变量指向旧文件# U-Boot 环境变量示例 setenv bootcmd fatload mmc 0:1 0x90000000 /boot/Image.new; booti 0x90000000 - 0x90020000 setenv bootargs consolettyS0,115200 root/dev/mmcblk0p2 rw saveenv不同板子 Bootloader 变量千差万别但核心思想是一致的不破坏旧文件只新增新文件通过修改启动参数指向新文件。这样万一新内核起不来还能在 Bootloader 里改回旧内核镜像名救回系统。6.2 安装新内核和模块的正确顺序部署顺序有个讲究先装内核模块再换内核镜像。为什么因为新内核和旧内核版本号不同时模块目录是按版本号区分的。如果你先把新内核镜像写进启动分区但根文件系统里还没有对应的/lib/modules/新版本那么启动后所有模块化驱动都会加载失败。反过来如果先把模块装好旧内核还在运行即使新内核镜像有问题你当前系统也还能正常使用可以从容排查。具体操作可以这样在主机上编译完把新内核模块安装到临时目录。把整个模块目录 scp 到板子根文件系统/lib/modules/下。在板子上执行depmod -a更新依赖。确认模块就绪后再复制新内核镜像和设备树到启动分区。修改 Bootloader 启动变量指向新内核。重启观察启动日志。6.3 新内核启动失败后的急救三板斧如果重启后起不来先不要慌按顺序排查第一板斧看串口日志。如果串口有输出认真读最后几行。最常见的两种输出停在内核解压之前说明 Bootloader 加载内核这一步有问题镜像格式不匹配或加载地址不对。输出到一半 panic说明内核本身或设备树有问题看 panic 前最后几行会有线索。第二板斧如果串口什么输出都没有检查 Bootloader 环境变量是否被意外修改尤其是bootcmd和bootargs。在 U-Boot 里执行pri打印当前环境变量对照之前记录的有效配置逐项检查。第三板斧在 Bootloader 停住手动加载备份的旧内核fatload mmc 0:1 0x90000000 /boot/backup-xxx/Image booti 0x90000000 - 0x90020000如果这条命令能起来说明硬件和存储都没问题纯粹是新内核的事。之后就可以回到主机上调试内核配置或设备树不用动板子。6.4 什么时候需要重新烧录整个系统内核升级如果做到了上面这几步基本不会变砖。但有一个例外如果你的板子 Bootloader 也被你一并升级或者搞坏了那就不是内核层面的问题了。所以这里有一条非常重要的经验内核升级过程中绝对不要顺手去烧 Bootloader。Bootloader 是最后一道防线它只要正常无论内核怎么折腾都能用上面的方法救回来Bootloader 一旦挂了很多板子只能通过烧录器或者特殊的强制升级模式救砖门槛直接高一个数量级。7. 常见问题速查与踩坑记录7.1 编译阶段典型报错现象排查思路解决方法flex: command not found主机缺词法分析器apt install flex*** No rule to make target “Image”架构没配对或源码不支持该架构确认ARCHloongarch检查arch/loongarch目录是否存在ld: unknown architecture of input file用了 x86 本地 gcc 编译确认CROSS_COMPILE设置正确且 PATH 能找到交叉编译器Kconfig: not found源码目录不干净make mrproper后重新配置openssl/xxx.h: No such file or directory缺少依赖apt install libssl-dev这些报错我基本都遇到过前几次可能还会慌后来发现绝大多数都是环境问题和内核代码本身无关。把所有环境依赖提前装好能少走很多弯路。7.2 启动阶段常见故障现象排查思路常见原因与处理方法串口无输出Bootloader 没找到内核镜像或串口参数不对检查波特率是否 115200、硬件流控是否关闭、bootcmd 指向的文件是否存在内核引导后 panic提示无法挂载根文件系统root 参数错误或对应驱动没编进内核检查 bootargs 中的root/dev/mmcblk0p2或PARTUUID确认存储控制器驱动为 built-in启动后外设节点找不到设备树没生效或 pinmux 配置错误用fdt print查看 Bootloader 加载的 dtb对比 dts 源码检查 pinctrl 节点insmod报 invalid module format模块版本与当前内核不匹配用modinfo hello.ko查看 vermagic对比uname -r根文件系统下/lib/modules/为空模块没安装检查INSTALL_MOD_PATH是否正确重跑modules_install并拷贝7.3 我踩过的两个最典型的坑第一个坑是交叉编译命令里忘了带ARCHloongarch结果 make 默认按 x86 来编。编译过程中没有任何明显报错但是生成的 Image 文件是 x86 格式拷到板子上 U-Boot 加载后一点反应都没有。当时排查了很久后来用file Image一看才发现格式不对。所以编译完一定要养成习惯用file命令检查产物架构file arch/loongarch/boot/Image正常输出应该包含ELF 64-bit LSB executable, *loongarch*字样。如果显示的是 x86-64不用怀疑肯定没交叉编译成功。第二个坑是设备树里的复用引脚和另一个外设冲突。当时我在设备树里加了一个 GPIO 按键节点编译部署一切正常但板子启动后系统日志疯狂刷引脚已经被占用的警告之前一直正常的串口也开始出现乱码。后来对照原理图才发现我用的 GPIO 引脚恰好和调试串口的 RX 引脚是同一个物理引脚硬件上根本不支持这种接法。从此之后我在改设备树前一定会先把原理图打开把引脚占用情况列一张表再动手改文件。7.4 一些提高效率的建议每次编译改动前先git diff看清楚自己改了哪些源码避免改乱。做好记录的习惯。包括编译命令、内核版本、设备树改动点、遇到的问题和解决方案。这个笔记以后就是你的“个人 BSP 维护手册”。在板子上跑 Linux 时尽量用 rootfs 的 NFS 挂载方式调试内核可以在主机上直接改 rootfs 内容省去反复烧写存储卡的时间。我个人后来养成了一个习惯每次发布一个能用的内核版本都会把.config、dts和编译脚本打成一个 tar 包标记好日期存起来。别嫌麻烦等你在新内核上把设备驱动调通之后回头看这份记录能帮你省下大量回退和复盘的时间。内核升级这件事本身不难难的是把整个流程控制得“可回退、可追溯”。如果你也是刚上手久久派建议先照着这个流程完整走一遍哪怕出厂内核用着没毛病也值得专门找个晚上编译一次不为别的就为把工具链、源码目录、部署路径这些关键节点都摸清楚。后面无论是做驱动开发、外设适配还是接 ROS 2 这类重量级框架都会因为你提前趟过这一遍流程而轻松很多。

相关新闻

Modbus RTU底层原理与STM32调试实战指南

Modbus RTU底层原理与STM32调试实战指南

2026/9/9 5:13:51

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

7.7 Huge Page 与 Fragment 机制

7.7 Huge Page 与 Fragment 机制

2026/9/9 5:13:51

上一篇 7-6《GPU 页表更新机制》 分析了 amdgpu_vm_bo_update() → amdgpu_vm_update_range() 的主干,并在遍历资源更新 PTE 的环节留下一个伏笔:连续的物理页可以合并为大页,以降低页表占用、提升 TLB 效率。本篇即展开这一优化,…

AI推动编程成通用技能:不会写代码也能用脚本解放双手

AI推动编程成通用技能:不会写代码也能用脚本解放双手

2026/9/9 5:13:51

1. 当财务同事开始用AI写脚本:编程正在变成通用技能 1.1 一个让我改观的小场景 上周,我帮一位在财务部门工作了十几年的朋友看脚本。她没学过任何编程语言,却在AI对话框里用自己的话描述了一遍报销表合并的流程,然后真的运行起了…

JSP+Servlet+JDBC+MySQL学生管理系统:从零搭建Java Web全栈项目

JSP+Servlet+JDBC+MySQL学生管理系统:从零搭建Java Web全栈项目

2026/9/9 6:23:54

简介:基于jspservletjdbcMySQL开发的学生管理系统,面向计算机相关专业需要完成课程设计或毕业设计的在校生。系统涵盖学生信息、课程成绩、用户管理等常见模块,采用经典的MVC分层结构,配有可直接运行的完整工程。压缩包共341个文件…

从脚本堆到智能任务信使:自研Agent框架设计实践

从脚本堆到智能任务信使:自研Agent框架设计实践

2026/9/9 6:23:54

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

图论必学:朴素版Dijkstra单源最短路算法详解

图论必学:朴素版Dijkstra单源最短路算法详解

2026/9/9 6:23:54

先说一个现象:很多人学图论单源最短路,一上来就抱着 priority_queue 堆优化版不放,觉得朴素版 Dijkstra 是“老古董”。但如果去刷题你会发现,当题目明确给出的是稠密图、点数只有几百甚至几千时,朴素版才是又快又不容…

企业级AI平台选型指南:从算力底座到应用落地的四层架构

企业级AI平台选型指南:从算力底座到应用落地的四层架构

2026/9/9 6:23:54

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

STM32H750+RT-Thread实战:从环境搭建到多线程应用完全指南

STM32H750+RT-Thread实战:从环境搭建到多线程应用完全指南

2026/9/9 6:23:54

简介:正点原子STM32H750北极星开发板与RT-Thread 4.1.1结合的完整工程包,面向希望基于Cortex-M7高性能芯片开展嵌入式RTOS开发的工程师和院校学生。资源包含完整的源码、构建脚本及HAL库文件,共418个文件,以258个.h头文件和137个.…

Pico USB-CDC虚拟串口与select同步机制深度解析

Pico USB-CDC虚拟串口与select同步机制深度解析

2026/9/9 6:13:53

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

2026/9/9 1:14:29

本文首发于“生态学者”!从“湿地面积”到“土壤碳密度”:为什么需要重新认识潮汐湿地蓝碳变化?潮汐湿地位于陆地与海洋的交汇地带,包括红树林、盐沼和潮滩,是全球重要的蓝碳生态系统。其土壤能够长期储存大量有机碳&a…

adb抓包

adb抓包

2026/9/8 4:55:53

前言 本文介绍如何通过 tcpdump 在 Android 手机上抓取网络数据包,并在电脑端使用 Wireshark 进行分析。适用于需要排查 App 网络请求、分析接口调用或调试网络问题的开发与测试场景。1. 手机要有 root 权限2. 下载 tcpdump3. adb push C:\Users\zhangkuixun\Downlo…

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

2026/9/8 22:37:26

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战 在云原生基础设施中,容器镜像体积直接决定了服务的部署速度与弹性扩容敏捷度。对于传统的 Go / Java 微服务,镜像体积通常被严格控制在 50MB 到 200MB 以内,拉取镜像只…

扩散模型图像恢复实战:从DDPM原理到PyQt5可视化系统

扩散模型图像恢复实战:从DDPM原理到PyQt5可视化系统

2026/9/9 0:03:36

简介:面向毕业设计场景的PyQt5扩散模型图像恢复项目,提供完整Python源码与项目说明,适合图像处理、深度学习方向的高年级本科生与研究生参考。项目在模块设计上覆盖图像处理、扩散模型、参数配置、用户界面与结果评估五部分,具体涉…

开关电源环路裕量测试实战:相位裕量与增益裕量详解

开关电源环路裕量测试实战:相位裕量与增益裕量详解

2026/9/9 0:03:36

1. 项目概述:为什么环路裕量测试是电子工程师绕不开的“体检项目”“从零开始的电子工程师生活(6)——环路裕量测试”,这个标题一出来,老电源工程师可能已经下意识摸了摸示波器探头,新同事则大概率在想&…

定时插座芯片怎么选?专用定时IC与单片机MCU选型对比

定时插座芯片怎么选?专用定时IC与单片机MCU选型对比

2026/9/9 0:03:36

拆开市面上不同价位的定时插座,你会发现一个有意思的现象:有的里面躺着一颗黑色的软封装芯片,丝印都看不清;有的则是一块小小的蓝色或绿色PCB,上面赫然印着STM8或者STC的字样。同样叫"定时插座",…

远程协作的工作台整理

远程协作的工作台整理

2026/9/8 4:23:39

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/8 3:19:39

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/8 4:00:23

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…