手里这块双核RISC-V开发板已经吃灰半年了,1GHz的应用级处理器、1GB内存、板载千兆网口、一个SATA接口。当路由器算力过剩,当通用开发板又不知道跑什么,典型的“高不成低不就”。直到家里一台旧笔记本退役,留下了整块硬盘的照片、工作文档和电影资源,才意识到自己真正缺的是一个NAS。盯了两天成品NAS的价格,再看了看这块板子的功耗,决定自己动手——从板级引导开始,一步步把它做成一个基于RISC-V的现代嵌入式轻量化NAS系统。
这篇文章记录的是完整的实现过程:从ROM启动、OpenSBI、U-Boot这套板级引导链路,到内核裁剪、根文件系统构建,再到Samba、NFS这些现代网络栈服务,最后是性能调优和踩坑实录。适合手里有RISC-V开发板还不知道能干点啥的人,也适合想搭轻量NAS但不想上x86大机箱的朋友。全文不讲虚的,所有步骤都是实际验证过的方案。
1. 项目概述与整体设计
1.1 为什么选RISC-V做NAS
先说个实话,RISC-V做NAS目前不是最省事的方案,x86或者ARM平台资料多、生态成熟,随便一个树莓派都能跑成品NAS系统。但RISC-V有它不可替代的价值,这也是我坚持用它的原因。
RISC-V的指令集是开放的,没有授权壁垒,这意味着从SoC设计到编译器、操作系统,整个工具链都是透明的。对于一个想搞懂“系统是怎么跑起来”的人来说,x86那套固件链复杂到让人头皮发麻,ARM的Trusted Firmware也不简单。RISC-V的引导链条非常清晰:ROM加载固化固件,OpenSBI运行在M模式提供运行时服务,U-Boot跑在S模式加载内核,内核跑在U模式。每一层干什么都非常明确,没有历史包袱,也没有各种兼容性黑魔法。
功耗和成本上,RISC-V应用级处理器也有明显优势。我这块板子满载也就7瓦左右,待机4瓦出头,挂一块3.5寸机械硬盘整机功耗稳定在10瓦内。如果换成x86平台,光是CPU和芯片组的待机功耗就远超这个数。对于7x24小时开机的NAS应用场景,一年下来的电费差距非常可观。
生态方面,2024年到2025年RISC-V的Linux主线支持已经相当成熟了,OpenSBI、U-Boot、Buildroot、Yocto这些基础组件都有完善的支持。我用的还是长期支持版内核,SATA、USB3.0、千兆网卡这些外设驱动都能直接编译进去,不需要一堆out-of-tree补丁。说句公道话,两年前的RISC-V开发板还真不适合做这种活,现在时机到了。
1.2 系统架构与核心选型原则
整个系统的软件架构可以分成四层,从上到下分别是:
- 应用层:Samba、NFS、rsync、SSH、smartd监控
- 系统层:Buildroot构建的根文件系统,glibc运行库
- 内核层:Linux 6.x LTS,裁剪掉用不到的驱动和子系统
- 固件层:OpenSBI + U-Boot,负责硬件初始化和引导内核
这个分层方式跟x86服务器的引导流程本质是一回事,但RISC-V的每个环节都更精简。选型的时候我给自己定了三个原则:
- 能编译进内核就不做模块。嵌入式设备追求稳定,模块加载机制在调试阶段有用,但运行阶段反而增加故障点。我直接把SATA、网络、文件系统全部编进内核,不要initramfs那套东西,启动更快更可靠。
- 能用一个服务解决就不装两个。局域网共享主要用SMB协议,NFS只作为备选方案部署。像DLNA这种媒体服务我干脆不装,一个SMB共享搞定所有设备访问,减少内存占用。
- 一切以低功耗高可靠优先。不做复杂的软RAID5,不用ZFS这种吃内存的文件系统,数据安全靠基础的RAID1加定期备份实现。
完整组件选型对比可以参考这个表:
| 组件 | 选型 | 备选方案 | 选择理由 |
|---|---|---|---|
| 引导固件 | OpenSBI + U-Boot | 只有U-Boot的SPL方案 | 标准S模式引导,便于调试 |
| 内核 | Linux 6.x LTS | 最新主线版 | LTS稳定,驱动支持够用 |
| 根文件系统 | Buildroot + glibc | musl libc | glibc兼容性好,Samba等软件行为更稳 |
| 数据文件系统 | ext4 | btrfs、f2fs | 老牌可靠,CPU占用低 |
| 网络共享 | Samba | NFS、FTP | Windows/Linux/macOS/手机全兼容 |
| 定时任务 | crond(BusyBox自带) | systemd timer | systemd在Buildroot里太臃肿 |
这套架构跑起来的最终效果,是一台功能完整的轻量化NAS,内存占用控制在300MB以内,CPU平时负载几乎为0,只有传输文件的时候才会短时间拉高。
2. 板级引导与系统移植
2.1 RISC-V引导链路:M模式、S模式与U模式
很多第一次接触RISC-V的人都会被引导流程绕晕,这里我用最直白的方式拆解。
RISC-V定义了三种特权模式:机器模式(M mode)、监督模式(S mode)、用户模式(U mode)。类比一下,M模式相当于CPU的“上帝模式”,能操作所有寄存器;S模式相当于现代操作系统的内核模式;U模式就是普通应用程序跑的受限模式。
开发板上电后,固化在ROM里的代码(BootROM)先执行,它把SPI Flash或者SD卡里的固件加载到内存,然后跳转执行。这一步里OpenSBI承担了M模式固件的角色,它负责初始化时钟、内存控制器、串口这些基础硬件,然后降级到S模式,把控制权交给U-Boot。U-Boot在S模式运行,负责更复杂的初始化(网卡、存储控制器),加载设备树和内核镜像,最终把控制权交给Linux内核,内核跑在S模式,用户进程跑在U模式。
这条链路里最关键的一个设计点在于运行时服务。内核在S模式运行,一旦需要操作M模式才允许访问的资源(比如定时器、IPI中断),就得通过ECALL指令陷入OpenSBI,由OpenSBI代为执行。所以OpenSBI不仅仅是“引导一下就算完事”的固件,它在整个系统运行期间都要常驻内存。这意味着OpenSBI在编译时的配置会直接影响内核能否正常启动。
2.2 U-Boot编译与设备树适配
U-Boot的编译过程本身不复杂,但有些细节直接决定成败。
首先是交叉编译工具链。我用的riscv64-linux-gnu-工具链,版本12.2以上,太老的版本在编译较新的U-Boot时会报隐式函数声明的错误。编译命令如下:
export CROSS_COMPILE=riscv64-linux-gnu- make ARCH=riscv <开发板_defconfig> make ARCH=riscv -j$(nproc)U-Boot的defconfig是按具体开发板命名的,选择对应配置后编译产物里会有u-boot.bin和u-boot.itb。RISC-V平台这里推荐使用FIT image(.itb)格式,因为FIT可以将OpenSBI、U-Boot本身和设备树打包成一个镜像,烧写和管理都更方便。U-Boot的配置里有一项CONFIG_FIT,会自动依赖OpenSBI的二进制文件,第一次编译时就需要提前把opensbi.bin放到指定目录。
设备树(DTB)是整个引导链中承上启下的环节。U-Boot通过设备树了解硬件资源,内核也需要设备树才能匹配驱动。实际工作中最常遇到的问题是设备树里的网卡PHY地址不对,或者SATA控制器节点被遗漏,导致内核启动后找不到设备。排查方法很朴素,用命令对比/proc/device-tree下的节点内容,跟原理图逐一核对:
ls /proc/device-tree/ cat /proc/device-tree/model我在适配过程中就遇到过U-Boot里网卡能识别、但内核启动后连不上网的问题,最后定位到是设备树里PHY的reset GPIO没有正确配置。改一行设备树源码重新编译,问题就解决了。这个经验是常规文档里不会有的,但实际项目里非常常见。
2.3 内核裁剪与启动参数
内核裁剪是嵌入式系统里最体现功夫的一步。裁剪的目的是降低内存占用、加快启动速度,同时不影响功能。我以最小化起步,按需添加驱动,最终内核镜像压缩后不到6MB,启动时间从上电到SSH可用大概9秒。
具体操作是用menuconfig图形界面逐项检查:
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- menuconfig以下几个配置组是必须保证的:
- 核心CPU功能:SMP多核、GENERIC_TIMER、RISCV_SBI
- 存储控制器:SATA_AHCI、AHCI_PLATFORM,以及对应的PCIe/GPIO控制器驱动
- 网络:NET_CORE、ETHERNET千兆网卡驱动(具体驱动取决于SoC集成方案)
- 文件系统:EXT4_FS、VFAT(兼容性考虑)、PROC_FS、SYSFS
- 内核网络服务:IPV4、IPV6(可选,Samba不需要IPV6但我开了备用)、PACKET,方便之后跑tcpdump
内核启动参数方面,我使用了非常精简的配置:
console=ttyS0,115200 root=/dev/sda2 rw noinitrd这里root=/dev/sda2指向根文件系统所在分区。如果系统盘和数据盘使用的都是SATA接口,设备名可能会因为枚举顺序变化而漂移,稳妥的做法是在内核启动参数里用root=PARTUUID=xxxx这种方式替代设备名。我最初没注意这个问题,有一次开机后系统起了但挂载不到根分区,排查半天发现是SATA枚举顺序变了,sda变成sdb了。用PARTUUID后彻底解决。
3. 存储层设计与根文件系统构建
3.1 存储设备规划:系统与数据分离
NAS的本质是存储,存储架构怎么设计,直接决定后续的稳定性和可维护性。
我把存储分成了两层:系统层和数据层。系统层用一张16GB的SD卡,只放boot分区和根文件系统。数据层用一块1TB的机械硬盘,通过SATA接口接入,独立分区存放所有共享数据。这样设计的好处是:系统崩溃、SD卡损坏或者系统需要重刷,数据盘完全不受影响,拔下来插到任何Linux机器上都能读取。
分区规划如下:
SD卡(/dev/mmcblk0): mmcblk0p1 64MB FAT32 /boot 存放U-Boot镜像、设备树、内核 mmcblk0p2 15GB ext4 / 根文件系统 SATA硬盘(/dev/sda): sda1 500MB ext4 (预留RAID元数据) sda2 剩余 ext4 /data 数据主分区数据盘我特意划分了一个500MB的小分区,这个分区不挂载,专门用于存放mdadm的RAID元数据。如果后面要加第二块盘组RAID1,元数据和数据分离可以降低降级恢复的复杂度。这个思路是从服务器存储方案里借鉴过来的,在嵌入式环境虽然有点“杀鸡用牛刀”,但成本几乎为零,收益却很实在。
3.2 文件系统选型与挂载参数
文件系统选型我主要对比了ext4、btrfs和f2fs三个方案。f2fs是为NAND闪存设计的,SD卡上用很合适,但机械硬盘上表现一般;btrfs功能强(快照、校验、压缩),但对CPU和内存的消耗明显高于ext4,在1GB内存的RISC-V平台上有点勉强。最终选择ext4,理由是它在机械硬盘上的顺序读写性能最好,CPU占用最低,而且内核支持最成熟。
挂载参数直接影响运行性能和磁盘寿命,这里给出的配置经过实测:
/dev/sda2 /data ext4 defaults,noatime,nodiratime,data=writeback 0 2三个关键参数的说明:
- noatime/nodiratime:关闭访问时间更新,减少每次读文件的写操作。NAS场景下大量读操作来自媒体播放,关掉atime能显著减少不必要的磁盘写入。
- data=writeback:ext4的写模式之一,不会像ordered模式那样强制日志先落盘,换取更高的写入性能。代价是系统突然断电时可能出现文件数据损坏但文件系统结构完好的情况。考虑到嵌入式NAS的UPS保护场景,这个取舍可以接受。如果对数据安全特别敏感,建议保留默认的ordered模式。
- commit=60:日志提交间隔改成60秒,减少高频小写入,也延长机械硬盘寿命。这个参数尤其适合家庭NAS的备份和媒体存储场景。
SD卡上的根文件系统挂载参数略有不同,我额外加了discard参数,配合闪存介质的TRIM命令,可以减缓SD卡磨损。不过ext4的discard在部分SD卡控制器上会引起卡顿,如果遇到这个问题,可以改成nodiscard并定期手动执行fstrim。
3.3 Buildroot构建根文件系统
根文件系统我直接用Buildroot生成。为什么不手动搭?因为手动构建glibc和几百个软件包的依赖关系是一个无底洞,Buildroot一次性解决编译、依赖、安装、交叉工具链集成的问题,生成的就是一个可直接烧写的SD卡镜像。
构建步骤并不复杂:
make buildroot_defconfig make menuconfigmenuconfig里需要调整的关键选项:
- Target options → Target Architecture:选择RISC-V 64
- Toolchain → C library:选择glibc,不用musl。我实测下来musl编译Samba时会有兼容性坑,某些版本编译能过但运行时报段错误,glibc虽然体积大一些,但行为更接近桌面/服务器环境,调试成本低。
- System configuration → root password:设置初始密码,同时开启root自动登录串口,方便调试。
- Target packages:勾选samba4、nfs-utils、mdadm、rsync、dropbear(SSH)、ttcp或iperf3(性能测试用)、smartmontools(硬盘健康监控)。
构建时间取决于机器性能,四核i5大概需要30到40分钟。产出物在output/images/目录下,其中sdcard.img就是可以直接dd进SD卡的完整系统镜像。
dd if=output/images/sdcard.img of=/dev/mmcblk0 bs=4M status=progressBuildroot生成的系统默认不包含包管理器,这是有意为之:嵌入式系统不需要在线安装软件,所有需要的软件在构建阶段就锁定版本。好处是系统具备可复现性,任何时刻出问题都可以用同一版本重新构建定位,而不是像发行版那样升级软件包后行为漂移。
3.4 数据保护:轻量RAID与监控
NAS上的数据保护是个绕不开的话题。我的方案是mdadm软件RAID1(镜像模式),两个同样的数据盘互为备份。有人会问为什么不用ZFS或者Btrfs RAID,原因还是那个:RISC-V平台的CPU算力有限,ZFS的压缩和校验功能吃内存也吃CPU,1GB内存跑起来会捉襟见肘。RAID1的机制最简单,原理是逐字节镜像,CPU开销几乎可以忽略。
创建RAID的命令如下:
mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda2 /dev/sdb2在文件系统之上再做RAID,而不是把RAID做成整块盘,这样就可以把系统分区和RAID卷放在同一块物理盘上,布局更灵活。实际部署时我顺手测了一下RAID1的写入性能,机械硬盘单盘顺序写大概150MB/s,RAID1后写入反而略有下降,这是镜像写机制的固有问题,但换来的是任意一块盘损坏,数据都不丢失。
RAID不是备份,它解决的是硬件故障场景,解决不了误删除或者勒索病毒。所以我还部署了smartd做硬盘健康监控,并配置了一个每日运行的rsync任务,把关键目录增量备份到另外一台机器上。
smartctl --scan systemctl enable smartd这些措施叠加起来,整套系统对所有常见的数据丢失场景都有对应的处理方案。
4. 现代网络栈与NAS服务实现
4.1 内核网络栈与网卡驱动确认
NAS的核心服务是网络文件共享,网络栈的性能决定了整个NAS的体验。启动内核后第一步就是确认网卡驱动正常工作,并且链路的协商速率是千兆全双工。
ethtool eth0 ip link set eth0 up ip addr add 192.168.1.100/24 dev eth0ethtool输出里Speed: 1000Mb/s和Duplex: Full是我希望看到的内容。如果协商速率掉到100Mb/s,多数情况是网线问题或者对端交换机端口协商异常,可以先换网线排除。
现代网络栈的性能关键点在内核的NAPI机制和中断处理。之前的网络驱动接收数据包时采用纯中断模式,高吞吐场景下CPU被中断风暴打满,性能上不去。现在主流驱动都实现NAPI(New API),在中断触发后切换到轮询模式批量收包,大幅减少中断次数。我在内核配置里确认了NET_NAPI和相关驱动的NAPI支持都编译进去了。
在嵌入式平台,DMA内存也需要关注。有些网卡驱动依赖内核预留的DMA缓冲区,如果CMA(Contiguous Memory Allocator)配置得太小,高吞吐时会出现收包丢包。我遇到的典型现象是iperf3测速初段正常,几秒后吞吐骤降,统计接收丢包率飙升。后来在内核命令行里额外保留了SMP内存区域并增大了CMA容量,问题才彻底解决。
coherent_pool=2M cma=64M这个配置对于1GB内存的设备完全够用,不影响系统可用内存。
4.2 Samba服务搭建与调优
在局域网共享场景里,SMB协议是兼容性最好的方案,Windows资源管理器直连、macOS访达直连、手机上的文件管理器也大多支持SMB。Samba的搭建在Buildroot阶段已经完成,主要工作是编辑/etc/samba/smb.conf配置文件。
这是我最终使用的核心配置:
[global] workgroup = WORKGROUP server min protocol = SMB3 server max protocol = SMB3 encrypt passwords = yes socket options = TCP_NODELAY read raw = yes write raw = yes aio read size = 1 aio write size = 1 use sendfile = yes strict allocate = no [media] path = /data/media browseable = yes read only = no valid users = nas create mask = 0664 directory mask = 0775几个关键参数的取舍说明:
- protocol设为SMB3:旧版协议(SMB1/CIFS)有很多已知安全漏洞,SMB3提供加密和更好的性能。代价是Windows XP这类老系统无法访问,现在应该没有人在意这个了。
- socket options = TCP_NODELAY:禁用Nagle算法,减少小包交互延迟。这个参数在局域网点播视频时感知非常明显,拖动进度条后响应更快。
- aio read/write size设为1:开启异步IO,Samba对磁盘的读写不会阻塞网络响应,多客户端并发访问时体验更好。在单核或双核CPU上这个参数尤其重要。
- use sendfile = yes:让内核直接负责数据搬运,减少用户态和内核态之间的拷贝,读吞吐量能提升10%到15%。
- strict allocate = no:写入大文件时不预分配磁盘空间,省掉一次FSYNC,写入性能更好,但碎片率略高。对媒体文件这种大文件顺序写场景,弊端可以忽略。
Samba用户和系统用户的关联也需要单独处理。我用smbpasswd -a nas命令为nas用户设置了独立的SMB密码,这个密码可以跟系统登录密码不同,日常共享访问时不会暴露SSH登录凭据。
4.3 NFS与Rsync:按需选择
局域网内如果是纯Linux设备互访,NFSv4比SMB效率更高,延迟更低,协议开销更小。我的做法是Samba做主力共享,NFS只对局域网内的Linux开发机开放特定目录。
NFS配置极其简单,编辑/etc/exports增加一行:
/data/nfs_share 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)注意我加了sync而不是async。NFS默认行为是写操作先落内存缓存,async模式虽然性能好,但掉电时数据可能不一致。在嵌入式环境,多花一点性能换一致性更稳妥。
rsync则是解决备份问题的,我写了一个简单的cron任务:
0 3 * * * rsync -avz --delete /data/ nas-backup:/backup/每天凌晨3点增量备份到另一台机器,--delete保证备份目录跟源目录严格同步,不会残留已删除的旧文件。这套方案跑了一个多月,数据一致性和可靠性都符合预期。
4.4 网络与存储整体性能实测
所有服务搭建完成后,我做了一轮完整性能测试,顺便检验整个系统的瓶颈在哪里。
网络层用iperf3测TCP吞吐:
iperf3 -c 192.168.1.100 -t 60结果稳定在939Mbps,基本跑满千兆网卡的线速。CPU占用大约40%到50%,对双核处理器来说已经是很好的成绩。这里能看到RISC-V核心的计算能力在千兆网络处理上没有任何问题。
文件传输层面,通过SMB拷贝一个大文件:
dd if=/dev/zero of=/data/testfile bs=1M count=4096 # 先在目标盘生成4GB测试文件Windows端拷贝这个4GB文件,实测写入速度105MB/s,读速度112MB/s。考虑到底层是RAID1镜像写,加上SMB协议开销,这个数据在机械硬盘方案的NAS里算是正常偏上的水平。
CPU和内存占用方面:
top -b -n 1传输过程中Samba进程CPU占用约30%,内存常驻约180MB,系统总内存占用稳定在280MB以下。整机功耗用功率计实测,空闲5W,传输峰值11W,挂机一个月电费不到3块钱。
5. 常见问题与性能优化实录
5.1 引导启动阶段的问题
这套系统前后折腾了三个周末,引导启动阶段踩的坑最多,也最有代表性。
第一个问题是SD卡启动后串口完全没有输出。一开始怀疑是镜像烧坏了,重新dd了一遍还是白屏。排查了很久,最后发现是U-Boot源码编译时,默认的串口配置和开发板实际使用的串口号不一致。RISC-V开发板的调试串口在设备树里通过stdout-path属性指定,U-Boot也读取这个属性,但如果U-Boot内置的CONFIG_CONS_INDEX没有对应修改,就会出现串口无输出的现象。解决方法很简单,在defconfig里显式指定正确的串口index,重新编译U-Boot。
第二个问题很经典:内核启动到一半panic,报Kernel panic - not syncing: VFS: Unable to mount root fs。这是根文件系统没挂载上。我刚踩完设备名漂移的坑,又踩了第二个坑:设备树里SATA控制器的reg地址在U-Boot阶段能识别,但内核阶段PHY初始化超时,导致硬盘没有正常上线。用rootwait这个内核参数可以解决启动时设备未就绪的问题,让它等设备出现再挂载,治标。治本是核对设备树里PHY的供电和复位时序配置,我最终选择了治本。
5.2 存储性能问题的定位
Samba写入速度一开始只有40MB/s,远低于预期,机械硬盘再怎么慢也不至于这个水平。排查过程是这样的:先用dd测试裸盘写入速度,排除文件系统问题。
dd if=/dev/zero of=/data/test bs=1M count=2048 conv=fdatasync裸盘写入有130MB/s,说明问题不在存储层,在Samba协议栈。看CPU占用发现Samba进程在传输时单核心几乎打满,推断是加解密或者数据拷贝的开销过大。检查发现smb.conf里没有开启use sendfile,而且SMB3加密默认开启。嵌入式CPU做加密计算的性能有限,我最终在安全性要求不高的家庭局域网环境关闭了强制加密,同时打开sendfile,速度直接翻倍到接近110MB/s。
注意:关闭SMB加密需要自己评估风险。我这个NAS只允许在家庭路由器的内网网段访问,并且通过防火墙限制外网访问才能这样设置。
5.3 网络吞吐上不去的瓶颈
iperf3测速只有300Mbps的时候,问题的根源不在应用层而在DMA内存不足,这个前面提到过。另一个容易被忽略的点是中断和CPU亲和性。默认情况下所有中断都落在CPU0上,高吞吐时CPU0被打满,CPU1空闲。解决方法是把网卡中断手动绑定到多个CPU核心上:
echo 2 > /proc/irq/$(grep eth0 /proc/interrupts | awk '{print $1}' | tr -d ':')/smp_affinityecho 2表示第二个CPU核心(CPU1),如果有四核就依次设置4和8。这个操作在RISC-V平台的嵌入式环境同样适用,实测几百Mbps级吞吐时效果明显,千兆线速下收益不大,因为单核已经接近处理极限了。
网络调优还有一个常被忽略的细节:TCP接收窗口。嵌入式系统默认的rmem_max可能只有几十KB,这在高延迟链路上会严重限制吞吐。局域网延迟足够低,影响不大,但如果是跨网段访问内网NAS,就需要调大:
sysctl -w net.core.rmem_max=41943045.4 稳定运行与日常维护
系统搭建完成只是第一步,长时间稳定运行才是NAS的核心价值。我整理了实际的维护经验和监控方法。
散热方面,RISC-V开发板本身发热不大,但3.5寸机械硬盘长时间运行温度会到45℃以上。我给硬盘加了一个USB供电的小风扇,温度稳定在38℃,机械硬盘在35℃到40℃之间寿命最长。SD卡一定要选工业级的,我之前用消费级SD卡连续写入跑了一周后文件系统损坏,换工业级和高耐久卡后稳定运行至今。
日常监控我用了一个很朴素的组合:crontab每5分钟记录一次CPU温度和负载,配合smartctl检查硬盘健康状态。
*/5 * * * * echo "$(date) $(cat /sys/class/thermal/thermal_zone0/temp)" >> /var/log/temp.logSSH密钥登录是必须配置的,密码登录在公网可达的环境里迟早被爆破。我在/etc/dropbear/authorized_keys里放了客户端公钥,关闭密码登录,同时在防火墙层面只允许内网IP访问SSH和SMB端口。
日志方面,Samba的日志级别默认是0,日常运行很安静。排查问题时可以先提升到2,再复现一次问题,注意排查完要改回来,否则日志会把SD卡空间吃光。
最后分享一点个人感想。这个项目做完之后,我对嵌入式系统“从零到一”的理解比看十本书都有用。很多东西不亲手走一遍,你永远不会知道U-Boot的FIT image里封装的OpenSBI和普通bin文件有什么区别,也不会理解为什么设备树里一个GPIO属性就能让整块网卡不工作。RISC-V平台的资料比x86少,但正是因为它少,逼着你去看源码、看文档、追根究底,反而把整个链路学了个通透。现在这块板子安安静静躺在电视柜里,每天凌晨做备份,平时给全家提供视频和照片共享,7瓦的功耗换来一整年的安心。后续我打算给它加一块SSD做缓存层,如果大家感兴趣,我到时候再写一篇缓存方案的详细记录。