跳到主要内容

5 篇博文 含有标签「OpenWrt」

查看所有标签

OPENWRT 系统 5:Docker 玩法介绍

· 阅读需 10 分钟
世玉轩
100askTeam yuxuan.

Docker 是一种开源的容器化平台,它通过“容器”来封装应用及其运行环境,使应用能够在不同系统之间快速、稳定地运行。容器轻量、启动快,占用资源少,适合微服务部署与持续集成/交付。Docker 还提供镜像管理、版本控制和环境一致性,让开发、测试、生产环境保持统一,大幅提升部署效率与可移植性。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

硬件环境:OpenWrt 跑在 ARM 高性能 SBC 上(比如 本文使用的Dshanpi-A1),家里还有光猫 + 交换机/AC/AP 等常规设备。
目标:在这块 SBC 上用 Docker 跑 家庭影院 + 下载器 + 网盘 + 广告过滤 + 简单监控,一机多用。

家庭网络

  • 光猫改桥接,把拨号交给 ARM SBC 上的 OpenWrt
  • ARM SBC 既当主路由,又当“轻量 NAS + 家庭影院服务器”
  • 电视盒子、手机、电脑都连在 LAN(有线/无线都行),统一访问 SBC 上的服务

机器配置

  • 设备:ARM 64 位架构 SBC,8G 内存版本
  • 系统:OpenWrt(自己编译/整合固件都可以,关键是要有 Docker)
  • 磁盘
    • 系统盘(eMMC/TF)装 OpenWrt
    • 外接 SSD/HDD/大 U 盘做数据盘,挂到 /mnt/data

Docker 环境 & 目录规划

先把环境和目录规划确认好,后续好维护,这步比较关键。

安装 Docker / Docker Compose

如果你的固件已经打包了 Docker,可以直接跳过安装,推荐安装 luci-app-dockerman,这是 OpenWrt 上专门的 Docker Web 管理界面插件:

opkg install luci-lib-docker dockerd luci-lib-jsonc docker ttyd --force-depends
opkg install luci-app-dockerman
  • dockerd:Docker 守护进程
  • docker:命令行客户端
  • luci-lib-docker / luci-lib-jsonc:Dockerman 的依赖
  • ttyd:用于 Web 终端与容器控制台
  • luci-app-dockerman:Web 管理界面插件

启动并设为开机自启:

/etc/init.d/dockerd start
/etc/init.d/dockerd enable

然后访问 LuCI 后台,菜单里会多出:服务 / Docker服务 / Dockerman

也可以通过命令行的方式,确认环境能用,示例如下:

root@LEDE:~# docker version
Client:
Version: 28.0.4
API version: 1.48
Go version: go1.25.4
Git commit: b8034c0
Built: Sun Sep 7 14:53:18 2025
OS/Arch: linux/arm64
Context: default

Server:
Engine:
Version: 28.0.4
API version: 1.48 (minimum version 1.24)
Go version: go1.25.4
Git commit: 6430e49
Built: Sun Sep 7 14:53:18 2025
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: 1.7.27
GitCommit:
runc:
Version: 1.2.6
GitCommit:
docker-init:
Version: 0.19.0
GitCommit: de40ad0
root@LEDE:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@LEDE:~#

能看到版本信息 & 空容器列表,就说明 OK。

docker-compose 推荐也装一个,方便后面多服务一起管理(以 ARM64 为例):

wget https://github.com/docker/compose/releases/download/v2.27.0/docker-compose-linux-aarch64 -O /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose version

数据盘挂载 & 目录规划

首先把emmc剩余空间新建分区,格式化为ext4,然后界面上挂载为docker数据分区使用,当然使用其他外部存储设备保存也是可以的,比如使用TF卡来做为docker数据分区使用,增加对应的挂载目录配置即可,示例如下:

数据盘以/opt/data为根目录,可以这样规划:

/opt/docker      # Docker 根目录(镜像、容器层等)
/opt/data
├─ media # 媒体文件(电影、剧集、音乐)
│ ├─ movies
│ └─ tv
├─ downloads # BT/PT 下载目录
└─ configs # 各容器配置文件
├─ jellyfin
├─ qbittorrent
└─ ...

再把目录建好:

mkdir -p /opt/data/{configs,downloads,media}
mkdir -p /opt/data/configs/{jellyfin,emby,transmission,qbittorrent,aria2,adguard,nextcloud}
mkdir -p /opt/data/media/{movies,tv,anime,music}
mkdir -p /opt/data/downloads/{bt,aria2,tmp}

后面所有容器都尽量挂到 /opt/data 下面,避免写爆系统盘。

这样做的好处:

  • 坏了一个容器就删了重建,数据不受影响
  • 换设备时只要把这块盘接过去,改一下路径就能继续用

配置内核选项支持docker运行

默认配置编译的kernel,docker运行的时候会有警告信息,提示缺少支持对应的功能支持,如下所示:

这些 WARNING 表示你的 内核未开启 cgroup v1/v2 的资源限制功能,导致 Docker 无法对容器进行 CPU、IO、内存 swap 等限制。 需要在我们的系统里面,打开下面对应的配置:

# 打开kernel配置页面
make kernel_menuconfig

按照下面配置,打开CGroup和Namespace支持:

重新编译,然后升级,启动后发现没有对应的报错信息即可。更多配置支持,请查看代码仓库里面的配置。

注意:有的docker版本,需要打开legacy cgroup v1相关的控制支持,此处保持关闭。

加速源配置

  1. 在安装下面的docker镜像的时候,可能会出现默认的仓库下载失败,可以配置内地的源,加速下载;

常见的加速镜像站地址:

{
"registry-mirrors": [
"https://docker.1panel.live",
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"https://docker.m.daocloud.io"
]
}
  1. 如果发现配置了加速源提示无法访问,可能是安装的openwrt代理插件的问题,修改配置或者禁用代理后重试即可;
  2. 配置好后,执行 docker pull hello-world看是否可以正常拉取镜像,可以则说明网络配置完成。下面是正常工作的概览示例:

常见的一些玩法

Jellyfin 家庭影院(Emby/Plex 同理)

说明:下面用命令行和图文方式进行操作实例,后续章节仅提供命令行示例。

拉取镜像

命令行执行:

# [--platform linux/arm64]是可选参数,可以去掉
docker pull --platform linux/arm64 jellyfin/jellyfin:latest

LUCI界面操作:

拉取成功后,可以在页面镜像列表看到,如下图所示:

启动容器

启动命令示例:

docker run -d \
--name=jellyfin \
--restart=unless-stopped \
-p 8096:8096 \
-v /opt/data/configs/jellyfin:/config \
-v /opt/data/media:/media \
jellyfin/jellyfin:latest

可以直接复制上面的命令,到界面上的解析CLI,点击命令行按钮,然后粘贴,最后点击应用。

增加后,页面可以看到状态为Created,这个时候选中jellyfin容器,然后点击启动:

如果 SBC 支持硬件解码(GPU 驱动也搞好了),可以尝试加上:

--device /dev/dri:/dev/dri

