2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00
2025-04-11 20:39:36 +02:00

Zynq 7000 Bare-Metal Rust Support

This crate collection provides support to write bare-metal Rust applications for the AMD Zynq 7000 family of SoCs.

List of crates

This workspace contains the following crates:

  • The zynq7000-rt run-time crate containing basic low-level startup code necessary to boot a Rust app on the Zynq7000.
  • The zynq7000 PAC crate containing basic low-level register definition.
  • The zynq7000-hal HAL crate containing higher-level abstractions on top of the PAC register crate.
  • The zynq7000-embassy crate containing support for running the embassy-rs RTOS.

It also contains the following helper crates:

  • The examples folder contains various example applications crates using the HAL and the PAC. This folder also contains dedicated example applications using the embassy native Rust RTOS.

The zedboard-fpga-design folder contains a sample FPGA design and block design which was used in some of the provided software examples. The project was created with Vivado version 2024.1. The folder contains a README with all the steps required to load this project from a TCL script.

Using the .cargo/config.toml file

Use the following command to have a starting config.toml file

cp .cargo/def-config.toml .cargo/config.toml

You then can adapt the config.toml to your needs. For example, you can configure runners to conveniently flash with cargo run.

Using the sample VS Code files

Use the following command to have a starting configuration for VS Code:

cp -rT vscode .vscode

You can then adapt the files in .vscode to your needs.

Building the blinky example

Building an application requires nightly to build the core and alloc library because the thumbv7a-none-eabihf Rust target only has Tier 3 support If you have not installed it yet, you can do so with

rustup toolchain install nightly

Assuming you have the following segments inside your .cargo/config.toml

[target.armv7a-none-eabihf]
rustflags = [
  "-Ctarget-cpu=cortex-a9",
  "-Ctarget-feature=+vfp3",
  "-Ctarget-feature=+neon",
  "-Clink-arg=-Tlink.x",
  # If this is not enabled, debugging / stepping can become problematic.
  "-Cforce-frame-pointers=yes",
  # Can be useful for debugging.
  # "-Clink-args=-Map=app.map"
]

# Tier 3 target, so no pre-compiled artifacts included.
[unstable]
build-std = ["core", "alloc"]

[build]
target = "armv7a-none-eabihf"

You can build the blinky example app using

cargo build --example simple

Flashing, running and debugging the software

This repository was only tested with the Zedboard but should be easily adaptable to other Zynq7000 based platforms and boards.

If you want to test and use this crate on a Zedboard, make sure that the board jumpers on the Zedboard are configured for JTAG boot.

Pre-Requisites

  • xsct tool installation. You have to install the Vitis tool to get access to this tool. You can minimize the download size by de-selecting all SoC families that you do not require. Vitis also includes a Vivado installation which is required to do anything with the FPGA.
  • hw_server installation which is generally included with Vitis/Vivado. This tool starts a GDB server which will be used to connect to and debug the target board. It also allows initializing the processing system and uploading the FPGA design via JTAG.
  • A valid ps7_init.tcl script to configure the processing system. This is necessary to even be able flashing application into the DDR via JTAG. There are multiple ways to generate this startup script, but the recommended way here is to the the sdtgen tool included in xsct which also generates a bitstream for the FPGA configuration. You can find a sample ps7_init.tcl script inside the scripts folder. However, it is strongly recommended to get familiar with Vivado and generate the SDT folder yourself.
  • gdb-multiarch installation to debug applications.
  • python3 installation to use the provided tooling.

Programming and Debug Flow

  1. Start the hw_server application first. This is required for other tooling provided by this repository as well.

  2. The provided scripts/zynq7000-init.py script can be used to initialize the processing system with the ps7_init.tcl script, program the bitstream, and load an ELF file to the DDR. You can run scripts/zynq7000-init.py to get some help and additional information. Here is an example command to initialize the processing system without loading a bitstream using the provided initialization script (adapt AMD_TOOLS to your system):

    export AMD_TOOLS="/tools/Xilinx/Vitis/2024.1"
    ./scripts/zynq7000-init.py --itcl ./scripts/ps7_init.tcl
    
  3. Assuming you have managed to build the blinky example, you can flash the example now using GDB:

    gdb-multiarch -q -x gdb.gdb target/armv7a-none-eabihf/debug/blinky
    

    You can use the -tui argument to also have a terminal UI. This repository provides a scripts/runner.sh which performs all the steps specified above. The .cargo/def-config.toml script contains the runner and some template environmental variables that need to be set for this to work. The command above also loaded the app, but this task can be performed by the zynq7000-init.py wrapper as well.

Using VS Code

The provided VS Code configuration files can be used to perform the CLI steps specified above in a GUI completely and to also have a graphical debugging interface. You can use this as a starting point for your own application. You need to adapt the options.env variables in .vscode/tasks.json for this to work.

Embedded Rust

If you have not done this yet, it is recommended to read some of the excellent resources available to learn Rust:

Description
Native Rust support for AMD Zynq 7000 SoC bare-metal programming
Readme 2.9 MiB
Languages
Rust 85%
Tcl 13.6%
Python 1%
VHDL 0.3%
Shell 0.1%