橘子のBlog
首页项目归档照片墙音乐灵境说说杂谈友链关于
封面

龙芯 2K0300 久久派 GPIO 点灯全记录——从交叉编译到 led 亮起的踩坑之旅

2026-07-12 16:26:16
✨ 心情:开心
# 实训
# 龙芯



背景

实训给了一块龙芯 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 亮了,累了一晚上的疲惫瞬间没了。

复盘与教训

  1. 不要盲信实验书。它的命令可能是针对别的版本、别的板子写的,实际环境总有差异。
  2. 看错误信息要逐行读。很多问题 error message 里已经写了答案,跳读等于浪费时间。
  3. 设备树是新手杀手。include 路径、标签引用、编译流程,每一步都可能卡住。建议先确认原始文件能编译过,再添加自己的修改。
  4. 内核模块版本校验是个很脆弱的机制。开发调试阶段 insmod -f 是合理的工具,不必纠结于完全一致的 .config。
  5. 交叉编译环境变量的设置要在同一个 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

avatar

橘子origin

一名正在和算法、数据结构死磕的计算机专业大三大学生 我相信,代码是逻辑的诗篇,而算法是其中最凝练的修辞。

2026年7月

一
二
三
四
五
六
日
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Recent Records

实训杂谈

2026-07-10 08:20:27

一个拍纪录片的人,正在被时代淘汰

2026-06-02 23:01:52

🐱煤球接入Deepseek

2026-06-01 17:13:10