ARM 平台硬解是个坑比较多的进阶话题,能成功算赚到,不能用就当纯软解顶着,1080p 问题不大。

启动参数说明:

Web 配置流程

浏览器访问:http://路由器IP:8096

  1. 创建管理员账号

  1. 添加媒体库:
    • 电影 → /media/movies
    • 电视剧 → /media/tv
    • 动漫 → /media/anime

  1. 语言选简体中文,元数据源可以切中文优先(刮削更顺)

之后你可以:

  • 安卓 TV/电视盒装 Jellyfin 客户端
  • 手机、平板、PC 直接 web/客户端访问
  • 家里的所有终端都在用 ARM SBC 这台“小服务器”作为服务器

使用简介

在上面的初始配置执行完成后,jellyfin就初始化好了,我们通过设置的管理员账户登录进去,可以看到如下界面:

我本地之前通过磁力链下载了Minions的的片源,现在直接点击,就可以在线观看了。

默认影片没有信息,我们可以通过刮削元数据,获取封面等信息,更多玩法请查阅jellyfin的官方文档:

核心玩法二:运行ubuntu

有很多服务,依赖完整的ubuntu环境,而不是openwrt的插件方式,这种时候我们可以在openwrt环境下安装docker ubuntu容器,实现拥有一台类似原生ubuntu的环境,实现各种自定义功能。下面以一个基础的Python实现的web服务器作为示例,展示运行容器版本的ubuntu强大的的自定义能力。

拉取镜像

命令执行:

docker pull ubuntu:24.04

启动容器

docker run -it ubuntu:24.04 bash

命令行启动示例:

docker run -it -d \
--name ubt-web \
--restart=unless-stopped \
-p 8080:8000 \
ubuntu:24.04 \
bash

进入容器,并执行简单HTTP服务器的Python代码,示例如下:

docker exec -it ubt-web bash
apt update
apt install python3 python3-pip -y

cat > /srv/app.py << 'EOF'
from http.server import HTTPServer, SimpleHTTPRequestHandler

PORT = 8000
httpd = HTTPServer(("", PORT), SimpleHTTPRequestHandler)
print(f"Serving on port {PORT}...")
httpd.serve_forever()
EOF

# 上面实现的web server root是当前执行python3的路径
python3 /srv/app.py

web访问测试

这个时候,通过http://路由器IP:8000,访问ubuntu容器里面python写的http服务器,会出现文件列表,如下图所示:

附加玩法:全网去广告

首先,拉取adgardhome镜像:

docker pull adguard/adguardhome:latest

然后启动容器,使用AdGuard Home:全家 DNS 去广告

docker run -d \
--name=adguardhome \
--restart=unless-stopped \
-p 3000:3000 \
-p 53:53/tcp \
-p 53:53/udp \
-v /opt/data/config/adguard:/opt/adguardhome/conf \
-v /opt/data/config/adguard/work:/opt/adguardhome/work \
adguard/adguardhome
  • 初始化地址:http://路由器IP:3000

  • 配置好之后,在 OpenWrt 的 LAN DHCP 里把 DNS 指向adguardhome容器的53端口,从而实现基于DNS的广告过滤功能。

更多配置详情,请查阅AdGuard Home官方文档。

FAQ / 踩坑小结

Q1:外网访问怎么弄?

  • 推荐:ZeroTier/Tailscale/FRP 做内网穿透,尽量别直接裸露端口在公网

Q3:备份怎么搞?

  • 必备:/opt/data/config 整个目录(所有服务的配置)
  • 重要数据:/opt/data/media 和需要保留的下载内容
  • 换机只要把这块盘接过去,重新挂载,容器改一下路径就能接着用

Q4:出问题怎么看?

  • docker logs 容器名 看日志
  • docker exec -it 容器名 /bin/sh 进去容器内部排查
  • 检查挂载目录权限、磁盘空间、内存占用这些基础项

参考链接

OPENWRT 系统 4:轻 NAS 玚法介绍

· 阅读需 10 分钟
世玉轩
100askTeam yuxuan.

方案介绍与选择

让 OpenWrt 上的 轻NAS(局域网文件共享)能在外网访问,也就是说,从任何地方都能安全地访问你的家用存储。 这是最简单的视线自建私有云的方式,只需要开发板要USB接口,3.0接口更佳,就可以接入USB移动硬盘,化身具有轻NAS功能的OpenWrt设备,下面是实现的步骤分析。

文件共享

我们首先需要实现局域网文件共享功能,下面是常见的局域网共享场景推荐的方法,我们这里选择samba4,FileBrowser,webDAV,三种常见的共享方式都支持上,下面是具体的场景推荐的协议,可以根据自己场景灵活选择。

场景推荐协议
Windows + Linux 通用文件共享Samba4
Linux 服务器挂载(如 Docker/K8s)NFS
外网访问 NAS(配合 frp/Tailscale)FileBrowser(Web)
最安全的传输(需要加密)SFTP
iPhone/macOS 挂载网盘WebDAV
媒体播放器(电视、DLNA)Samba4 或 NFS

内网访问

在完成局域网网络共享后,要想实现轻NAS,还有个关键的功能,就是可以远程随时查看家里共享的文件,那么我们就需要实现内网穿透,下面是常见的内网穿透方法,及以对应的优缺点,我们选择使用frp(自建中转服务器)和现在比较流行的方法DDNSTO,前者需要自己有一个公网的服务器来做数据转发,后者操作简便只需要安装对应的插件,然后在易有云平台绑定自己的设备即可,由易有云服务商的服务器来做数据转发。

下面是常见的内网访问的方案对比:

方案优点缺点安全性
公网 IP + 端口映射简单直连,速度快需要公网 IP(电信一般不给)较低(需防火墙)
🌐 DDNS + 公网 IP适合动态 IP 用户同样需要公网访问权限中等
🔐 ZeroTier / Tailscale VPN无需公网 IP,自动穿透 NAT需第三方 VPN 控制平面
☁️ frp / Cloudflare Tunnel自建隧道,无需公网 IP依赖中间服务器
DDNSTO路由远程简单操作,无需公网IP依赖第三方服务商

这里我们优先使用DDNSTO插件+插件提供商的云服务来实现轻NAS应用的内网穿透,也可在自己的VPS上自建frp云服务来实现轻NAS应用的内网穿透(适合高阶用户,需要配置很多参数和一些网络知识,当然也可以问AI来生成对应的配置),可根据自己的实际情况选择适合自己的方案。

DDNSTO插件实现轻NAS应用

挂载硬盘

首先,我们需要将移动硬盘插入DshanPi A1的USB TYPE-A口上,然后配置对应的挂载目录,并且设置为每次开机自动挂载。这里使用U盘进行测试示例,移动硬盘配置方法完全一样。

首先,在 **系统 -> 挂载点 **页面,配置磁盘自动挂载的目录,并启用。

配置好后,重启设备,观察配置是否断电也有效,生效的话可以看到下面的打印:

/media的默认权限:

使能文件共享服务

Samba共享

Samba是在Linux系统上实现SMB协议的一个免费软件,我们可以使用支持SMB协议的终端设备, 来实现局域网内的文件共享。

