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

云端杂谈

“ 代码、学术、提瓦特与泰拉大陆的碎片记录 ”

cover
✨ 开心
2026-07-12 16:26:16

龙芯 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 亮了,累了一晚上的疲惫瞬间没了。 ## **复盘与教训** 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*
#实训#龙芯
cover
✨ 疲惫
2026-07-10 08:20:27

实训杂谈

VMware:功能强大的桌面虚拟计算机软件,自行下载:下载地址 Ubuntu镜像:当前用的是ubuntu-22.04.4 桌面版本的,可根据需要自行选择版本下载 ‍ ‍![](https://bu.dusays.com/2026/07/11/6a512257c439d.png) 分配资源建议: ‌内存 ≥ 4GB‌(推荐 8GB) ‌CPU ≥ 2核‌(推荐 4核) ‌磁盘 ≥ 60GB ‍ ![](https://bu.dusays.com/2026/07/11/6a51223a5efdf.png) ‍ ## 第一步:在 Ubuntu 22.04 上查看 IP 地址 在 Ubuntu 终端中运行以下任一命令: # 方法 1:推荐,显示所有网络接口的 IP ``` ip addr show ``` # 方法 2:简洁输出,只看 IPv4 地址 ``` ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' ``` # 方法 3:传统方式 ``` ifconfig ``` 通常你需要的 IP 是 eth0 或 ens33 等接口上的 inet 地址,一般是 192.168.x.x 或 10.x.x.x 这样的局域网地址。 ## 第二步:确保 Ubuntu 上 SSH 服务已开启 # 检查 SSH 是否已安装并运行 ``` sudo systemctl status ssh ``` # 如果未安装,安装 OpenSSH Server ``` sudo apt update && sudo apt install openssh-server -y ``` # 确保 SSH 服务开机自启并正在运行 ``` sudo systemctl enable ssh --now ``` # 如果开启了防火墙,放行 SSH 端口 ``` sudo ufw allow ssh ``` ``` tip: 如果你不清楚 Ubuntu 的用户名,在 Ubuntu 终端运行 whoami 即可查看。 ``` ### 在使用MobaXterm,ssh(ip)连接ubuntu时发现以下问题: ``` sudo systemctl status ssh Unit ssh.service could not be found. sudo systemctl enable ssh --now Failed to enable unit: Unit file ssh.service does not exist. ``` **SSH 服务未安装。Ubuntu 22.04 默认不带 SSH Server,需要手动安装:** ``` sudo apt update && sudo apt install openssh-server -y ``` 如果在终端安装时出现: ``` 仓库 “https://ppa.launchpadcontent.net/gnurubuntu/rubuntu/ubuntu jammy Release” 没有 Release 文件。 ``` 这个警告不影响安装 SSH。它只是一个第三方 PPA(gnurubuntu/rubuntu)不支持你的 Ubuntu 22.04 版本,被自动跳过了。openssh-server 来自 Ubuntu 官方源,不依赖这个 PPA。 继续重新输入一遍 ``` sudo apt update && sudo apt install openssh-server -y ``` ‍ ![](https://bu.dusays.com/2026/07/11/6a518a5bbd969.png) ### 现在已经通过 MobaXterm SSH 登录到 Ubuntu 22.04 了。 关于虚拟机重新开机后的连接: 目前想到的方法就是设置成静态IP,这样可以确保每次链接的IP地址相同 ‍
cover
2026-06-02 23:01:52

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

这两天看到了一个视频,讲的是一位田野就是乡工作者,也就是我们所说的纪录片导演,对当今世界的思考,受益良多: 在如今信息洪流的快节奏时代,一切都如同流星一样划过。短视频时代使得人们的耐心变得越来越少,但是这些纪录片记录者,放慢姿态,用时间来弥补,用热爱来守护。越是瞬息万变的节奏,越要定下心去守护内心的宁静,正如作者说的: > 这几年越来越意识到: > 很多人并不是不痛苦, > 只是已经学会了快速地活着。 > > 但纪录片这门手艺, > 偏偏反着来。 > > 谨以此片献给时代洪流下, > 仍认真用力活着的平凡人。 > > 我们不是时代的注脚, > 我们就是时代本身。 [一个拍纪录片的人,正在被时代淘汰\_哔哩哔哩\_bilibili](https://www.bilibili.com/video/BV1NSRXBwEZp/?spm_id_from=333.1391.0.0&vd_source=20fae464d78a66a35f63c35e32543721) ‍![](https://bu.dusays.com/2026/06/02/6a1ef03057ebe.png) ‍
cover
✨ Emo
2026-06-01 17:13:10

🐱煤球接入Deepseek

在此之前,煤球的模型是Gemini: [**my-blog-manager/app/api/chat/route.ts**](vscode-webview://1cte5emmbpca15lv39mqrfijum16bt8hnmbiov069074au52roah/my-blog-manager/app/api/chat/route.ts) 这是小猫 AI 的**后端路由**,直接对接 **Google Gemini API**: * 第 13 行:从环境变量 `GEMINI_API_KEY` 或 `OPENAI_API_KEY` 读取密钥 * 第 21-22 行:从 `siteConfig.geminiConfig` 读取模型 ID,构建请求 URL: ``` https://generativelanguage.googleapis.com/v1beta/models/{modelId}:generateContent?key={apiKey} ``` * 第 29-42 行:发送请求体,包含 `system_instruction`(猫设 prompt)、用户消息、`generationConfig`(token 上限、temperature) --- ### 2. API 配置(模型参数 + 猫设 Prompt) ``` geminiConfig: { modelId: "", systemPrompt: "", maxOutputTokens: , temperature: , }, ``` --- ### 3. 前端调用方 * [**my-blog-manager/components/CyberCat.tsx**](vscode-webview://1cte5emmbpca15lv39mqrfijum16bt8hnmbiov069074au52roah/my-blog-manager/components/CyberCat.tsx) — 页面右下角的赛博小猫组件,`handleFeed()`和 `handleChatSubmit()`都向 `/api/chat` 发 POST 请求 * [**my-blog-manager/components/settings/AICatSection.tsx**](vscode-webview://1cte5emmbpca15lv39mqrfijum16bt8hnmbiov069074au52roah/my-blog-manager/components/settings/AICatSection.tsx) — 后台设置页面,可修改 modelId、systemPrompt、temperature、maxOutputTokens,点"暂存至队列"写入 `geminiConfig` --- ‍ 而接入Deepseek有两个需要注意的点: ‍ * DeepSeek 用的是 OpenAI 兼容接口,跟 Gemini 的请求体结构完全不同: * **端点,鉴别权限都不相同** ‍ 此外:CMS 管理后台(Settings 页面 → AI 小猫配置)点「暂存至队列」并应用,**会丢失** `apiKey` **和** `baseUrl`。 原因是 [cms\_core/api/config.py:178-185](vscode-webview://1cte5emmbpca15lv39mqrfijum16bt8hnmbiov069074au52roah/my-blog-manager/cms_core/api/config.py#L178) 的写入逻辑——前端只传 4 个字段: ``` { modelId, systemPrompt, maxOutputTokens, temperature } ``` 后端用正则直接把整个 `geminiConfig` 块替换掉,新增的 `apiKey` 和 `baseUrl` 不在前端传的字段里 ‍ 解决问题:在 config.py 的 update\_site\_config 里加一个合并逻辑 —— 更新 dict 之前先保留已有字段,缺少的 key 不被丢弃。不影响现有任何功能。 ``` existing = {} m = re.search(rf"{key}\s*:\s*\{{([\s\S]*?)\}}", content) if m: existing = parse_ts_dict(m.group(1)) merged = {**existing, **value} ``` 不过!!!把 key 明文写在代码里相当于把房门钥匙贴在门上。🐖 所以我在**在 Vercel Dashboard → Settings → Environment Variables 加入环境变量,这样就不用把API放在仓库里面** ![](https://bu.dusays.com/2026/06/01/6a1d4c7e9676c.png) 搞定!
cover
2026-05-31 02:20:42

😋如何在不与 update.py 冲突的前提下为博客添加自定义功能

### `layout.tsx` **— 全局外壳** `XHBlogs/app/layout.tsx` 是 Next.js App Router 的**根布局**,它定义了: **职责具体内容**HTML 元数据页面标题、图标、SEO 描述字体加载Geist、Noto Serif SC 等全局字体全局 Provider主题切换 (`ThemeProvider`)、音乐播放 (`MusicProvider`)全局 UI 组件背景特效、浮动播放器、CyberCat、启动画面、弹幕背景全局样式`globals.css`、Tailwind 基础样式 `layout.tsx` **里的东西会出现在博客的每一个页面上。** 导航栏、背景、播放器这些"壳"都在这里。 **所以说**`page.tsx` **只负责它自己那条路由的内容部分,然后被套进** `layout.tsx` **的外壳里。** --- ## **二、update.py 覆盖规则速查** `update.py` 从上游 `XinghuisamaBlogs` 拉取最新代码,**只覆盖它名单里的文件** **会被覆盖:** ``` XHBlogs/components/ — 所有公共组件 XHBlogs/app/**/page.tsx — 所有页面的 page.tsx XHBlogs/app/layout.tsx — 根布局 XHBlogs/app/globals.css — 全局样式 my-blog-manager/cms_core/ — CMS 后端 my-blog-manager/components/— CMS 组件 my-blog-manager/app/**/page.tsx — CMS 页面 ``` 不会被覆盖: ``` XHBlogs/data/ — 数据文件 (albums.ts, friends.ts, projects.ts) XHBlogs/posts/ — 文章 .md XHBlogs/chatters/ — 说说 .md XHBlogs/moments/ — 瞬间 .md XHBlogs/siteConfig.ts — 全站配置 XHBlogs/public/ — 静态资源 my-blog-manager/data/ — CMS 数据文件 my-blog-manager/siteConfig.ts — CMS 配置 ``` ## **三、实践** ### **1:加一个独立页面(最推荐,零冲突)** 直接在 `XHBlogs/app/` 下新建目录 + `page.tsx`,Next.js 自动识别为路由。 ```  XHBlogs/  └── app/     └── tools/                     └── page.tsx       ← 访问 /tools 即可看到 ``` **优点:** 完全独立,不需要改动任何已有文件,永远不会冲突。 --- ### **B:全局组件(但需要改 layout.tsx / Navbar.tsx)** 因为我的功能需要出现在**每个页面**上(比如全局公告栏、回到顶部按钮),必须改 `layout.tsx` 或 `Navbar.tsx`。 **做法:把自定义代码放在独立目录,用 git patch 管理改动。** ```  步骤 1:创建自定义组件  XHBlogs/  └── custom/                 ← 扩展目录(update.py 不碰)     ├── index.ts           ← 统一导出入口     └── BackToTop.tsx       ← 组件  ​  步骤 2:在 layout.tsx 中引入组件,然后生成补丁  git diff HEAD -- XHBlogs/app/layout.tsx > XHBlogs/custom/layout-custom.patch ``` **update.py 恢复:** 一行命令全自动恢复 ```  git apply XHBlogs/custom/layout-custom.patch  git apply XHBlogs/custom/navbar-custom.patch   ``` --- ### **C:改已有页面** 给**已有的页面**(比如首页 `page.tsx`)加模块。 把新增模块写在 `custom/` 里,在 `page.tsx` 中引入。同样,跑 `update.py` 后补回 import 即可。 --- ## **四、siteConfig.ts 作为功能开关** `siteConfig.ts` 不在覆盖名单里,所以把它当作**自定义功能的控制面板**: **Vercel部署:** ``` XHBlogs (本地博客源码) │ ▼ CMS → deploy.py → git push OriginBlogsS2 (GitHub 源码仓库) │ ▼ Vercel 检测到 push → next build ``` 跑完 `update.py` 后、触发 Vercel 部署前,两条命令: ```  git apply XHBlogs/custom/layout-custom.patch  git apply XHBlogs/custom/navbar-custom.patch ``` > **结论:patch 文件在** `custom/` **安全区里,不会被覆盖。两条命令即可恢复全部自定义功能。** 搞定!!!😋😋😋