
龙芯 2K0300 久久派 GPIO 点灯全记录——从交叉编译到 led 亮起的踩坑之旅
背景
实训给了一块龙芯 2K0300 久久派开发板,要求写一个 GPIO LED 驱动。实验指导书只有一页不到的步骤,看着简单——下载工具链、写驱动、编译、加载、灯亮,一条龙。按部就班跑一遍,仿佛半小时搞定。结果我从晚上折腾到凌晨一点,踩了无数坑。记录下来,既给自己备忘,也给同样被 2K0300 折磨的朋友一个参考。
环境
- 开发机:Ubuntu 虚拟机(VMware)
- 目标板:龙芯 2K0300 久久派(LoongArch 架构)
- 内核版本:4.19.190+
- 工具链:
loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.6
第一坑:文件管理混乱
实验书说先下载工具链和内核源码,但下载链接的网速感人,我把文件都下到了 ~/Downloads/,然后创建了 ~/loongarch-dev/ 工作目录。结果解压时发现文件根本不在工作目录里……
$ cd ~/loongarch-dev
$ tar -xvf linux-4.19-0627.tar.gz
tar: Cannot open: No such file or directory
解决方案倒简单——从 Downloads 移过来就行。但提醒自己:先检查文件在哪,再执行命令。
第二坑:CROSS_COMPILE 前缀不对
实验书上写:
export CROSS_COMPILE=loongarch64-unknown-linux-gnu-
但实际工具链的前缀是 loongarch64-linux-gnu-,没有那个 unknown。这种小差异如果不注意,后续 make 会报"找不到编译器"——错误信息也很容易让人怀疑人生。正确做法是先 ls bin/ 看一下实际的可执行文件前缀。
第三坑:内核配置——找不到 2K0300 的 defconfig
$ ls arch/loongarch/configs/
loongson2_defconfig loongson_2k2000_pai_config loongson_2k300_defconfig ...
没有 loongson_2k0300_defconfig。2K0300 用的是 loongson2_defconfig,这个要靠猜,或者仔细看龙芯的文档。
第四坑:menuconfig 缺少依赖
$ make menuconfig
scripts/extract-cert.c:21:10: fatal error: openssl/bio.h
缺 libssl-dev 和 libncurses5-dev。内核编译的依赖问题很常见:
sudo apt install libssl-dev libncurses5-dev flex bison -y
第五坑:设备树编译——最痛苦的环节
这是整个实验最耗时的地方。
5.1 DTB 根本不编译
make dtbs 跑完什么也没生成。原因是 CONFIG_BUILTIN_DTB_NAME="" 是空的。需要在 .config 里指定:
CONFIG_BUILTIN_DTB_NAME="loongson_2k0300_pai_99"
5.2 include 路径不存在
设好 DTB 名字后编译报错:
FATAL ERROR: Unable to parse input tree
根因是 arch/loongarch/boot/dts/include 目录不存在,DTS 里 #include 找不到头文件。需要手动创建符号链接:
ln -s ../../../../include arch/loongarch/boot/dts/include
5.3 设备树语法——&dc 不是 dc
加 LED 节点时缩进搞乱了,&dc 写成了 dc,DTC 报语法错。排查了半天才发现少了个 &。设备树语法严格,引用标签必须带 &。
5.4 在哪加 LED 节点
实验书说改 loongson_2k0300.dtsi,但频繁编译不过。最终改在 loongson_2k0300_pai_99.dts 里,放在 / { } 根节点下,编译一次过。
第六坑:内核版本不匹配——module_layout
驱动编译好了,拷到久久派上加载:
# insmod leds-2k0300-gpio.ko
disagrees about version of symbol module_layout
LOCALVERSION 不对。开发板 uname -r 输出是 4.19.190+,而源码默认编译出来是 4.19.190。那一个 + 号就会导致模块校验失败。
sed -i 's/CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION="+"/' .config
make olddefconfig && make modules -j$(nproc)
改完还是不行!报错反过来了——开发板有 modversions,我们模块没有。最终解决方案是 insmod -f 强制加载。GPIO 的核心 API(gpio_request、gpio_set_value 等)是稳定的,即使配置有微小差异也不会崩溃。
第七坑:U 盘文件系统
FAT32 格式的 U 盘,久久派的内核没编译 VFAT 支持,挂载报 unknown filesystem type 'vfat'。需要格式化成 ext4:
sudo mkfs.ext4 /dev/sdb1
而且虚拟机会自动把 U 盘挂载到 /media/zhangruijie/ 下面,需要先 umount 才能格式化。
第八坑:U 盘设备名不停变
每次拔插 U 盘,久久派分配的 /dev/sd* 字母就往后挪一个(sdb → sdc → sdd → sde)。每次挂载前都得先 ls /dev/sd* 确认当前设备名。
最终
root@LoongOS:~# insmod -f /mnt/leds-2k0300-gpio.ko
[ 2988.090198] Simple LED driver loading
[ 2988.097591] LED on GPIO 83 turned ON
看到这几行,LED 亮了,累了一晚上的疲惫瞬间没了。
复盘与教训
- 不要盲信实验书。它的命令可能是针对别的版本、别的板子写的,实际环境总有差异。
- 看错误信息要逐行读。很多问题 error message 里已经写了答案,跳读等于浪费时间。
- 设备树是新手杀手。include 路径、标签引用、编译流程,每一步都可能卡住。建议先确认原始文件能编译过,再添加自己的修改。
- 内核模块版本校验是个很脆弱的机制。开发调试阶段
insmod -f是合理的工具,不必纠结于完全一致的.config。 - 交叉编译环境变量的设置要在同一个 shell 会话里。如果中途关掉终端重开,PATH 和 CROSS_COMPILE 都得重新 export。
彩蛋
dmesg 里还有一行:
loongson pinctrl 16000490.pinctrl: request pin 83 (GPA80-3) for GPA80:83
GPA80-3 —— 龙芯把 GPIO83 映射到了 A80 组的第 3 号引脚。能看出来龙芯的 pinctrl 命名挺有意思的(虽然我至今不确定 GPA80 这个编号逻辑是什么)。
实验日期:2026年7月12日
目标板:龙芯 2K0300 久久派 (LoongArch)
工具链:GCC 8.3.0