安装Samba

首先,我们需要在编译前选中luci-app-samba4,或者刷机后通过在线安装ipk的方式安装samba4服务端程序到系统内。安装完成后,在页面: 服务 -> 网络共享 可以看到对应的配置,如下图:

创建Samba用户

在进行网络共享时,我们应该避免使用root用户来登录samba服务器。 为此,我们单独创建一个用户来用于samba服务器的访问,并为它赋予文件夹的访问权限。

打开 **服务 -> 终端 **,执行下面的命令,创建用户,并给用户开启共享目录的访问权限。

#添加名为samba的用户
useradd samba

#为用户samba创建smb服务的密码,这个和用户名的密码是单独的,可以设置不同
smbpasswd -a samba

#使用户samba获得共享目录的权限
#注意:只有ext4的文件系统才能修改权限,根据自己磁盘格式做对应调整
chown -R samba:samba /media/

修改/etc/passwd,配置samba用户无法登陆,下面是示例:

修改samba4配置

打开 服务 -> 网络共享 进行参数的配置。

选择接口为lan,可以使内网设备访问。勾选 允许旧协议与身份验证。

点击 新增 一个条目。

  • 名称:共享时显示的文件夹名称,可随意设置,这里设置为media
  • 路径:将要共享的文件夹路径,这里设置为上一章节挂载的目录<font style={{color: 'rgb(64, 64, 64)', backgroundColor: 'rgb(252, 252, 252)'}}>/media</font>
  • 允许用户:具有访问权限的用户,这里设置为刚刚创建的用户samba。
主要设置就是这些,保存并应用这些配置,其他的设置可自行探索其他高阶配置。

SFTP共享

安装SFTP server

Dropbear 不支持 SFTP,但它支持 调用外部 sftp-server。

OpenWrt 已提供独立的 openssh-sftp-server 包:

opkg update
opkg install openssh-sftp-server

安装好后,sftp-server会放在:/usr/lib/sftp-server,这种方案适合需要有界面配置ssh秘钥的功能,但是也需要sftp server功能的场景,如果全部替换成openssh的全家桶,会因为OpenSSH 在 OpenWrt 中无官方 LuCI 配置界面,导致所以配置都要通过终端来完成。

配置SFTP

在安装好后,不用做其他配置,都可以直接使用,例如用Xftp直接连接,就能看到系统内的文件。

WebDAV共享

在安装完DDNSTO插件后,内部自带了一个轻量的webdav服务,不用再单独安装,直接使用即可。

配置内网穿透

首先登录DDNSTO控制台,注册登录后,记录用户Token,然后在板端配置DDNSTO远程控制页面,配置对应的参数,示例如下:

配置Samba远程访问

登录DDNSTO控制台,在文件管理栏下,点击添加文件管理,增加Samba协议的文件管理服务,填入对应参数,示例如下:

  1. 添加配置

  1. 点击连接
  2. 输入Samba4配置中的用户和密码
  3. 连接成功,可以看到对应目录下的文件,如下所示:

配置SFTP远程访问

登录DDNSTO控制台,在文件管理栏下,点击添加文件管理,增加Sftp协议的文件管理服务,填入对应参数,示例如下:

  1. 添加配置

  1. 点击访问

  1. 输入ssh可以登录的用户名和密码,这里输入root对应的密码
  2. 连接成功,可以看到对应目录下的文件,如下所示:

配置WebDAV远程访问

登录DDNSTO控制台,在文件管理栏下,点击添加文件管理,增加webdav协议的文件管理服务,填入对应参数,示例如下:

  1. 添加配置

  1. 点击访问

  1. 输入路由器系统里面DDSNTO插件中,填写的授权用户名和密码到登录页面中

  1. 连接成功,可以看到对应目录下的文件,如下所示:

配置远程访问路由器后台

登录DDNSTO控制台,选择外网域名栏,然后点击添加域名,按照下面示例填写配置:

配置完成后,点击外网域名栏,可以直接跳转到外网域名页面,这样就可以在任何地方远程配置局域网内的路由器了。

总结一下:DDNSTO插件把很多远程场景都整合起来了,轻度使用的话,付费用4Mbps的就可以了,延迟低,省去了各种复杂的环境搭建过程,和自建VPS的繁琐流程,推荐!

自建Frp云服务实现轻NAS应用

挂载硬盘并使能文件共享服务

自建方案中的挂载硬盘并使能文件共享服务,与使用DDNSTO插件方式完全一致,详细步骤轻查阅上一章节中的内容,此处不再累述。

配置内网穿透服务

这里需要配置的参数较多,并且需要考虑安全,需要涉及的配置项和证书等步骤较多,限于篇幅影响,这里不再详细描述,更多的请查阅frp的官方文档,搭建对应的内网穿透服务。

OPENWRT 系统 3:现有功能优化

· 阅读需 14 分钟
世玉轩
100askTeam yuxuan.

在下载百问网官方适配后的Openwrt源码后,发现使用上有很多功能没有完全适配,出现部分使用过程中体验不好的问题,下面是针对笔者使用中发现的问题的记录与解决办法分析,希望给读者遇到类似问题后,一些解决问题的思路。因为本人知识有限,有什么错误的地方,欢迎交流讨论。

安装第三方ipk无法使用

默认的云端mirror库的libc使用musl,使用glibc后烧进去,发现安装的程序都用不了,默认openwrt都是用的musl libc。

安装第三方的fdisk无法使用

默认的busybox配置,很多工具都没有,fdisk通过opkg安装后某个提示库不存在,需要手动配置Busybox的选项,我们把打开自定义busybox选项,然后配置fdisk使能。

然后重新编译镜像,然后刷入,测试便可以发现fdisk可以使用了。

sysupgrade镜像无法使用

使用默认生成的sysupgrade镜像,在界面【系统-备份与升级-刷写新的固件】里面选择了编出来的固件的时候,发现无法使用,有如下错误打印信息:

Tue Dec  2 17:27:21 2025 user.info upgrade: Device 100ask,dshanpi-a1 not supported by this image
Tue Dec 2 17:27:21 2025 user.info upgrade: Supported devices: 100ask,dshanpia1
Tue Dec 2 17:27:21 2025 user.info upgrade: Reading partition table from bootdisk...
Tue Dec 2 17:27:22 2025 user.info upgrade: Reading partition table from image...
Tue Dec 2 17:27:22 2025 user.info upgrade: Device 100ask,dshanpi-a1 not supported by this image
Tue Dec 2 17:27:22 2025 user.info upgrade: Supported devices: 100ask,dshanpia1
Tue Dec 2 17:27:22 2025 user.info upgrade: Reading partition table from bootdisk...
Tue Dec 2 17:27:22 2025 user.info upgrade: Reading partition table from image..

检查发现是armv8.mk里面定义的设备名称,和dts中的compatible不一致, 致 sysupgrade 拒绝刷机。

OpenWrt sysupgrade 会读取:

  1. 当前运行设备的标识:

来自:

  • /proc/device-tree/compatible
  • /etc/board.json
  1. 固件中 embedded 的 supported_devices 列表

