4 个版本
新增 0.1.5 | 2024年8月20日 |
---|---|
0.1.4 | 2024年8月19日 |
0.1.3 |
|
0.1.1 | 2024年7月8日 |
0.0.0 | 2024年5月28日 |
#125 in 硬件支持
每月315 次下载
715KB
15K SLoC
moondancer
Great Scott Gadgets Cynthion 的 Moondancer 固件。
构建和运行
构建 SoC 位流
在您运行任何固件之前,您首先需要构建 Moondancer SoC 位流
cd cynthion.git/cynthion/python
make soc
执行固件
一旦构建了 SoC 位流,您可以使用
cargo run --release
以下命令执行您的固件:cargo run
如果由 runner
参数在 .cargo/config.toml
文件中控制。
默认情况下,它使用 .cargo/cynthion.sh
脚本来按以下顺序执行以下步骤
- 将 Rust 编译器生成的 ELF 可执行文件转换为固件二进制镜像。
- 使用
cynthion
命令行工具将固件二进制镜像闪存到 Cynthion 的 SPI 闪存。 - 使用
cynthion
命令行工具使用 SoC 位流配置 Cynthion 的 FPGA。 - 启动一个串行终端以查看固件日志输出。
使用 Cynthion 的控制端口 (USB2)
默认情况下,Cynthion 的控制端口被 Apollo 使用。
如果您想从 Apollo 接管控制并用于自己的固件,可以使用以下命令禁用 ApolloAdvertiser 外设
let peripherals = pac::Peripherals::take().unwrap();
let advertiser = peripherals.ADVERTISER;
advertiser.enable().write(|w| w.enable().bit(true));
请注意,在这种情况下,您将无法通过 Apollo 访问 SoC 的 UART0 外设,需要改用 UART1。
固件调试
Moondancer SoC 在 Cynthion 的 PMOD B 连接器上公开了第二个 UART 和一个 JTAG 连接器
PMOD B
+-----+-----+----+----+----+----+
| 3v3 | gnd | 4 | 3 | 2 | 1 |
+-----+-----+----+----+----+----+
| 3v3 | gnd | 10 | 9 | 8 | 7 |
+-----+-----+----+----+----+----+
Pin 1: UART rx
Pin 2: UART tx
Pin 7: JTAG tms
Pin 8: JTAG tdi
Pin 9: JTAG tdo
Pin 10: JTAG tck
UART
Cynthion SoC 提供了两个 UART 端口。
UART0 连接到 Cynthion 的 SAMD11 微控制器,并且只有在 SoC 固件不使用 Cynthion 的控制端口 (USB2) 时才能访问。
UART1 连接到 Cynthion PMOD B 端口的引脚 1 和 2,可以通过串行适配器访问。
picocom --imap lfcrlf -b 115200 /dev/cu.usbserial-1301
JTAG
JTAG 端口直接连接到 Vexriscv 处理器,可用于加载固件和调试 CPU。
使用此功能的详细步骤将取决于您使用的特定JTAG探头和调试软件,但以示例来说,您可以使用openocd
和gdb
,如下所示
1. 配置openocd
要为FTDI适配器配置openocd,您需要类似以下内容
#
# .cargo/openocd.cfg
#
# select adapter driver
adapter driver ftdi
# configure adapter driver
ftdi vid_pid 0x0403 0x6011
ftdi channel 0
ftdi layout_init 0xfff8 0xfffb
ftdi tdo_sample_edge falling
# configure transport
transport select jtag
adapter speed 25000
# configure jtag tap
set _CHIPNAME riscv
set _TARGETNAME $_CHIPNAME.cpu
# create jtag tap
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10002FFF
target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
然后您可以使用以下方式运行openocd
openocd -f .cargo/openocd.cfg
如果一切正常,应该会得到类似以下内容
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
riscv.cpu
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 25000 kHz
Info : JTAG tap: riscv.cpu tap/device found: 0x10002fff (mfg: 0x7ff (<invalid>), part: 0x0002, ver: 0x1)
Info : datacount=1 progbufsize=2
Info : Disabling abstract command reads from CSRs.
Info : Examined RISC-V core; found 1 harts
Info : hart 0: XLEN=32, misa=0x40000042
Info : starting gdb server for riscv.cpu.0 on 3333
Info : Listening on port 3333 for gdb connections
2. 配置gdb
您需要一个基本的gdb配置文件,其外观可能如下
#
# .cargo/openocd.gdb
#
# connect to openocd
target extended-remote :3333
# print demangled symbols
set print asm-demangle on
# detect unhandled exceptions, hard faults and panics
break DefaultHandler
break HardFault
break rust_begin_unwind
# load firmware into memory
load
3. 配置cargo以使用gdb
默认情况下,固件使用cynthion
命令行工具来将固件和位流烧写到Cynthion。
因此,您需要修改.cargo/config.toml
配置文件,以便使用gdb
作为固件的运行器
#
# .cargo/config.toml
#
[target.riscv32imac-unknown-none-elf]
runner = "cynthion.sh" # <==
rustflags = [
"-C", "link-arg=-Tmemory.x",
"-C", "link-arg=-Tlink.x",
]
[build]
target = "riscv32imac-unknown-none-elf"
找到runner
参数并按以下方式修改它
runner = "riscv64-unknown-elf-gdb -q -x .cargo/openocd.gdb"
4. 配置memory.x
通常,固件从Cynthion的SPI闪存启动,但在使用JTAG时,您将直接将其加载到SoC主内存中。
但是,要执行此操作,您首先需要让Rust链接器了解您的计划!
在顶层cynthion.git/firmware/
目录中,您应该看到一个名为memory.x
的文件,该文件包含Rust链接器使用的内存布局
#
# memory.x
#
MEMORY {
...
}
REGION_ALIAS("REGION_TEXT", spiflash); # <==
REGION_ALIAS("REGION_RODATA", spiflash); # <==
REGION_ALIAS("REGION_DATA", mainram);
REGION_ALIAS("REGION_BSS", mainram);
REGION_ALIAS("REGION_HEAP", mainram);
REGION_ALIAS("REGION_STACK", mainram);
您需要修改此文件,并将指向spiflash
的两个REGION_ALIAS
指令更改为指向mainram
REGION_ALIAS("REGION_TEXT", mainram);
REGION_ALIAS("REGION_RODATA", mainram);
如果不这样做,gdb
将尝试将您的固件加载到spiflash
地址,考虑到SoC的SPI控制器外围设备是只读的,这会导致轻微的荒谬。
5. 配置Cynthion位流
您几乎完成了!在能够调试固件之前,您需要执行的最后一步是构建SoC并使用位流配置Cynthion
cd cynthion.git/cynthion/python
make soc
make load
6. 启动gdb
如果您已成功完成上述所有步骤,并通过openocd
与SoC建立了功能连接,您现在应该能够通过以下方式执行固件
cargo run --release --bin hello
如果一切顺利,您将进入一个熟悉的gdb
外壳
Reading symbols from target/riscv32imac-unknown-none-elf/release/hello
_start () at asm.S:27
Breakpoint 1 at 0x4000109a: file src/lib.rs, line 498.
Function "HardFault" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
Breakpoint 2 at 0x40001054: file moondancer/src/panic_log.rs, line 15.
Loading section .text, size 0x1172 lma 0x40000000
Loading section .rodata, size 0x2f4 lma 0x40001174
Loading section .data, size 0x10 lma 0x40001468
Start address 0x40000000, load size 5238
Transfer rate: 196 KB/sec, 1746 bytes/write.
(gdb)
要开始执行,只需键入continue
,如果您打开了一个连接到Cynthion UART端口的串行终端,您将看到类似以下内容
INFO Peripherals initialized, entering main loop.
INFO left: 3
INFO right: 7
INFO left: 11
...
有关嵌入式Rust调试的更多信息,请参阅嵌入式Rust书籍 - 硬件。
依赖关系
~2.7–4MB
~68K SLoC