如何使用和开发 VSRV
支持的芯片: VSRVES01
1 介绍
本文档旨在作为 VSRVES01 原型芯片功能的教程和参考,包含不属于数据手册的详细信息。
VSRV1 是由 VLSI Solution 设计的 RV32IMSU zicsr zifencei RISC-V 核心实现。它是一个 32 位核心,拥有内存管理单元,并且能够运行标准的 Linux。
VSRVES01 芯片不仅包括 RISC-V 通用处理器,还包括 VLSI Solution 自有的 VSDSP6 数字信号处理器,并运行 VLSI Solution 的实时操作系统 VSOS。
有多种方式可以理解这款芯片。一种是将它视为嵌入式 Linux 设备,另一种是将其视为音频数字信号处理器(DSP)。然而,由于处理器之间在优势和劣势上的差异,最佳的解决方案是充分发挥整合系统的优势。
2 免责声明
VLSI Solution 尽一切可能确保本文档的准确性。然而,对于本文档的正确性,VLSI Solution 不提供任何担保或保证。
3 定义
ADC:模数转换器(Analog to Digital Converter)。
B:字节,8 位。
b:比特。
DAC:数模转换器(Digital to Analog Converter)。
DSP:数字信号处理器(Digital Signal Processor)。
I-mem:32 位 VSDSP 指令内存(Instruction Memory)。
ISA:指令集架构(Instruction Set Architecture)。
RAM:随机存取存储器(Random Access Memory)。
RISC:简化指令集计算机(Reduced Instruction Set Computer)。
RISC-V:基于已建立的简化指令集计算机(RISC)原则的开放标准指令集架构(ISA)。
PCB:印刷电路板(Printed Circuit Board)。
ROM:只读存储器(Read Only Memory)。
TBD:待定义(To Be Defined,未来定义)。
VSIDE:VLSI Solution 集成开发环境(Integrated Development Environment)。
VSOS:VLSI Solution 实时操作系统(Real-Time Operating System)。
X-mem:32/16 位 VSDSP X 数据内存(X-Data Memory)。
Y-mem:32/16 位 VSDSP Y 数据内存(Y-Data Memory)。
4 VSRV 架构概述
图 1:VSRVES01 方框图
VSRVES01 的方框图如图 1 所示。该图中,外设按照其所属的电源域进行着色。
4.1 时钟管理
VSRVES01 配备了一个晶体振荡器,用于连接 12.288 MHz 的晶体。这为音频和系统应用提供了低抖动和高质量的时钟。出于性能考虑,VSRVES01 配备了独立的相位锁定环(PLL),为 VSRV1 和 VSDSP 提供更高的时钟速度。VSRVES01 芯片支持 98 MHz 及以上的时钟频率。
4.2 VSDSP6 核心
VSDSP6 是一款 16/40/72 位的数字信号处理器。该处理器连接到 RAM 和 ROM 的 32 位指令内存(I-mem),RAM 的 X 和 Y 数据内存(X-mem 和 Y-mem),以及多个外设。一小部分 Y 数据内存空间被外设占用。
在最大位深度下, VSDSP6 每个时钟周期可以执行以下操作:
- 进行 32x32 位到 64 位的乘法运算,并将结果加到 72 位的和中,或者执行其他高达 72 位的算术或逻辑运算,包括桶移位器。
- 更新两个线性、环形缓冲区或位反转指针。
- 执行两个 32 位数据内存操作(读和/或写),一个针对 X 数据内存,一个针对 Y 数据内存。
- 循环计数器递减,并硬件检查循环是否结束。
具备这些特性使得 VSDSP6 在其 MHz 数字指标之外,拥有强大的信号处理能力。
极低的中断响应延迟(通常即使在负载较大的系统中,也显着低于 10 微秒)使得它能够实现实时系统,在音频输入到输出之间的延迟可以低至 5 毫秒以内。
4.3 VSRV1 核心
VSRV1 核心是由 VLSI Solution 实现的 RISC-V 核心。该核心的具体类型是 RV32IMSU zicsr zifencei。
VSRV1 配备了内存管理单元(MMU)以及指令和数据缓存,这使得运行 Linux 成为可能。
4.4 VSDSP6 外设
VSDSP6 的外设如下所示。请参阅数据手册以获取详细信息。
- RCAP
用于模拟部分的参考电压生成器。相关的引脚需要接一个电容到地,以确保芯片的模拟部分具有良好的参考电压。
- ADC
音频立体声模数转换器(Analog to Digital Converter)。该 ADC 可以处理正常的线路电平信号。
- DAC
DAC 将数字立体声音频样本转换为模拟线路电平立体声音频信号。DAC 需要一个输出放大器。
DAC 的采样率可以以约 0.01 Hz 的步长进行调整,这个步长几乎是无法察觉的。采样率也可以在运行时调整,而不会产生任何可闻的故障。这样可以在例如收听网络广播时,微调采样率,因为接收器无法控制传输速率,时钟偏差如果没有及时调整,可能会导致音频丢失或过载,从而引起卡顿。
- GPIO
所有数字引脚都可以以 GPIO 模式访问。引脚以矩阵形式排列,可以重新路由到任何外设功能。
- UART0
UART0 是运行在 VSDSP 上的 VSOS 的主要用户接口。它在速度和字长方面具有很高的灵活性。
- SPI
SPI 用于连接 SPI Flash,并可能连接到其他设备。在启动时,VSOS 从 SPI Flash 加载。SPI 总线能够进行非常高速度的数据传输,传输速度可达到数十兆位每秒。
- SD 卡
SD 卡是 VSDSP 的另一种大容量数据源。当前(2025-05-28)版本的 VSOS 期望从 SD 卡中找到系统磁盘文件。未来版本中,SD 卡将成为可选项,另一个系统磁盘文件选项将是 SPI Flash。
- UARTMUX
UARTMUX 连接到 VSRV1 启动 UART。
- UARTRV
UARTRV 连接到 VSRV1 的 16550 UART0。它充当 VSRV1 和 VSDSP 之间的内部通信链接。
- LPDDR2 存取
VSDSP 对 LPDDR2 的访问用于加载启动程序和将 Linux 加载到芯片的 RISC-V 端。如果 RISC-V 端未使用,LPDDR2 也可以作为 VSDSP 的存储空间。
- 以太网音频捕获接口
以太网音频捕获接口旨在将音频数据包转发到 VSDSP,在那里音频数据包可以被接收并从 DAC 播放,或进行其他处理。
4.5 VSRV1 外设
VSRV1 的外设如下所示:
- 以太网
支持10/100Mbit/s.
- GPIO
可以通过矩阵选择性地路由到输出引脚。
- SPI
可以通过矩阵选择性地路由到输出引脚。
- 16550 compatible UART 0
16550 兼容 UART 0 连接到 VSDSP 的 UARTRV。它充当 VSRV1 和 VSDSP 之间的内部通信链接。
兼容 UART 1 和 2
可以通过矩阵选择性地路由到输出引脚。
- 启动 UART
连接到引脚 RV_TX 和 RV_RX,或者连接到 VSDSP6 的 UARTMUX。其速度始终为 RVCLKI/12,其中 RVCLKI 是 RISC-V 的内部时钟。
- LPDDR2 接口
LPDDR2连接到 VSRV1 的指令缓存和数据缓存,使其成为单元的主要 RAM 内存。没有 LPDDR2,RISC-V 无法运行。
5 VSRV CAT 板
5.1 CAT 板介绍
那么,你已经收到了 VSRV CAT 板,并且正在尝试弄清楚该如何使用它?
CAT 这个名字是 Completely Absurd Thing 的缩写。或者,也有可能是有人在 PCB 丝印层上画了一只猫。
5.2 CAT 板特点
图 2: CAT 板方框图
CAT 板是一块电路板,可用于运行 RISC-V Linux 和 VSDSP VSOS 程序。VSRVES01 最有可能被使用的特性已经在此板上得以实现。
图 2 显示了 CAT 板上一些特性的位置。
提供的一些特性包括:
- CAT 板
- 用于数据和固件的 SD 卡连接器
- 为 VSDSP VSOS 焊接在板上的 SPI Flash
- RISC-V 和 VSDSP 的 UART 引脚排针
- 以太网连接器
- 3.5 毫米插孔,用于线路输入和耳机输出
- 2 个用户按钮
- 重置按钮
LPDDR2 内存芯片位于板的底面。
5.3 UART 通信速度
|
CAT 板 UART 连接器 |
||
|
UART |
Speed [bps] |
Features |
|
(RISC-V) 启动 UART |
RVCLKI / 12 |
8 位,无奇偶校验,无流量控制 |
|
(VSDSP) UART 0 |
115200 |
8 位,无奇偶校验,无流量控制 |
|
Signal level 3.3V, Pins: Ground, Tx, Rx, 5V |
||
表 1:CAT 板连接器的默认 UART 参数
RISC-V 启动 UART 连接到 RISC-V 的 RX 和 TX 引脚,如图 1 所示。它始终以 RISC-V 时钟频率除以 12 的速度运行。简单的情况是,当一切都使用 XTALI(12.288 MHz)时,UART 速度大约为 1 Mbps。然而,当时钟速度达到约 100 MHz 时,速度会接近 10 Mbps,信号可能会变得在电气上无法使用。
幸运的是,还有其他方式可以连接到 RISC-V 端。VSOS 有一个名为 “Term” 的程序,它通过图 1 中的红色线提供对 RISC-V 启动 UART 的访问。
另一种选择是在计算机上设置 DHCP 服务器,并通过以太网使用 PC 的 telnet 进行连接(参见第 7.3 章,向 CAT 板提供 DHCP 服务)。
5.4 防止 VSDSP 从 SPI 启动
有时,例如在将新的操作系统刷入 SPI Flash 时,可能希望防止 SPI 启动发生。可以通过短接 JP1 "No SPI boot" 跳线,并使用重置按钮重置芯片来实现这一点。
通常,当你重置板子时,你将在 VSDSP UART 终端上看到类似于 “<C1305Sc2:20:18=10M:24B” 的启动字符串,后面会跟随其他启动消息。如果你短接了 "No SPI boot" 跳线,启动信息将缩短为 “<C1305->”,并且后面不会再有其他信息。
6 运行系统
请参阅第 7 章《在 CAT 板上运行示例程序》以获取使用教程。
6.1 准备 microSD 卡
你需要一张已经格式化为 FAT32 的 microSD 卡。ExFAT 不被支持。
如果你使用的是 Microsoft Windows,microSD 卡的最大容量应为 32 GiB。如果卡的容量更大,Windows 将无法将其格式化为 FAT32。
如果使用 Windows,你可以使用更大容量的卡,只要它们被格式化为 FAT32。到目前为止(2025-05-30),已测试的最大卡容量为 1 GiB。
接下来,将系统根文件复制到此 microSD 卡。确保保持目录结构不变。系统根文件可以在 VSDSP 论坛下载,链接为:
http://www.vsdsp-forum.com/phpbb/viewtopic.php?t=3242
6.2 进入 VSOS Shell
有两份文档描述了如何以最大效率使用 VSOS Shell,它们分别是:
- VSRV VSOS Shell - 解释了 shell 的工作原理,并列出了其程序和驱动程序。
- VSRV VSOS Audio - 解释了 VSRV VSOS 的音频子系统是如何工作的。
6.3 启动 Linux 并访问它
待定义(TBD)
7 在CAT板上运行示例程序
本教程将通过不同的工具和驱动程序演示来指导你。这些演示应该按顺序进行,因为后续的演示是基于前一个演示的结果构建的。
图 3:Cat 板 VLC 音频流演示中软件与硬件之间的信息流
图 3 显示了在运行第 7.8 章《从线路输入到耳机输出流音频》的最终演示时,从运行 VLC 的 PC 到 CAT 板耳机输出的数据和音频路径。在图中,运行在 PC 上的 VLC 创建一个音频流,通过 VSRVES01 的以太网硬件传输到 VSDSP6/VSOS 端,然后通过 VSOS 驱动程序 AUIETH、AUXPLAYB 和 AUODAC 输出到耳机。
以下指令是在运行 Kubuntu 24.04.2 LTS 的笔记本电脑上执行的,或是运行 Linux 版本 retardis 6.8.0-48-generic #48-Ubuntu SMP PREEMPT_DYNAMIC Fri Sep 27 14:04:52 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux 的系统。
在准备阶段,首先参阅第 5 章《VSRV CAT 板》。.
阅读完该章节后,启动一个终端仿真器,如 microcom,并设置波特率为 115200 bps,8N1:
microcom -p /dev/ttyUSB0 -s 115200
例如,安装 microcom:
sudo apt-get install microcom
如果你收到以下消息:
Exitcode 2 - cannot open device /dev/ttyUSB0
这通常意味着你没有被加入到允许访问串口的用户组。这个用户组通常叫做 dialout。可以通过运行以下命令来验证:
groups
现在,你可以选择以 root 用户身份使用 sudo 运行 microcom,或者更推荐的做法是将自己添加到所需的 dialout 用户组(或你所在的 Linux/Unix 系统中,能给你访问权限的用户组)。运行以下命令:
sudo adduser myusername dialout
将 myusername 替换为你的用户名。然后,注销并重新登录整个窗口系统(或重启),使更改生效。
7.1 启动 CAT 板
启动 CAT 板或按下重置按钮。你应该会迅速看到以下文本:
<C1305Sc2:20:18=10M:24B
<[
Hello.
R’VSOS 3.68 build May 12 2025 10:24:18’
R’VLSI Solution Oy 2012-2025 - www.vlsi.fi’
R’Starting Kernel...’
R’Starting Devices...’
E’SD Ident / Card stuck’
System devices:
- S: 240M SD/SD Card, handled by FAT.
Run S:STARTUP.TXT, config = 0
-- 8: BadBit
-- 9: Driver +BADBIT
-- 10: BadBit
-- 11: Driver -BADBIT
-- 13: SetClock -l130 98
UART0 115.11 kHz target: 115200 bps, error 0.1%
SPI0 12.29 MHz
SD 49.15 MHz 24.58 MB/s
TIMER0 1000.00 Hz
COREPLL 98.30 MHz
RISCVPLL 98.30 MHz
-- 14: Driver +CATSEYES +l +r
-- 16: Driver +uartin
-- 17: CATSEyes -l +r
-- 19: PReg UARTRV_DIV=0xff14
Y:0xfccb=0xff14 UARTRV_DIV
15:8 ff UART_DIV_D1
7:0 14 UART_DIV_D2
-- 20: PReg UARTMUX_DIV=0xff14
Y:0xfcd3=0xff14 UARTMUX_DIV
15:8 ff UART_DIV_D1
7:0 14 UART_DIV_D2
-- 22: CATsEyes +l +r
-- 25: Driver +rvparam
-- 27: RvParam -mba:67:11:fd:5f:fa
-- 29: ddrload -brvlbne.bin -B -bcatboard.dtb linux61.vri
Disable Risc-V
DDR parameters:
Manufact.: 0x8 (Winbond)
I/O width: 0x1 -> 16 bits
Density: 0x4 -> 128 MiB
Type: 0x0 -> S4 SDRAM
Banks: 8
Load binary file rvlbne.bin @ 0x80000000, 28160 bytes
DDR size 128 MiB
Load binary file _ddrBlob @ 0x80006e00, 56 bytes
Load binary file catboard.dtb @ 0x80006e38, 2465 bytes
Load VSRV image linux61.vri
linux61.vri, 10053940 bytes
Sect 0: addr 80400000, size 168, flags 7 (RWE)
Sect 1: addr 80400168, size e98, flags f (RWEB)
[... many similar lines omitted ...]
Sect 64: addr 81c7dd20, size d228, flags 7 (RWE)
0x65 sections, 10053940 bytes in file, 25734984 bytes transferred to DDR
Hand over SD RAM to Risc-V
Enable Risc-V
Execution took 1.065 seconds
-- 30: CATsEyes +l -r
-- 32: Driver +AUIEth s
2a00798e 2a00798e
IB: 0x2000
InitEnd
-- 34: Driver +AUODac s
-- 36: AuOutput -l-12
-- 37: CATsEyes +l +r
-- 39: Driver +AUXPlayB q
-- 44: CATsEyes
-- 45: Driver -CATSEYES
-- 49: Echo Welcome to the shell! Type \"more README.TXT\" on the command line.
Welcome to the shell! Type "more README.TXT" on the command line.
-- 50: !Shell
VSOS SHELL
S:>
你现在已经进入了 VSOS Shell 命令行。
7.2 CAT 板 VSOS 命令行
你可以通过以下命令来熟悉命令行操作,例如:
S:>dir
S:>dir -h
S:>dir sysr
S:>type startup.txt
S:>more startup.txt
S:>type readme.txt
要进入 Linux 端,输入以下命令:
S:>term -a
如果你额外按下回车键,你将看到以下内容:
rv32 login:
那是 Linux 的登录提示符。尝试使用用户名 root 和密码 vsrv 登录。用户名 vsrv 和密码 vsrv 也可以使用。然而,请注意,一些操作需要你以 root 用户身份执行,因此在进行这些初始测试时,请使用 root 用户。
要从 RISC-V/Linux 终端返回到 VSDSP/VSOS,按下 F4 键。确保你的终端控制台以 VT2xx 兼容的方式处理 F4,否则退出将无法正常工作。
7.2.1 闪闪猫的眼睛
要查看你可以如何操作猫的眼睛,运行以下命令:
S:>catseyes -h
然后你可以尝试以下命令:
S:>catseyes -l -r
S:>catseyes +l +r
S:>catseyes /l /r /l /r /r /l /r /l
7.3 为 CAT 板提供 DHCP 服务
CAT 板需要一个 DHCP 服务器才能通过局域网流式传输音频或提供 Web 服务。你需要提供一台笔记本电脑或平板电脑来实现这一点。
要设置 DHCP 服务器,你可以使用例如 dnsmasq(我们将只使用其 DHCP 功能,而不使用 DNS 功能)。在你的电脑上安装它,使用以下命令:
sudo apt-get install dnsmasq
目前的 Linux 系统似乎会自动将 dnsmasq 作为守护进程运行,我们将通过以下命令来阻止这一行为:
% sudo systemctl stop dnsmasq
% sudo systemctl disable dnsmasq
(可能需要重启后这些命令才会生效。)
现在,使用以下命令检查你的以太网设备名称:
% ip a
设备名称通常以字母 “e” 开头,例如 eno0 或 enp1s0。在这个示例中,我们将使用 enp1s0,但你可以根据自己的实际情况进行修改。
现在,作为 root 用户,编辑你电脑上的 /etc/dnsmasq.conf 文件。修改以下几行:
# 禁用解析器部分,演示中不需要该功能。port=0
no-resolv no-poll
# 调整下面的行,以反映你的主机上将提供 DHCP 服务的以太网接口
interface=enp1s0
bind-interfaces no-hosts
dhcp-range=192.168.2.120,192.168.2.140,255.255.255.0,5m
# 不要发送任何默认路由。
dhcp-option=3
现在,根据之前的配置文件,将一个地址添加到本地计算机的接口,这个地址来自同一网络,并且已经在 dhcp-range 中分配:
sudo ip a a 192.168.2.42/24 dev enp1s0
注意:/24部分等同于子网掩码 255.255.255.0,只是使用了“ip”命令中的不同语法。
现在,你已经准备好在计算机上启用 DHCP 了。
% sudo dnsmasq -d
dnsmasq: started, version 2.90 DNS disabled
dnsmasq: compile time options: IPv6 GNU-getopt DBus no-UBus i18n IDN2 DHCP DHCP v6 no-Lua TFTP conntrack ipset nftset auth cryptohash DNSSEC loop-detect inotif y dumpfile
dnsmasq-dhcp: DHCP, IP range 192.168.2.120 -- 192.168.2.140, lease time 12h
dnsmasq-dhcp: DHCP, sockets bound exclusively to interface enp1s0
dnsmasq-dhcp: DHCPDISCOVER(enp1s0) ba:67:11:fd:5f:fa
dnsmasq-dhcp: DHCPOFFER(enp1s0) 192.168.2.139 ba:67:11:fd:5f:fa
dnsmasq-dhcp: DHCPREQUEST(enp1s0) 192.168.2.139 ba:67:11:fd:5f:fa
dnsmasq-dhcp: DHCPACK(enp1s0) 192.168.2.139 ba:67:11:fd:5f:fa
在这种情况下,CAT 板已经分配了地址 192.168.2.139。请在进行接下来章节的练习时使用您现在拥有的地址。
7.4 通过 Telnet 连接到 CAT 板:
现在 DHCP 已经运行,你可以通过以下命令测试连接:
# telnet 192.168.2.139
Trying 192.168.2.139...
Connected to 192.168.2.139
Escape character is ’^]’.
rv-139 login:
以用户 vsrv 登录,密码为 vsrv。然后可以使用 su - 切换到 root 用户。
恭喜!你现在能够通过 Telnet 登录到 CAT 板了!
7.5 CAT 板 Web 服务器
Figure 4: Cat Board web server
现在你已经有了一个有效的以太网连接,打开你最喜欢的网页浏览器,然后输入地址:
(注意,地址应该是 http,而不是 https.)
你应该能看到一份 2025 年 5 月初 VLSI 解决方案的网页外观副本,如图 4 所示。
7.6 运行 VLC
在获取以太网连接后,安装 VLC 媒体播放器到你的计算机:
sudo apt-get install vlc
然后,运行:
% vlc -v my_music/* --sout ’\#transcode{vcodec=none,acodec=s16l,channels=2,sampl erate=44100,scodec=none}:rtp{dst=192.168.2.139,port=5004}’.
注意:将之前的命令写成一行,并且小心输入错误!
现在,如果你已将耳机输出连接到耳机,你应该能够听到你最喜欢的音乐目录。
7.7 配置 VLC
VLC 默认设置有两个问题需要修正,以获得最佳体验。
7.7.1 修复 VLC 流媒体播放突发问题
在你开始播放时,就可以看到 VLC 的一个问题:每首歌的前一两秒会被切掉。这是因为 VLC 在开始正常流媒体播放之前,会先流式传输大量的数据。你可以通过复制 ratecount.dr3 程序(可以从 VSDSP 论坛的 RISC-V 部分下载)并按如下方式运行,来看到这个问题:
S:>ratecount -i
Push ’c’ to clear sample rate counter, Ctrl-C to quit.
Nominal rate 0.000 Hz, burst 0, 1 sec 0 Hz, 0.990s 0.000 Hz
Nominal rate 0.000 Hz, burst 0, 1 sec 0 Hz, 1.990s 0.000 Hz
Nominal rate 0.000 Hz, burst 0, 1 sec 0 Hz, 2.990s 0.000 Hz
Nominal rate 0.000 Hz, burst 0, 1 sec 0 Hz, 3.990s 0.000 Hz
Nominal rate 0.000 Hz, burst 33895, 1 sec 33895 Hz, 4.990s 6792.585 Hz
Nominal rate 0.000 Hz, burst 76839, 1 sec 45307 Hz, 5.990s 13222.371 Hz
Nominal rate 0.000 Hz, burst 53317, 1 sec 48444 Hz, 6.990s 18261.230 Hz
Nominal rate 0.000 Hz, burst 52551, 1 sec 50250 Hz, 7.990s 22264.831 Hz
Nominal rate 0.000 Hz, burst 51854, 1 sec 51854 Hz, 8.990s 25556.174 Hz
在 5.990 秒时,你可以看到一个 76839 个立体声样本的突发,这对于我们的音频缓冲区来说太大了,无法处理。
为了解决这个问题,打开 VLC 菜单 工具 -> 首选项 -> 界面。菜单如下图 5 所示。
在左下角,将 “显示设置” 从 “简单” 改为 “所有”,这样你就会看到如图 6 所示的菜单结构。
接下来,修改 “输入 / 编解码器” -> “文件缓存(毫秒)” 的值,从 1000 改为 100。然后关闭 VLC 并重新启动,使更改生效。
现在,每首歌开始时的音频卡顿问题应该已经消失,且在开始播放新歌曲时的峰值突发率应该会明显降低,如下所示:
S:>ratecount -i
Nominal rate 0.000 Hz, burst 0, 1 sec 0 Hz, 1323.990s 4894.669 Hz
Nominal rate 0.000 Hz, burst 0, 1 sec 0 Hz, 1324.990s 4890.975 Hz
图 5:VLC 界面设置,显示设置 = 简单
图 6:VLC 界面设置,显示设置 = 所有
Nominal rate 0.000 Hz, burst 40096, 1 sec 40096 Hz, 1325.990s 4917.525 Hz
Nominal rate 0.000 Hz, burst 57638, 1 sec 45108 Hz, 1326.990s 4947.812 Hz
Nominal rate 0.000 Hz, burst 50120, 1 sec 50120 Hz, 1327.990s 4981.827 Hz
在这个例子中,歌曲开始时的突发已经减少了 20000 个样本,使其变得可控,适合我们的音频路径。
7.7.2 VLC 重采样
在我们的例子中,我们将采样率设置为固定的 48 kHz。然而,并非所有音频都是这个采样率,在这种情况下,VLC 需要进行采样率转换,例如从 44.1 kHz 转换到 48 kHz。
不幸的是,所使用的协议不允许我们使用 VSRV 的优秀采样率转换器,而 VLC 的默认采样率转换器效果不好,导致很多混叠失真,这可以听到音频中的尖锐声和不需要的元素。幸运的是,VLC 提供了几种采样率转换器选项,其中一些实际上表现不错。
要更改 VLC 中的活动采样率转换器,选择菜单 工具 -> 首选项 -> 界面,然后启用扩展设置菜单,如图 5 和图 6 所示。
默认的转换器是 libsamplerate,但它工作不正常,导致混叠失真。因此,我们需要将其去除。
选择 音频 -> “音频重采样器”。在这里,将 “音频重采样器” 设置为 soxr。然后选择 音频 -> “音频重采样器” -> “SoX 重采样器”。在这里,将 “重采样质量” 设置为 “非常高质量”。
如果 soxr 不可用,你可以尝试使用 Speex 重采样器,方法是选择 音频 -> “音频重采样器”,并将 “音频重采样器” 设置为 “Speex 重采样器”。
现在关闭 VLC 并重新启动,以使更改生效。
7.8 从线路输入流式传输音频到耳机输出
要从线路输入流式传输音频到耳机输出,你需要在 VSOS 终端命令行中输入以下指令。不要输入 # 后面的部分,那些是注释,说明了指令的作用。
S:>driver -aux # Remove auxplay driver from memory
S:>driver -aui # Remove any audio input driver from memory
S:>driver +auiadc s # Add analog audio input driver, ’s’ = connect to stdaudioin
S:>driver +auxplay # Add stdaudioin to stdaudioout player driver S:>frags # See all the drivers in memory and memory map S:>auinput # See what’s connected to stdaudioin S:>auoutput # See what’s connected to stdaudioout S:>auoutput -l-20 # Change output volume to -20 dB of maximum
S:>auoutput -h # See all the other exciting options of auoutput
7.9 通过 VSDSP 启动 Linux
在当前系统(2025-05-27)上,可以使用以下指令重新启动 Linux:
S:>ddrload -brvlbne.bin -B -bcatboard.dtb linux61.vri
如果你在这之后快速输入:term -a,你将能够看到 Linux 启动消息。或者,如果你希望始终在 VSDSP 终端上看到 Linux 启动消息,你可以在 microSD 卡的 startup.txt 文件中添加(或取消注释)term -a 这一行,放在 !Shell 命令之前。
有关如何使用 VSOS Shell 的更多信息,请查看文档《VSRV VSOS Shell》,该文档可在以下位置获得:
https://www.vlsi.fi/fileadmin/products/vsrv/vsrv_vsos_shell.pdf
8 安装和更新 VSOS
8.1 VSOS 简介
VLSI 解决方案开发了一款专门为 VSDSP 设计的抢占式实时多任务操作系统 —— VSOS。
VSOS 支持多种设备,并且支持 FAT12/16/32 文件系统。另一个重要特点是支持动态加载和卸载可执行文件。
VSOS 的 C 语言接口对于标准音频流的处理与标准程序处理标准输入输出的概念相似。就像标准 C 提供了 stdin 和 stdout,VSOS 也提供了 stdaudioin 和 stdaudioout 文件句柄,这使得编写具有单一输入和输出的音频应用程序变得非常简单。对于更复杂的音频系统,应用程序需要自行打开额外的音频句柄。
VSOS 的开发历程已超过 10 年。它最初出现在 VS1005 系列中,后来在 VS1010 ROM 中以不同的功能集出现,而 VSRVES01 又进行了大规模的修改。某些功能与 VS1005 有显着不同。然而,大多数程序可以很容易地从 VS1005 移植到 VSRVES01。
8.2 构建 VSOS
当前版本的 VSOS 并未以源代码形式发布。它仍在积极开发中,预计在功能停止变化并且 VLSI 准备好发布工具链后发布,可能在 2025 年第三季度结束前。
一旦发布 VSOS 的源代码,将是完整的且免费使用和修改,就像 VS1005 系列的情况一样。
8.3 将 VSOS 镜像闪存到 SPI 闪存
待定
8.4 将所需程序添加到 SD 卡
VSOS 系统根文件可以在 VSDSP 论坛找到:
http://www.vsdsp-forum.com/phpbb/viewtopic.php?t=3242
9 开发 VSDSP 程序
待定,预计在 2025 年第三季度结束前发布 VSRV 的 VSIDE 更新。
9.1 准备 VSIDE 与 VSRV 配合使用
待定
9.2 开发程序
待定
10 为 VSRV 构建 RISC-V 工具链
首先,您需要获取 RISC-V 工具链的仓库,官方的 RISC-V 工具链就足够了。请注意,这一步大约需要 20GB 的硬盘空间,大部分空间在编译后可以回收,但这样做会使后续的重建时间变长。
git checkout –depth 1 https://github.com/riscv/riscv-gnu-toolchain
然后进入该目录,进行配置并编译。当然,/local/new-toolchain 路径需要根据您的系统需求进行调整。这个步骤会花费一些时间,具体时间取决于您的机器,可能需要几个小时。
配置过程中,最重要的部分是架构设置,因为 VSRV 是 32 位 RISC-V,且包含两个扩展(ma)。i 选项实际上选择了完整版本的 RISC-V,而不是 e(微控制器版本),后者具有较少的寄存器。
m 扩展:是整数乘法和除法的标准扩展。 a 扩展:是原子指令的标准扩展。zicsr:表示控制状态寄存器(CSR)指令,这对于访问 hart 寄存器非常重要,特别是用于控制异常、屏蔽中断和委派等。
接下来,我们选择代码模型(cmodel)为 medlow,这是 GCC 的默认设置,虽然技术上可以不指定这个选项,但如果未来 GCC 发布的新版本有所变动,指定这个参数可以确保我们获得兼容的二进制文件。
最后一个参数选择浮点实现,在我们的情况下,由于没有硬件支持浮点运算,因此选择 32 位软浮点(ilp32)。
cd riscv-gnu-toolchain
./configure \
--prefix=/local/new-toolchain \
--with-arch=rv32ima_zicsr \
--enable-linux \
--with-cmodel=medlow \
--with-abi=ilp32 make -j ‘nproc‘ linux
下一步是将新的工具链添加到 PATH 中,像这样:
export PATH=$PATH:/local/new-toolchain/bin
当然,您可以将上述设置添加到您选择的 shell 配置文件中。另外,请注意,添加到 PATH 变量中的路径末尾有一个 /bin,这与我们在配置时传递的路径不同。原因是,配置中的前缀是指期望的顶层目录,所有工具链文件都会放在该目录中,而编译器二进制文件会相对于该路径放置在 bin 目录下。
现在,我们已经有了编译器,接下来让我们验证是否设置正确,并且它可以编译一个非常简单的程序。首先,我们需要一段测试代码,比如:
#include <stdio.h>
int main() {
printf("Hello RiscV\n");
return 0;
}
然后我们可以编译它,编译两次以确保静态链接和动态链接都能正常工作。
riscv32-unknown-linux-gnu-gcc -o hello.dyn hello.c
riscv32-unknown-linux-gnu-gcc -o hello hello.c -static
现在我们可以检查它们是否符合我们的要求,即动态链接和静态链接的二进制文件。
file hello.dyn
hello.dyn: ELF 32 位 LSB 可执行文件,UCB RISC-V,版本 1(SYSV),动态链接,解释器 /lib/ld-linux-riscv32-ilp32.so.1,适用于 GNU/Linux 5.4.0,未去除符号表。
file hello
hello: ELF 32 位 LSB 可执行文件,UCB RISC-V,版本 1(GNU/Linux),静态链接,适用于 GNU/Linux 5.4.0,未去除符号表。
11 为 RISC-V 构建 Linux(VSRV 部分)
以下部分假设读者具有一定的 Linux 使用经验,内容的顺序是根据完成完整重建所需的顺序来排列的。不过,如果任务仅仅是获取一些额外的软件并将其添加到现有镜像中,完全可以按照不同的顺序执行这些步骤,甚至可以跳过其中的一些。
主机系统需要大约 2GB 的空间来编译内核。我们还假设第 10 章中提到的工具链已经可以通过 $PATH 访问。
11.1 获取源码
11.1.1 Linux 内核
我们可以从 https://kernel.org/ 获取 tar 包,或者直接从 Git 获取最新的源码,地址是 https://github.com/torvalds/linux
为了简便和可重现的结果,本指南假设使用 tar 包。我们还选择了在编写本指南时(2025-06-19)最新的稳定内核版本 6.1。
$ xz -d < linux-6.1.141.tar.xz | tar xv
目前内核只需要进行一次手动修改。编辑 drivers/clocksource/timer-riscv.c 文件,大约在第 88 行,将 clock-events_config_and_register 中的值 100 修改为大约 1000。
现在是时候将 VLSI Solution 提供的模板内核配置复制到新解压的内核源码中。
$ cp config-6.1.txt linux-6.1.141/.config
11.1.2 VLSI 驱动程序
待定
11.2 配置和构建 Linux 内核
对于第一次构建,最好不要修改模板配置中提供的值,直接使用这些值进行构建,因为我们需要编译好的内核来构建驱动程序。
现在开始构建,如果您的内核版本比用于准备配置文件的内核版本(6.1.0)更新,可能会有一些问题,但通常可以安全地假设默认值是安全的。我们也可以在稍后的任何时候进行更改。
在这个步骤中,我们还会安装模块,以便更新初始内存盘(initramfs)。
在这个步骤中,我们还会安装模块,以便更新初始内存盘(initramfs)。
$ cd ~/linux-6.1.141
$ touch catboard.cpio
$ CROSS_COMPILE=riscv32-unknown-linux-gnu- ARCH=riscv \
make modules Image
### now install them into some temporary directory
$ CROSS_COMPILE=riscv32-unknown-linux-gnu- ARCH=riscv \
make INSTALL_MOD_PATH=/tmp/rv-krnl modules_install
现在我们已经准备好了所有必要的部分,可以针对这个内核编译外部驱动程序。
$ cd ~/vlsi-lnx-drv
$ CROSS_COMPILE=riscv32-unknown-linux-gnu- \ KSRC=/path/to/linux-6.1.141 make
上面的步骤应该会生成针对由 KSRC 变量指定的内核编译的驱动程序。
现在我们需要将包含 CAT 板配置的 cpio 存档放入,完成构建和模块安装,然后重新构建 cpio 存档,最后重新链接内核。
$ cp catboard.cpio linux-6.1.141/catboard.cpio
如果需要,我们可以像下面的示例一样再次运行 menuconfig,修改需要构建的模块,然后再次安装模块。如果不需要,可以跳过这一步,这是安全的。
$ CROSS_COMPILE=riscv32-unknown-linux-gnu- ARCH=riscv \ INSTALL_MOD_PATH=/tmp/rv-krnl \
make menuconfig Image modules modules_install
11.3 初始内存盘
内核需要一些程序来执行,对于 VSRVES01 来说,选择只使用 RAM 文件系统,该文件系统由内核在启动时通过提供的 cpio 存档初始化。这对于开发来说不是最方便的,因为每次修改初始内存盘都需要重新链接内核,但它可以实现非常简单和快速的启动过程。
现在假设我们有一个文件 foobar,我们想将其添加到根目录。但在做任何修改之前,我们先确保在修改之前已经备份了当前的 cpio 文件。
$ cp catboard.cpio catboard_old.cpio
现在我们需要做几件事,首先是将更新后的模块放入新内核版本中,因为原始的 cpio 存档包含的是旧内核的模块,同时我们还需要将在工具链准备过程中生成的 hello 程序添加进来。
但首先,我们来检查 initrd 中有哪些模块,以便更新正确的模块。
$ cpio -t -F catboard.cpio|grep "lib/modules/"
现在我们需要的是 mii.ko,它应该是 Linux 内核的一部分,我们可以用以下命令查找它:
$ find /tmp/rv-krnl -type f -iname "mii.ko"
另外一个是我们之前编译的驱动程序。
我们可以使用现有的存盘并将文件追加到其中进行测试,这是更新一两个文件的最简单方式。当然,每次这样做会使文件变得更大,因此如果这成为问题,重新从原始副本开始可能会比较方便。
$ mkdir -p initrd-addon/root initrd-addon/lib/modules
$ cp ~/hello initrd-addon/root/hello
$ cp ~/vlsi-lnx-drv/vlsi-mac.ko initrd-addon/lib/modules/
### grab updated modules from temporary install directory
$ cp /tmp/rv-krnl/lib/modules/6.1.141/kernel/drivers/net/mii.ko \
initrd-addon/lib/modules/
### at this step you can copy any other files or modules into initrd-addon
### with the same directory structure as you want them to be at on target.
$ (cd initrd-addon; find -type f | cpio -o -H newc -O ../catboard.cpio -vA)
现在我们有了更新的 catboard.cpio,它包含了我们新增的文件和为新内核重建的模块。让我们检查一下它是否包含了额外的文件。
$ cpio -t -F catboard.cpio|tail
现在我们可以再次执行之前描述的命令来构建内核,我们只需要运行 Image 目标即可。
11.4 准备 VRI 镜像
在完成内核编译后,我们需要将其转换为 VLSI Solution 的专有 VRI 格式,以利用 DDRLoad 提供的快速加载功能。
$ elf2vri +v -a 0x80400000 -B arch/riscv/boot/Image - newlinux.vri
当然,上述命令需要在 linux-6.1.141 目录中执行,或者修改以反映实际的 Image 路径。下一步是将 newlinux.vri 复制到 SD 卡上,然后我们可以测试启动。
起始地址(0x80400000)是 rvlbne.bin 中的加载器代码期望内核映像加载的位置。目前,除了编辑加载器代码并重新编译,无法调整这个地址。不过,这种情况可能会改变。
现在,我们可以通过键入或复制以下命令到 VSOS Shell 提示符来测试新构建的镜像。
S:>ddrload -brvlbne.bin -B -bcatboard.dtb newlinux.vri
在上述命令中,第一个参数使 RISC-V 引导加载器加载到默认地址,即 0x80000000,然后 -B 使得 ddrload 在其后追加其参数数据,这些数据包含 MAC 地址、时钟和内存配置,接着它会附加 dtb 文件,最后是我们在创建时定义的 VRI 文件,将会加载到我们指定的地址。
12 VRI 镜像文件格式
VRI(Vlsi Risc-v 镜像)文件格式经过优化,旨在使从 VSDSP/VSOS 加载文件到 DDR 内存的速度非常快。
该文件以 4 字节的魔术头 “VRI1” 开头,后面跟随零个或多个部分:
"VRI1" Section0
... SectionN-1
部分可以有两种类型,要么是字面运行区段,要么是 RLE 零运行区段:
Section, literal run:
56 78 12 34 ADDR: Address (0x12345678), must be divisable by 4
56 78 12 34 SIZE: Literal run size in bytes, must be divisable by 4
00 0? 00 00 FLAGS: FL_READ 1, FL_WRITE 2, FL_EXECUTE 4, no FL_BSS 8
00 00 00 00 EXTENSION: 0
n*56 78 12 34 Literal data, n=SIZE/4, file bytes: 0x78 0x56 0x34 0x12
Section, RLE zero run:
|
56 |
78 |
12 |
34 |
ADDR: Address (0x12345678), must be divisable by 4 |
|
56 |
78 |
12 |
34 |
SIZE: RLE zero run size in bytes, must be divisable by 4 |
|
00 |
0? |
00 |
00 |
FLAGS: FL_READ 1, FL_WRITE 2, FL_EXECUTE 4, set FL_BSS 8 |
|
00 |
00 |
00 |
00 |
EXTENSION: 0 |
下面是一个文本文件的示例,包含 13 个字符 “Hello, world!” 后跟 551 个零,以及它在编码为 VRI 文件后的样子。
% hd helo.txt
00000000 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 00 00 00 |Hello, world!...|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000234
% elf2vri +v -a 0x80400000 -B helo.txt - helo.vri RLE/BSS/strip compressed 0 bytes to 4 (0.0% compression) RAW file at 80400000, helo.txt
RLE: a=80400000, lit 10, bss 224
RAW compressed 564 bytes to 48 (91.5% compression)
% hd helo.vri
|
|
---ADDR---- ---SIZE---- ---FLAGS--- |
|
|
00000000 |
56 52 49 31*00 00 80 40 00 10 00 00 00 07 00 00 |
|VRI1...@........| |
|
|
-EXTENSION- -LITERAL-RUN-DATA-LITERAL-RUN-DATA-L |
|
|
00000010 |
00 00 00 00 65 48 6c 6c 2c 6f 77 20 72 6f 64 6c |
|....eHll,ow rodl| |
|
|
ITERAL-RUN- ---ADDR---- ---SIZE---- ---FLAGS--- |
|
|
00000020 |
00 21 00 00*00 10 80 40 02 24 00 00 00 0f 00 00 |
|.!.....@.$......| |
|
|
-EXTENSION- |
|
|
00000030 |
00 00 00 00 |
|....| |
|
00000034 |
|
|
各个部分彼此独立,因此可以毫无问题地将新部分附加到现有的镜像中。
所有的 32 位值都以混合字节序的方式进行编码,如上所示。需要注意的是,对于字面运行部分,字节顺序会被改变。因此,一个读取为 “HELO” 的文本文件在 VRI 文件中会变成 “EHOL”。
字面运行部分和 RLE 零运行部分可以通过 FL_BSS 位来识别:如果设置了 FL_BSS,则该部分是 RLE 零运行部分;如果 FL_BSS 清除,则该部分是字面运行部分。
VRI 格式可以自由地用于任何目的,但请不要破坏它!
13 最新文档版本变更
本章描述了此文档的最新变更。
版本 0.10, 2025-06-19
- 向第 10 章《为 VSRV 构建 RISC-V 工具链》中添加了编译 Linux 工具链的必要信息。
- 向第 11 章《为 VSRV 构建 Linux》添加了如何编译您自己的 Linux 的信息。
- 添加了第 12 章《VRI 镜像文件格式》。
- 在第 6.2 章《进入 VSOS shell》中添加了全新 VSRV VSOS 音频文档的参考。
版本 0.03, 2025-05-30
在第 6.2 章《进入 VSOS shell》中添加了全新 VSRV VSOS Shell 文档的参考。
版本 0.02, 2025-05-30
清理了现有的文本内容。
版本 0.01, 2025-05-28
第一次发布的初步版本。