二者任意一个字符不匹配就报:Device XXX not supported by this image

这里知道问题所在了,修改就比较简单了,按照如下方式修改:

  1. 修改 target/linux/rockchip/image/armv8.mk,保持和dts中的一致

  1. 重新执行make menuconfig,选择target,会自动更新.config文件

  1. 重新执行make V=s -j8,进行镜像编译即可。

sftp无法使用

默认的使用的dropbear做为ssh server,没有sftp功能,这里我们修改配置,关掉dropbear,然后在Network -> SSH下面打开openssh,如下图所示。

编译无法通过,openssh-sk-helper编译依赖libfido2,我们手动使能这个库,选中为y,然后重新编译即可。

注意:openssh-server和openssh-server-pam无法同时使能,我们打开没有PAM支持的编译即可。

rootfs空间太小

我们优先刷的squashfs格式的镜像,可以比较方便的恢复出厂配置,因为squashfs格式的rom是基于overlayfs的,更新的配置不会直接改到rom里面的内容。但是我们可以发现默认配置的rootfs的大小比较小,而板载的EMMC有58G,我们可以将rootfs空间扩大到8G,剩下的空间单独分配一个分区。

默认配置的rootfs分区为512M,如下所示:

修改配置,默认rootfs分区大小为2G,修改 Target Images下的Rootfs分区大小配置,如下所示:

usb设备无法识别

当我们只简单的在设备树使能usb0和usb1过后,会发现能识别到U盘了,但是usb驱动probe期间会打印dr_mode强制设置为host的打印,查找代码发现是默认配置的otg,但是没有otg对应的配置,并且drd相关的代码都未编译。

需要修改设备树文件,使能usb0和usb1控制器,默认角色为host。使能DRD ROLE SWITCH功能,然后就可以动态配置控制器角色,然后还可以指定默认角色。

必须要打开了 USB Gadget才能是能双角色功能,那么我们打开,然后在Mode Selection里面选中Dual Role mode,这样会在内核生成usb_role的sysfs节点,可以动态配置成host或者peripheral,在dshan pi a1上,usb1固定为host,usb0可以配置为双角色,可以切换,那么我们做如下dts配置:

--- a/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3576-100ask-dshanpi-a1.dts
+++ b/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3576-100ask-dshanpi-a1.dts
@@ -770,6 +770,20 @@
status = "okay";
};

+// usb0 as type-c port, can be host or peripheral.
+&usb_drd0_dwc3 {
+ status = "okay";
+ usb-role-switch;
+ role-switch-default-mode ="host";
+};
+
+// usb1 as type-a port, fixed to host
+&usb_drd1_dwc3 {
+ status = "okay";
+ usb-role-switch;
+ role-switch-default-mode ="host";
+};
+
&uart0 {
pinctrl-0 = <&uart0m0_xfer>;
status = "okay";

配置后,usb1可以使用,但是usb0无法使用,并且板载Hynetek HUSB311 Type-C 芯片,可以提供USB PD和USB Type-C的功能。发现默认6.12内核版本的驱动,没有该芯片的支持,查看rockip官方仓库,有这款芯片的支持,需要移植过赖,我们暂时不需要DP功能,屏蔽掉。

PWM风扇一直最大风速

上电后,风扇一直以最大转速工作,声音比较大,需要修改下,支持按照温度自动调整转速,这样更符合常见的应用场景。排查记录如下:

查硬件

风扇使用的树莓派5的4针风扇,是标准的4针JST插口,实物图和原理图如下:

风扇插口为1mm间距JST SH插座,有四个引脚:
PIN序号功能
1+5V
2PWM
3GND
4转速

查看了手册,2脚连接的PWM1,4脚连接的风扇转速口,说明不支持读取转速,只能PWM控制转速。看原理图是PWM1_CH0,dts里面也有对应的配置,根据compatible字段"pwm-fan"到驱动里面搜索,发现存在linux-6.12.43/drivers/hwmon/pwm-fan.c这个文件没有编译,那么就是KCONFIG没有选中,没有编译pwm-fan的驱动。

使能PWM驱动

那么我们直接make kernel_menuconfig,搜索COFNIG_SENSORS_PWM_FAN,然后输入搜索结果对应的序号,然后就会直接跳转到配置对应的地方,直接输入Y使能即可。

编译刷写后,启动过程中发现pwm-fan驱动启动失败,有如下打印:

可以得出,没有找到上游的PWM设备,搜索引用的节点的compatible,发现对应的驱动未打开,在单独的目录下:drivers/soc/rockchip

打开的驱动:

打开后,会出现编译问题,我们修改如下:

修改如下:

--- a/include/soc/rockchip/utils.h	2025-11-23 03:35:07.695086227 +0800
+++ b/include/soc/rockchip/utils.h 2025-11-23 03:34:43.946599951 +0800
@@ -50,6 +50,7 @@
*
* Return: the value, shifted into place, with the required write-enable bits
*/
+#if 0
#define REG_UPDATE_WE(_val, _low, _high) ( \
BUILD_BUG_ON_ZERO(const_true((_low) > (_high))) + \
BUILD_BUG_ON_ZERO(const_true((_high) > 15)) + \
@@ -57,6 +58,11 @@
BUILD_BUG_ON_ZERO(const_true((u64) (_val) > U16_MAX)) + \
((_val & GENMASK((_high) - (_low), 0)) << (_low) | \
(GENMASK((_high), (_low)) << 16)))
+#else
+#define REG_UPDATE_WE(_val, _low, _high) ( \
+ ((_val & GENMASK((_high) - (_low), 0)) << (_low) | \
+ (GENMASK((_high), (_low)) << 16)))
+#endif

/**
* REG_UPDATE_BIT_WE - update a bit with a write-enable mask
@@ -68,9 +74,14 @@
*
* Return: a value with bit @__bit set to @__val and @__bit << 16 set to ``1``
*/
+#if 0
#define REG_UPDATE_BIT_WE(__val, __bit) ( \
BUILD_BUG_ON_ZERO(const_true((__val) > 1)) + \
BUILD_BUG_ON_ZERO(const_true((__val) < 0)) + \
REG_UPDATE_WE((__val), (__bit), (__bit)))
+#else
+#define REG_UPDATE_BIT_WE(__val, __bit) ( \
+ REG_UPDATE_WE((__val), (__bit), (__bit)))
+#endif

#endif /* __SOC_ROCKCHIP_UTILS_H__ */

配置转速方法

手动配置pwm-fan的方法,在sysfs下面查找pwm-fan的目录,进入/sys/class/hwmon/hwmon0/下,即可看到两个文件pwm1_enable和pwm1,先配置pwm1为100,观察风扇声音是否减小,试验发现确实变小了,说明PWM控制生效了。

root@LEDE:~# ls /sys/class/hwmon/hwmon0/
device of_node pwm1 subsystem
name power pwm1_enable uevent
root@LEDE:~# echo 100 > /sys/class/hwmon/hwmon0/pwm1

kernel文档关于pwm_fan的sysfs节点说明

