initial commit
This commit is contained in:
commit
51c4de4347
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
result
|
||||
__pycache__
|
||||
|
||||
build
|
165
LICENSE
Normal file
165
LICENSE
Normal file
@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
61
README.md
Normal file
61
README.md
Normal file
@ -0,0 +1,61 @@
|
||||
Rust Pitaya
|
||||
===========
|
||||
|
||||
Minimalist bare metal Rust firmware for Red Pitaya.
|
||||
|
||||
Development instructions
|
||||
------------------------
|
||||
|
||||
Configure Nix channels:
|
||||
|
||||
```shell
|
||||
nix-channel --add https://nixbld.m-labs.hk/channel/custom/artiq/fast-beta/artiq-fast
|
||||
nix-channel --update
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- Rust Pitaya does not depend on ARTIQ but uses some packages available in the ARTIQ channel.
|
||||
- If you are using Nix channels the first time, you need to be aware of this bug: https://github.com/NixOS/nix/issues/3831.
|
||||
|
||||
Pure build with Nix and execution on a remote JTAG server:
|
||||
|
||||
```shell
|
||||
nix-build -A rust-pitaya-jtag
|
||||
./remote_run.sh
|
||||
```
|
||||
|
||||
Impure incremental build and execution on a remote JTAG server:
|
||||
|
||||
```shell
|
||||
nix-shell
|
||||
cd src
|
||||
gateware/rust-pitaya.py -g ../build/gateware # build gateware
|
||||
make # build firmware
|
||||
cd ..
|
||||
./remote_run.sh -i
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- This is developed with Nixpkgs 20.09, and the ``nixbld.m-labs.hk`` binary substituter can also be used here (see the ARTIQ manual for the public key and instructions).
|
||||
- The impure build process is also compatible with non-Nix systems.
|
||||
- If the board is connected to the local machine, use the ``local_run.sh`` script.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Copyright (C) 2019-2020 M-Labs Limited.
|
||||
|
||||
Rust Pitaya is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Rust Pitaya is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with Rust Pitaya. If not, see <http://www.gnu.org/licenses/>.
|
87
default.nix
Normal file
87
default.nix
Normal file
@ -0,0 +1,87 @@
|
||||
let
|
||||
zynq-rs = (import ./zynq-rs.nix);
|
||||
pkgs = import <nixpkgs> { overlays = [ (import "${zynq-rs}/nix/mozilla-overlay.nix") ]; };
|
||||
rustPlatform = (import "${zynq-rs}/nix/rust-platform.nix" { inherit pkgs; });
|
||||
cargo-xbuild = (import zynq-rs).cargo-xbuild;
|
||||
rust-pitaya-szl = (import zynq-rs).rust-pitaya-szl;
|
||||
mkbootimage = import "${zynq-rs}/nix/mkbootimage.nix" { inherit pkgs; };
|
||||
artiqpkgs = import <artiq-fast/default.nix> { inherit pkgs; };
|
||||
vivado = import <artiq-fast/vivado.nix> { inherit pkgs; };
|
||||
in rec {
|
||||
rust-pitaya-firmware = rustPlatform.buildRustPackage {
|
||||
name = "rust-pitaya-firmware";
|
||||
|
||||
src = ./src;
|
||||
cargoSha256 = "097f4y54cc5m0pib08ypzwbf221knj5a079izixkhhz66g5fmgsq";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.gnumake
|
||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc artiq ])))
|
||||
cargo-xbuild
|
||||
pkgs.llvmPackages_9.llvm
|
||||
pkgs.llvmPackages_9.clang-unwrapped
|
||||
];
|
||||
buildPhase = ''
|
||||
export XARGO_RUST_SRC="${rustPlatform.rust.rustc.src}/library"
|
||||
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
||||
make
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out $out/nix-support
|
||||
cp ../build/runtime.bin $out/firmware.bin
|
||||
cp ../build/firmware/armv7-none-eabihf/release/firmware $out/firmware.elf
|
||||
echo file binary-dist $out/firmware.bin >> $out/nix-support/hydra-build-products
|
||||
echo file binary-dist $out/firmware.elf >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
doCheck = false;
|
||||
dontFixup = true;
|
||||
};
|
||||
rust-pitaya-gateware = pkgs.runCommand "rust-pitaya-gateware"
|
||||
{
|
||||
nativeBuildInputs = [
|
||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc ])))
|
||||
vivado
|
||||
];
|
||||
}
|
||||
''
|
||||
python ${./src/gateware}/zc706.py -g build
|
||||
mkdir -p $out $out/nix-support
|
||||
cp build/top.bit $out
|
||||
echo file binary-dist $out/top.bit >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
|
||||
rust-pitaya-jtag = pkgs.runCommand "rust-pitaya-jtag" {}
|
||||
''
|
||||
mkdir $out
|
||||
ln -s ${rust-pitaya-szl}/szl.elf $out
|
||||
ln -s ${rust-pitaya-firmware}/firmware.bin $out
|
||||
ln -s ${rust-pitaya-gateware}/top.bit $out
|
||||
'';
|
||||
sd = pkgs.runCommand "rust-pitaya-sd"
|
||||
{
|
||||
buildInputs = [ mkbootimage ];
|
||||
}
|
||||
''
|
||||
# Do not use "long" paths in boot.bif, because embedded developers
|
||||
# can't write software (mkbootimage will segfault).
|
||||
bifdir=`mktemp -d`
|
||||
cd $bifdir
|
||||
ln -s ${rust-pitaya-szl}/szl.elf szl.elf
|
||||
ln -s ${rust-pitaya-firmware}/runtime.elf runtime.elf
|
||||
ln -s ${rust-pitaya-gateware}/top.bit top.bit
|
||||
cat > boot.bif << EOF
|
||||
the_ROM_image:
|
||||
{
|
||||
[bootloader]szl.elf
|
||||
top.bit
|
||||
runtime.elf
|
||||
}
|
||||
EOF
|
||||
mkdir $out $out/nix-support
|
||||
mkbootimage boot.bif $out/boot.bin
|
||||
echo file binary-dist $out/boot.bin >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
}
|
48
local_run.sh
Executable file
48
local_run.sh
Executable file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$OPENOCD_ZYNQ" ]; then
|
||||
echo "OPENOCD_ZYNQ environment variable must be set"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$SZL" ]; then
|
||||
echo "SZL environment variable must be set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
impure=0
|
||||
load_bitstream=1
|
||||
board_host="192.168.1.55"
|
||||
|
||||
while getopts "ilb:" opt; do
|
||||
case "$opt" in
|
||||
\?) exit 1
|
||||
;;
|
||||
i) impure=1
|
||||
;;
|
||||
l) load_bitstream=0
|
||||
;;
|
||||
b) board_host=$OPTARG
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
load_bitstream_cmd=""
|
||||
|
||||
build_dir=`pwd`/build
|
||||
result_dir=`pwd`/result
|
||||
cd $OPENOCD_ZYNQ
|
||||
openocd -f redpitaya.cfg -c "load_image $SZL; resume 0; exit"
|
||||
sleep 5
|
||||
if [ $impure -eq 1 ]; then
|
||||
if [ $load_bitstream -eq 1 ]; then
|
||||
load_bitstream_cmd="-g $build_dir/gateware/top.bit"
|
||||
fi
|
||||
artiq_netboot $load_bitstream_cmd -f $build_dir/runtime.bin -b $board_host
|
||||
else
|
||||
if [ $load_bitstream -eq 1 ]; then
|
||||
load_bitstream_cmd="-g $result_dir/top.bit"
|
||||
fi
|
||||
artiq_netboot $load_bitstream_cmd -f $result_dir/runtime.bin -b $board_host
|
||||
fi
|
64
remote_run.sh
Executable file
64
remote_run.sh
Executable file
@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$OPENOCD_ZYNQ" ]; then
|
||||
echo "OPENOCD_ZYNQ environment variable must be set"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$SZL" ]; then
|
||||
echo "SZL environment variable must be set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
target_host="rpi-4.m-labs.hk"
|
||||
impure=0
|
||||
pure_dir="result"
|
||||
impure_dir="build"
|
||||
sshopts=""
|
||||
load_bitstream=1
|
||||
board_host="192.168.1.52"
|
||||
|
||||
while getopts "h:id:o:l" opt; do
|
||||
case "$opt" in
|
||||
\?) exit 1
|
||||
;;
|
||||
h) target_host=$OPTARG
|
||||
;;
|
||||
i) impure=1
|
||||
;;
|
||||
d) pure_dir=$OPTARG;
|
||||
impure_dir=$OPTARG;
|
||||
;;
|
||||
o) sshopts=$OPTARG
|
||||
;;
|
||||
l) load_bitstream=0
|
||||
;;
|
||||
b) board_host=$OPTARG
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
target_folder="/tmp/zynq-$USER"
|
||||
load_bitstream_cmd=""
|
||||
|
||||
echo "Creating $target_folder..."
|
||||
ssh $sshopts $target_host "mkdir -p $target_folder"
|
||||
echo "Copying files..."
|
||||
rsync -e "ssh $sshopts" -Lc $OPENOCD_ZYNQ/* $target_host:$target_folder
|
||||
rsync -e "ssh $sshopts" -Lc $SZL $target_host:$target_folder
|
||||
if [ $impure -eq 1 ]; then
|
||||
if [ $load_bitstream -eq 1 ]; then
|
||||
load_bitstream_cmd="-g build/gateware/top.bit"
|
||||
fi
|
||||
firmware="build/runtime.bin"
|
||||
else
|
||||
if [ $load_bitstream -eq 1 ]; then
|
||||
load_bitstream_cmd="-g $pure_dir/top.bit"
|
||||
fi
|
||||
firmware="$pure_dir/runtime.bin"
|
||||
fi
|
||||
echo "Programming board..."
|
||||
ssh $sshopts $target_host "cd $target_folder; openocd -f zc706.cfg -c'load_image szl.elf; resume 0; exit'"
|
||||
sleep 5
|
||||
artiq_netboot $load_bitstream_cmd -f $firmware -b $board_host
|
33
shell.nix
Normal file
33
shell.nix
Normal file
@ -0,0 +1,33 @@
|
||||
let
|
||||
zynq-rs = (import ./zynq-rs.nix);
|
||||
pkgs = import <nixpkgs> { overlays = [ (import "${zynq-rs}/nix/mozilla-overlay.nix") ]; };
|
||||
rustPlatform = (import "${zynq-rs}/nix/rust-platform.nix" { inherit pkgs; });
|
||||
cargo-xbuild = (import zynq-rs).cargo-xbuild;
|
||||
artiq-fast = <artiq-fast>;
|
||||
artiqpkgs = import "${artiq-fast}/default.nix" { inherit pkgs; };
|
||||
vivado = import "${artiq-fast}/vivado.nix" { inherit pkgs; };
|
||||
redpitaya-szl = (import zynq-rs).redpitaya-szl;
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "rust-pitaya-env";
|
||||
buildInputs = [
|
||||
pkgs.gnumake
|
||||
rustPlatform.rust.rustc
|
||||
rustPlatform.rust.cargo
|
||||
pkgs.llvmPackages_9.llvm
|
||||
pkgs.cacert
|
||||
cargo-xbuild
|
||||
|
||||
pkgs.openocd
|
||||
pkgs.openssh pkgs.rsync
|
||||
|
||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc ])))
|
||||
vivado
|
||||
|
||||
(import "${zynq-rs}/nix/mkbootimage.nix" { inherit pkgs; })
|
||||
];
|
||||
|
||||
XARGO_RUST_SRC = "${rustPlatform.rust.rustc.src}/library";
|
||||
OPENOCD_ZYNQ = "${zynq-rs}/openocd";
|
||||
SZL = "${redpitaya-szl}/szl.elf";
|
||||
}
|
9
src/.cargo/config
Normal file
9
src/.cargo/config
Normal file
@ -0,0 +1,9 @@
|
||||
[target.armv7-none-eabihf]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "target-feature=a9,armv7-a,neon",
|
||||
"-C", "target-cpu=cortex-a9",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "armv7-none-eabihf.json"
|
213
src/Cargo.lock
generated
Normal file
213
src/Cargo.lock
generated
Normal file
@ -0,0 +1,213 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cd0782e0a7da7598164153173e5a5d4d9b1da094473c98dce0ff91406112369"
|
||||
|
||||
[[package]]
|
||||
name = "core_io"
|
||||
version = "0.1.20200410"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#6266d280951c3fe5d4963a4b1ca45ce369d6b773"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa998ce59ec9765d15216393af37a58961ddcefb14c753b4816ba2191d865fcb"
|
||||
dependencies = [
|
||||
"nb 0.1.3",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fatfs"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93079df23039e52059e1f03b4c29fb0c72da2c792aad91bb2236c9fb81d3592e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"core_io",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "firmware"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libboard_zynq",
|
||||
"libconfig",
|
||||
"libcortex_a9",
|
||||
"libregister",
|
||||
"libsupport_zynq",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libboard_zynq"
|
||||
version = "0.0.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#80d12d57802b9b78aa45b821a147f71444d401f0"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"embedded-hal",
|
||||
"libcortex_a9",
|
||||
"libregister",
|
||||
"log",
|
||||
"nb 0.1.3",
|
||||
"smoltcp",
|
||||
"void",
|
||||
"volatile-register",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libconfig"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#80d12d57802b9b78aa45b821a147f71444d401f0"
|
||||
dependencies = [
|
||||
"core_io",
|
||||
"fatfs",
|
||||
"libboard_zynq",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libcortex_a9"
|
||||
version = "0.0.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#80d12d57802b9b78aa45b821a147f71444d401f0"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"libregister",
|
||||
"volatile-register",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libregister"
|
||||
version = "0.0.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#80d12d57802b9b78aa45b821a147f71444d401f0"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"vcell",
|
||||
"volatile-register",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsupport_zynq"
|
||||
version = "0.0.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#80d12d57802b9b78aa45b821a147f71444d401f0"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"libboard_zynq",
|
||||
"libcortex_a9",
|
||||
"libregister",
|
||||
"linked_list_allocator",
|
||||
"r0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked_list_allocator"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84565678e403453d1a27a0886882b3b271701e65146d972d9d7d9a4c4a0ff498"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "managed"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
||||
dependencies = [
|
||||
"nb 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
|
||||
|
||||
[[package]]
|
||||
name = "r0"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
||||
|
||||
[[package]]
|
||||
name = "smoltcp"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fe46639fd2ec79eadf8fe719f237a7a0bd4dac5d957f1ca5bbdbc1c3c39e53a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"managed",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcell"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "volatile-register"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
|
||||
dependencies = [
|
||||
"vcell",
|
||||
]
|
14
src/Cargo.toml
Normal file
14
src/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"firmware"
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
debug = true
|
||||
codegen-units = 1
|
||||
opt-level = 2
|
||||
lto = true
|
||||
|
||||
[patch.crates-io]
|
||||
core_io = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" }
|
14
src/Makefile
Normal file
14
src/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
all: ../build/firmware/armv7-none-eabihf/release/firmware ../build/firmware.bin
|
||||
|
||||
.PHONY: all
|
||||
|
||||
|
||||
../build/pl.rs: gateware/*
|
||||
mkdir -p ../build
|
||||
python gateware/rust-pitaya.py -r ../build/pl.rs
|
||||
|
||||
../build/firmware/armv7-none-eabihf/release/firmware: ../build/pl.rs $(shell find . -print)
|
||||
XBUILD_SYSROOT_PATH=`pwd`/../build/sysroot cargo xbuild --release -p firmware --target-dir ../build/firmware
|
||||
|
||||
../build/firmware.bin: ../build/firmware/armv7-none-eabihf/release/firmware
|
||||
llvm-objcopy -O binary ../build/firmware/armv7-none-eabihf/release/firmware ../build/firmware.bin
|
28
src/armv7-none-eabihf.json
Normal file
28
src/armv7-none-eabihf.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"abi-blacklist": [
|
||||
"stdcall",
|
||||
"fastcall",
|
||||
"vectorcall",
|
||||
"thiscall",
|
||||
"win64",
|
||||
"sysv64"
|
||||
],
|
||||
"arch": "arm",
|
||||
"data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
|
||||
"emit-debug-gdb-scripts": false,
|
||||
"env": "",
|
||||
"executables": true,
|
||||
"features": "+v7,+vfp3,-d32,+thumb2,-neon",
|
||||
"is-builtin": false,
|
||||
"linker": "rust-lld",
|
||||
"linker-flavor": "ld.lld",
|
||||
"llvm-target": "armv7-unknown-none-eabihf",
|
||||
"max-atomic-width": 32,
|
||||
"os": "none",
|
||||
"panic-strategy": "abort",
|
||||
"relocation-model": "static",
|
||||
"target-c-int-width": "32",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "32",
|
||||
"vendor": ""
|
||||
}
|
15
src/firmware/Cargo.toml
Normal file
15
src/firmware/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "firmware"
|
||||
description = "Rust Pitaya firmware"
|
||||
version = "0.1.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
|
||||
libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git", features = ["target_redpitaya", "ipv6"] }
|
||||
libsupport_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git", features = ["target_redpitaya"] }
|
||||
libcortex_a9 = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git", features = ["power_saving"] }
|
||||
libregister = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" }
|
||||
libconfig = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git", features = ["target_redpitaya", "ipv6"] }
|
18
src/firmware/build.rs
Normal file
18
src/firmware/build.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
// Put the linker script somewhere the linker can find it
|
||||
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||
File::create(out.join("link.x"))
|
||||
.unwrap()
|
||||
.write_all(include_bytes!("link.x"))
|
||||
.unwrap();
|
||||
println!("cargo:rustc-link-search={}", out.display());
|
||||
|
||||
// Only re-run the build script when link.x is changed,
|
||||
// instead of when any part of the source code changes.
|
||||
println!("cargo:rerun-if-changed=link.x");
|
||||
}
|
72
src/firmware/link.x
Normal file
72
src/firmware/link.x
Normal file
@ -0,0 +1,72 @@
|
||||
ENTRY(Reset);
|
||||
|
||||
MEMORY
|
||||
{
|
||||
SDRAM : ORIGIN = 0x00100000, LENGTH = 0x1FF00000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
__text_start = .;
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.text.exceptions));
|
||||
*(.text.boot);
|
||||
*(.text .text.*);
|
||||
} > SDRAM
|
||||
__text_end = .;
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > SDRAM
|
||||
__exidx_end = .;
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
* (.ARM.extab*)
|
||||
} > SDRAM
|
||||
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
*(.rodata .rodata.*);
|
||||
} > SDRAM
|
||||
|
||||
.data : ALIGN(4)
|
||||
{
|
||||
*(.data .data.*);
|
||||
} > SDRAM
|
||||
|
||||
.bss (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
__bss_start = .;
|
||||
*(.bss .bss.*);
|
||||
. = ALIGN(4);
|
||||
__bss_end = .;
|
||||
} > SDRAM
|
||||
|
||||
.heap (NOLOAD) : ALIGN(8)
|
||||
{
|
||||
__heap0_start = .;
|
||||
. += 0x8000000;
|
||||
__heap0_end = .;
|
||||
__heap1_start = .;
|
||||
. += 0x8000000;
|
||||
__heap1_end = .;
|
||||
} > SDRAM
|
||||
|
||||
.stack1 (NOLOAD) : ALIGN(8)
|
||||
{
|
||||
__stack1_end = .;
|
||||
. += 0x1000000;
|
||||
__stack1_start = .;
|
||||
} > SDRAM
|
||||
|
||||
.stack0 (NOLOAD) : ALIGN(8)
|
||||
{
|
||||
__stack0_end = .;
|
||||
. += 0x20000;
|
||||
__stack0_start = .;
|
||||
} > SDRAM
|
||||
}
|
85
src/firmware/src/main.rs
Normal file
85
src/firmware/src/main.rs
Normal file
@ -0,0 +1,85 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use core::{cmp, str};
|
||||
use log::{info, warn};
|
||||
|
||||
use libcortex_a9::asm;
|
||||
use libboard_zynq::{timer::GlobalTimer, slcr};
|
||||
use libsupport_zynq::ram;
|
||||
use libconfig::Config;
|
||||
use libregister::RegisterW;
|
||||
|
||||
#[path = "../../../build/pl.rs"]
|
||||
mod pl;
|
||||
|
||||
fn init_gateware() {
|
||||
// Set up PS->PL clocks
|
||||
slcr::RegisterBlock::unlocked(|slcr| {
|
||||
// As we are touching the mux, the clock may glitch, so reset the PL.
|
||||
slcr.fpga_rst_ctrl.write(
|
||||
slcr::FpgaRstCtrl::zeroed()
|
||||
.fpga0_out_rst(true)
|
||||
.fpga1_out_rst(true)
|
||||
.fpga2_out_rst(true)
|
||||
.fpga3_out_rst(true)
|
||||
);
|
||||
slcr.fpga0_clk_ctrl.write(
|
||||
slcr::Fpga0ClkCtrl::zeroed()
|
||||
.src_sel(slcr::PllSource::IoPll)
|
||||
.divisor0(8)
|
||||
.divisor1(1)
|
||||
);
|
||||
slcr.fpga_rst_ctrl.write(
|
||||
slcr::FpgaRstCtrl::zeroed()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn identifier_read(buf: &mut [u8]) -> &str {
|
||||
unsafe {
|
||||
pl::csr::identifier::address_write(0);
|
||||
let len = pl::csr::identifier::data_read();
|
||||
let len = cmp::min(len, buf.len() as u8);
|
||||
for i in 0..len {
|
||||
pl::csr::identifier::address_write(1 + i);
|
||||
buf[i as usize] = pl::csr::identifier::data_read();
|
||||
}
|
||||
str::from_utf8_unchecked(&buf[..len as usize])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main_core0() {
|
||||
let mut timer = GlobalTimer::start();
|
||||
log::set_max_level(log::LevelFilter::Info);
|
||||
|
||||
info!("Rust Pitaya firmware starting...");
|
||||
|
||||
ram::init_alloc_core0();
|
||||
|
||||
init_gateware();
|
||||
info!("detected gateware: {}", identifier_read(&mut [0; 64]));
|
||||
|
||||
let cfg = match Config::new() {
|
||||
Ok(cfg) => cfg,
|
||||
Err(err) => {
|
||||
warn!("config initialization failed: {}", err);
|
||||
Config::new_dummy()
|
||||
}
|
||||
};
|
||||
|
||||
loop {
|
||||
asm::wfe();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main_core1() {
|
||||
loop {
|
||||
asm::wfe();
|
||||
}
|
||||
}
|
52
src/gateware/rust-pitaya.py
Executable file
52
src/gateware/rust-pitaya.py
Executable file
@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
from operator import itemgetter
|
||||
|
||||
from migen import *
|
||||
from migen.build.generic_platform import *
|
||||
from migen_axi.integration.soc_core import SoCCore
|
||||
from migen_axi.platforms import redpitaya
|
||||
from misoc.integration import cpu_interface
|
||||
|
||||
|
||||
class RustPitaya(SoCCore):
|
||||
def __init__(self):
|
||||
platform = redpitaya.Platform()
|
||||
platform.toolchain.bitstream_commands.extend([
|
||||
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
||||
])
|
||||
ident = self.__class__.__name__
|
||||
SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident)
|
||||
|
||||
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
||||
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
||||
|
||||
|
||||
def write_csr_file(soc, filename):
|
||||
with open(filename, "w") as f:
|
||||
f.write(cpu_interface.get_csr_rust(
|
||||
soc.get_csr_regions(), soc.get_csr_groups(), soc.get_constants()))
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Rust Pitaya gateware")
|
||||
parser.add_argument("-r", default=None, metavar="FILE",
|
||||
help="build Rust interface into the specified file")
|
||||
parser.add_argument("-g", default=None, metavar="DIRECTORY",
|
||||
help="build gateware into the specified directory")
|
||||
args = parser.parse_args()
|
||||
|
||||
soc = RustPitaya()
|
||||
soc.finalize()
|
||||
|
||||
if args.r is not None:
|
||||
write_csr_file(soc, args.r)
|
||||
if args.g is not None:
|
||||
soc.build(build_dir=args.g)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
8
zynq-rs.nix
Normal file
8
zynq-rs.nix
Normal file
@ -0,0 +1,8 @@
|
||||
let
|
||||
pkgs = import <nixpkgs> {};
|
||||
in
|
||||
pkgs.fetchgit {
|
||||
url = "https://git.m-labs.hk/M-Labs/zynq-rs.git";
|
||||
rev = "80d12d57802b9b78aa45b821a147f71444d401f0";
|
||||
sha256 = "0q91x3kvhaikgzcz1ki24y6vgx5w5w2dwjikx67z2hx5wzrp6jw0";
|
||||
}
|
Loading…
Reference in New Issue
Block a user