参考文档:

  • Documentation/hwmon/pwm-fan.rst
  • Documentation/devicetree/bindings/hwmon/pwm-fan.yaml
  • Documentation/driver-api/thermal/sysfs-api.rst

也可以根据thermal框架,下面的cooling_device找到pwm-fan。在thermal cooling device框架下有注册的sysfs接口,对应绑定pwm_fan驱动提供的ops,将state数值对应dts中配置的cooling_levels数组索引,进而可以通过配置0..max_state的数值,来配置pwm驱动里面对应的相对速度,在shell里面直接。

static const struct thermal_cooling_device_ops pwm_fan_cooling_ops = {
.get_max_state = pwm_fan_get_max_state,
.get_cur_state = pwm_fan_get_cur_state,
.set_cur_state = pwm_fan_set_cur_state,
};

//dts
fan: pwm-fan {
status = "okay";
compatible = "pwm-fan";
#cooling-cells = <2>;
pwms = <&pwm1_6ch_0 0 50000 1>;

// 这里对应state从0..5
cooling-levels = <0 100 125 150 200 255>;

// 这里配置的trips,没有生效。我们需要将它放到thermal框架里去
rockchip,temp-trips = <
40000 1
50000 2
60000 3
65000 4
70000 5
>;
};
root@LEDE:~# ls /sys/class/thermal/cooling_device0/
cur_state max_state power subsystem type uevent
root@LEDE:~# cat /sys/class/thermal/cooling_device0/max_state
5
# 这里等同于 echo 100 > /sys/class/hwmon/hwmon0/pwm1
root@LEDE:~# echo 1 > /sys/class/thermal/cooling_device0/cur_state

增加自动调整转速功能

自动调整转速,依赖于thermal系统,主要有theraml_zone,cooling_device,trip_point三个组成。

参考文章:Linux Thermal 框架解析-CSDN博客

在原本的dts里面配置的thermal_zones节点下新增对应的trip。

单独编译dts 失败

make target/linux/prepare V=s
make target/linux/compile DTBS=1 V=s

然后你就可以直接找到生成的:

build_dir/target-*/linux-*/linux-*/arch/arm64/boot/dts/*.dtb

配置pwm1或者cur_state=0的时候,风扇转速最大。根据kernel文档关于pwm_fan的sysfs节点说明,可以由pwm1_enable文件进行配置当pwm1=0的时候的具体行为。默认的值为1,即disable pwm, keep regulator enabled。所以设置成0的时候,会直接拉满。

所以这里我们配置cooling-levels数组的时候,第0个元素的值设置为10,以较低速度转动。然后pwm1_enable设置为2,即pwn=0的时候,pwm和regulator都还有输出,即占空比0。

板载LED灯没有驱动

这是一个 由单线串行控制的 RGB LED 灯带链路

  • 芯片:WS2812C-2020
  • 灯的数量:4 个(RUN × 4)
  • 每个 LED 既是 RGB LED,又集成了驱动芯片
  • 只需要 1 根 GPIO 数字信号线 就能控制一串灯

典型用途:

  • 状态灯
  • 跑马灯
  • 主板灯光
  • 工控指示灯
  • 路由器/电视盒子的呼吸灯

WS2812 是 单线 800kHz NRZ 协议,不是普通 PWM。Linux 内核无法直接 bit-bang 得够快,必须使用能产生精确的波形才能驱动。

通过搜索源码,发现工程里面有提供的两种驱动,一个是leds-ws2812b,一个是ws2812-pio-rp1。仔细检查发现一个是基于spi,一个是基于pio扩展芯片的方式,我们原理图里面只能使用spi hacking的方式。

配置方法参考redmi的配置,适配到dshanpi即可。

原理图里面的PIN脚没有MOSI功能,无法使用SPI HACKING,咨询得到,需要使用PWM HACKING方式。

MMC驱动经常打印报错

驱动报错信息:

[ 1344.988178] mmc0: Timeout waiting for hardware interrupt.
[ 1344.988672] mmc0: sdhci: ============ SDHCI REGISTER DUMP ===========
[ 1344.989235] mmc0: sdhci: Sys addr: 0x00000002 | Version: 0x00000005
[ 1344.989800] mmc0: sdhci: Blk size: 0x00007200 | Blk cnt: 0x00000002
[ 1344.990364] mmc0: sdhci: Argument: 0x00069e72 | Trn mode: 0x0000003f
[ 1344.990929] mmc0: sdhci: Present: 0x03f700f1 | Host ctl: 0x00000035
[ 1344.991493] mmc0: sdhci: Power: 0x0000000d | Blk gap: 0x00000000
[ 1344.992057] mmc0: sdhci: Wake-up: 0x00000000 | Clock: 0x0000030f
[ 1344.992621] mmc0: sdhci: Timeout: 0x0000000e | Int stat: 0x00000000
[ 1344.993185] mmc0: sdhci: Int enab: 0x03ff000b | Sig enab: 0x03ff000b
[ 1344.993749] mmc0: sdhci: ACmd stat: 0x00000000 | Slot int: 0x00000000
[ 1344.994313] mmc0: sdhci: Caps: 0x3a6dc881 | Caps_1: 0x08000007
[ 1344.994876] mmc0: sdhci: Cmd: 0x0000123a | Max curr: 0x00000000
[ 1344.995439] mmc0: sdhci: Resp[0]: 0x00000900 | Resp[1]: 0xfff6dbff
[ 1344.996003] mmc0: sdhci: Resp[2]: 0x320f5903 | Resp[3]: 0x00009001
[ 1344.996566] mmc0: sdhci: Host ctl2: 0x0000380f
[ 1344.996957] mmc0: sdhci: ADMA Err: 0x00000060 | ADMA Ptr: 0x00000000fc300210
[ 1344.997581] mmc0: sdhci: ============================================

dmesg里面probe的信息:

[ 0.438699] mmc0: SDHCI controller on 2a330000.mmc [2a330000.mmc] using ADMA 64-bit
[ 0.499319] mmc0: new HS400 Enhanced strobe MMC card at address 0001
[ 0.500422] mmcblk0: mmc0:0001 CJNB4R 58.2 GiB
[ 0.502009] mmcblk0: p1 p2 p3
[ 0.502655] mmcblk0boot0: mmc0:0001 CJNB4R 4.00 MiB
[ 0.503828] mmcblk0boot1: mmc0:0001 CJNB4R 4.00 MiB
[ 0.504873] mmcblk0rpmb: mmc0:0001 CJNB4R 4.00 MiB, chardev (247:0)

根据AI搜索和DTS里面的信息, 看得出来 eMMC 在上电初始化阶段是 完全正常工作的, 控制器寄存器/时钟/复位/pinctrl 基本没问题,否则根本不会成功切到 HS400 ES、识别分区 。

,可以尝试降档到HS200或者降低频率的方式,来进行测试,找一个稳定工作的版本,本地测试了两种方法:

  1. 降档到HS200,不修改频率
mmc-hs200-1_8v;
//mmc-hs400-1_8v;
//mmc-hs400-enhanced-strobe;

测试后发现,HS200工作没问题,启动打印:

[    0.439179] mmc0: SDHCI controller on 2a330000.mmc [2a330000.mmc] using ADMA 64-bit
[ 0.492249] mmc0: new HS200 MMC card at address 0001
[ 0.493187] mmcblk0: mmc0:0001 CJNB4R 58.2 GiB
[ 0.494771] mmcblk0: p1 p2 p3
[ 0.495416] mmcblk0boot0: mmc0:0001 CJNB4R 4.00 MiB
[ 0.496586] mmcblk0boot1: mmc0:0001 CJNB4R 4.00 MiB
[ 0.497629] mmcblk0rpmb: mmc0:0001 CJNB4R 4.00 MiB, chardev (247:0)

  1. 保持HS400不变,降低频率到100M
//max-frequency = <200000000>;
max-frequency = <100000000>; //work perfect on 100M

测试后发现,也能正常工作,启动打印:

[    0.439264] mmc0: SDHCI controller on 2a330000.mmc [2a330000.mmc] using ADMA 64-bit
[ 0.492185] mmc0: new HS400 Enhanced strobe MMC card at address 0001
[ 0.493275] mmcblk0: mmc0:0001 CJNB4R 58.2 GiB
[ 0.494696] mmcblk0: p1 p2 p3
[ 0.495331] mmcblk0boot0: mmc0:0001 CJNB4R 4.00 MiB
[ 0.496498] mmcblk0boot1: mmc0:0001 CJNB4R 4.00 MiB
[ 0.497546] mmcblk0rpmb: mmc0:0001 CJNB4R 4.00 MiB, chardev (247:0)

但是发现使用docker的时候会有各种错误打印:

就现使用最小修改的方法,设备树删除HS400模式配置,设置HS200模式,测试稳定运行,就先用这种。

OPENWRT 系统 2:构建自定义系统

· 阅读需 10 分钟
世玉轩
100askTeam yuxuan.

序言

本文档旨在为开发者和爱好者提供一份清晰、简洁的 OpenWrt(LEDE)固件编译指南,专用于 DshanPi A1(基于瑞芯微 RK3576 平台) 开发板。通过本流程,您将完成从源码获取、依赖更新、配置定制(包括 OP 域与 Kernel 域)、到最终固件生成的完整编译过程。文档同时涵盖最小化配置生成方法、常见问题提示及镜像输出说明,帮助用户高效构建适配硬件的稳定固件,为后续开发、调试或部署奠定基础。无论您是初次接触 OpenWrt 编译,还是希望针对 RK3576 平台进行深度定制,本文均可作为实用参考。

配置编译环境

如果是基于WSL编译的,请参考《一、单板介绍与开发环境搭建 - 开发环境》章节,配置好WSL的基础环境。

然后按照仓库readme安装编译需要的编译工具链,安装好编译相关,示例如下:

sudo apt install -y ack antlr3 asciidoc autoconf automake autopoint binutils bison build-essential \
bzip2 ccache clang cmake cpio curl device-tree-compiler flex gawk gcc-multilib g++-multilib gettext \
genisoimage git gperf haveged help2man intltool libc6-dev-i386 libelf-dev libfuse-dev libglib2.0-dev \
libgmp3-dev libltdl-dev libmpc-dev libmpfr-dev libncurses5-dev libncursesw5-dev libpython3-dev \
libreadline-dev libssl-dev libtool llvm lrzsz msmtp ninja-build p7zip p7zip-full patch pkgconf \
python3 python3-pyelftools python3-setuptools qemu-utils rsync scons squashfs-tools subversion \
swig texinfo uglifyjs upx-ucl unzip vim wget xmlto xxd zlib1g-dev

获取源码

直接git clone百问网的仓库即可,注意有些环境可能github访问受限,克隆不下来,可以参考《一、单板介绍与开发环境搭建 - 3.3 WSL网络代理设置》中的内容,配置http/https终端代理即可。

git clone https://github.com/dshanpi/RK3576-DshanPiA1_LEDE.git

在下载完源码后,更新feeds,下载对应的包:

cd RK3576-DshanPiA1_LEDE
./scripts/feeds update -a
./scripts/feeds install -a

自定义选项

在更新feeds完成后,我们可以先使用默认的minimal配置做为基础,然后在上面做自定义配置即可,示例如下:

cp minimal.config .config
make defconfig # 会自动补齐缺失的配置项,使其成为可编译的完整配置

后续的配置可以保存为defconfig,加入版本管理中,具体方法查看本文 《4.5 保存配置》章节。

生成了基础配置后,就可以进行自定义配置了,自定义配置的命令为:

make menuconfig

系统的配置,简单划分的话,可以主要分为以下几个部分:

  • busybox

这部分是基础系统的特性配置,openwrt的基础系统是使用的busybox。

  • app

这部分对应一些命令或者luci-xxx这类待页面的应用,主要靠这部分扩展路由器的功能,和暴露易用的配置界面。

  • libs

这部分主要是配置openwrt的系统里面集成的库,可以按需增加,常规情况下是选中某些命令或者luci类的app的时候,会自动选中对应的库。

  • kernel

这部分主要是配置kernel,包含一些内核功能和驱动,在有新的外设支持的时候,需要配置到。

配置编译选项

这部分主要配置编译目标文件时候的一些优化参数和编译工具链的一些选项,按照下面的方法打开:

  1. 首先使能 Advanced configuration options (for developers):

  1. 使能 Target Options,并填入目标优化的GCC编译参数:

目标优化编译参数配置

  1. 使能Toolchain Options,配置工具链选项:

警告:此处C库实现要选择musl,不然刷机完进如系统后,通过Opkg下载的包全都无法使用!(因为默认的包都是musl c库)!

配置busybox选项

在有些场景,openwrt的非busybox类的配置无法覆盖要求,需要通过busybox里面的包来实现,这个时候就需要自定义busybox的选项。可以参考下面的配置方法:

  1. 选中 Base System -> Customize busybox options

其中Settings是一些额外的参数配置,如编译选项等;Applets是一些命令行工具的配置,我们按需进行相应的配置即可。

需要注意的是,当openwrt的包能提供对应的功能的时候,我们不应在busybox的配置里面再提供,不然在编译的最后环节,会提示已经提供但是Busybox里面也有的错误提示。

配置应用

openwrt包含丰富的应用集,可以极大地丰富路由器的功能,包含各种各样的库,命令行工具,带界面的APP(常称为插件)等,这里只对配置一些常见的APP做一些配置示例。

大部分包都按照分类,有序的按照字母顺序排列在各个大项下面,如我们想使能一下sftp-server,那么可以在:Network -> SSH 页面下找到,然后选中即可,示例如下:

还有一种比较快捷的方法,可以通过menuconfig的配置项搜索功能,快速定位到需要配置的页面去选中,下面已sftp-server为目标,搜索打开的方法示例:

  1. 在menuconfig主界面,输入/,进如搜索页面,然后在搜索页面输入sftp-server

  1. 根据搜索结果页面中(N)对应的数字索引,可以快速跳转到某条结果,如此处只有一个结果,那么索引是1,直接输入1,会直接跳转到对应的页面。

  1. 可以看到目前搜索页面对应的包是=n,未使能的;输入索引值跳转过去后发现确实是未使能,相对应,这个时候我们只需要输入y使能即可。

  1. 针对有多条搜索结果的情况,我们可以通过输入空格键实现整页翻页查看结果,也可以通过输入上下键实现按行翻页查看结果,通过查看搜索页面的详细信息,确定是否是自己要找的包。

说明:推荐两种方法都灵活使用,可以大大加快开发效率。

配置kernel选项

kernel的配置选项和其他不同,不是make menuconfig配置的,而是有单独的make目标,示例如下:

make kernel_menuconfig

在未编译过整个工程的情况下,执行上述命令会自动去先编译依赖的工具链,可能比较耗时,推荐先整个工程编译一次,然后再自定义配置kernel选项。

因为第一次整个编译工程的时候,会下载依赖的所有源码包,并编译对应的工具链,比较耗时。

保存配置

针对OP域的配置,使用下面命令,生成最小配置文件:

./scripts/diffconfig.sh > defconfig

针对kernel域的配置,在配置kernel的时候,会自动更新配置到target下面的config文件里面,不用手动保存。

编译

流程

首先执行下载操作,解决完下载过程中可能遇到的问题,然后再执行编译流程。

避免默认的编译过程中下载,可能会某个包失败了后,再编译的时候,会挨个检查之前的包是否下载和编译完成了,这样不利于调试,执行命令如下:

# 当下载失败的时候,使用-j1查看具体的失败信息
# 下载的源码包都存放在工程根目录的dl目录下
make download -j$(nproc)

#第一次编译推荐用单线程,测试多线程编译会失败!
make V=s -j1

二次编译的时候,可以执行:

make V=s -j$(nproc)

如果需要重新配置,按照下面流程执行:

rm -rf .config
make menuconfig
make V=s -j$(nproc)

常见编译错误

有些程序编译的时候会失败,这个时候我们需要重新使用make V=s -j1的方式重新跑一遍,才能较好的看到编译过程中的错误,比较场景的有未定义或者库找不到的错误,或者Werror导致的报错,下面是一个简单的解决方式示例。

如最开始使用glibc进行编译,发现mbedtls和vlmcsd一直编不过,增加如下修改可以编过:

diff --git a/package/libs/mbedtls/Makefile b/package/libs/mbedtls/Makefile
index 4e0a4a034..54a0b2d45 100644
--- a/package/libs/mbedtls/Makefile
+++ b/package/libs/mbedtls/Makefile
@@ -121,7 +121,7 @@ This package contains mbedtls helper programs for private key and
CSR generation (gen_key, cert_req)
endef

-TARGET_CFLAGS += -ffunction-sections -fdata-sections
+TARGET_CFLAGS += -ffunction-sections -fdata-sections -Wno-error=stringop-overflow
TARGET_CFLAGS := $(filter-out -O%,$(TARGET_CFLAGS))

CMAKE_OPTIONS +=
--- Makefile.orig       2025-11-14 01:58:43.376952312 +0800
+++ Makefile 2025-11-14 01:53:50.865983762 +0800
@@ -37,4 +37,6 @@
$(INSTALL_BIN) ./files/vlmcsd.ini $(1)/etc/vlmcsd/vlmcsd.ini
endef

+TARGET_LDFLAGS += -lresolv -lpthread
+
$(eval $(call BuildPackage,vlmcsd))

更多编译过程中的错误,灵活使用AI工具和搜索引擎,基本都能解决编译中遇到的问题。

烧写

编译完成后,会在对应的bin/target/xxxx目录生成两个类型的镜像包,一个是ext4一个是squashfs的,如果有恢复默认配置需求,需要使用squashfs的镜像包。

注意:在OpenWrt编译完成后,可以刷写的镜像会被压缩成zip格式文件,需要先执行解压操作,然后才能做为烧录工具的刷机镜像,示例如下:
jason@ubuntu24:~/LEDE/bin/targets/rockchip/armv8$ gunzip -k openwrt-rockchip-armv8-100ask_dshanpia1-squashfs-sysupgrade.img.gz -f
gzip: openwrt-rockchip-armv8-100ask_dshanpia1-squashfs-sysupgrade.img.gz: decompression OK, trailing garbage ignored

解压得到img镜像后,参考《单板介绍与开发环境搭建 - 4.3开始烧录》内容,进行刷机。

openwrt系统自带的在线刷机功能使用的时候有问题,参考《现有功能优化 - 1.3 sysupgrade镜像无法使用》章节进行适配,适配后便可以直接通过web的方式直接刷机,示例如下:

注意:web页面在线升级选择的为压缩后的镜像包!

OPENWRT 系统 1:A1 主板介绍与开发环境搭建

· 阅读需 11 分钟
世玉轩
100askTeam yuxuan.
DShanPl-A1 Education专为人工智能教育及项目开发深度优化,基于瑞芯微的RK3576处理器设计,集成了4个Cortex-A72和4个Cortex-A53及支持NEON指令集,支持8K@30fps的H.265,VP9AVS2 和 AV1解码器,4k@60fps的H.264解码器和4K@60fps的AV1解码器;还支持4K@60fps的H.264和H.265编码器。内置3D GPU,能够完全兼容OpenGl ES1.1/2.0/3.2、0penCL2.0和Vulkan 1.1。内嵌的NPU算力高达6TopS,支持INT4/INT8/INT16/FP16混合运算。

板子有丰富的外设接口,板载SOC性能强劲,可以提供中高端性能 SBC(Single Board Computer-卡片电脑)体验,智能路由器等,下面是一些对应的应用场景示例:

  • 智能单机小电脑,具备办公,教育,编程开发,嵌入式开发等功能
  • 个人git仓库,服务器,nas,软路由,私有云
  • 机器人,无人机等项目
  • 电视机盒子,智能家居中枢,家庭安防监控,智能音箱等智能设备
OpenWrt 是一个基于 Linux 的开源嵌入式操作系统,主要用于路由器等网络设备。与传统路由器固件相比,OpenWrt 不是固定功能的固件,而是可自由扩展的软件平台,用户可以通过 opkg 软件包系统安装各种组件,实现路由、防火墙、VPN、NAS、内网穿透等多种功能。它提供 SSH 命令行与 LuCI Web 界面,配置灵活,支持 VLAN、IPv6、QoS、多 WAN 等高级网络特性。OpenWrt 结构清晰、模块化,核心包括 UCI 配置系统、netifd 网络管理、dnsmasq、hostapd 和防火墙框架等。凭借高度可定制性和强大的社区支持,OpenWrt 适用于家庭、企业网络以及二次开发,是打造高功能路由器和网络应用平台的理想选择。 Lean 的 OpenWrt LEDE 仓库是一个由 Lean 所维护的开源项目,旨在为 OpenWrt 系统提供稳定、高效且功能丰富的支持。作为 OpenWrt 和 LEDE 项目的结合,Lean 版本为广泛的路由器和嵌入式设备提供了优化的固件及增强功能,广泛应用于家庭、企业及实验室环境。Lean 仓库包含了来自全球开源社区的众多补丁、优化、驱动程序以及各种第三方应用,极大地提升了 OpenWrt 系统的可定制性和性能。

本次项目的目标是基于 DShanPl-A1 Education 单板构建一个轻量化 NAS(轻NAS)应用。最佳实现路径是采用成熟且高度可扩展的开源路由系统 OpenWrt LEDE。借助 OpenWrt 完整的 Linux 环境与丰富的生态插件,我们能够在系统中按需安装存储服务、网络服务、内网穿透、安全访问等功能模块。通过这些插件之间的协作配置,再结合 OpenWrt 强大的网络管理能力,即可构建一个基于软路由架构的轻NAS 方案。

开发环境

环境说明

编译openwrt官方推荐使用原生 GNU/Linux environment,但是也支持使用Windows WSL的模式进行编译。在Windows上使用WSL的开发环境,不用去配置虚拟机环境,在某些限制按照vmware的环境下也可以使用,估笔者的编译和开发环境大多数优先使用WSL进行。

WSL(Windows Subsystem for Linux)在 Windows 上提供原生级 Linux 环境,适合开发者进行跨平台或 Linux 相关项目开发。其主要优点包括:

  1. 轻量快速:无需虚拟机或双系统,启动和运行几乎与原生 Linux 一样快,资源占用低。
  2. 无缝集成 Windows:可以直接访问 Windows 文件系统、使用 Windows 工具(如 VSCode、浏览器)与 Linux 工具协同工作。
  3. 原生 Linux 体验:支持大多数 Linux 命令、包管理器、构建工具,可直接进行编译、调试、运行服务。
  4. 易于安装维护:从 Microsoft Store 一键安装,系统更新、环境切换都非常方便。
  5. 优秀的开发体验:支持 Docker(WSL2)、Git、Python、Node.js、C/C++ 等主流开发环境,适合嵌入式、服务器、网络、AI 等领域。
  6. 跨平台兼容性好:能在 Windows 上构建 Linux 可运行的软件,如编译 OpenWrt、构建驱动、生成交叉编译包等。
总体来说,WSL 让开发者在 Windows 下以最小成本获得接近原生的 Linux 能力,大大提升效率与灵活性,我们采用VSCode远程访问的方式,很方便的可以完成开发工作。 下面是一些需要在编译前需要配置的WSL环境,把这部分复制到

环境变量配置

参考官方文档:Build system setup WSL

在WSL环境下面,编译用户的.bashrc里面,按照下面说明增加对应的配置信息,解决默认环境下,Windows的环境变量也会在WSL里面默认生效的问题,这样设置过后,基本上环境和原生的GNU/LINUX环境保持一致,不会用WSL的机制导入的问题。

# GO编译配置,如果编译不了打开这个
#export GO111MODULE=on
#export GOPROXY=https://goproxy.cn

# proxy,这里替换成自己的Windows环境的代理服务IP:PORT
export http_proxy=http://192.168.31.50:6080
export https_proxy=http://192.168.31.50:6080

export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'

# Filter Windows PATH stuff
export PATH=$(echo $PATH | sed -e 's|:[^:]*WindowsApps[^:]*||g')
export PATH=$(echo $PATH | tr ':' '\n' | grep -v NVIDIA | tr '\n' ':')
export PATH=$(echo $PATH | tr ':' '\n' | grep -v 'Files' | paste -sd ':' -)
export PATH=$(echo $PATH | tr ':' '\n' | grep -v 'VS' | paste -sd ':' -)
export PATH=$(echo $PATH | tr ':' '\n' | grep -v '/mnt/' | paste -sd ':' -)

WSL网络代理设置

针对有的工具包在github上,默认网络下载可能会经常失败,我们可以选择在Windows上运行对应的代理软件,然后开启允许其它设备连接,然后在WSL中配置对应的http_proxy和https_proxy环境变量,就可以很方便的对github访问进行加速了。

下面是一些配置示例:

  1. 代理软件使能局域网设备连接

  1. WSL Settings中设置网络模式为Mirrored

更多说明请查阅微软的官方稳文档:使用 WSL 访问网络应用程序 - 镜像模式网络

  1. 配置好后,先wsl --shutdown,然后再重新启动wsl ubuntu
  2. 检查环境变量WSL_PAC_URL是否已经配置成功,成功的示例如下:

  1. 配置终端http和https代理,自动PAC过滤
export http_proxy=$WSL_PAC_URL
export https_proxy=$WSL_PAC_URL

Tips: 可以直接写入当前用户的.bashrc里面,这样不用每次都执行一遍代理设置。

刷机测试方法

这里介绍刷入LEDE镜像的基础方法,需要提前掌握刷入镜像的方法,下面是详细步骤介绍。

硬件连接

烧录系统镜像,除了dshanpi-a1板子,还需要准备 TypeC USB线 、30W PD电源适配器 (建议韦东山店铺购买),如下所示:

安装驱动和刷机软件

需要下载的工具包和镜像文件如下:

在前面下载的资料里找到驱动安装工具包 DriverAssitant_v5.1.1.zip,解压 ,然后打开启动下载程序 DriverInstall.exe ,点击驱动安装即,如下:

解压前面下载链接下载的烧录工具RKDevTool_Release_v3.32.zip,然后直接双击RKDevTool.exe即可。

开始烧录

准备工作完成后,按照下面的步骤操作,使设备进如MASKROM烧录模式:

① 接上 usb2.0/3.0 otg 线(也即type-c烧录数据线,数据线另一端接电脑的 USB2.0/3.0 蓝色接口);

② 按住 **<font style={{color: 'rgb(28, 30, 33)', backgroundColor: 'rgb(246, 247, 248)'}}>MASKROM</font>** 按键,先不松开

③ 再接上电源,dshanpi-a1 就会进入 **<font style={{color: 'rgb(28, 30, 33)', backgroundColor: 'rgb(246, 247, 248)'}}>MASKROM</font>** 烧录模式;

打开烧录工具,按照下面的选择界面参数,配置烧录镜像和参数,然后点击执行,等待下载完成,在刷入完成后,会自动重启单板,然后出现LEDE的像素LOGO,即刷入完成。

OpenWrt刷写EMMC的参数配置示例

系统启动后shell提示

注意:在OpenWrt编译完成后,可以刷写的镜像会被压缩成zip格式文件,需要先执行解压操作,然后才能做为烧录工具的刷机镜像,示例如下:
jason@ubuntu24:~/LEDE/bin/targets/rockchip/armv8$ gunzip -k openwrt-rockchip-armv8-100ask_dshanpia1-squashfs-sysupgrade.img.gz -f
gzip: openwrt-rockchip-armv8-100ask_dshanpia1-squashfs-sysupgrade.img.gz: decompression OK, trailing garbage ignored

# 待输入img镜像文件
jason@ubuntu24:~/LEDE/bin/targets/rockchip/armv8$ ls -lh openwrt-rockchip-armv8-100ask_dshanpia1-squashfs-sysupgrade.img
-rw-r--r-- 1 jason jason 640M Nov 28 02:24 openwrt-rockchip-armv8-100ask_dshanpia1-squashfs-sysupgrade.img

参考文档