Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

54 changed files with 556 additions and 2334 deletions

42
flake.lock generated
View File

@ -11,11 +11,11 @@
"src-pythonparser": "src-pythonparser" "src-pythonparser": "src-pythonparser"
}, },
"locked": { "locked": {
"lastModified": 1743144117, "lastModified": 1734418848,
"narHash": "sha256-LOh3KwjcEKcLA2vva6awAnMLUEyq4d+LPLCu7FwMAhw=", "narHash": "sha256-FiK84edtdmpJ3FUA58XAUmDDp4oVPgupmf1CcgJ6rC0=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "4ddad5fd17bb07fc754d764d3ff157300d27e109", "rev": "366bb0fc59dbe4d5f544908b0f3e31f8eb19f7c1",
"revCount": 9204, "revCount": 9121,
"type": "git", "type": "git",
"url": "https://github.com/m-labs/artiq.git" "url": "https://github.com/m-labs/artiq.git"
}, },
@ -37,11 +37,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1734270714, "lastModified": 1720768567,
"narHash": "sha256-7bzGn/hXLIsLQHGQsvo+uoIFUrw9DjXSlMC449BY4ME=", "narHash": "sha256-3VoK7o5MtHtbHLrc6Pv+eQWFtaz5Gd/YWyV5TD3c5Ss=",
"owner": "m-labs", "owner": "m-labs",
"repo": "artiq-comtools", "repo": "artiq-comtools",
"rev": "7e3152314af8f5987370e33b347b2ec2697567ed", "rev": "f93570d8f2ed5a3cfb3e1c16ab00f2540551e994",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -70,11 +70,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1741851582, "lastModified": 1733940404,
"narHash": "sha256-cPfs8qMccim2RBgtKGF+x9IBCduRvd/N5F4nYpU0TVE=", "narHash": "sha256-Pj39hSoUA86ZePPF/UXiYHHM7hMIkios8TYG29kQT4g=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6607cf789e541e7873d40d3a8f7815ea92204f32", "rev": "5d67ea6b4b63378b9c13be21e2ec9d1afc921713",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -158,11 +158,11 @@
"src-migen": { "src-migen": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1738906518, "lastModified": 1727677091,
"narHash": "sha256-GproDJowtcgbccsT+I0mObzFhE483shcS8MSszKXwlc=", "narHash": "sha256-Zg3SQnTwMM/VkOGKogbPyuCC2NhLy8HB2SPEUWWNgCU=",
"owner": "m-labs", "owner": "m-labs",
"repo": "migen", "repo": "migen",
"rev": "2828df54594673653a641ab551caf6c6b1bfeee5", "rev": "c19ae9f8ae162ffe2d310a92bfce53ac2a821bc8",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -174,11 +174,11 @@
"src-misoc": { "src-misoc": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1741001607, "lastModified": 1729234629,
"narHash": "sha256-05BGqWV4Zc9ArwaW0uuBYWjg4oTeP4vznPQQjEpQPEM=", "narHash": "sha256-TLsTCXV5AC2xh+bS7EhBVBKqdqIU3eKrnlWcFF9LtAM=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "fa73f42f3c163833f17fc99399bb41005970c503", "rev": "6085a312bca26adeca6584e37d08c8ba2e1d6e38",
"revCount": 2495, "revCount": 2460,
"submodules": true, "submodules": true,
"type": "git", "type": "git",
"url": "https://github.com/m-labs/misoc.git" "url": "https://github.com/m-labs/misoc.git"
@ -229,11 +229,11 @@
"rust-overlay": "rust-overlay_2" "rust-overlay": "rust-overlay_2"
}, },
"locked": { "locked": {
"lastModified": 1743144882, "lastModified": 1734668221,
"narHash": "sha256-B1J8Ou/T8EDNcPVAu+c5bRiRUjoCiWCh6WNo60sRyDc=", "narHash": "sha256-X0U2yPmlsD3VLBZQyfWv8qw04Qn0qFWIONJUPPigB0U=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "c98c30c6565f0aa35a2f4ab31e5174f167714841", "rev": "213529cf7a50aa1b2d9ffdf575e3e38202ff9bd6",
"revCount": 696, "revCount": 666,
"type": "git", "type": "git",
"url": "https://git.m-labs.hk/m-labs/zynq-rs" "url": "https://git.m-labs.hk/m-labs/zynq-rs"
}, },

View File

@ -134,14 +134,14 @@
nativeBuildInputs = [ nativeBuildInputs = [
pkgs.gnumake pkgs.gnumake
(pkgs.python3.withPackages(ps: [ ps.jsonschema artiqpkgs.migen migen-axi artiqpkgs.misoc artiqpkgs.artiq ])) (pkgs.python3.withPackages(ps: [ ps.jsonschema artiqpkgs.migen migen-axi artiqpkgs.misoc artiqpkgs.artiq ]))
pkgs.cargo-xbuild zynqpkgs.cargo-xbuild
pkgs.llvmPackages_18.llvm pkgs.llvmPackages_13.llvm
pkgs.llvmPackages_18.clang-unwrapped pkgs.llvmPackages_13.clang-unwrapped
]; ];
buildPhase = '' buildPhase = ''
export ZYNQ_REV=${zynqRev} export ZYNQ_REV=${zynqRev}
export XARGO_RUST_SRC="${rust}/lib/rustlib/src/rust/library" export XARGO_RUST_SRC="${rust}/lib/rustlib/src/rust/library"
export CLANG_EXTRA_INCLUDE_DIR="${pkgs.llvmPackages_18.clang-unwrapped.lib}/lib/clang/18/include" export CLANG_EXTRA_INCLUDE_DIR="${pkgs.llvmPackages_13.clang-unwrapped.lib}/lib/clang/13.0.1/include"
export CARGO_HOME=$(mktemp -d cargo-home.XXX) export CARGO_HOME=$(mktemp -d cargo-home.XXX)
export ZYNQ_RS=${zynq-rs} export ZYNQ_RS=${zynq-rs}
make TARGET=${target} GWARGS="${if json == null then "-V ${variant}" else json}" ${fwtype} make TARGET=${target} GWARGS="${if json == null then "-V ${variant}" else json}" ${fwtype}
@ -345,7 +345,6 @@
{ {
inherit fastnumbers artiq-netboot ramda migen-axi binutils-arm; inherit fastnumbers artiq-netboot ramda migen-axi binutils-arm;
} // } //
(board-package-set { target = "zc706"; variant = "cxp_4r_fmc"; }) //
(board-package-set { target = "zc706"; variant = "nist_clock"; }) // (board-package-set { target = "zc706"; variant = "nist_clock"; }) //
(board-package-set { target = "zc706"; variant = "nist_clock_master"; }) // (board-package-set { target = "zc706"; variant = "nist_clock_master"; }) //
(board-package-set { target = "zc706"; variant = "nist_clock_master_100mhz"; }) // (board-package-set { target = "zc706"; variant = "nist_clock_master_100mhz"; }) //
@ -377,11 +376,11 @@
name = "artiq-zynq-dev-shell"; name = "artiq-zynq-dev-shell";
buildInputs = with pkgs; [ buildInputs = with pkgs; [
rust rust
llvmPackages_18.llvm llvmPackages_13.llvm
llvmPackages_18.clang-unwrapped llvmPackages_13.clang-unwrapped
gnumake gnumake
cacert cacert
pkgs.cargo-xbuild zynqpkgs.cargo-xbuild
zynqpkgs.mkbootimage zynqpkgs.mkbootimage
openocd openocd
openssh rsync openssh rsync
@ -393,7 +392,7 @@
]; ];
ZYNQ_REV="${zynqRev}"; ZYNQ_REV="${zynqRev}";
XARGO_RUST_SRC = "${rust}/lib/rustlib/src/rust/library"; XARGO_RUST_SRC = "${rust}/lib/rustlib/src/rust/library";
CLANG_EXTRA_INCLUDE_DIR = "${pkgs.llvmPackages_18.clang-unwrapped.lib}/lib/clang/18/include"; CLANG_EXTRA_INCLUDE_DIR = "${pkgs.llvmPackages_13.clang-unwrapped.lib}/lib/clang/13.0.1/include";
ZYNQ_RS = "${zynq-rs}"; ZYNQ_RS = "${zynq-rs}";
OPENOCD_ZYNQ = "${zynq-rs}/openocd"; OPENOCD_ZYNQ = "${zynq-rs}/openocd";
SZL = "${zynqpkgs.szl}"; SZL = "${zynqpkgs.szl}";

View File

@ -1,6 +1,7 @@
[target.armv7-none-eabihf] [target.armv7-none-eabihf]
rustflags = [ rustflags = [
"-C", "link-arg=-Tlink.x", "-C", "link-arg=-Tlink.x",
"-C", "target-feature=a9,armv7-a,neon",
"-C", "target-cpu=cortex-a9", "-C", "target-cpu=cortex-a9",
] ]

64
src/Cargo.lock generated
View File

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 3
[[package]] [[package]]
name = "approx" name = "approx"
@ -19,9 +19,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]] [[package]]
name = "async-recursion" name = "async-recursion"
version = "1.1.1" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -82,9 +82,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "compiler_builtins" name = "compiler_builtins"
version = "0.1.108" version = "0.1.49"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d68bc55329711cd719c2687bb147bc06211b0521f97ef398280108ccb23227e9" checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"
[[package]] [[package]]
name = "core_io" name = "core_io"
@ -148,9 +148,9 @@ dependencies = [
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.31" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@ -162,9 +162,9 @@ dependencies = [
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.31" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@ -172,21 +172,21 @@ dependencies = [
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.31" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
[[package]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.31" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.31" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -195,21 +195,21 @@ dependencies = [
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.31" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.31" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
[[package]] [[package]]
name = "futures-util" name = "futures-util"
version = "0.3.31" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-macro", "futures-macro",
@ -264,6 +264,7 @@ dependencies = [
"embedded-hal", "embedded-hal",
"libcortex_a9", "libcortex_a9",
"nb 1.0.0", "nb 1.0.0",
"pin-utils",
"smoltcp", "smoltcp",
] ]
@ -272,7 +273,6 @@ name = "libboard_artiq"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"build_zynq", "build_zynq",
"byteorder",
"core_io", "core_io",
"crc", "crc",
"embedded-hal", "embedded-hal",
@ -426,9 +426,9 @@ dependencies = [
[[package]] [[package]]
name = "num-derive" name = "num-derive"
version = "0.4.2" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -457,9 +457,9 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.19" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"libm", "libm",
@ -485,18 +485,18 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.93" version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.38" version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -590,9 +590,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.98" version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -4,7 +4,7 @@
"emit-debug-gdb-scripts": false, "emit-debug-gdb-scripts": false,
"env": "", "env": "",
"executables": true, "executables": true,
"features": "+v7,+vfp3,-d32,+thumb2,+neon,+a9,+armv7-a", "features": "+v7,+vfp3,-d32,+thumb2,-neon",
"is-builtin": false, "is-builtin": false,
"linker": "rust-lld", "linker": "rust-lld",
"linker-flavor": "ld.lld", "linker-flavor": "ld.lld",

View File

@ -1,74 +0,0 @@
from migen.build.generic_platform import *
fmc_adapter_io = [
# CoaXPress high speed link
("CXP_HS", 0,
Subsignal("rxp", Pins("HPC:DP0_M2C_P")),
Subsignal("rxn", Pins("HPC:DP0_M2C_N")),
),
("CXP_HS", 1,
Subsignal("rxp", Pins("HPC:DP1_M2C_P")),
Subsignal("rxn", Pins("HPC:DP1_M2C_N")),
),
("CXP_HS", 2,
Subsignal("rxp", Pins("HPC:DP2_M2C_P")),
Subsignal("rxn", Pins("HPC:DP2_M2C_N")),
),
("CXP_HS", 3,
Subsignal("rxp", Pins("HPC:DP3_M2C_P")),
Subsignal("rxn", Pins("HPC:DP3_M2C_N")),
),
# CoaXPress low speed link
("CXP_LS", 0, Pins("HPC:LA00_CC_P"), IOStandard("LVCMOS33")),
("CXP_LS", 1, Pins("HPC:LA01_CC_N"), IOStandard("LVCMOS33")),
("CXP_LS", 2, Pins("HPC:LA01_CC_P"), IOStandard("LVCMOS33")),
("CXP_LS", 3, Pins("HPC:LA02_N"), IOStandard("LVCMOS33")),
# CoaXPress green and red LED
("CXP_LED", 0,
Subsignal("green", Pins("HPC:LA11_P"), IOStandard("LVCMOS33")),
Subsignal("red", Pins("HPC:LA11_N"), IOStandard("LVCMOS33")),
),
("CXP_LED", 1,
Subsignal("green", Pins("HPC:LA12_P"), IOStandard("LVCMOS33")),
Subsignal("red", Pins("HPC:LA12_N"), IOStandard("LVCMOS33")),
),
("CXP_LED", 2,
Subsignal("green", Pins("HPC:LA13_P"), IOStandard("LVCMOS33")),
Subsignal("red", Pins("HPC:LA13_N"), IOStandard("LVCMOS33")),
),
("CXP_LED", 3,
Subsignal("green", Pins("HPC:LA14_P"), IOStandard("LVCMOS33")),
Subsignal("red", Pins("HPC:LA14_N"), IOStandard("LVCMOS33")),
),
# Power over CoaXPress
("PoCXP", 0,
Subsignal("enable", Pins("HPC:LA21_N"), IOStandard("LVCMOS33")),
Subsignal("alert", Pins("HPC:LA18_CC_P"), IOStandard("LVCMOS33")),
),
("PoCXP", 1,
Subsignal("enable", Pins("HPC:LA21_P"), IOStandard("LVCMOS33")),
Subsignal("alert", Pins("HPC:LA19_N"), IOStandard("LVCMOS33")),
),
("PoCXP", 2,
Subsignal("enable", Pins("HPC:LA22_N"), IOStandard("LVCMOS33")),
Subsignal("alert", Pins("HPC:LA19_P"), IOStandard("LVCMOS33")),
),
("PoCXP", 3,
Subsignal("enable", Pins("HPC:LA22_P"), IOStandard("LVCMOS33")),
Subsignal("alert", Pins("HPC:LA20_N"), IOStandard("LVCMOS33")),
),
("i2c", 0,
Subsignal("scl", Pins("HPC:IIC_SCL")),
Subsignal("sda", Pins("HPC:IIC_SDA")),
IOStandard("LVCMOS33")
),
# On board 125MHz reference
("clk125", 0,
Subsignal("p", Pins("HPC:GBTCLK0_M2C_P")),
Subsignal("n", Pins("HPC:GBTCLK0_M2C_N")),
),
]

View File

@ -432,7 +432,6 @@ class GenericSatellite(SoCCore):
clk_freq = description["rtio_frequency"] clk_freq = description["rtio_frequency"]
with_wrpll = description["enable_wrpll"] with_wrpll = description["enable_wrpll"]
has_drtio_over_eem = any(peripheral["type"] == "shuttler" for peripheral in description["peripherals"])
self.acpki = acpki self.acpki = acpki
platform = kasli_soc.Platform() platform = kasli_soc.Platform()
@ -481,8 +480,6 @@ class GenericSatellite(SoCCore):
self.rtio_channels = [] self.rtio_channels = []
has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"]) has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"])
if has_drtio_over_eem:
self.eem_drtio_channels = []
if has_grabber: if has_grabber:
self.grabber_csr_group = [] self.grabber_csr_group = []
eem_7series.add_peripherals(self, description["peripherals"], iostandard=eem_iostandard) eem_7series.add_peripherals(self, description["peripherals"], iostandard=eem_iostandard)
@ -497,15 +494,15 @@ class GenericSatellite(SoCCore):
self.submodules.rtio_tsc = rtio.TSC(glbl_fine_ts_width=3) self.submodules.rtio_tsc = rtio.TSC(glbl_fine_ts_width=3)
self.drtioaux_csr_group = [] drtioaux_csr_group = []
self.drtioaux_memory_group = [] drtioaux_memory_group = []
self.drtiorep_csr_group = [] drtiorep_csr_group = []
self.drtio_cri = [] self.drtio_cri = []
for i in range(len(self.gt_drtio.channels)): for i in range(len(self.gt_drtio.channels)):
coreaux_name = "drtioaux" + str(i) coreaux_name = "drtioaux" + str(i)
memory_name = "drtioaux" + str(i) + "_mem" memory_name = "drtioaux" + str(i) + "_mem"
self.drtioaux_csr_group.append(coreaux_name) drtioaux_csr_group.append(coreaux_name)
self.drtioaux_memory_group.append(memory_name) drtioaux_memory_group.append(memory_name)
cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)}) cdr = ClockDomainsRenamer({"rtio_rx": "rtio_rx" + str(i)})
@ -518,7 +515,7 @@ class GenericSatellite(SoCCore):
self.csr_devices.append("drtiosat") self.csr_devices.append("drtiosat")
else: else:
corerep_name = "drtiorep" + str(i-1) corerep_name = "drtiorep" + str(i-1)
self.drtiorep_csr_group.append(corerep_name) drtiorep_csr_group.append(corerep_name)
core = cdr(DRTIORepeater( core = cdr(DRTIORepeater(
self.rtio_tsc, self.gt_drtio.channels[i])) self.rtio_tsc, self.gt_drtio.channels[i]))
@ -541,9 +538,9 @@ class GenericSatellite(SoCCore):
self.add_memory_region(memory_name, self.mem_map["csr"] + memory_address, mem_size * 2) self.add_memory_region(memory_name, self.mem_map["csr"] + memory_address, mem_size * 2)
self.config["HAS_DRTIO"] = None self.config["HAS_DRTIO"] = None
self.config["HAS_DRTIO_ROUTING"] = None self.config["HAS_DRTIO_ROUTING"] = None
if has_drtio_over_eem: self.add_csr_group("drtioaux", drtioaux_csr_group)
self.add_eem_drtio(self.eem_drtio_channels) self.add_memory_group("drtioaux_mem", drtioaux_memory_group)
self.add_drtio_cpuif_groups() self.add_csr_group("drtiorep", drtiorep_csr_group)
if self.acpki: if self.acpki:
self.config["KI_IMPL"] = "acp" self.config["KI_IMPL"] = "acp"
@ -628,50 +625,6 @@ class GenericSatellite(SoCCore):
self.comb += [self.virtual_leds.get(i).eq(channel.rx_ready) self.comb += [self.virtual_leds.get(i).eq(channel.rx_ready)
for i, channel in enumerate(self.gt_drtio.channels)] for i, channel in enumerate(self.gt_drtio.channels)]
def add_eem_drtio(self, eem_drtio_channels):
# Must be called before constructing CRIInterconnectShared
self.submodules.eem_transceiver = eem_serdes.EEMSerdes(self.platform, eem_drtio_channels)
self.csr_devices.append("eem_transceiver")
self.config["HAS_DRTIO_EEM"] = None
self.config["EEM_DRTIO_COUNT"] = len(eem_drtio_channels)
for i in range(len(self.eem_transceiver.channels)):
channel = i + len(self.gt_drtio.channels)
coreaux_name = "drtioaux" + str(channel)
memory_name = "drtioaux" + str(channel) + "_mem"
self.drtioaux_csr_group.append(coreaux_name)
self.drtioaux_memory_group.append(memory_name)
cdr = ClockDomainsRenamer({"rtio_rx": "sys"})
corerep_name = "drtiorep" + str(channel-1)
self.drtiorep_csr_group.append(corerep_name)
core = cdr(DRTIORepeater(
self.rtio_tsc, self.eem_transceiver.channels[i]))
setattr(self.submodules, corerep_name, core)
self.drtio_cri.append(core.cri)
self.csr_devices.append(corerep_name)
coreaux = cdr(drtio_aux_controller.DRTIOAuxControllerBare(core.link_layer))
setattr(self.submodules, coreaux_name, coreaux)
self.csr_devices.append(coreaux_name)
mem_size = coreaux.get_mem_size()
tx_port = coreaux.get_tx_port()
rx_port = coreaux.get_rx_port()
memory_address = self.axi2csr.register_port(tx_port, mem_size)
# rcv in upper half of the memory, thus added second
self.axi2csr.register_port(rx_port, mem_size)
# and registered in PS interface
# manually, because software refers to rx/tx by halves of entire memory block, not names
self.add_memory_region(memory_name, self.mem_map["csr"] + memory_address, mem_size * 2)
def add_drtio_cpuif_groups(self):
self.add_csr_group("drtiorep", self.drtiorep_csr_group)
self.add_csr_group("drtioaux", self.drtioaux_csr_group)
self.add_memory_group("drtioaux_mem", self.drtioaux_memory_group)
def main(): def main():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="ARTIQ device binary builder for generic Kasli-SoC systems") description="ARTIQ device binary builder for generic Kasli-SoC systems")

View File

@ -13,7 +13,7 @@ from misoc.interconnect.csr import *
from misoc.cores import gpio from misoc.cores import gpio
from artiq.gateware import rtio, nist_clock, nist_qc2 from artiq.gateware import rtio, nist_clock, nist_qc2
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2, edge_counter, cxp_grabber from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2, edge_counter
from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path
from artiq.gateware.drtio.transceiver import gtx_7series from artiq.gateware.drtio.transceiver import gtx_7series
from artiq.gateware.drtio.siphaser import SiPhaser7Series from artiq.gateware.drtio.siphaser import SiPhaser7Series
@ -25,7 +25,6 @@ import analyzer
import acpki import acpki
import drtio_aux_controller import drtio_aux_controller
import zynq_clocking import zynq_clocking
import cxp_4r_fmc
from config import generate_ident, write_csr_file, write_mem_file, write_rustc_cfg_file from config import generate_ident, write_csr_file, write_mem_file, write_rustc_cfg_file
class SMAClkinForward(Module): class SMAClkinForward(Module):
@ -139,7 +138,7 @@ class ZC706(SoCCore):
platform.add_extension(si5324_fmc33) platform.add_extension(si5324_fmc33)
self.comb += platform.request("si5324_33").rst_n.eq(1) self.comb += platform.request("si5324_33").rst_n.eq(1)
self.cdr_clk = Signal() cdr_clk = Signal()
cdr_clk_buf = Signal() cdr_clk_buf = Signal()
si5324_out = platform.request("si5324_clkout") si5324_out = platform.request("si5324_clkout")
platform.add_period_constraint(si5324_out.p, 8.0) platform.add_period_constraint(si5324_out.p, 8.0)
@ -147,11 +146,11 @@ class ZC706(SoCCore):
Instance("IBUFDS_GTE2", Instance("IBUFDS_GTE2",
i_CEB=0, i_CEB=0,
i_I=si5324_out.p, i_IB=si5324_out.n, i_I=si5324_out.p, i_IB=si5324_out.n,
o_O=self.cdr_clk, o_O=cdr_clk,
p_CLKCM_CFG="TRUE", p_CLKCM_CFG="TRUE",
p_CLKRCV_TRST="TRUE", p_CLKRCV_TRST="TRUE",
p_CLKSWING_CFG=3), p_CLKSWING_CFG=3),
Instance("BUFG", i_I=self.cdr_clk, o_O=cdr_clk_buf) Instance("BUFG", i_I=cdr_clk, o_O=cdr_clk_buf)
] ]
self.config["HAS_SI5324"] = None self.config["HAS_SI5324"] = None
self.config["SI5324_AS_SYNTHESIZER"] = None self.config["SI5324_AS_SYNTHESIZER"] = None
@ -653,56 +652,6 @@ class _NIST_QC2_RTIO:
self.add_rtio(rtio_channels) self.add_rtio(rtio_channels)
class _CXP_4R_FMC_RTIO():
"""
CoaXpress host FMC card
"""
def __init__(self):
platform = self.platform
platform.add_extension(cxp_4r_fmc.fmc_adapter_io)
platform.add_extension(leds_fmc33)
rtio_channels = []
clk_freq = 125e6
self.submodules.cxp_grabber = cxp_grabber.CXPGrabber(
refclk=self.cdr_clk,
tx_pads=[platform.request("CXP_LS", 0)],
rx_pads=[platform.request("CXP_HS", 0)],
sys_clk_freq=clk_freq,
)
mem_size = self.cxp_grabber.core.get_mem_size()
# upper half is tx while lower half is rx
memory_address = self.axi2csr.register_port(self.cxp_grabber.core.get_tx_port(), mem_size)
self.axi2csr.register_port(self.cxp_grabber.core.get_rx_port(), mem_size)
self.add_memory_region("cxp_mem", self.mem_map["csr"] + memory_address, mem_size * 2)
self.csr_devices.append("cxp_grabber")
print("CoaXPress at RTIO channel 0x{:06x}".format(len(rtio_channels)))
rtio_channels += [
rtio.Channel(self.cxp_grabber.trigger),
rtio.Channel(self.cxp_grabber.config),
rtio.Channel(self.cxp_grabber.gate_data),
]
# max freq of cxp_gt_rx = linerate/internal_datawidth = 12.5Gbps/40 = 312.5MHz
# zc706 use speed grade 2 which only support up to 10.3125Gbps (~4ns)
# pushing to 12.5Gbps (3.2ns) will result in Pulse width violation but setup/hold times will still meet
rx = self.cxp_grabber.phy_rx.phys[0]
platform.add_period_constraint(rx.gtx.cd_cxp_gt_rx.clk, 3.2)
# constraint the clk path
platform.add_false_path_constraints(self.sys_crg.cd_sys.clk, rx.gtx.cd_cxp_gt_rx.clk)
# Add a user LED for rtio moninj
print("USER LED at RTIO channel 0x{:06x}".format(len(rtio_channels)))
phy = ttl_simple.Output(self.platform.request("user_led_33", 0))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
self.config["HAS_RTIO_LOG"] = None
rtio_channels.append(rtio.LogChannel())
self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels)
self.add_rtio(rtio_channels)
class NIST_CLOCK(ZC706, _NIST_CLOCK_RTIO): class NIST_CLOCK(ZC706, _NIST_CLOCK_RTIO):
def __init__(self, acpki, drtio100mhz): def __init__(self, acpki, drtio100mhz):
ZC706.__init__(self, acpki) ZC706.__init__(self, acpki)
@ -735,13 +684,8 @@ class NIST_QC2_Satellite(_SatelliteBase, _NIST_QC2_RTIO):
_SatelliteBase.__init__(self, acpki, drtio100mhz) _SatelliteBase.__init__(self, acpki, drtio100mhz)
_NIST_QC2_RTIO.__init__(self) _NIST_QC2_RTIO.__init__(self)
class CXP_4R_FMC(ZC706, _CXP_4R_FMC_RTIO):
def __init__(self, acpki, drtio100mhz):
ZC706.__init__(self, acpki)
_CXP_4R_FMC_RTIO.__init__(self)
VARIANTS = {cls.__name__.lower(): cls for cls in [NIST_CLOCK, NIST_CLOCK_Master, NIST_CLOCK_Satellite, VARIANTS = {cls.__name__.lower(): cls for cls in [NIST_CLOCK, NIST_CLOCK_Master, NIST_CLOCK_Satellite,
NIST_QC2, NIST_QC2_Master, NIST_QC2_Satellite, CXP_4R_FMC]} NIST_QC2, NIST_QC2_Master, NIST_QC2_Satellite]}
def main(): def main():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(

View File

@ -24,7 +24,6 @@ core_io = { git = "https://git.m-labs.hk/M-Labs/rs-core_io.git", rev = "e9d3edf0
embedded-hal = "0.2" embedded-hal = "0.2"
nb = "1.0" nb = "1.0"
void = { version = "1", default-features = false } void = { version = "1", default-features = false }
byteorder = { version = "1.3", default-features = false }
io = { path = "../libio", features = ["byteorder"] } io = { path = "../libio", features = ["byteorder"] }
libboard_zynq = { path = "@@ZYNQ_RS@@/libboard_zynq" } libboard_zynq = { path = "@@ZYNQ_RS@@/libboard_zynq" }

View File

@ -1,305 +0,0 @@
use core::fmt;
use embedded_hal::blocking::delay::DelayMs;
use libboard_zynq::{time::Milliseconds, timer::GlobalTimer};
use log::debug;
use crate::{cxp_ctrl::Error as CtrlErr,
cxp_packet::{read_u32, read_u64, reset_tag, send_test_packet, write_bytes_no_ack, write_u32, write_u64},
cxp_phys::{rx, tx, CXPSpeed},
pl::csr};
// Bootstrap registers address
const REVISION: u32 = 0x0004;
const CONNECTION_RESET: u32 = 0x4000;
const DEVICE_CONNECTION_ID: u32 = 0x4004;
const MASTER_HOST_CONNECTION_ID: u32 = 0x4008;
const STREAM_PACKET_SIZE_MAX: u32 = 0x4010;
const CONNECTION_CFG: u32 = 0x4014;
const CONNECTION_CFG_DEFAULT: u32 = 0x4018;
const TESTMODE: u32 = 0x401C;
const TEST_ERROR_COUNT_SELECTOR: u32 = 0x4020;
const TEST_ERROR_COUNT: u32 = 0x4024;
const TEST_PACKET_COUNT_TX: u32 = 0x4028;
const TEST_PACKET_COUNT_RX: u32 = 0x4030;
const VERSION_SUPPORTED: u32 = 0x4044;
const VERSION_USED: u32 = 0x4048;
// Setup const
const CHANNEL_LEN: u8 = 1;
const HOST_CONNECTION_ID: u32 = 0x00006303; // TODO: rename to CXP grabber sinara number when it comes out
// The MAX_STREAM_PAK_SIZE should be set as large as possible - Section 9.5.2 (CXP-001-2021)
// Since the ROI pipeline just consume all pixel data without buffering, any big number will do.
const MAX_STREAM_PAK_SIZE: u32 = 16384; // 16 KiB
const TX_TEST_CNT: u8 = 10;
// From DS191 (v1.18.1), max CDR time lock is 37*10^6 UI,
// 37*10^6 UI at lowest CXP linerate of 1.25Gbps = 29.6 ms, double it to account for overhead
const MONITOR_TIMEOUT_MS: u64 = 60;
pub enum Error {
CameraNotDetected,
ConnectionLost,
UnstableRX,
UnstableTX,
UnsupportedSpeed(u32),
UnsupportedTopology,
UnsupportedVersion,
CtrlPacketError(CtrlErr),
}
impl From<CtrlErr> for Error {
fn from(value: CtrlErr) -> Error {
Error::CtrlPacketError(value)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Error::CameraNotDetected => write!(f, "CameraNotDetected"),
&Error::ConnectionLost => write!(f, "ConnectionLost - Channel #0 cannot be detected"),
&Error::UnstableRX => write!(f, "UnstableRX - RX connection test failed"),
&Error::UnstableTX => write!(f, "UnstableTX - TX connection test failed"),
&Error::UnsupportedSpeed(linerate_code) => write!(
f,
"UnsupportedSpeed - {:#X} linerate code is not supported",
linerate_code
),
&Error::UnsupportedTopology => {
write!(
f,
"UnsupportedTopology - Channel #0 should be connected to the master channel"
)
}
&Error::UnsupportedVersion => write!(
f,
"UnsupportedVersion - Cannot find a compatible protocol version between the cxp grabber & camera"
),
&Error::CtrlPacketError(ref err) => write!(f, "{}", err),
}
}
}
pub fn master_channel_ready() -> bool {
unsafe { csr::cxp_grabber::core_rx_ready_read() == 1 }
}
fn monitor_channel_status_timeout(timer: GlobalTimer) -> Result<(), Error> {
let limit = timer.get_time() + Milliseconds(MONITOR_TIMEOUT_MS);
while timer.get_time() < limit {
if master_channel_ready() {
return Ok(());
}
}
Err(Error::ConnectionLost)
}
pub fn discover_camera(mut timer: GlobalTimer) -> Result<(), Error> {
// Section 7.6 (CXP-001-2021)
// 1.25Gbps (CXP_1) and 3.125Gbps (CXP_3) are the discovery rate
// both linerate need to be checked as camera only support ONE of discovery rates
for speed in [CXPSpeed::CXP1, CXPSpeed::CXP3].iter() {
// Section 12.1.2 (CXP-001-2021)
// set tx linerate -> send ConnectionReset -> wait 200ms -> set rx linerate -> monitor connection status with a timeout
tx::change_linerate(*speed);
write_bytes_no_ack(CONNECTION_RESET, &1_u32.to_be_bytes(), false)?;
timer.delay_ms(200);
rx::change_linerate(*speed);
if monitor_channel_status_timeout(timer).is_ok() {
debug!("camera detected at linerate {:}", speed);
return Ok(());
}
}
Err(Error::CameraNotDetected)
}
fn check_master_channel() -> Result<(), Error> {
if read_u32(DEVICE_CONNECTION_ID, false)? == 0 {
Ok(())
} else {
Err(Error::UnsupportedTopology)
}
}
fn disable_excess_channels(timer: GlobalTimer) -> Result<(), Error> {
let current_cfg = read_u32(CONNECTION_CFG, false)?;
let active_camera_chs = current_cfg >> 16;
// After camera receive ConnectionReset, only the master connection should be active while
// the extension connections shall not be active - Section 12.3.33 (CXP-001-2021)
// In case some camera didn't follow the spec properly (e.g. Basler boA2448-250cm),
// the grabber need to manually disable the excess channels
if active_camera_chs > CHANNEL_LEN as u32 {
debug!(
"only {} channel(s) is available on cxp grabber, disabling excess channels on camera",
CHANNEL_LEN
);
// disable excess channels and preserve the discovery linerate
write_u32(CONNECTION_CFG, current_cfg & 0xFFFF | (CHANNEL_LEN as u32) << 16, false)?;
// check if the master channel is down after the cfg change
monitor_channel_status_timeout(timer)
} else {
Ok(())
}
}
fn set_host_connection_id() -> Result<(), Error> {
debug!("set host connection id to = {:#X}", HOST_CONNECTION_ID);
write_u32(MASTER_HOST_CONNECTION_ID, HOST_CONNECTION_ID, false)?;
Ok(())
}
fn negotiate_cxp_version() -> Result<bool, Error> {
let rev = read_u32(REVISION, false)?;
let mut major_rev: u32 = rev >> 16;
let mut minor_rev: u32 = rev & 0xFF;
debug!("camera's CoaXPress revision is {}.{}", major_rev, minor_rev);
// Section 12.1.4 (CXP-001-2021)
// For CXP 2.0 and onward, Host need to check the VersionSupported register to determine
// the highest common version that supported by both device & host
if major_rev >= 2 {
let reg = read_u32(VERSION_SUPPORTED, false)?;
// grabber support CXP 2.1, 2.0 and 1.1 only
if ((reg >> 3) & 1) == 1 {
major_rev = 2;
minor_rev = 1;
} else if ((reg >> 2) & 1) == 1 {
major_rev = 2;
minor_rev = 0;
} else if ((reg >> 1) & 1) == 1 {
major_rev = 1;
minor_rev = 1;
} else {
return Err(Error::UnsupportedVersion);
}
write_u32(VERSION_USED, major_rev << 16 | minor_rev, false)?;
}
debug!(
"both camera and cxp grabber support CoaXPress {}.{}, switch to CoaXPress {}.{} protocol now",
major_rev, minor_rev, major_rev, minor_rev
);
Ok(major_rev >= 2)
}
fn negotiate_pak_max_size(with_tag: bool) -> Result<(), Error> {
write_u32(STREAM_PACKET_SIZE_MAX, MAX_STREAM_PAK_SIZE, with_tag)?;
Ok(())
}
fn decode_cxp_speed(linerate_code: u32) -> Option<CXPSpeed> {
match linerate_code {
0x28 => Some(CXPSpeed::CXP1),
0x30 => Some(CXPSpeed::CXP2),
0x38 => Some(CXPSpeed::CXP3),
0x40 => Some(CXPSpeed::CXP5),
0x48 => Some(CXPSpeed::CXP6),
0x50 => Some(CXPSpeed::CXP10),
0x58 => Some(CXPSpeed::CXP12),
_ => None,
}
}
fn set_operation_linerate(with_tag: bool, timer: GlobalTimer) -> Result<(), Error> {
let recommended_linerate_code = read_u32(CONNECTION_CFG_DEFAULT, with_tag)? & 0xFFFF;
if let Some(speed) = decode_cxp_speed(recommended_linerate_code) {
debug!("changing linerate to {}", speed);
// preserve the number of active channels
let current_cfg = read_u32(CONNECTION_CFG, with_tag)?;
write_u32(
CONNECTION_CFG,
current_cfg & 0xFFFF0000 | recommended_linerate_code,
with_tag,
)?;
tx::change_linerate(speed);
rx::change_linerate(speed);
monitor_channel_status_timeout(timer)
} else {
Err(Error::UnsupportedSpeed(recommended_linerate_code))
}
}
fn test_counter_reset(with_tag: bool) -> Result<(), Error> {
unsafe { csr::cxp_grabber::core_rx_test_counts_reset_write(1) };
write_u32(TEST_ERROR_COUNT_SELECTOR, 0, with_tag)?;
write_u32(TEST_ERROR_COUNT, 0, with_tag)?;
write_u64(TEST_PACKET_COUNT_TX, 0, with_tag)?;
write_u64(TEST_PACKET_COUNT_RX, 0, with_tag)?;
Ok(())
}
fn verify_test_result(with_tag: bool) -> Result<(), Error> {
write_u32(TEST_ERROR_COUNT_SELECTOR, 0, with_tag)?;
// Section 9.9.3 (CXP-001-2021)
// verify grabber -> camera connection test result
if read_u64(TEST_PACKET_COUNT_RX, with_tag)? != TX_TEST_CNT as u64 {
return Err(Error::UnstableTX);
};
if read_u32(TEST_ERROR_COUNT, with_tag)? > 0 {
return Err(Error::UnstableTX);
};
// Section 9.9.4 (CXP-001-2021)
// verify camera -> grabber connection test result
let camera_test_pak_cnt = read_u64(TEST_PACKET_COUNT_TX, true)?;
unsafe {
if csr::cxp_grabber::core_rx_test_packet_counter_read() != camera_test_pak_cnt as u16 {
return Err(Error::UnstableRX);
};
if csr::cxp_grabber::core_rx_test_error_counter_read() > 0 {
return Err(Error::UnstableRX);
};
};
debug!("channel #0 passed connection test");
Ok(())
}
fn test_channel_stability(with_tag: bool, mut timer: GlobalTimer) -> Result<(), Error> {
test_counter_reset(with_tag)?;
// cxp grabber -> camera connection test
for _ in 0..TX_TEST_CNT {
send_test_packet()?;
// sending the whole test sequence @ 20.833Mbps will take a minimum of 1.972ms
// and leave some room to send IDLE word
timer.delay_ms(2);
}
// camera -> grabber connection test
// enabling the TESTMODE on master channel will send test packets on all channels
// and ctrl packet write overhead is used as a delay
write_u32(TESTMODE, 1, with_tag)?;
write_u32(TESTMODE, 0, with_tag)?;
verify_test_result(with_tag)?;
Ok(())
}
pub fn camera_setup(timer: GlobalTimer) -> Result<bool, Error> {
reset_tag();
check_master_channel()?;
disable_excess_channels(timer)?;
set_host_connection_id()?;
let with_tag = negotiate_cxp_version()?;
negotiate_pak_max_size(with_tag)?;
set_operation_linerate(with_tag, timer)?;
test_channel_stability(with_tag, timer)?;
Ok(with_tag)
}

View File

@ -1,250 +0,0 @@
use core::fmt;
use byteorder::{ByteOrder, NetworkEndian};
use core_io::{Error as IoError, Read, Write};
use crc::crc32::checksum_ieee;
use io::{Cursor, ProtoRead, ProtoWrite};
pub const CTRL_PACKET_MAXSIZE: usize = 128; // for compatibility with version1.x compliant Devices - Section 12.1.6 (CXP-001-2021)
pub const DATA_MAXSIZE: usize =
CTRL_PACKET_MAXSIZE - /*packet start KCodes, data packet types, CMD, Tag, Addr, CRC, packet end KCode*/4*7;
pub enum Error {
CorruptedPacket,
CtrlAckError(u8),
Io(IoError),
LengthOutOfRange(u32),
TagMismatch,
TimedOut,
UnexpectedReply,
UnknownPacket(u8),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Error::CorruptedPacket => write!(f, "CorruptedPacket - Received packet fail CRC test"),
&Error::CtrlAckError(ref ack_code) => match ack_code {
0x40 => write!(f, "CtrlAckError - Invalid Address"),
0x41 => write!(f, "CtrlAckError - Invalid data for the address"),
0x42 => write!(f, "CtrlAckError - Invalid operation code"),
0x43 => write!(f, "CtrlAckError - Write attempted to a read-only address"),
0x44 => write!(f, "CtrlAckError - Read attempted from a write-only address"),
0x45 => write!(f, "CtrlAckError - Size field too large, exceed packet size limit"),
0x46 => write!(f, "CtrlAckError - Message size is inconsistent with size field"),
0x47 => write!(f, "CtrlAckError - Malformed packet"),
0x80 => write!(f, "CtrlAckError - Failed CRC test in last received command"),
_ => write!(f, "CtrlAckError - Unknown ack code {:#X}", ack_code),
},
&Error::Io(ref err) => write!(f, "IoError - {:?}", err),
&Error::LengthOutOfRange(length) => write!(
f,
"LengthOutOfRange - Message length {} is not between 1 and {}",
length, DATA_MAXSIZE
),
&Error::TagMismatch => write!(f, "TagMismatch - Received tag is different from the transmitted tag"),
&Error::TimedOut => write!(f, "MessageTimedOut"),
&Error::UnexpectedReply => write!(f, "UnexpectedReply"),
&Error::UnknownPacket(packet_type) => {
write!(f, "UnknownPacket - Unknown packet type id {:#X} ", packet_type)
}
}
}
}
impl From<IoError> for Error {
fn from(value: IoError) -> Error {
Error::Io(value)
}
}
fn get_cxp_crc(bytes: &[u8]) -> u32 {
// Section 9.2.2.2 (CXP-001-2021)
// Only Control packet need CRC32 appended in the end of the packet
// CoaXpress use the polynomial of IEEE-802.3 (Ethernet) CRC but the checksum calculation is different
(!checksum_ieee(bytes)).swap_bytes()
}
trait CxpRead: Read {
fn read_exact_4x(&mut self, buf: &mut [u8]) -> Result<(), Error> {
let mut temp = [0u8; 4];
for byte in buf {
// Section 9.2.2.1 (CXP-001-2021)
// decoder should immune to single bit errors when handling 4x duplicated characters
self.read_exact(&mut temp)?;
let [a, b, c, d] = temp;
// vote and return majority
*byte = a & b & c | a & b & d | a & c & d | b & c & d;
}
Ok(())
}
fn read_4x_u8(&mut self) -> Result<u8, Error> {
let mut bytes = [0; 1];
self.read_exact_4x(&mut bytes)?;
Ok(bytes[0])
}
}
impl<T: Read> CxpRead for T {}
impl<T: Write> CxpWrite for T {}
#[derive(Debug)]
pub enum RXCTRLPacket {
CtrlReply {
tag: Option<u8>,
length: u32,
data: [u8; DATA_MAXSIZE],
},
CtrlDelay {
tag: Option<u8>,
time: u32,
},
CtrlAck {
tag: Option<u8>,
},
}
impl RXCTRLPacket {
pub fn read_from(reader: &mut Cursor<&[u8]>) -> Result<Self, Error> {
match reader.read_4x_u8()? {
0x03 => RXCTRLPacket::get_ctrl_packet(reader, false),
0x06 => RXCTRLPacket::get_ctrl_packet(reader, true),
ty => Err(Error::UnknownPacket(ty)),
}
}
fn get_ctrl_packet(reader: &mut Cursor<&[u8]>, with_tag: bool) -> Result<Self, Error> {
let mut tag: Option<u8> = None;
if with_tag {
tag = Some(reader.read_4x_u8()?);
}
let ackcode = reader.read_4x_u8()?;
match ackcode {
0x00 | 0x04 => {
let length = reader.read_u32::<NetworkEndian>()?;
let mut data: [u8; DATA_MAXSIZE] = [0; DATA_MAXSIZE];
reader.read(&mut data[0..length as usize])?;
// Section 9.6.3 (CXP-001-2021)
// when length is not multiple of 4, dummy bits are padded to align to the word boundary
// set position to next word boundary for CRC calculation
let padding = (4 - (reader.position() % 4)) % 4;
reader.set_position(reader.position() + padding);
// Section 9.6.3 (CXP-001-2021)
// only bytes after the first 4 are used in calculating the checksum
let checksum = get_cxp_crc(&reader.get_ref()[4..reader.position()]);
if reader.read_u32::<NetworkEndian>()? != checksum {
return Err(Error::CorruptedPacket);
}
if ackcode == 0x00 {
return Ok(RXCTRLPacket::CtrlReply { tag, length, data });
} else {
return Ok(RXCTRLPacket::CtrlDelay {
tag,
time: NetworkEndian::read_u32(&data[..4]),
});
}
}
0x01 => return Ok(RXCTRLPacket::CtrlAck { tag }),
_ => return Err(Error::CtrlAckError(ackcode)),
}
}
}
trait CxpWrite: Write {
fn write_all_4x(&mut self, buf: &[u8]) -> Result<(), Error> {
for byte in buf {
self.write_all(&[*byte; 4])?;
}
Ok(())
}
fn write_4x_u8(&mut self, value: u8) -> Result<(), Error> {
self.write_all_4x(&[value])
}
}
#[derive(Debug)]
pub enum TXCTRLPacket {
CtrlRead {
tag: Option<u8>,
addr: u32,
length: u32,
},
CtrlWrite {
tag: Option<u8>,
addr: u32,
length: u32,
data: [u8; DATA_MAXSIZE],
},
}
impl TXCTRLPacket {
pub fn write_to(&self, writer: &mut Cursor<&mut [u8]>) -> Result<(), Error> {
match *self {
TXCTRLPacket::CtrlRead { tag, addr, length } => {
match tag {
Some(t) => {
writer.write_4x_u8(0x05)?;
writer.write_4x_u8(t)?;
}
None => {
writer.write_4x_u8(0x02)?;
}
}
let mut bytes = [0; 3];
NetworkEndian::write_u24(&mut bytes, length);
writer.write_all(&[0x00, bytes[0], bytes[1], bytes[2]])?;
writer.write_u32::<NetworkEndian>(addr)?;
// Section 9.6.2 (CXP-001-2021)
// only bytes after the first 4 are used in calculating the checksum
let checksum = get_cxp_crc(&writer.get_ref()[4..writer.position()]);
writer.write_u32::<NetworkEndian>(checksum)?;
}
TXCTRLPacket::CtrlWrite {
tag,
addr,
length,
data,
} => {
match tag {
Some(t) => {
writer.write_4x_u8(0x05)?;
writer.write_4x_u8(t)?;
}
None => {
writer.write_4x_u8(0x02)?;
}
}
let mut bytes = [0; 3];
NetworkEndian::write_u24(&mut bytes, length);
writer.write_all(&[0x01, bytes[0], bytes[1], bytes[2]])?;
writer.write_u32::<NetworkEndian>(addr)?;
writer.write_all(&data[0..length as usize])?;
// Section 9.6.2 (CXP-001-2021)
// when length is not multiple of 4, dummy bites are padded to align to the word boundary
let padding = (4 - (writer.position() % 4)) % 4;
for _ in 0..padding {
writer.write_u8(0)?;
}
// Section 9.6.2 (CXP-001-2021)
// only bytes after the first 4 are used in calculating the checksum
let checksum = get_cxp_crc(&writer.get_ref()[4..writer.position()]);
writer.write_u32::<NetworkEndian>(checksum)?;
}
}
Ok(())
}
}

View File

@ -1,90 +0,0 @@
use libboard_zynq::timer::GlobalTimer;
use libcortex_a9::mutex::Mutex;
use log::{error, info};
use crate::{cxp_camera_setup::{camera_setup, discover_camera, master_channel_ready},
pl::csr};
#[derive(Clone, Copy, Debug, PartialEq)]
enum State {
Connected,
Detected,
Disconnected,
}
// Mutex as they are needed by core1 cxp api calls
static mut STATE: Mutex<State> = Mutex::new(State::Disconnected);
static mut WITH_TAG: Mutex<bool> = Mutex::new(false);
pub fn camera_connected() -> bool {
unsafe { *STATE.lock() == State::Connected }
}
pub fn with_tag() -> bool {
unsafe { *WITH_TAG.lock() }
}
pub fn tick(timer: GlobalTimer) {
let mut state_guard = unsafe { STATE.lock() };
let mut with_tag_guard = unsafe { WITH_TAG.lock() };
*state_guard = match *state_guard {
State::Disconnected => match discover_camera(timer) {
Ok(_) => {
info!("camera detected, setting up camera...");
State::Detected
}
Err(_) => State::Disconnected,
},
State::Detected => match camera_setup(timer) {
Ok(with_tag) => {
info!("camera setup complete");
*with_tag_guard = with_tag;
State::Connected
}
Err(e) => {
error!("camera setup failure: {}", e);
*with_tag_guard = false;
State::Disconnected
}
},
State::Connected => {
if master_channel_ready() {
unsafe {
if csr::cxp_grabber::stream_decoder_crc_error_read() == 1 {
error!("frame packet has CRC error");
csr::cxp_grabber::stream_decoder_crc_error_write(1);
};
if csr::cxp_grabber::stream_decoder_stream_type_error_read() == 1 {
error!("Non CoaXPress stream type detected, the CXP grabber doesn't support GenDC stream type");
csr::cxp_grabber::stream_decoder_stream_type_error_write(1);
};
if csr::cxp_grabber::core_rx_trigger_ack_read() == 1 {
info!("received CXP linktrigger ack");
csr::cxp_grabber::core_rx_trigger_ack_write(1);
};
if csr::cxp_grabber::stream_decoder_new_frame_read() == 1 {
let width = csr::cxp_grabber::stream_decoder_x_size_read();
let height = csr::cxp_grabber::stream_decoder_y_size_read();
match csr::cxp_grabber::stream_decoder_pixel_format_code_read() {
0x0101 => info!("received frame: {}x{} with MONO8 format", width, height),
0x0102 => info!("received frame: {}x{} with MONO10 format", width, height),
0x0103 => info!("received frame: {}x{} with MONO12 format", width, height),
0x0104 => info!("received frame: {}x{} with MONO14 format", width, height),
0x0105 => info!("received frame: {}x{} with MONO16 format", width, height),
_ => info!("received frame: {}x{} with Unsupported pixel format", width, height),
};
csr::cxp_grabber::stream_decoder_new_frame_write(1);
};
}
State::Connected
} else {
*with_tag_guard = false;
info!("camera disconnected");
State::Disconnected
}
}
};
}

View File

@ -1,192 +0,0 @@
use core::slice;
use byteorder::{ByteOrder, NetworkEndian};
use io::Cursor;
use libboard_zynq::{time::Milliseconds, timer::GlobalTimer};
use crate::{cxp_ctrl::{Error, RXCTRLPacket, TXCTRLPacket, CTRL_PACKET_MAXSIZE, DATA_MAXSIZE},
mem::mem,
pl::csr};
const TRANSMISSION_TIMEOUT: u64 = 200;
// Section 9.6.1.2 (CXP-001-2021)
// CTRL packet need to be tagged for CXP 2.0 or greater
static mut TAG: u8 = 0;
pub fn reset_tag() {
unsafe { TAG = 0 };
}
fn increment_tag() {
unsafe { TAG = TAG.wrapping_add(1) };
}
fn check_tag(tag: Option<u8>) -> Result<(), Error> {
unsafe {
if tag.is_some() && tag != Some(TAG) {
Err(Error::TagMismatch)
} else {
Ok(())
}
}
}
fn receive_ctrl_packet() -> Result<Option<RXCTRLPacket>, Error> {
if unsafe { csr::cxp_grabber::core_rx_pending_packet_read() == 1 } {
unsafe {
let read_buffer_ptr = csr::cxp_grabber::core_rx_read_ptr_read() as usize;
let ptr = (mem::CXP_MEM_BASE + mem::CXP_MEM_SIZE / 2 + read_buffer_ptr * CTRL_PACKET_MAXSIZE) as *mut u32;
let mut reader = Cursor::new(slice::from_raw_parts(ptr as *const u8, CTRL_PACKET_MAXSIZE));
let packet = RXCTRLPacket::read_from(&mut reader);
csr::cxp_grabber::core_rx_pending_packet_write(1);
Ok(Some(packet?))
}
} else {
Ok(None)
}
}
fn receive_ctrl_packet_timeout(timeout_ms: u64) -> Result<RXCTRLPacket, Error> {
// assume timer was initialized successfully
let timer = unsafe { GlobalTimer::get() };
let limit = timer.get_time() + Milliseconds(timeout_ms);
while timer.get_time() < limit {
match receive_ctrl_packet()? {
None => (),
Some(packet) => return Ok(packet),
}
}
Err(Error::TimedOut)
}
fn send_ctrl_packet(packet: &TXCTRLPacket) -> Result<(), Error> {
unsafe {
while csr::cxp_grabber::core_tx_writer_busy_read() == 1 {}
let ptr = mem::CXP_MEM_BASE as *mut u32;
let mut writer = Cursor::new(slice::from_raw_parts_mut(ptr as *mut u8, CTRL_PACKET_MAXSIZE));
packet.write_to(&mut writer)?;
csr::cxp_grabber::core_tx_writer_word_len_write((writer.position() / 4) as u8);
csr::cxp_grabber::core_tx_writer_stb_write(1);
}
Ok(())
}
pub fn send_test_packet() -> Result<(), Error> {
unsafe {
while csr::cxp_grabber::core_tx_writer_busy_read() == 1 {}
csr::cxp_grabber::core_tx_writer_stb_testseq_write(1);
}
Ok(())
}
fn get_ctrl_ack(timeout: u64) -> Result<(), Error> {
match receive_ctrl_packet_timeout(timeout) {
Ok(RXCTRLPacket::CtrlAck { tag }) => {
check_tag(tag)?;
Ok(())
}
Ok(RXCTRLPacket::CtrlDelay { tag, time }) => {
check_tag(tag)?;
get_ctrl_ack(time as u64)
}
Ok(_) => Err(Error::UnexpectedReply),
Err(e) => Err(e),
}
}
fn get_ctrl_reply(timeout: u64, expected_length: u32) -> Result<[u8; DATA_MAXSIZE], Error> {
match receive_ctrl_packet_timeout(timeout) {
Ok(RXCTRLPacket::CtrlReply { tag, length, data }) => {
check_tag(tag)?;
if length != expected_length {
return Err(Error::UnexpectedReply);
};
Ok(data)
}
Ok(RXCTRLPacket::CtrlDelay { tag, time }) => {
check_tag(tag)?;
get_ctrl_reply(time as u64, expected_length)
}
Ok(_) => Err(Error::UnexpectedReply),
Err(e) => Err(e),
}
}
fn check_length(length: u32) -> Result<(), Error> {
if length > DATA_MAXSIZE as u32 || length == 0 {
Err(Error::LengthOutOfRange(length))
} else {
Ok(())
}
}
pub fn write_bytes_no_ack(addr: u32, val: &[u8], with_tag: bool) -> Result<(), Error> {
let length = val.len() as u32;
check_length(length)?;
let mut data: [u8; DATA_MAXSIZE] = [0; DATA_MAXSIZE];
data[..length as usize].clone_from_slice(val);
let tag: Option<u8> = if with_tag { Some(unsafe { TAG }) } else { None };
send_ctrl_packet(&TXCTRLPacket::CtrlWrite {
tag,
addr,
length,
data,
})
}
pub fn write_bytes(addr: u32, val: &[u8], with_tag: bool) -> Result<(), Error> {
write_bytes_no_ack(addr, val, with_tag)?;
get_ctrl_ack(TRANSMISSION_TIMEOUT)?;
if with_tag {
increment_tag();
};
Ok(())
}
pub fn write_u32(addr: u32, val: u32, with_tag: bool) -> Result<(), Error> {
write_bytes(addr, &val.to_be_bytes(), with_tag)
}
pub fn write_u64(addr: u32, val: u64, with_tag: bool) -> Result<(), Error> {
write_bytes(addr, &val.to_be_bytes(), with_tag)
}
pub fn read_bytes(addr: u32, bytes: &mut [u8], with_tag: bool) -> Result<(), Error> {
let length = bytes.len() as u32;
check_length(length)?;
let tag: Option<u8> = if with_tag { Some(unsafe { TAG }) } else { None };
send_ctrl_packet(&TXCTRLPacket::CtrlRead { tag, addr, length })?;
let data = get_ctrl_reply(TRANSMISSION_TIMEOUT, length)?;
bytes.clone_from_slice(&data[..length as usize]);
if with_tag {
increment_tag();
};
Ok(())
}
pub fn read_u32(addr: u32, with_tag: bool) -> Result<u32, Error> {
let mut bytes: [u8; 4] = [0; 4];
read_bytes(addr, &mut bytes, with_tag)?;
let val = NetworkEndian::read_u32(&bytes);
Ok(val)
}
pub fn read_u64(addr: u32, with_tag: bool) -> Result<u64, Error> {
let mut bytes: [u8; 8] = [0; 8];
read_bytes(addr, &mut bytes, with_tag)?;
let val = NetworkEndian::read_u64(&bytes);
Ok(val)
}

View File

@ -1,193 +0,0 @@
use core::fmt;
use crate::pl::csr;
#[derive(Clone, Copy)]
pub enum CXPSpeed {
CXP1,
CXP2,
CXP3,
CXP5,
CXP6,
CXP10,
CXP12,
}
impl fmt::Display for CXPSpeed {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&CXPSpeed::CXP1 => write!(f, "1.25 Gbps"),
&CXPSpeed::CXP2 => write!(f, "2.5 Gbps"),
&CXPSpeed::CXP3 => write!(f, "3.125 Gbps"),
&CXPSpeed::CXP5 => write!(f, "5 Gbps"),
&CXPSpeed::CXP6 => write!(f, "6.25 Gbps"),
&CXPSpeed::CXP10 => write!(f, "10 Gbps"),
&CXPSpeed::CXP12 => write!(f, "12.5 Gbps"),
}
}
}
pub fn setup() {
let init_speed = CXPSpeed::CXP1;
tx::setup();
tx::change_linerate(init_speed);
rx::setup();
rx::change_linerate(init_speed);
}
pub mod tx {
use super::*;
pub fn setup() {
unsafe {
csr::cxp_grabber::phy_tx_enable_write(1);
}
}
pub fn change_linerate(speed: CXPSpeed) {
unsafe {
match speed {
CXPSpeed::CXP1 | CXPSpeed::CXP2 | CXPSpeed::CXP3 | CXPSpeed::CXP5 | CXPSpeed::CXP6 => {
csr::cxp_grabber::phy_tx_bitrate2x_enable_write(0);
}
CXPSpeed::CXP10 | CXPSpeed::CXP12 => {
csr::cxp_grabber::phy_tx_bitrate2x_enable_write(1);
}
};
csr::cxp_grabber::phy_tx_clk_reset_write(1);
}
}
}
pub mod rx {
use super::*;
pub fn setup() {
unsafe {
csr::cxp_grabber::phy_rx_gtx_refclk_stable_write(1);
}
}
pub fn change_linerate(speed: CXPSpeed) {
change_qpll_fb_divider(speed);
change_gtx_divider(speed);
change_cdr_cfg(speed);
unsafe {
csr::cxp_grabber::phy_rx_qpll_reset_write(1);
while csr::cxp_grabber::phy_rx_qpll_locked_read() != 1 {}
// Changing RXOUT_DIV via DRP requires a manual reset
// https://adaptivesupport.amd.com/s/question/0D52E00006hplwnSAA/re-gtx-line-rate-change
csr::cxp_grabber::phy_rx_gtx_restart_write(1);
}
}
fn change_qpll_fb_divider(speed: CXPSpeed) {
let qpll_div_reg = match speed {
CXPSpeed::CXP1 | CXPSpeed::CXP2 | CXPSpeed::CXP5 | CXPSpeed::CXP10 => 0x0120, // FB_Divider = 80, QPLL VCO @ 10GHz
CXPSpeed::CXP3 | CXPSpeed::CXP6 | CXPSpeed::CXP12 => 0x0170, // FB_Divider = 100, QPLL VCO @ 12.5GHz
};
qpll_write(0x36, qpll_div_reg);
}
fn change_gtx_divider(speed: CXPSpeed) {
let div_reg = match speed {
CXPSpeed::CXP1 => 0x33, // RXOUT_DIV = 8
CXPSpeed::CXP2 | CXPSpeed::CXP3 => 0x22, // RXOUT_DIV = 4
CXPSpeed::CXP5 | CXPSpeed::CXP6 => 0x11, // RXOUT_DIV = 2
CXPSpeed::CXP10 | CXPSpeed::CXP12 => 0x00, // RXOUT_DIV = 1
};
gtx_write(0x88, div_reg);
}
fn change_cdr_cfg(speed: CXPSpeed) {
struct CdrConfig {
pub cfg_reg0: u16, // addr = 0xA8
pub cfg_reg1: u16, // addr = 0xA9
pub cfg_reg2: u16, // addr = 0xAA
pub cfg_reg3: u16, // addr = 0xAB
pub cfg_reg4: u16, // addr = 0xAC
}
let cdr_cfg = match speed {
// when RXOUT_DIV = 8
CXPSpeed::CXP1 => CdrConfig {
cfg_reg0: 0x0020,
cfg_reg1: 0x1008,
cfg_reg2: 0x23FF,
cfg_reg3: 0x0000,
cfg_reg4: 0x0003,
},
// when RXOUT_DIV = 4
CXPSpeed::CXP2 | CXPSpeed::CXP5 => CdrConfig {
cfg_reg0: 0x0020,
cfg_reg1: 0x1010,
cfg_reg2: 0x23FF,
cfg_reg3: 0x0000,
cfg_reg4: 0x0003,
},
// when RXOUT_DIV= 2
CXPSpeed::CXP3 | CXPSpeed::CXP6 => CdrConfig {
cfg_reg0: 0x0020,
cfg_reg1: 0x1020,
cfg_reg2: 0x23FF,
cfg_reg3: 0x0000,
cfg_reg4: 0x0003,
},
// when RXOUT_DIV= 1
CXPSpeed::CXP10 | CXPSpeed::CXP12 => CdrConfig {
cfg_reg0: 0x0020,
cfg_reg1: 0x1040,
cfg_reg2: 0x23FF,
cfg_reg3: 0x0000,
cfg_reg4: 0x000B,
},
};
gtx_write(0x0A8, cdr_cfg.cfg_reg0);
gtx_write(0x0A9, cdr_cfg.cfg_reg1);
gtx_write(0x0AA, cdr_cfg.cfg_reg2);
gtx_write(0x0AB, cdr_cfg.cfg_reg3);
gtx_write(0x0AC, cdr_cfg.cfg_reg4);
}
#[allow(dead_code)]
fn gtx_read(address: u16) -> u16 {
unsafe {
csr::cxp_grabber::phy_rx_gtx_daddr_write(address);
csr::cxp_grabber::phy_rx_gtx_dread_write(1);
while csr::cxp_grabber::phy_rx_gtx_dready_read() != 1 {}
csr::cxp_grabber::phy_rx_gtx_dout_read()
}
}
fn gtx_write(address: u16, value: u16) {
unsafe {
csr::cxp_grabber::phy_rx_gtx_daddr_write(address);
csr::cxp_grabber::phy_rx_gtx_din_write(value);
csr::cxp_grabber::phy_rx_gtx_din_stb_write(1);
while csr::cxp_grabber::phy_rx_gtx_dready_read() != 1 {}
}
}
#[allow(dead_code)]
fn qpll_read(address: u8) -> u16 {
unsafe {
csr::cxp_grabber::phy_rx_qpll_daddr_write(address);
csr::cxp_grabber::phy_rx_qpll_dread_write(1);
while csr::cxp_grabber::phy_rx_qpll_dready_read() != 1 {}
csr::cxp_grabber::phy_rx_qpll_dout_read()
}
}
fn qpll_write(address: u8, value: u16) {
unsafe {
csr::cxp_grabber::phy_rx_qpll_daddr_write(address);
csr::cxp_grabber::phy_rx_qpll_din_write(value);
csr::cxp_grabber::phy_rx_qpll_din_stb_write(1);
while csr::cxp_grabber::phy_rx_qpll_dready_read() != 1 {}
}
}
}

View File

@ -1,7 +1,7 @@
use core::{arch::asm, slice}; use core::slice;
use byteorder::NativeEndian;
use core_io::{Error as IoError, ErrorKind as IoErrorKind}; use core_io::{Error as IoError, ErrorKind as IoErrorKind};
use crc;
use io::{proto::{ProtoRead, ProtoWrite}, use io::{proto::{ProtoRead, ProtoWrite},
Cursor}; Cursor};
use libboard_zynq::{time::Milliseconds, timer::GlobalTimer}; use libboard_zynq::{time::Milliseconds, timer::GlobalTimer};
@ -39,7 +39,6 @@ pub fn copy_work_buffer(src: *mut u32, dst: *mut u32, len: isize) {
// fix for artiq-zynq#344 // fix for artiq-zynq#344
unsafe { unsafe {
for i in 0..(len / 4) { for i in 0..(len / 4) {
asm!("", options(preserves_flags, nostack, readonly));
*dst.offset(i) = *src.offset(i); *dst.offset(i) = *src.offset(i);
} }
} }
@ -100,7 +99,7 @@ pub fn recv(linkno: u8) -> Result<Option<Packet>, Error> {
let checksum_at = reader.position() + padding; let checksum_at = reader.position() + padding;
let checksum = crc::crc32::checksum_ieee(&reader.get_ref()[0..checksum_at]); let checksum = crc::crc32::checksum_ieee(&reader.get_ref()[0..checksum_at]);
reader.set_position(checksum_at); reader.set_position(checksum_at);
if reader.read_u32::<NativeEndian>()? != checksum { if reader.read_u32()? != checksum {
return Err(Error::CorruptedPacket); return Err(Error::CorruptedPacket);
} }
Ok(packet) Ok(packet)
@ -147,7 +146,7 @@ pub fn send(linkno: u8, packet: &Packet) -> Result<(), Error> {
} }
let checksum = crc::crc32::checksum_ieee(&writer.get_ref()[0..writer.position()]); let checksum = crc::crc32::checksum_ieee(&writer.get_ref()[0..writer.position()]);
writer.write_u32::<NativeEndian>(checksum)?; writer.write_u32(checksum)?;
Ok(writer.position()) Ok(writer.position())
}) })

View File

@ -1,11 +1,12 @@
use core::slice; use core::slice;
use byteorder::NativeEndian;
use core_io::{Error as IoError, ErrorKind as IoErrorKind}; use core_io::{Error as IoError, ErrorKind as IoErrorKind};
use crc;
use io::{proto::{ProtoRead, ProtoWrite}, use io::{proto::{ProtoRead, ProtoWrite},
Cursor}; Cursor};
use libasync::{block_async, task}; use libasync::{block_async, task};
use libboard_zynq::{time::Milliseconds, timer::GlobalTimer}; use libboard_zynq::{time::Milliseconds, timer::GlobalTimer};
use nb;
use void::Void; use void::Void;
pub use crate::drtioaux_proto::{Packet, MAX_PACKET}; pub use crate::drtioaux_proto::{Packet, MAX_PACKET};
@ -67,7 +68,7 @@ pub async fn recv(linkno: u8) -> Result<Option<Packet>, Error> {
let checksum_at = reader.position() + padding; let checksum_at = reader.position() + padding;
let checksum = crc::crc32::checksum_ieee(&reader.get_ref()[0..checksum_at]); let checksum = crc::crc32::checksum_ieee(&reader.get_ref()[0..checksum_at]);
reader.set_position(checksum_at); reader.set_position(checksum_at);
if reader.read_u32::<NativeEndian>()? != checksum { if reader.read_u32()? != checksum {
return Err(Error::CorruptedPacket); return Err(Error::CorruptedPacket);
} }
Ok(packet) Ok(packet)
@ -123,7 +124,7 @@ pub async fn send(linkno: u8, packet: &Packet) -> Result<(), Error> {
} }
let checksum = crc::crc32::checksum_ieee(&writer.get_ref()[0..writer.position()]); let checksum = crc::crc32::checksum_ieee(&writer.get_ref()[0..writer.position()]);
writer.write_u32::<NativeEndian>(checksum)?; writer.write_u32(checksum)?;
Ok(writer.position()) Ok(writer.position())
}) })

View File

@ -1,5 +1,4 @@
use byteorder::NativeEndian; use core_io::{Error as IoError, Read, Write};
use core_io::Error as IoError;
use io::proto::{ProtoRead, ProtoWrite}; use io::proto::{ProtoRead, ProtoWrite};
pub const MAX_PACKET: usize = 1024; pub const MAX_PACKET: usize = 1024;
@ -364,7 +363,8 @@ pub enum Packet {
} }
impl Packet { impl Packet {
pub fn read_from<R: ProtoRead>(reader: &mut R) -> Result<Self, Error> { pub fn read_from<R>(reader: &mut R) -> Result<Self, Error>
where R: Read + ?Sized {
Ok(match reader.read_u8()? { Ok(match reader.read_u8()? {
0x00 => Packet::EchoRequest, 0x00 => Packet::EchoRequest,
0x01 => Packet::EchoReply, 0x01 => Packet::EchoReply,
@ -378,13 +378,13 @@ impl Packet {
0x21 => Packet::DestinationDownReply, 0x21 => Packet::DestinationDownReply,
0x22 => Packet::DestinationOkReply, 0x22 => Packet::DestinationOkReply,
0x23 => Packet::DestinationSequenceErrorReply { 0x23 => Packet::DestinationSequenceErrorReply {
channel: reader.read_u16::<NativeEndian>()?, channel: reader.read_u16()?,
}, },
0x24 => Packet::DestinationCollisionReply { 0x24 => Packet::DestinationCollisionReply {
channel: reader.read_u16::<NativeEndian>()?, channel: reader.read_u16()?,
}, },
0x25 => Packet::DestinationBusyReply { 0x25 => Packet::DestinationBusyReply {
channel: reader.read_u16::<NativeEndian>()?, channel: reader.read_u16()?,
}, },
0x30 => { 0x30 => {
@ -403,21 +403,21 @@ impl Packet {
0x40 => Packet::MonitorRequest { 0x40 => Packet::MonitorRequest {
destination: reader.read_u8()?, destination: reader.read_u8()?,
channel: reader.read_u16::<NativeEndian>()?, channel: reader.read_u16()?,
probe: reader.read_u8()?, probe: reader.read_u8()?,
}, },
0x41 => Packet::MonitorReply { 0x41 => Packet::MonitorReply {
value: reader.read_u64::<NativeEndian>()?, value: reader.read_u64()?,
}, },
0x50 => Packet::InjectionRequest { 0x50 => Packet::InjectionRequest {
destination: reader.read_u8()?, destination: reader.read_u8()?,
channel: reader.read_u16::<NativeEndian>()?, channel: reader.read_u16()?,
overrd: reader.read_u8()?, overrd: reader.read_u8()?,
value: reader.read_u8()?, value: reader.read_u8()?,
}, },
0x51 => Packet::InjectionStatusRequest { 0x51 => Packet::InjectionStatusRequest {
destination: reader.read_u8()?, destination: reader.read_u8()?,
channel: reader.read_u16::<NativeEndian>()?, channel: reader.read_u16()?,
overrd: reader.read_u8()?, overrd: reader.read_u8()?,
}, },
0x52 => Packet::InjectionStatusReply { 0x52 => Packet::InjectionStatusReply {
@ -476,7 +476,7 @@ impl Packet {
0x92 => Packet::SpiWriteRequest { 0x92 => Packet::SpiWriteRequest {
destination: reader.read_u8()?, destination: reader.read_u8()?,
busno: reader.read_u8()?, busno: reader.read_u8()?,
data: reader.read_u32::<NativeEndian>()?, data: reader.read_u32()?,
}, },
0x93 => Packet::SpiReadRequest { 0x93 => Packet::SpiReadRequest {
destination: reader.read_u8()?, destination: reader.read_u8()?,
@ -484,7 +484,7 @@ impl Packet {
}, },
0x94 => Packet::SpiReadReply { 0x94 => Packet::SpiReadReply {
succeeded: reader.read_bool()?, succeeded: reader.read_bool()?,
data: reader.read_u32::<NativeEndian>()?, data: reader.read_u32()?,
}, },
0x95 => Packet::SpiBasicReply { 0x95 => Packet::SpiBasicReply {
succeeded: reader.read_bool()?, succeeded: reader.read_bool()?,
@ -494,8 +494,8 @@ impl Packet {
destination: reader.read_u8()?, destination: reader.read_u8()?,
}, },
0xa1 => Packet::AnalyzerHeader { 0xa1 => Packet::AnalyzerHeader {
sent_bytes: reader.read_u32::<NativeEndian>()?, sent_bytes: reader.read_u32()?,
total_byte_count: reader.read_u64::<NativeEndian>()?, total_byte_count: reader.read_u64()?,
overflow_occurred: reader.read_bool()?, overflow_occurred: reader.read_bool()?,
}, },
0xa2 => Packet::AnalyzerDataRequest { 0xa2 => Packet::AnalyzerDataRequest {
@ -503,7 +503,7 @@ impl Packet {
}, },
0xa3 => { 0xa3 => {
let last = reader.read_bool()?; let last = reader.read_bool()?;
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut data: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE]; let mut data: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut data[0..length as usize])?; reader.read_exact(&mut data[0..length as usize])?;
Packet::AnalyzerData { Packet::AnalyzerData {
@ -516,9 +516,9 @@ impl Packet {
0xb0 => { 0xb0 => {
let source = reader.read_u8()?; let source = reader.read_u8()?;
let destination = reader.read_u8()?; let destination = reader.read_u8()?;
let id = reader.read_u32::<NativeEndian>()?; let id = reader.read_u32()?;
let status = reader.read_u8()?; let status = reader.read_u8()?;
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut trace: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE]; let mut trace: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut trace[0..length as usize])?; reader.read_exact(&mut trace[0..length as usize])?;
Packet::DmaAddTraceRequest { Packet::DmaAddTraceRequest {
@ -533,13 +533,13 @@ impl Packet {
0xb1 => Packet::DmaAddTraceReply { 0xb1 => Packet::DmaAddTraceReply {
source: reader.read_u8()?, source: reader.read_u8()?,
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32::<NativeEndian>()?, id: reader.read_u32()?,
succeeded: reader.read_bool()?, succeeded: reader.read_bool()?,
}, },
0xb2 => Packet::DmaRemoveTraceRequest { 0xb2 => Packet::DmaRemoveTraceRequest {
source: reader.read_u8()?, source: reader.read_u8()?,
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32::<NativeEndian>()?, id: reader.read_u32()?,
}, },
0xb3 => Packet::DmaRemoveTraceReply { 0xb3 => Packet::DmaRemoveTraceReply {
destination: reader.read_u8()?, destination: reader.read_u8()?,
@ -548,8 +548,8 @@ impl Packet {
0xb4 => Packet::DmaPlaybackRequest { 0xb4 => Packet::DmaPlaybackRequest {
source: reader.read_u8()?, source: reader.read_u8()?,
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32::<NativeEndian>()?, id: reader.read_u32()?,
timestamp: reader.read_u64::<NativeEndian>()?, timestamp: reader.read_u64()?,
}, },
0xb5 => Packet::DmaPlaybackReply { 0xb5 => Packet::DmaPlaybackReply {
destination: reader.read_u8()?, destination: reader.read_u8()?,
@ -558,17 +558,17 @@ impl Packet {
0xb6 => Packet::DmaPlaybackStatus { 0xb6 => Packet::DmaPlaybackStatus {
source: reader.read_u8()?, source: reader.read_u8()?,
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32::<NativeEndian>()?, id: reader.read_u32()?,
error: reader.read_u8()?, error: reader.read_u8()?,
channel: reader.read_u32::<NativeEndian>()?, channel: reader.read_u32()?,
timestamp: reader.read_u64::<NativeEndian>()?, timestamp: reader.read_u64()?,
}, },
0xc0 => { 0xc0 => {
let destination = reader.read_u8()?; let destination = reader.read_u8()?;
let id = reader.read_u32::<NativeEndian>()?; let id = reader.read_u32()?;
let status = PayloadStatus::from(reader.read_u8()?); let status = PayloadStatus::from(reader.read_u8()?);
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE]; let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut data[0..length as usize])?; reader.read_exact(&mut data[0..length as usize])?;
Packet::SubkernelAddDataRequest { Packet::SubkernelAddDataRequest {
@ -585,9 +585,9 @@ impl Packet {
0xc4 => Packet::SubkernelLoadRunRequest { 0xc4 => Packet::SubkernelLoadRunRequest {
source: reader.read_u8()?, source: reader.read_u8()?,
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32::<NativeEndian>()?, id: reader.read_u32()?,
run: reader.read_bool()?, run: reader.read_bool()?,
timestamp: reader.read_u64::<NativeEndian>()?, timestamp: reader.read_u64()?,
}, },
0xc5 => Packet::SubkernelLoadRunReply { 0xc5 => Packet::SubkernelLoadRunReply {
destination: reader.read_u8()?, destination: reader.read_u8()?,
@ -595,7 +595,7 @@ impl Packet {
}, },
0xc8 => Packet::SubkernelFinished { 0xc8 => Packet::SubkernelFinished {
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32::<NativeEndian>()?, id: reader.read_u32()?,
with_exception: reader.read_bool()?, with_exception: reader.read_bool()?,
exception_src: reader.read_u8()?, exception_src: reader.read_u8()?,
}, },
@ -606,7 +606,7 @@ impl Packet {
0xca => { 0xca => {
let destination = reader.read_u8()?; let destination = reader.read_u8()?;
let last = reader.read_bool()?; let last = reader.read_bool()?;
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE]; let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut data[0..length as usize])?; reader.read_exact(&mut data[0..length as usize])?;
Packet::SubkernelException { Packet::SubkernelException {
@ -619,9 +619,9 @@ impl Packet {
0xcb => { 0xcb => {
let source = reader.read_u8()?; let source = reader.read_u8()?;
let destination = reader.read_u8()?; let destination = reader.read_u8()?;
let id = reader.read_u32::<NativeEndian>()?; let id = reader.read_u32()?;
let status = reader.read_u8()?; let status = reader.read_u8()?;
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE]; let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut data[0..length as usize])?; reader.read_exact(&mut data[0..length as usize])?;
Packet::SubkernelMessage { Packet::SubkernelMessage {
@ -654,7 +654,7 @@ impl Packet {
}, },
0xd4 => { 0xd4 => {
let destination = reader.read_u8()?; let destination = reader.read_u8()?;
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut key: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE]; let mut key: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut key[0..length as usize])?; reader.read_exact(&mut key[0..length as usize])?;
Packet::CoreMgmtConfigReadRequest { Packet::CoreMgmtConfigReadRequest {
@ -669,7 +669,7 @@ impl Packet {
0xd6 => { 0xd6 => {
let destination = reader.read_u8()?; let destination = reader.read_u8()?;
let last = reader.read_bool()?; let last = reader.read_bool()?;
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE]; let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut data[0..length as usize])?; reader.read_exact(&mut data[0..length as usize])?;
Packet::CoreMgmtConfigWriteRequest { Packet::CoreMgmtConfigWriteRequest {
@ -681,7 +681,7 @@ impl Packet {
} }
0xd7 => { 0xd7 => {
let destination = reader.read_u8()?; let destination = reader.read_u8()?;
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut key: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE]; let mut key: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut key[0..length as usize])?; reader.read_exact(&mut key[0..length as usize])?;
Packet::CoreMgmtConfigRemoveRequest { Packet::CoreMgmtConfigRemoveRequest {
@ -701,12 +701,12 @@ impl Packet {
}, },
0xdb => Packet::CoreMgmtFlashRequest { 0xdb => Packet::CoreMgmtFlashRequest {
destination: reader.read_u8()?, destination: reader.read_u8()?,
payload_length: reader.read_u32::<NativeEndian>()?, payload_length: reader.read_u32()?,
}, },
0xdc => { 0xdc => {
let destination = reader.read_u8()?; let destination = reader.read_u8()?;
let last = reader.read_bool()?; let last = reader.read_bool()?;
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE]; let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut data[0..length as usize])?; reader.read_exact(&mut data[0..length as usize])?;
Packet::CoreMgmtFlashAddDataRequest { Packet::CoreMgmtFlashAddDataRequest {
@ -722,7 +722,7 @@ impl Packet {
0xde => Packet::CoreMgmtDropLink, 0xde => Packet::CoreMgmtDropLink,
0xdf => { 0xdf => {
let last = reader.read_bool()?; let last = reader.read_bool()?;
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut data: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE]; let mut data: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut data[0..length as usize])?; reader.read_exact(&mut data[0..length as usize])?;
Packet::CoreMgmtGetLogReply { Packet::CoreMgmtGetLogReply {
@ -733,7 +733,7 @@ impl Packet {
} }
0xe0 => { 0xe0 => {
let last = reader.read_bool()?; let last = reader.read_bool()?;
let length = reader.read_u16::<NativeEndian>()?; let length = reader.read_u16()?;
let mut value: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE]; let mut value: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE];
reader.read_exact(&mut value[0..length as usize])?; reader.read_exact(&mut value[0..length as usize])?;
Packet::CoreMgmtConfigReadReply { Packet::CoreMgmtConfigReadReply {
@ -750,7 +750,8 @@ impl Packet {
}) })
} }
pub fn write_to<W: ProtoWrite>(&self, writer: &mut W) -> Result<(), IoError> { pub fn write_to<W>(&self, writer: &mut W) -> Result<(), IoError>
where W: Write + ?Sized {
match *self { match *self {
Packet::EchoRequest => writer.write_u8(0x00)?, Packet::EchoRequest => writer.write_u8(0x00)?,
Packet::EchoReply => writer.write_u8(0x01)?, Packet::EchoReply => writer.write_u8(0x01)?,
@ -766,15 +767,15 @@ impl Packet {
Packet::DestinationOkReply => writer.write_u8(0x22)?, Packet::DestinationOkReply => writer.write_u8(0x22)?,
Packet::DestinationSequenceErrorReply { channel } => { Packet::DestinationSequenceErrorReply { channel } => {
writer.write_u8(0x23)?; writer.write_u8(0x23)?;
writer.write_u16::<NativeEndian>(channel)?; writer.write_u16(channel)?;
} }
Packet::DestinationCollisionReply { channel } => { Packet::DestinationCollisionReply { channel } => {
writer.write_u8(0x24)?; writer.write_u8(0x24)?;
writer.write_u16::<NativeEndian>(channel)?; writer.write_u16(channel)?;
} }
Packet::DestinationBusyReply { channel } => { Packet::DestinationBusyReply { channel } => {
writer.write_u8(0x25)?; writer.write_u8(0x25)?;
writer.write_u16::<NativeEndian>(channel)?; writer.write_u16(channel)?;
} }
Packet::RoutingSetPath { destination, hops } => { Packet::RoutingSetPath { destination, hops } => {
@ -795,12 +796,12 @@ impl Packet {
} => { } => {
writer.write_u8(0x40)?; writer.write_u8(0x40)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u16::<NativeEndian>(channel)?; writer.write_u16(channel)?;
writer.write_u8(probe)?; writer.write_u8(probe)?;
} }
Packet::MonitorReply { value } => { Packet::MonitorReply { value } => {
writer.write_u8(0x41)?; writer.write_u8(0x41)?;
writer.write_u64::<NativeEndian>(value)?; writer.write_u64(value)?;
} }
Packet::InjectionRequest { Packet::InjectionRequest {
destination, destination,
@ -810,7 +811,7 @@ impl Packet {
} => { } => {
writer.write_u8(0x50)?; writer.write_u8(0x50)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u16::<NativeEndian>(channel)?; writer.write_u16(channel)?;
writer.write_u8(overrd)?; writer.write_u8(overrd)?;
writer.write_u8(value)?; writer.write_u8(value)?;
} }
@ -821,7 +822,7 @@ impl Packet {
} => { } => {
writer.write_u8(0x51)?; writer.write_u8(0x51)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u16::<NativeEndian>(channel)?; writer.write_u16(channel)?;
writer.write_u8(overrd)?; writer.write_u8(overrd)?;
} }
Packet::InjectionStatusReply { value } => { Packet::InjectionStatusReply { value } => {
@ -915,7 +916,7 @@ impl Packet {
writer.write_u8(0x92)?; writer.write_u8(0x92)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u8(busno)?; writer.write_u8(busno)?;
writer.write_u32::<NativeEndian>(data)?; writer.write_u32(data)?;
} }
Packet::SpiReadRequest { destination, busno } => { Packet::SpiReadRequest { destination, busno } => {
writer.write_u8(0x93)?; writer.write_u8(0x93)?;
@ -925,7 +926,7 @@ impl Packet {
Packet::SpiReadReply { succeeded, data } => { Packet::SpiReadReply { succeeded, data } => {
writer.write_u8(0x94)?; writer.write_u8(0x94)?;
writer.write_bool(succeeded)?; writer.write_bool(succeeded)?;
writer.write_u32::<NativeEndian>(data)?; writer.write_u32(data)?;
} }
Packet::SpiBasicReply { succeeded } => { Packet::SpiBasicReply { succeeded } => {
writer.write_u8(0x95)?; writer.write_u8(0x95)?;
@ -942,8 +943,8 @@ impl Packet {
overflow_occurred, overflow_occurred,
} => { } => {
writer.write_u8(0xa1)?; writer.write_u8(0xa1)?;
writer.write_u32::<NativeEndian>(sent_bytes)?; writer.write_u32(sent_bytes)?;
writer.write_u64::<NativeEndian>(total_byte_count)?; writer.write_u64(total_byte_count)?;
writer.write_bool(overflow_occurred)?; writer.write_bool(overflow_occurred)?;
} }
Packet::AnalyzerDataRequest { destination } => { Packet::AnalyzerDataRequest { destination } => {
@ -953,7 +954,7 @@ impl Packet {
Packet::AnalyzerData { last, length, data } => { Packet::AnalyzerData { last, length, data } => {
writer.write_u8(0xa3)?; writer.write_u8(0xa3)?;
writer.write_bool(last)?; writer.write_bool(last)?;
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&data[0..length as usize])?; writer.write_all(&data[0..length as usize])?;
} }
@ -968,11 +969,11 @@ impl Packet {
writer.write_u8(0xb0)?; writer.write_u8(0xb0)?;
writer.write_u8(source)?; writer.write_u8(source)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32::<NativeEndian>(id)?; writer.write_u32(id)?;
writer.write_u8(status as u8)?; writer.write_u8(status as u8)?;
// trace may be broken down to fit within drtio aux memory limit // trace may be broken down to fit within drtio aux memory limit
// will be reconstructed by satellite // will be reconstructed by satellite
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&trace[0..length as usize])?; writer.write_all(&trace[0..length as usize])?;
} }
Packet::DmaAddTraceReply { Packet::DmaAddTraceReply {
@ -984,7 +985,7 @@ impl Packet {
writer.write_u8(0xb1)?; writer.write_u8(0xb1)?;
writer.write_u8(source)?; writer.write_u8(source)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32::<NativeEndian>(id)?; writer.write_u32(id)?;
writer.write_bool(succeeded)?; writer.write_bool(succeeded)?;
} }
Packet::DmaRemoveTraceRequest { Packet::DmaRemoveTraceRequest {
@ -995,7 +996,7 @@ impl Packet {
writer.write_u8(0xb2)?; writer.write_u8(0xb2)?;
writer.write_u8(source)?; writer.write_u8(source)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32::<NativeEndian>(id)?; writer.write_u32(id)?;
} }
Packet::DmaRemoveTraceReply { destination, succeeded } => { Packet::DmaRemoveTraceReply { destination, succeeded } => {
writer.write_u8(0xb3)?; writer.write_u8(0xb3)?;
@ -1011,8 +1012,8 @@ impl Packet {
writer.write_u8(0xb4)?; writer.write_u8(0xb4)?;
writer.write_u8(source)?; writer.write_u8(source)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32::<NativeEndian>(id)?; writer.write_u32(id)?;
writer.write_u64::<NativeEndian>(timestamp)?; writer.write_u64(timestamp)?;
} }
Packet::DmaPlaybackReply { destination, succeeded } => { Packet::DmaPlaybackReply { destination, succeeded } => {
writer.write_u8(0xb5)?; writer.write_u8(0xb5)?;
@ -1030,10 +1031,10 @@ impl Packet {
writer.write_u8(0xb6)?; writer.write_u8(0xb6)?;
writer.write_u8(source)?; writer.write_u8(source)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32::<NativeEndian>(id)?; writer.write_u32(id)?;
writer.write_u8(error)?; writer.write_u8(error)?;
writer.write_u32::<NativeEndian>(channel)?; writer.write_u32(channel)?;
writer.write_u64::<NativeEndian>(timestamp)?; writer.write_u64(timestamp)?;
} }
Packet::SubkernelAddDataRequest { Packet::SubkernelAddDataRequest {
@ -1045,9 +1046,9 @@ impl Packet {
} => { } => {
writer.write_u8(0xc0)?; writer.write_u8(0xc0)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32::<NativeEndian>(id)?; writer.write_u32(id)?;
writer.write_u8(status as u8)?; writer.write_u8(status as u8)?;
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&data[0..length as usize])?; writer.write_all(&data[0..length as usize])?;
} }
Packet::SubkernelAddDataReply { succeeded } => { Packet::SubkernelAddDataReply { succeeded } => {
@ -1064,9 +1065,9 @@ impl Packet {
writer.write_u8(0xc4)?; writer.write_u8(0xc4)?;
writer.write_u8(source)?; writer.write_u8(source)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32::<NativeEndian>(id)?; writer.write_u32(id)?;
writer.write_bool(run)?; writer.write_bool(run)?;
writer.write_u64::<NativeEndian>(timestamp)?; writer.write_u64(timestamp)?;
} }
Packet::SubkernelLoadRunReply { destination, succeeded } => { Packet::SubkernelLoadRunReply { destination, succeeded } => {
writer.write_u8(0xc5)?; writer.write_u8(0xc5)?;
@ -1081,7 +1082,7 @@ impl Packet {
} => { } => {
writer.write_u8(0xc8)?; writer.write_u8(0xc8)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32::<NativeEndian>(id)?; writer.write_u32(id)?;
writer.write_bool(with_exception)?; writer.write_bool(with_exception)?;
writer.write_u8(exception_src)?; writer.write_u8(exception_src)?;
} }
@ -1099,7 +1100,7 @@ impl Packet {
writer.write_u8(0xca)?; writer.write_u8(0xca)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_bool(last)?; writer.write_bool(last)?;
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&data[0..length as usize])?; writer.write_all(&data[0..length as usize])?;
} }
Packet::SubkernelMessage { Packet::SubkernelMessage {
@ -1113,9 +1114,9 @@ impl Packet {
writer.write_u8(0xcb)?; writer.write_u8(0xcb)?;
writer.write_u8(source)?; writer.write_u8(source)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32::<NativeEndian>(id)?; writer.write_u32(id)?;
writer.write_u8(status as u8)?; writer.write_u8(status as u8)?;
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&data[0..length as usize])?; writer.write_all(&data[0..length as usize])?;
} }
Packet::SubkernelMessageAck { destination } => { Packet::SubkernelMessageAck { destination } => {
@ -1149,7 +1150,7 @@ impl Packet {
} => { } => {
writer.write_u8(0xd4)?; writer.write_u8(0xd4)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&key[0..length as usize])?; writer.write_all(&key[0..length as usize])?;
} }
Packet::CoreMgmtConfigReadContinue { destination } => { Packet::CoreMgmtConfigReadContinue { destination } => {
@ -1165,7 +1166,7 @@ impl Packet {
writer.write_u8(0xd6)?; writer.write_u8(0xd6)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_bool(last)?; writer.write_bool(last)?;
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&data[0..length as usize])?; writer.write_all(&data[0..length as usize])?;
} }
Packet::CoreMgmtConfigRemoveRequest { Packet::CoreMgmtConfigRemoveRequest {
@ -1175,7 +1176,7 @@ impl Packet {
} => { } => {
writer.write_u8(0xd7)?; writer.write_u8(0xd7)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&key[0..length as usize])?; writer.write_all(&key[0..length as usize])?;
} }
Packet::CoreMgmtConfigEraseRequest { destination } => { Packet::CoreMgmtConfigEraseRequest { destination } => {
@ -1196,7 +1197,7 @@ impl Packet {
} => { } => {
writer.write_u8(0xdb)?; writer.write_u8(0xdb)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32::<NativeEndian>(payload_length)?; writer.write_u32(payload_length)?;
} }
Packet::CoreMgmtFlashAddDataRequest { Packet::CoreMgmtFlashAddDataRequest {
destination, destination,
@ -1207,7 +1208,7 @@ impl Packet {
writer.write_u8(0xdc)?; writer.write_u8(0xdc)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_bool(last)?; writer.write_bool(last)?;
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&data[..length as usize])?; writer.write_all(&data[..length as usize])?;
} }
Packet::CoreMgmtDropLinkAck { destination } => { Packet::CoreMgmtDropLinkAck { destination } => {
@ -1218,13 +1219,13 @@ impl Packet {
Packet::CoreMgmtGetLogReply { last, length, data } => { Packet::CoreMgmtGetLogReply { last, length, data } => {
writer.write_u8(0xdf)?; writer.write_u8(0xdf)?;
writer.write_bool(last)?; writer.write_bool(last)?;
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&data[0..length as usize])?; writer.write_all(&data[0..length as usize])?;
} }
Packet::CoreMgmtConfigReadReply { last, length, value } => { Packet::CoreMgmtConfigReadReply { last, length, value } => {
writer.write_u8(0xe0)?; writer.write_u8(0xe0)?;
writer.write_bool(last)?; writer.write_bool(last)?;
writer.write_u16::<NativeEndian>(length)?; writer.write_u16(length)?;
writer.write_all(&value[0..length as usize])?; writer.write_all(&value[0..length as usize])?;
} }
Packet::CoreMgmtReply { succeeded } => { Packet::CoreMgmtReply { succeeded } => {

View File

@ -1,5 +1,3 @@
use core::arch::asm;
use libboard_zynq::{println, stdio}; use libboard_zynq::{println, stdio};
use libcortex_a9::{interrupt_handler, regs::MPIDR}; use libcortex_a9::{interrupt_handler, regs::MPIDR};
use libregister::RegisterR; use libregister::RegisterR;

View File

@ -111,23 +111,18 @@ impl IoExpander {
fn write(&self, i2c: &mut i2c::I2c, addr: u8, value: u8) -> Result<(), &'static str> { fn write(&self, i2c: &mut i2c::I2c, addr: u8, value: u8) -> Result<(), &'static str> {
i2c.start()?; i2c.start()?;
let write_res = i2c i2c.write(self.address)?;
.write(self.address) i2c.write(addr)?;
.and_then(|_| i2c.write(addr)) i2c.write(value)?;
.and_then(|_| i2c.write(value)); i2c.stop()?;
let stop_res = i2c.stop(); Ok(())
write_res.and(stop_res).map_err(|e| e.into())
} }
fn check_ack(&self, i2c: &mut i2c::I2c) -> Result<bool, &'static str> { fn check_ack(&self, i2c: &mut i2c::I2c) -> Result<bool, &'static str> {
// Check for ack from io expander // Check for ack from io expander
self.select(i2c)?; self.select(i2c)?;
i2c.start()?; i2c.start()?;
let ack = match i2c.write(self.address) { let ack = i2c.write(self.address)?;
Ok(()) => true,
Err(i2c::Error::Nack) => false,
Err(e) => return Err(e.into()),
};
i2c.stop()?; i2c.stop()?;
Ok(ack) Ok(ack)
} }

View File

@ -1,6 +1,7 @@
#![no_std] #![no_std]
#![feature(never_type)] #![feature(never_type)]
#![feature(naked_functions)] #![feature(naked_functions)]
#![feature(asm)]
extern crate core_io; extern crate core_io;
extern crate crc; extern crate crc;
@ -24,7 +25,7 @@ pub mod fiq;
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
pub mod io_expander; pub mod io_expander;
pub mod logger; pub mod logger;
#[cfg(any(has_drtio, has_cxp_grabber))] #[cfg(has_drtio)]
#[rustfmt::skip] #[rustfmt::skip]
#[path = "../../../build/mem.rs"] #[path = "../../../build/mem.rs"]
pub mod mem; pub mod mem;
@ -41,17 +42,6 @@ pub mod si5324;
pub mod si549; pub mod si549;
use core::{cmp, str}; use core::{cmp, str};
#[cfg(has_cxp_grabber)]
pub mod cxp_camera_setup;
#[cfg(has_cxp_grabber)]
pub mod cxp_ctrl;
#[cfg(has_cxp_grabber)]
pub mod cxp_grabber;
#[cfg(has_cxp_grabber)]
pub mod cxp_packet;
#[cfg(has_cxp_grabber)]
pub mod cxp_phys;
pub fn identifier_read(buf: &mut [u8]) -> &str { pub fn identifier_read(buf: &mut [u8]) -> &str {
unsafe { unsafe {
pl::csr::identifier::address_write(0); pl::csr::identifier::address_write(0);

View File

@ -1,4 +1,4 @@
use core::{cell::Cell, fmt::Write, mem::MaybeUninit}; use core::{cell::Cell, fmt::Write};
use libboard_zynq::{println, timer::GlobalTimer}; use libboard_zynq::{println, timer::GlobalTimer};
use libcortex_a9::mutex::{Mutex, MutexGuard}; use libcortex_a9::mutex::{Mutex, MutexGuard};
@ -42,7 +42,7 @@ pub struct BufferLogger {
buffer_filter: Cell<LevelFilter>, buffer_filter: Cell<LevelFilter>,
} }
static mut LOGGER: MaybeUninit<BufferLogger> = MaybeUninit::uninit(); static mut LOGGER: Option<BufferLogger> = None;
impl BufferLogger { impl BufferLogger {
pub fn new(buffer: &'static mut [u8]) -> BufferLogger { pub fn new(buffer: &'static mut [u8]) -> BufferLogger {
@ -55,13 +55,13 @@ impl BufferLogger {
pub fn register(self) { pub fn register(self) {
unsafe { unsafe {
LOGGER.write(self); LOGGER = Some(self);
log::set_logger(LOGGER.assume_init_ref()).expect("global logger can only be initialized once"); log::set_logger(LOGGER.as_ref().unwrap()).expect("global logger can only be initialized once");
} }
} }
pub fn get_logger() -> &'static mut BufferLogger { pub unsafe fn get_logger() -> &'static mut Option<BufferLogger> {
unsafe { LOGGER.assume_init_mut() } &mut LOGGER
} }
pub fn buffer<'a>(&'a self) -> Option<LogBufferRef<'a>> { pub fn buffer<'a>(&'a self) -> Option<LogBufferRef<'a>> {

View File

@ -1,9 +1,7 @@
use core::result; use core::result;
use embedded_hal::blocking::delay::DelayUs; use embedded_hal::blocking::delay::DelayUs;
use libboard_zynq::{i2c::{Error as I2cError, I2c}, use libboard_zynq::{i2c::I2c, time::Milliseconds, timer::GlobalTimer};
time::Milliseconds,
timer::GlobalTimer};
use log::info; use log::info;
#[cfg(not(si5324_soft_reset))] #[cfg(not(si5324_soft_reset))]
@ -99,18 +97,15 @@ fn map_frequency_settings(settings: &FrequencySettings) -> Result<FrequencySetti
fn write(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> { fn write(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
i2c.start().unwrap(); i2c.start().unwrap();
i2c.write(ADDRESS << 1).map_err(|err| match err { if !i2c.write(ADDRESS << 1).unwrap() {
I2cError::Nack => "Si5324 failed to ack write address", return Err("Si5324 failed to ack write address");
err => err.into(), }
})?; if !i2c.write(reg).unwrap() {
i2c.write(reg).map_err(|err| match err { return Err("Si5324 failed to ack register");
I2cError::Nack => "Si5324 failed to ack register", }
err => err.into(), if !i2c.write(val).unwrap() {
})?; return Err("Si5324 failed to ack value");
i2c.write(val).map_err(|err| match err { }
I2cError::Nack => "Si5324 failed to ack value",
err => err.into(),
})?;
i2c.stop().unwrap(); i2c.stop().unwrap();
Ok(()) Ok(())
} }
@ -118,37 +113,29 @@ fn write(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
#[allow(dead_code)] #[allow(dead_code)]
fn write_no_ack_value(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> { fn write_no_ack_value(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
i2c.start().unwrap(); i2c.start().unwrap();
i2c.write(ADDRESS << 1).map_err(|err| match err { if !i2c.write(ADDRESS << 1).unwrap() {
I2cError::Nack => "Si5324 failed to ack write address", return Err("Si5324 failed to ack write address");
err => err.into(),
})?;
i2c.write(reg).map_err(|err| match err {
I2cError::Nack => "Si5324 failed to ack register",
err => err.into(),
})?;
match i2c.write(val) {
Ok(()) | Err(I2cError::Nack) => (),
Err(e) => return Err(e.into()),
} }
if !i2c.write(reg).unwrap() {
return Err("Si5324 failed to ack register");
}
i2c.write(val).unwrap();
i2c.stop().unwrap(); i2c.stop().unwrap();
Ok(()) Ok(())
} }
fn read(i2c: &mut I2c, reg: u8) -> Result<u8> { fn read(i2c: &mut I2c, reg: u8) -> Result<u8> {
i2c.start().unwrap(); i2c.start().unwrap();
i2c.write(ADDRESS << 1).map_err(|err| match err { if !i2c.write(ADDRESS << 1).unwrap() {
I2cError::Nack => "Si5324 failed to ack write address", return Err("Si5324 failed to ack write address");
err => err.into(), }
})?; if !i2c.write(reg).unwrap() {
i2c.write(reg).map_err(|err| match err { return Err("Si5324 failed to ack register");
I2cError::Nack => "Si5324 failed to ack register", }
err => err.into(),
})?;
i2c.restart().unwrap(); i2c.restart().unwrap();
i2c.write((ADDRESS << 1) | 1).map_err(|err| match err { if !i2c.write((ADDRESS << 1) | 1).unwrap() {
I2cError::Nack => "Si5324 failed to ack read address", return Err("Si5324 failed to ack read address");
err => err.into(), }
})?;
let val = i2c.read(false).unwrap(); let val = i2c.read(false).unwrap();
i2c.stop().unwrap(); i2c.stop().unwrap();
Ok(val) Ok(val)

View File

@ -85,7 +85,7 @@ unsafe fn get_ttype_entry(
encoding | DW_EH_PE_pcrel, encoding | DW_EH_PE_pcrel,
ttype_base, ttype_base,
) )
.map(|v| (v != 0).then(|| v as *const u8)) .map(|v| (v != ttype_base).then(|| v as *const u8))
} }
pub unsafe fn find_eh_action( pub unsafe fn find_eh_action(
@ -275,11 +275,6 @@ unsafe fn read_encoded_pointer_with_base(reader: &mut DwarfReader, encoding: u8,
_ => return Err(()), _ => return Err(()),
}; };
if result == 0 {
// null is just encoded as 0, even if a relative encoding is used for the table.
return Ok(0);
}
result += if (encoding & 0x70) == DW_EH_PE_pcrel { result += if (encoding & 0x70) == DW_EH_PE_pcrel {
original_ptr as usize original_ptr as usize
} else { } else {

View File

@ -1,5 +1,6 @@
#![no_std] #![no_std]
#![feature(never_type)] #![feature(never_type)]
#![feature(asm)]
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;

View File

@ -2,54 +2,58 @@
use alloc::{string::String, vec}; use alloc::{string::String, vec};
use core::str::Utf8Error; use core::str::Utf8Error;
use byteorder::ByteOrder; use byteorder::{ByteOrder, NativeEndian};
use core_io::{Error, Read, Write}; use core_io::{Error as IoError, Read, Write};
#[cfg(feature = "alloc")] #[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum ReadStringError<T> { pub enum ReadStringError<T> {
Utf8(Utf8Error), Utf8(Utf8Error),
Other(T), Other(T),
} }
pub trait ProtoRead: Read { pub trait ProtoRead {
type ReadError;
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::ReadError>;
#[inline] #[inline]
fn read_u8(&mut self) -> Result<u8, Error> { fn read_u8(&mut self) -> Result<u8, Self::ReadError> {
let mut bytes = [0; 1]; let mut bytes = [0; 1];
self.read_exact(&mut bytes)?; self.read_exact(&mut bytes)?;
Ok(bytes[0]) Ok(bytes[0])
} }
#[inline] #[inline]
fn read_u16<T: ByteOrder>(&mut self) -> Result<u16, Error> { fn read_u16(&mut self) -> Result<u16, Self::ReadError> {
let mut bytes = [0; 2]; let mut bytes = [0; 2];
self.read_exact(&mut bytes)?; self.read_exact(&mut bytes)?;
Ok(T::read_u16(&bytes)) Ok(NativeEndian::read_u16(&bytes))
} }
#[inline] #[inline]
fn read_u32<T: ByteOrder>(&mut self) -> Result<u32, Error> { fn read_u32(&mut self) -> Result<u32, Self::ReadError> {
let mut bytes = [0; 4]; let mut bytes = [0; 4];
self.read_exact(&mut bytes)?; self.read_exact(&mut bytes)?;
Ok(T::read_u32(&bytes)) Ok(NativeEndian::read_u32(&bytes))
} }
#[inline] #[inline]
fn read_u64<T: ByteOrder>(&mut self) -> Result<u64, Error> { fn read_u64(&mut self) -> Result<u64, Self::ReadError> {
let mut bytes = [0; 8]; let mut bytes = [0; 8];
self.read_exact(&mut bytes)?; self.read_exact(&mut bytes)?;
Ok(T::read_u64(&bytes)) Ok(NativeEndian::read_u64(&bytes))
} }
#[inline] #[inline]
fn read_bool(&mut self) -> Result<bool, Error> { fn read_bool(&mut self) -> Result<bool, Self::ReadError> {
Ok(self.read_u8()? != 0) Ok(self.read_u8()? != 0)
} }
#[inline] #[inline]
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
fn read_bytes<T: ByteOrder>(&mut self) -> Result<vec::Vec<u8>, Error> { fn read_bytes(&mut self) -> Result<vec::Vec<u8>, Self::ReadError> {
let length = self.read_u32::<T>()?; let length = self.read_u32()?;
let mut value = vec![0; length as usize]; let mut value = vec![0; length as usize];
self.read_exact(&mut value)?; self.read_exact(&mut value)?;
Ok(value) Ok(value)
@ -57,85 +61,105 @@ pub trait ProtoRead: Read {
#[inline] #[inline]
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
fn read_string<T: ByteOrder>(&mut self) -> Result<String, ReadStringError<Error>> { fn read_string(&mut self) -> Result<String, ReadStringError<Self::ReadError>> {
let bytes = self.read_bytes::<T>().map_err(ReadStringError::Other)?; let bytes = self.read_bytes().map_err(ReadStringError::Other)?;
String::from_utf8(bytes).map_err(|err| ReadStringError::Utf8(err.utf8_error())) String::from_utf8(bytes).map_err(|err| ReadStringError::Utf8(err.utf8_error()))
} }
} }
pub trait ProtoWrite: Write { pub trait ProtoWrite {
type WriteError;
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::WriteError>;
#[inline] #[inline]
fn write_u8(&mut self, value: u8) -> Result<(), Error> { fn write_u8(&mut self, value: u8) -> Result<(), Self::WriteError> {
let bytes = [value; 1]; let bytes = [value; 1];
self.write_all(&bytes) self.write_all(&bytes)
} }
#[inline] #[inline]
fn write_i8(&mut self, value: i8) -> Result<(), Error> { fn write_i8(&mut self, value: i8) -> Result<(), Self::WriteError> {
let bytes = [value as u8; 1]; let bytes = [value as u8; 1];
self.write_all(&bytes) self.write_all(&bytes)
} }
#[inline] #[inline]
fn write_u16<T: ByteOrder>(&mut self, value: u16) -> Result<(), Error> { fn write_u16(&mut self, value: u16) -> Result<(), Self::WriteError> {
let mut bytes = [0; 2]; let mut bytes = [0; 2];
T::write_u16(&mut bytes, value); NativeEndian::write_u16(&mut bytes, value);
self.write_all(&bytes) self.write_all(&bytes)
} }
#[inline] #[inline]
fn write_i16<T: ByteOrder>(&mut self, value: i16) -> Result<(), Error> { fn write_i16(&mut self, value: i16) -> Result<(), Self::WriteError> {
let mut bytes = [0; 2]; let mut bytes = [0; 2];
T::write_i16(&mut bytes, value); NativeEndian::write_i16(&mut bytes, value);
self.write_all(&bytes) self.write_all(&bytes)
} }
#[inline] #[inline]
fn write_u32<T: ByteOrder>(&mut self, value: u32) -> Result<(), Error> { fn write_u32(&mut self, value: u32) -> Result<(), Self::WriteError> {
let mut bytes = [0; 4]; let mut bytes = [0; 4];
T::write_u32(&mut bytes, value); NativeEndian::write_u32(&mut bytes, value);
self.write_all(&bytes) self.write_all(&bytes)
} }
#[inline] #[inline]
fn write_i32<T: ByteOrder>(&mut self, value: i32) -> Result<(), Error> { fn write_i32(&mut self, value: i32) -> Result<(), Self::WriteError> {
let mut bytes = [0; 4]; let mut bytes = [0; 4];
T::write_i32(&mut bytes, value); NativeEndian::write_i32(&mut bytes, value);
self.write_all(&bytes) self.write_all(&bytes)
} }
#[inline] #[inline]
fn write_u64<T: ByteOrder>(&mut self, value: u64) -> Result<(), Error> { fn write_u64(&mut self, value: u64) -> Result<(), Self::WriteError> {
let mut bytes = [0; 8]; let mut bytes = [0; 8];
T::write_u64(&mut bytes, value); NativeEndian::write_u64(&mut bytes, value);
self.write_all(&bytes) self.write_all(&bytes)
} }
#[inline] #[inline]
fn write_i64<T: ByteOrder>(&mut self, value: i64) -> Result<(), Error> { fn write_i64(&mut self, value: i64) -> Result<(), Self::WriteError> {
let mut bytes = [0; 8]; let mut bytes = [0; 8];
T::write_i64(&mut bytes, value); NativeEndian::write_i64(&mut bytes, value);
self.write_all(&bytes) self.write_all(&bytes)
} }
#[inline] #[inline]
fn write_bool(&mut self, value: bool) -> Result<(), Error> { fn write_bool(&mut self, value: bool) -> Result<(), Self::WriteError> {
self.write_u8(value as u8) self.write_u8(value as u8)
} }
#[inline] #[inline]
fn write_bytes<T: ByteOrder>(&mut self, value: &[u8]) -> Result<(), Error> { fn write_bytes(&mut self, value: &[u8]) -> Result<(), Self::WriteError> {
self.write_u32::<T>(value.len() as u32)?; self.write_u32(value.len() as u32)?;
self.write_all(value) self.write_all(value)
} }
#[inline] #[inline]
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
fn write_string<T: ByteOrder>(&mut self, value: &str) -> Result<(), Error> { fn write_string(&mut self, value: &str) -> Result<(), Self::WriteError> {
self.write_bytes::<T>(value.as_bytes()) self.write_bytes(value.as_bytes())
} }
} }
impl<T: Read> ProtoRead for T {} impl<T> ProtoRead for T
where T: Read + ?Sized
{
type ReadError = IoError;
impl<T: Write> ProtoWrite for T {} fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::ReadError> {
T::read_exact(self, buf)
}
}
impl<T> ProtoWrite for T
where T: Write + ?Sized
{
type WriteError = IoError;
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::WriteError> {
T::write_all(self, buf)
}
}

View File

@ -1,228 +0,0 @@
use alloc::{string::{String, ToString},
vec::Vec};
use core::fmt;
use byteorder::{ByteOrder, NetworkEndian};
use cslice::CMutSlice;
use libboard_artiq::{cxp_ctrl::{Error as CtrlErr, DATA_MAXSIZE},
cxp_grabber::{camera_connected, with_tag},
cxp_packet::{read_bytes, read_u32, write_u32}};
use log::info;
use crate::{artiq_raise, pl::csr::cxp_grabber};
const ROI_MAX_SIZE: usize = 4096;
#[repr(C)]
pub struct ROIViewerFrame {
width: i32,
height: i32,
pixel_width: i32,
}
enum Error {
BufferSizeTooSmall(usize, usize),
ROISizeTooBig(usize, usize),
InvalidLocalUrl(String),
CtrlPacketError(CtrlErr),
}
impl From<CtrlErr> for Error {
fn from(value: CtrlErr) -> Error {
Error::CtrlPacketError(value)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Error::BufferSizeTooSmall(required_size, buffer_size) => {
write!(
f,
"BufferSizeTooSmall - The required size is {} bytes but the buffer size is {} bytes",
required_size, buffer_size
)
}
&Error::ROISizeTooBig(width, height) => {
write!(
f,
"ROISizeTooBig - The maximum ROIViewer height and total size are {} and {} pixels respectively \
but the ROI is set to {} ({}x{}) pixels",
ROI_MAX_SIZE / 4,
ROI_MAX_SIZE,
width * height,
width,
height
)
}
&Error::InvalidLocalUrl(ref s) => {
write!(f, "InvalidLocalUrl - Cannot download xml file locally from {}", s)
}
&Error::CtrlPacketError(ref err) => write!(f, "{}", err),
}
}
}
fn read_xml_url(with_tag: bool) -> Result<String, Error> {
let mut addr = read_u32(0x0018, with_tag)?;
let mut buffer = Vec::new();
// Strings stored in the bootstrap and manufacturer-specific registers space shall be NULL-terminated, encoded ASCII - Section 12.3.1 (CXP-001-2021)
// String length is not known during runtime, grabber must read 4 bytes at a time until NULL-terminated
loop {
let mut bytes: [u8; 4] = [0; 4];
read_bytes(addr, &mut bytes, with_tag)?;
addr += 4;
for b in bytes {
if b == 0 {
// UTF-8 is compatible with ASCII encoding
// use U+FFFD REPLACEMENT_CHARACTER to represent decoding error
return Ok(String::from_utf8_lossy(&buffer).to_string());
} else {
buffer.push(b);
}
}
}
}
fn read_xml_location(with_tag: bool) -> Result<(String, u32, u32), Error> {
let url = read_xml_url(with_tag)?;
// url example - Section 13.2.3 (CXP-001-2021)
// Available on camera - "Local:MyFilename.zip;B8000;33A?SchemaVersion=1.0.0"
// => ZIP file starting at address 0xB8000 in the Device with a length of 0x33A bytes
//
// Available online - "Web:http://www.example.com/xml/MyFilename.xml"
// => xml is available at http://www.example.com/xml/MyFilename.xml
let mut splitter = url.split(|c| c == ':' || c == ';' || c == '?');
let scheme = splitter.next().unwrap();
if scheme.eq_ignore_ascii_case("local") {
if let (Some(file_name), Some(addr_str), Some(size_str)) = (splitter.next(), splitter.next(), splitter.next()) {
let addr = u32::from_str_radix(addr_str, 16).map_err(|_| Error::InvalidLocalUrl(url.to_string()))?;
let size = u32::from_str_radix(size_str, 16).map_err(|_| Error::InvalidLocalUrl(url.to_string()))?;
return Ok((file_name.to_string(), addr, size));
}
}
Err(Error::InvalidLocalUrl(url.to_string()))
}
fn read_xml_file(buffer: &mut [i32], with_tag: bool) -> Result<u32, Error> {
let (file_name, base_addr, size) = read_xml_location(with_tag)?;
if buffer.len() * 4 < size as usize {
return Err(Error::BufferSizeTooSmall(size as usize, buffer.len() * 4));
};
info!("downloading xml file {} with {} bytes...", file_name, size);
let mut v: Vec<u8> = Vec::new();
let mut addr = base_addr;
let mut bytesleft = size;
let mut bytes: [u8; DATA_MAXSIZE] = [0; DATA_MAXSIZE];
while bytesleft > 0 {
let read_len = DATA_MAXSIZE.min(bytesleft as usize);
read_bytes(addr, &mut bytes[..read_len], with_tag)?;
v.extend(&bytes[..read_len]);
addr += read_len as u32;
bytesleft -= read_len as u32;
}
info!("download successful");
// pad to 32 bit boundary
let padding = (4 - (size % 4)) % 4;
for _ in 0..padding {
v.push(0);
}
NetworkEndian::read_i32_into(&v, &mut buffer[..((size + padding) / 4) as usize]);
Ok((size + padding) / 4)
}
pub extern "C" fn download_xml_file(buffer: &mut CMutSlice<i32>) -> i32 {
if camera_connected() {
match read_xml_file(buffer.as_mut_slice(), with_tag()) {
Ok(size_read) => size_read as i32,
Err(e) => artiq_raise!("CXPError", format!("{}", e)),
}
} else {
artiq_raise!("CXPError", "Camera is not connected");
}
}
pub extern "C" fn read32(addr: i32) -> i32 {
if camera_connected() {
match read_u32(addr as u32, with_tag()) {
Ok(result) => result as i32,
Err(e) => artiq_raise!("CXPError", format!("{}", e)),
}
} else {
artiq_raise!("CXPError", "Camera is not connected");
}
}
pub extern "C" fn write32(addr: i32, val: i32) {
if camera_connected() {
match write_u32(addr as u32, val as u32, with_tag()) {
Ok(_) => {}
Err(e) => artiq_raise!("CXPError", format!("{}", e)),
}
} else {
artiq_raise!("CXPError", "Camera is not connected");
}
}
pub extern "C" fn start_roi_viewer(x0: i32, y0: i32, x1: i32, y1: i32) {
let (width, height) = ((x1 - x0) as usize, (y1 - y0) as usize);
if width * height > ROI_MAX_SIZE || height > ROI_MAX_SIZE / 4 {
artiq_raise!("CXPError", format!("{}", Error::ROISizeTooBig(width, height)));
} else {
unsafe {
// flush the fifo before arming
while cxp_grabber::roi_viewer_fifo_stb_read() == 1 {
cxp_grabber::roi_viewer_fifo_ack_write(1);
}
cxp_grabber::roi_viewer_x0_write(x0 as u16);
cxp_grabber::roi_viewer_x1_write(x1 as u16);
cxp_grabber::roi_viewer_y0_write(y0 as u16);
cxp_grabber::roi_viewer_y1_write(y1 as u16);
cxp_grabber::roi_viewer_arm_write(1);
}
}
}
pub extern "C" fn download_roi_viewer_frame(buffer: &mut CMutSlice<i64>) -> ROIViewerFrame {
if buffer.len() * 4 < ROI_MAX_SIZE {
// each pixel is 16 bits
artiq_raise!(
"CXPError",
format!("{}", Error::BufferSizeTooSmall(ROI_MAX_SIZE * 2, buffer.len() * 8))
);
};
let buf = buffer.as_mut_slice();
unsafe {
while cxp_grabber::roi_viewer_ready_read() == 0 {}
let mut i = 0;
while cxp_grabber::roi_viewer_fifo_stb_read() == 1 {
buf[i] = cxp_grabber::roi_viewer_fifo_data_read() as i64;
i += 1;
cxp_grabber::roi_viewer_fifo_ack_write(1);
}
let width = (cxp_grabber::roi_viewer_x1_read() - cxp_grabber::roi_viewer_x0_read()) as i32;
let height = (cxp_grabber::roi_viewer_y1_read() - cxp_grabber::roi_viewer_y0_read()) as i32;
let pixel_width = match cxp_grabber::stream_decoder_pixel_format_code_read() {
0x0101 => 8,
0x0102 => 10,
0x0103 => 12,
0x0104 => 14,
0x0105 => 16,
_ => artiq_raise!("CXPError", "UnsupportedPixelFormat"),
};
ROIViewerFrame {
width,
height,
pixel_width,
}
}
}

View File

@ -14,7 +14,6 @@
use core::mem; use core::mem;
use byteorder::NativeEndian;
use core_io::Error as ReadError; use core_io::Error as ReadError;
use cslice::{AsCSlice, CSlice}; use cslice::{AsCSlice, CSlice};
use dwarf::eh::{self, EHAction, EHContext}; use dwarf::eh::{self, EHAction, EHContext};
@ -303,9 +302,9 @@ pub unsafe extern "C" fn raise(exception: *const Exception) -> ! {
} }
fn read_exception_string<'a>(reader: &mut Cursor<&[u8]>) -> Result<CSlice<'a, u8>, ReadError> { fn read_exception_string<'a>(reader: &mut Cursor<&[u8]>) -> Result<CSlice<'a, u8>, ReadError> {
let len = reader.read_u32::<NativeEndian>()? as usize; let len = reader.read_u32()? as usize;
if len == usize::MAX { if len == usize::MAX {
let data = reader.read_u32::<NativeEndian>()?; let data = reader.read_u32()?;
Ok(unsafe { CSlice::new(data as *const u8, len) }) Ok(unsafe { CSlice::new(data as *const u8, len) })
} else { } else {
let pos = reader.position(); let pos = reader.position();
@ -330,19 +329,19 @@ fn read_exception(raw_exception: &[u8]) -> Result<Exception, ReadError> {
while byte != 0x09 { while byte != 0x09 {
byte = reader.read_u8()?; byte = reader.read_u8()?;
} }
let _len = reader.read_u32::<NativeEndian>()?; let _len = reader.read_u32()?;
// ignore the remaining exceptions, stack traces etc. - unwinding from another device would be unwise anyway // ignore the remaining exceptions, stack traces etc. - unwinding from another device would be unwise anyway
Ok(Exception { Ok(Exception {
id: reader.read_u32::<NativeEndian>()?, id: reader.read_u32()?,
message: read_exception_string(&mut reader)?, message: read_exception_string(&mut reader)?,
param: [ param: [
reader.read_u64::<NativeEndian>()? as i64, reader.read_u64()? as i64,
reader.read_u64::<NativeEndian>()? as i64, reader.read_u64()? as i64,
reader.read_u64::<NativeEndian>()? as i64, reader.read_u64()? as i64,
], ],
file: read_exception_string(&mut reader)?, file: read_exception_string(&mut reader)?,
line: reader.read_u32::<NativeEndian>()?, line: reader.read_u32()?,
column: reader.read_u32::<NativeEndian>()?, column: reader.read_u32()?,
function: read_exception_string(&mut reader)?, function: read_exception_string(&mut reader)?,
}) })
} }
@ -483,7 +482,7 @@ extern "C" fn stop_fn(
} }
// Must be kept in sync with preallocate_runtime_exception_names() in `artiq.compiler.embedding` // Must be kept in sync with preallocate_runtime_exception_names() in `artiq.compiler.embedding`
static EXCEPTION_ID_LOOKUP: [(&str, u32); 23] = [ static EXCEPTION_ID_LOOKUP: [(&str, u32); 22] = [
("RTIOUnderflow", 0), ("RTIOUnderflow", 0),
("RTIOOverflow", 1), ("RTIOOverflow", 1),
("RTIODestinationUnreachable", 2), ("RTIODestinationUnreachable", 2),
@ -506,7 +505,6 @@ static EXCEPTION_ID_LOOKUP: [(&str, u32); 23] = [
("ZeroDivisionError", 19), ("ZeroDivisionError", 19),
("LinAlgError", 20), ("LinAlgError", 20),
("UnwrapNoneError", 21), ("UnwrapNoneError", 21),
("CXPError", 22),
]; ];
pub fn get_exception_id(name: &str) -> u32 { pub fn get_exception_id(name: &str) -> u32 {

View File

@ -0,0 +1,97 @@
use libboard_zynq;
use crate::artiq_raise;
pub static mut I2C_BUS: Option<libboard_zynq::i2c::I2c> = None;
pub extern "C" fn start(busno: i32) {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
unsafe {
if (&mut I2C_BUS).as_mut().unwrap().start().is_err() {
artiq_raise!("I2CError", "I2C start failed");
}
}
}
pub extern "C" fn restart(busno: i32) {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
unsafe {
if (&mut I2C_BUS).as_mut().unwrap().restart().is_err() {
artiq_raise!("I2CError", "I2C restart failed");
}
}
}
pub extern "C" fn stop(busno: i32) {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
unsafe {
if (&mut I2C_BUS).as_mut().unwrap().stop().is_err() {
artiq_raise!("I2CError", "I2C stop failed");
}
}
}
pub extern "C" fn write(busno: i32, data: i32) -> bool {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
unsafe {
match (&mut I2C_BUS).as_mut().unwrap().write(data as u8) {
Ok(r) => r,
Err(_) => artiq_raise!("I2CError", "I2C write failed"),
}
}
}
pub extern "C" fn read(busno: i32, ack: bool) -> i32 {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
unsafe {
match (&mut I2C_BUS).as_mut().unwrap().read(ack) {
Ok(r) => r as i32,
Err(_) => artiq_raise!("I2CError", "I2C read failed"),
}
}
}
pub extern "C" fn switch_select(busno: i32, address: i32, mask: i32) {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
let ch = match mask {
//decode from mainline, PCA9548-centric API
0x00 => None,
0x01 => Some(0),
0x02 => Some(1),
0x04 => Some(2),
0x08 => Some(3),
0x10 => Some(4),
0x20 => Some(5),
0x40 => Some(6),
0x80 => Some(7),
_ => artiq_raise!("I2CError", "switch select supports only one channel"),
};
unsafe {
if (&mut I2C_BUS)
.as_mut()
.unwrap()
.pca954x_select(address as u8, ch)
.is_err()
{
artiq_raise!("I2CError", "switch select failed");
}
}
}
pub fn init() {
let mut i2c = libboard_zynq::i2c::I2c::i2c0();
i2c.init().expect("I2C bus initialization failed");
unsafe { I2C_BUS = Some(i2c) };
}

View File

@ -1,5 +1,4 @@
use core::{arch::asm, use core::sync::atomic::{AtomicBool, Ordering};
sync::atomic::{AtomicBool, Ordering}};
use libboard_zynq::{gic, mpcore, println, stdio}; use libboard_zynq::{gic, mpcore, println, stdio};
use libcortex_a9::{asm, interrupt_handler, notify_spin_lock, regs::MPIDR, spin_lock_yield}; use libcortex_a9::{asm, interrupt_handler, notify_spin_lock, regs::MPIDR, spin_lock_yield};

View File

@ -2,18 +2,16 @@ use alloc::vec;
use core::{ffi::VaList, ptr, str}; use core::{ffi::VaList, ptr, str};
use libc::{c_char, c_int, size_t}; use libc::{c_char, c_int, size_t};
use libm;
use log::{info, warn}; use log::{info, warn};
#[cfg(has_drtio)] #[cfg(has_drtio)]
use super::subkernel; use super::subkernel;
use super::{cache, use super::{cache,
core1::rtio_get_destination_status, core1::rtio_get_destination_status,
dma, i2c, linalg, dma, linalg,
rpc::{rpc_recv, rpc_send, rpc_send_async}, rpc::{rpc_recv, rpc_send, rpc_send_async}};
rtio}; use crate::{eh_artiq, i2c, rtio};
#[cfg(has_cxp_grabber)]
use crate::cxp;
use crate::eh_artiq;
extern "C" { extern "C" {
fn vsnprintf_(buffer: *mut c_char, count: size_t, format: *const c_char, va: VaList) -> c_int; fn vsnprintf_(buffer: *mut c_char, count: size_t, format: *const c_char, va: VaList) -> c_int;
@ -128,18 +126,6 @@ pub fn resolve(required: &[u8]) -> Option<u32> {
#[cfg(has_drtio)] #[cfg(has_drtio)]
api!(subkernel_await_message = subkernel::await_message), api!(subkernel_await_message = subkernel::await_message),
// cxp grabber
#[cfg(has_cxp_grabber)]
api!(cxp_download_xml_file = cxp::download_xml_file),
#[cfg(has_cxp_grabber)]
api!(cxp_read32 = cxp::read32),
#[cfg(has_cxp_grabber)]
api!(cxp_write32 = cxp::write32),
#[cfg(has_cxp_grabber)]
api!(cxp_start_roi_viewer = cxp::start_roi_viewer),
#[cfg(has_cxp_grabber)]
api!(cxp_download_roi_viewer_frame = cxp::download_roi_viewer_frame),
// Double-precision floating-point arithmetic helper functions // Double-precision floating-point arithmetic helper functions
// RTABI chapter 4.1.2, Table 2 // RTABI chapter 4.1.2, Table 2
api!(__aeabi_dadd), api!(__aeabi_dadd),

View File

@ -4,17 +4,17 @@ use alloc::borrow::ToOwned;
use core::{cell::UnsafeCell, mem, ptr}; use core::{cell::UnsafeCell, mem, ptr};
use cslice::CSlice; use cslice::CSlice;
use dyld::{elf::EXIDX_Entry, Library}; use dyld::{self, elf::EXIDX_Entry, Library};
use libboard_zynq::{gic, mpcore}; use libboard_zynq::{gic, mpcore};
use libcortex_a9::{asm::{dsb, isb}, use libcortex_a9::{asm::{dsb, isb},
cache::{bpiall, dcci_slice, iciallu}, cache::{bpiall, dcci_slice, iciallu},
sync_channel}; enable_fpu, sync_channel};
use libsupport_zynq::ram; use libsupport_zynq::ram;
use log::{debug, error, info}; use log::{debug, error, info};
use super::{api::resolve, dma, rpc::rpc_send_async, rtio, Message, CHANNEL_0TO1, CHANNEL_1TO0, CHANNEL_SEM, INIT_LOCK, use super::{api::resolve, dma, rpc::rpc_send_async, Message, CHANNEL_0TO1, CHANNEL_1TO0, CHANNEL_SEM, INIT_LOCK,
KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE}; KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE};
use crate::{eh_artiq, get_async_errors}; use crate::{eh_artiq, get_async_errors, rtio};
// linker symbols // linker symbols
extern "C" { extern "C" {
@ -25,14 +25,12 @@ extern "C" {
} }
unsafe fn attribute_writeback(typeinfo: *const ()) { unsafe fn attribute_writeback(typeinfo: *const ()) {
#[repr(C)]
struct Attr { struct Attr {
offset: usize, offset: usize,
tag: CSlice<'static, u8>, tag: CSlice<'static, u8>,
name: CSlice<'static, u8>, name: CSlice<'static, u8>,
} }
#[repr(C)]
struct Type { struct Type {
attributes: *const *const Attr, attributes: *const *const Attr,
objects: *const *const (), objects: *const *const (),
@ -128,6 +126,7 @@ impl KernelImage {
#[no_mangle] #[no_mangle]
pub extern "C" fn main_core1() { pub extern "C" fn main_core1() {
enable_fpu();
debug!("Core1 started"); debug!("Core1 started");
ram::init_alloc_core1(); ram::init_alloc_core1();

View File

@ -1,10 +1,10 @@
use alloc::{string::String, vec::Vec}; use alloc::{string::String, vec::Vec};
use core::{mem, ptr}; use core::mem;
use cslice::CSlice; use cslice::CSlice;
use super::{rtio, Message, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE}; use super::{Message, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE};
use crate::{artiq_raise, pl::csr}; use crate::{artiq_raise, pl::csr, rtio};
#[repr(C)] #[repr(C)]
pub struct DmaTrace { pub struct DmaTrace {
@ -26,7 +26,7 @@ static mut RECORDER: Option<DmaRecorder> = None;
pub unsafe fn init_dma_recorder() { pub unsafe fn init_dma_recorder() {
// as static would remain after restart, we have to reset it, // as static would remain after restart, we have to reset it,
// without running its destructor. // without running its destructor.
mem::forget(ptr::replace(&raw mut RECORDER, None)); mem::forget(mem::replace(&mut RECORDER, None));
} }
pub extern "C" fn dma_record_start(name: CSlice<u8>) { pub extern "C" fn dma_record_start(name: CSlice<u8>) {

View File

@ -1,192 +0,0 @@
use core::mem::MaybeUninit;
use libboard_zynq::i2c::{Error, I2c};
#[cfg(has_drtio)]
use super::{Message, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0};
use crate::artiq_raise;
static mut I2C_BUS: MaybeUninit<I2c> = MaybeUninit::uninit();
pub extern "C" fn start(busno: i32) {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
let reply = unsafe {
KERNEL_CHANNEL_1TO0
.as_mut()
.unwrap()
.send(Message::I2cStartRequest(busno as u32));
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cBasicReply(true) => return,
Message::I2cBasicReply(false) => artiq_raise!("I2CError", "I2C remote start fail"),
msg => panic!("Expected I2cBasicReply for I2cStartRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
if get_bus().start().is_err() {
artiq_raise!("I2CError", "I2C start failed");
}
}
pub extern "C" fn restart(busno: i32) {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
let reply = unsafe {
KERNEL_CHANNEL_1TO0
.as_mut()
.unwrap()
.send(Message::I2cRestartRequest(busno as u32));
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cBasicReply(true) => return,
Message::I2cBasicReply(false) => artiq_raise!("I2CError", "I2C remote restart fail"),
msg => panic!("Expected I2cBasicReply for I2cRetartRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
if get_bus().restart().is_err() {
artiq_raise!("I2CError", "I2C restart failed");
}
}
pub extern "C" fn stop(busno: i32) {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
// remote
let reply = unsafe {
KERNEL_CHANNEL_1TO0
.as_mut()
.unwrap()
.send(Message::I2cStopRequest(busno as u32));
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cBasicReply(true) => return,
Message::I2cBasicReply(false) => artiq_raise!("I2CError", "I2C remote stop fail"),
msg => panic!("Expected I2cBasicReply for I2cStopRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
if get_bus().stop().is_err() {
artiq_raise!("I2CError", "I2C stop failed");
}
}
pub extern "C" fn write(busno: i32, data: i32) -> bool {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
// remote
let reply = unsafe {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::I2cWriteRequest {
busno: busno as u32,
data: data as u8,
});
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cWriteReply { succeeded: true, ack } => return ack,
Message::I2cWriteReply { succeeded: false, .. } => artiq_raise!("I2CError", "I2C remote write fail"),
msg => panic!("Expected I2cWriteReply for I2cWriteRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
match get_bus().write(data as u8) {
Ok(()) => true,
Err(Error::Nack) => false,
Err(_) => artiq_raise!("I2CError", "I2C write failed"),
}
}
pub extern "C" fn read(busno: i32, ack: bool) -> i32 {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
let reply = unsafe {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::I2cReadRequest {
busno: busno as u32,
ack,
});
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cReadReply { succeeded: true, data } => return data as i32,
Message::I2cReadReply { succeeded: false, .. } => artiq_raise!("I2CError", "I2C remote read fail"),
msg => panic!("Expected I2cReadReply for I2cReadRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
match get_bus().read(ack) {
Ok(r) => r as i32,
Err(_) => artiq_raise!("I2CError", "I2C read failed"),
}
}
pub extern "C" fn switch_select(busno: i32, address: i32, mask: i32) {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
// remote
let reply = unsafe {
KERNEL_CHANNEL_1TO0
.as_mut()
.unwrap()
.send(Message::I2cSwitchSelectRequest {
busno: busno as u32,
address: address as u8,
mask: mask as u8,
});
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cBasicReply(true) => return,
Message::I2cBasicReply(false) => artiq_raise!("I2CError", "I2C remote start fail"),
msg => panic!("Expected I2cBasicReply for I2cSwitchSelectRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
let ch = match mask {
//decode from mainline, PCA9548-centric API
0x00 => None,
0x01 => Some(0),
0x02 => Some(1),
0x04 => Some(2),
0x08 => Some(3),
0x10 => Some(4),
0x20 => Some(5),
0x40 => Some(6),
0x80 => Some(7),
_ => artiq_raise!("I2CError", "switch select supports only one channel"),
};
if get_bus().pca954x_select(address as u8, ch).is_err() {
artiq_raise!("I2CError", "switch select failed");
}
}
pub fn init() {
let mut i2c = I2c::i2c0();
i2c.init().expect("I2C bus initialization failed");
unsafe { I2C_BUS.write(i2c) };
}
pub fn get_bus() -> &'static mut I2c {
unsafe { I2C_BUS.assume_init_mut() }
}

View File

@ -10,14 +10,7 @@ pub use control::Control;
mod api; mod api;
pub mod core1; pub mod core1;
mod dma; mod dma;
pub mod i2c;
mod rpc; mod rpc;
#[cfg(ki_impl = "csr")]
#[path = "rtio_csr.rs"]
pub mod rtio;
#[cfg(ki_impl = "acp")]
#[path = "rtio_acp.rs"]
pub mod rtio;
pub use dma::DmaRecorder; pub use dma::DmaRecorder;
mod cache; mod cache;
mod linalg; mod linalg;
@ -48,10 +41,6 @@ pub enum Message {
&'static [(usize, usize)], &'static [(usize, usize)],
u8, u8,
), ),
#[cfg(has_drtio)]
RtioInitRequest,
RpcSend { RpcSend {
is_async: bool, is_async: bool,
data: Vec<u8>, data: Vec<u8>,
@ -87,41 +76,6 @@ pub enum Message {
#[cfg(has_drtio)] #[cfg(has_drtio)]
UpDestinationsReply(bool), UpDestinationsReply(bool),
#[cfg(has_drtio)]
I2cStartRequest(u32),
#[cfg(has_drtio)]
I2cRestartRequest(u32),
#[cfg(has_drtio)]
I2cStopRequest(u32),
#[cfg(has_drtio)]
I2cWriteRequest {
busno: u32,
data: u8,
},
#[cfg(has_drtio)]
I2cWriteReply {
succeeded: bool,
ack: bool,
},
#[cfg(has_drtio)]
I2cReadRequest {
busno: u32,
ack: bool,
},
#[cfg(has_drtio)]
I2cReadReply {
succeeded: bool,
data: u8,
},
#[cfg(has_drtio)]
I2cBasicReply(bool),
#[cfg(has_drtio)]
I2cSwitchSelectRequest {
busno: u32,
address: u8,
mask: u8,
},
#[cfg(has_drtio)] #[cfg(has_drtio)]
SubkernelLoadRunRequest { SubkernelLoadRunRequest {
id: u32, id: u32,

View File

@ -2,8 +2,8 @@ use alloc::vec::Vec;
use cslice::CSlice; use cslice::CSlice;
use super::{rtio::now_mu, Message, SubkernelStatus, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0}; use super::{Message, SubkernelStatus, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0};
use crate::{artiq_raise, eh_artiq, rpc::send_args}; use crate::{artiq_raise, eh_artiq, rpc::send_args, rtio::now_mu};
pub extern "C" fn load_run(id: u32, destination: u8, run: bool) { pub extern "C" fn load_run(id: u32, destination: u8, run: bool) {
unsafe { unsafe {

View File

@ -1,16 +1,16 @@
#![no_std] #![no_std]
#![allow(incomplete_features)]
#![feature(c_variadic)] #![feature(c_variadic)]
#![feature(const_btree_len)] #![feature(const_btree_new)]
#![feature(inline_const)] #![feature(inline_const)]
#![feature(naked_functions)] #![feature(naked_functions)]
#![feature(raw_ref_op)] #![feature(asm)]
#[macro_use] #[macro_use]
extern crate alloc; extern crate alloc;
use alloc::{collections::BTreeMap, string::String}; use alloc::{collections::BTreeMap, string::String};
use byteorder::NativeEndian;
use io::{Cursor, ProtoRead}; use io::{Cursor, ProtoRead};
use libasync::block_async; use libasync::block_async;
use libconfig::Config; use libconfig::Config;
@ -22,15 +22,20 @@ pub use pl::csr::rtio_core;
use void::Void; use void::Void;
pub mod eh_artiq; pub mod eh_artiq;
pub mod i2c;
pub mod irq; pub mod irq;
pub mod kernel; pub mod kernel;
pub mod rpc; pub mod rpc;
#[cfg(ki_impl = "csr")]
#[path = "rtio_csr.rs"]
pub mod rtio;
#[cfg(ki_impl = "acp")]
#[path = "rtio_acp.rs"]
pub mod rtio;
#[rustfmt::skip] #[rustfmt::skip]
#[path = "../../../build/pl.rs"] #[path = "../../../build/pl.rs"]
pub mod pl; pub mod pl;
#[cfg(has_cxp_grabber)]
pub mod cxp;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RPCException { pub struct RPCException {
@ -118,10 +123,10 @@ fn read_device_map(cfg: &Config) -> BTreeMap<u32, String> {
.read("device_map") .read("device_map")
.and_then(|raw_bytes| { .and_then(|raw_bytes| {
let mut bytes_cr = Cursor::new(raw_bytes); let mut bytes_cr = Cursor::new(raw_bytes);
let size = bytes_cr.read_u32::<NativeEndian>().unwrap(); let size = bytes_cr.read_u32().unwrap();
for _ in 0..size { for _ in 0..size {
let channel = bytes_cr.read_u32::<NativeEndian>().unwrap(); let channel = bytes_cr.read_u32().unwrap();
let device_name = bytes_cr.read_string::<NativeEndian>().unwrap(); let device_name = bytes_cr.read_string().unwrap();
if let Some(old_entry) = device_map.insert(channel, device_name.clone()) { if let Some(old_entry) = device_map.insert(channel, device_name.clone()) {
warn!( warn!(
"conflicting device map entries for RTIO channel {}: '{}' and '{}'", "conflicting device map entries for RTIO channel {}: '{}' and '{}'",
@ -141,15 +146,17 @@ fn read_device_map(cfg: &Config) -> BTreeMap<u32, String> {
device_map device_map
} }
pub fn resolve_channel_name(channel: u32) -> String { fn _resolve_channel_name(channel: u32, device_map: &BTreeMap<u32, String>) -> String {
unsafe { match device_map.get(&channel) {
match RTIO_DEVICE_MAP.get(&channel) { Some(val) => val.clone(),
Some(val) => val.clone(), None => String::from("unknown"),
None => String::from("unknown"),
}
} }
} }
pub fn resolve_channel_name(channel: u32) -> String {
_resolve_channel_name(channel, unsafe { &RTIO_DEVICE_MAP })
}
pub fn setup_device_map(cfg: &Config) { pub fn setup_device_map(cfg: &Config) {
unsafe { unsafe {
RTIO_DEVICE_MAP = read_device_map(cfg); RTIO_DEVICE_MAP = read_device_map(cfg);

View File

@ -1,7 +1,7 @@
use core::str; use core::str;
use byteorder::{ByteOrder, NativeEndian}; use byteorder::{ByteOrder, NativeEndian};
use core_io::Error; use core_io::{Error, Read, Write};
use cslice::{CMutSlice, CSlice}; use cslice::{CMutSlice, CSlice};
use io::{ProtoRead, ProtoWrite}; use io::{ProtoRead, ProtoWrite};
use log::trace; use log::trace;
@ -37,7 +37,7 @@ pub unsafe fn align_ptr_mut<T>(ptr: *mut ()) -> *mut T {
// versions for reader rather than TcpStream // versions for reader rather than TcpStream
// they will be made into sync for satellite subkernels later // they will be made into sync for satellite subkernels later
unsafe fn recv_elements<F, R: ProtoRead>( unsafe fn recv_elements<F, R>(
reader: &mut R, reader: &mut R,
elt_tag: Tag, elt_tag: Tag,
length: usize, length: usize,
@ -46,6 +46,7 @@ unsafe fn recv_elements<F, R: ProtoRead>(
) -> Result<(), Error> ) -> Result<(), Error>
where where
F: FnMut(usize) -> *mut (), F: FnMut(usize) -> *mut (),
R: Read + ?Sized,
{ {
match elt_tag { match elt_tag {
Tag::Bool => { Tag::Bool => {
@ -56,7 +57,7 @@ where
let ptr = storage as *mut u32; let ptr = storage as *mut u32;
let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 4); let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 4);
reader.read_exact(dest)?; reader.read_exact(dest)?;
let _ = dest; drop(dest);
let dest = core::slice::from_raw_parts_mut(ptr, length); let dest = core::slice::from_raw_parts_mut(ptr, length);
NativeEndian::from_slice_u32(dest); NativeEndian::from_slice_u32(dest);
} }
@ -64,7 +65,7 @@ where
let ptr = storage as *mut u64; let ptr = storage as *mut u64;
let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 8); let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 8);
reader.read_exact(dest)?; reader.read_exact(dest)?;
let _ = dest; drop(dest);
let dest = core::slice::from_raw_parts_mut(ptr, length); let dest = core::slice::from_raw_parts_mut(ptr, length);
NativeEndian::from_slice_u64(dest); NativeEndian::from_slice_u64(dest);
} }
@ -81,7 +82,7 @@ where
unsafe fn recv_value<F, R>(reader: &mut R, tag: Tag, data: &mut *mut (), alloc: &mut F) -> Result<(), Error> unsafe fn recv_value<F, R>(reader: &mut R, tag: Tag, data: &mut *mut (), alloc: &mut F) -> Result<(), Error>
where where
F: FnMut(usize) -> *mut (), F: FnMut(usize) -> *mut (),
R: ProtoRead, R: Read + ?Sized,
{ {
macro_rules! consume_value { macro_rules! consume_value {
($ty:ty, | $ptr:ident | $map:expr) => {{ ($ty:ty, | $ptr:ident | $map:expr) => {{
@ -98,16 +99,16 @@ where
Ok(()) Ok(())
}), }),
Tag::Int32 => consume_value!(i32, |ptr| { Tag::Int32 => consume_value!(i32, |ptr| {
*ptr = reader.read_u32::<NativeEndian>()? as i32; *ptr = reader.read_u32()? as i32;
Ok(()) Ok(())
}), }),
Tag::Int64 | Tag::Float64 => consume_value!(i64, |ptr| { Tag::Int64 | Tag::Float64 => consume_value!(i64, |ptr| {
*ptr = reader.read_u64::<NativeEndian>()? as i64; *ptr = reader.read_u64()? as i64;
Ok(()) Ok(())
}), }),
Tag::String | Tag::Bytes | Tag::ByteArray => { Tag::String | Tag::Bytes | Tag::ByteArray => {
consume_value!(CMutSlice<u8>, |ptr| { consume_value!(CMutSlice<u8>, |ptr| {
let length = reader.read_u32::<NativeEndian>()? as usize; let length = reader.read_u32()? as usize;
*ptr = CMutSlice::new(alloc(length) as *mut u8, length); *ptr = CMutSlice::new(alloc(length) as *mut u8, length);
reader.read_exact((*ptr).as_mut())?; reader.read_exact((*ptr).as_mut())?;
Ok(()) Ok(())
@ -132,7 +133,7 @@ where
} }
consume_value!(*mut List, |ptr_to_list| { consume_value!(*mut List, |ptr_to_list| {
let tag = it.clone().next().expect("truncated tag"); let tag = it.clone().next().expect("truncated tag");
let length = reader.read_u32::<NativeEndian>()? as usize; let length = reader.read_u32()? as usize;
let list_size = 4 + 4; let list_size = 4 + 4;
let storage_offset = round_up(list_size, tag.alignment()); let storage_offset = round_up(list_size, tag.alignment());
@ -151,7 +152,7 @@ where
consume_value!(*mut (), |buffer| { consume_value!(*mut (), |buffer| {
let mut total_len: usize = 1; let mut total_len: usize = 1;
for _ in 0..num_dims { for _ in 0..num_dims {
let len = reader.read_u32::<NativeEndian>()? as usize; let len = reader.read_u32()? as usize;
total_len *= len; total_len *= len;
consume_value!(usize, |ptr| *ptr = len) consume_value!(usize, |ptr| *ptr = len)
} }
@ -182,7 +183,7 @@ pub fn recv_return<'a, F, R>(
) -> Result<&'a [u8], Error> ) -> Result<&'a [u8], Error>
where where
F: FnMut(usize) -> *mut (), F: FnMut(usize) -> *mut (),
R: ProtoRead, R: Read + ?Sized,
{ {
let mut it = TagIterator::new(tag_bytes); let mut it = TagIterator::new(tag_bytes);
trace!("recv ...->{}", it); trace!("recv ...->{}", it);
@ -194,13 +195,16 @@ where
Ok(it.data) Ok(it.data)
} }
unsafe fn send_elements<W: ProtoWrite>( unsafe fn send_elements<W>(
writer: &mut W, writer: &mut W,
elt_tag: Tag, elt_tag: Tag,
length: usize, length: usize,
data: *const (), data: *const (),
write_tags: bool, write_tags: bool,
) -> Result<(), Error> { ) -> Result<(), Error>
where
W: Write + ?Sized,
{
if write_tags { if write_tags {
writer.write_u8(elt_tag.as_u8())?; writer.write_u8(elt_tag.as_u8())?;
} }
@ -229,12 +233,8 @@ unsafe fn send_elements<W: ProtoWrite>(
Ok(()) Ok(())
} }
unsafe fn send_value<W: ProtoWrite>( unsafe fn send_value<W>(writer: &mut W, tag: Tag, data: &mut *const (), write_tags: bool) -> Result<(), Error>
writer: &mut W, where W: Write + ?Sized {
tag: Tag,
data: &mut *const (),
write_tags: bool,
) -> Result<(), Error> {
macro_rules! consume_value { macro_rules! consume_value {
($ty:ty, | $ptr:ident | $map:expr) => {{ ($ty:ty, | $ptr:ident | $map:expr) => {{
let $ptr = align_ptr::<$ty>(*data); let $ptr = align_ptr::<$ty>(*data);
@ -249,14 +249,12 @@ unsafe fn send_value<W: ProtoWrite>(
match tag { match tag {
Tag::None => Ok(()), Tag::None => Ok(()),
Tag::Bool => consume_value!(u8, |ptr| writer.write_u8(*ptr)), Tag::Bool => consume_value!(u8, |ptr| writer.write_u8(*ptr)),
Tag::Int32 => consume_value!(u32, |ptr| writer.write_u32::<NativeEndian>(*ptr)), Tag::Int32 => consume_value!(u32, |ptr| writer.write_u32(*ptr)),
Tag::Int64 | Tag::Float64 => consume_value!(u64, |ptr| writer.write_u64::<NativeEndian>(*ptr)), Tag::Int64 | Tag::Float64 => consume_value!(u64, |ptr| writer.write_u64(*ptr)),
Tag::String => consume_value!(CSlice<u8>, |ptr| { Tag::String => consume_value!(CSlice<u8>, |ptr| {
writer.write_string::<NativeEndian>(str::from_utf8((*ptr).as_ref()).unwrap()) writer.write_string(str::from_utf8((*ptr).as_ref()).unwrap())
}), }),
Tag::Bytes | Tag::ByteArray => { Tag::Bytes | Tag::ByteArray => consume_value!(CSlice<u8>, |ptr| writer.write_bytes((*ptr).as_ref())),
consume_value!(CSlice<u8>, |ptr| writer.write_bytes::<NativeEndian>((*ptr).as_ref()))
}
Tag::Tuple(it, arity) => { Tag::Tuple(it, arity) => {
let mut it = it.clone(); let mut it = it.clone();
if write_tags { if write_tags {
@ -279,7 +277,7 @@ unsafe fn send_value<W: ProtoWrite>(
} }
consume_value!(&List, |ptr| { consume_value!(&List, |ptr| {
let length = (**ptr).length as usize; let length = (**ptr).length as usize;
writer.write_u32::<NativeEndian>((*ptr).length)?; writer.write_u32((*ptr).length)?;
let tag = it.clone().next().expect("truncated tag"); let tag = it.clone().next().expect("truncated tag");
send_elements(writer, tag, length, (**ptr).elements, write_tags) send_elements(writer, tag, length, (**ptr).elements, write_tags)
}) })
@ -294,7 +292,7 @@ unsafe fn send_value<W: ProtoWrite>(
let mut total_len = 1; let mut total_len = 1;
for _ in 0..num_dims { for _ in 0..num_dims {
consume_value!(u32, |len| { consume_value!(u32, |len| {
writer.write_u32::<NativeEndian>(*len)?; writer.write_u32(*len)?;
total_len *= *len; total_len *= *len;
}) })
} }
@ -315,7 +313,7 @@ unsafe fn send_value<W: ProtoWrite>(
name: CSlice<'a, u8>, name: CSlice<'a, u8>,
} }
consume_value!(Keyword, |ptr| { consume_value!(Keyword, |ptr| {
writer.write_string::<NativeEndian>(str::from_utf8((*ptr).name.as_ref()).unwrap())?; writer.write_string(str::from_utf8((*ptr).name.as_ref()).unwrap())?;
let tag = it.clone().next().expect("truncated tag"); let tag = it.clone().next().expect("truncated tag");
let mut data = ptr.offset(1) as *const (); let mut data = ptr.offset(1) as *const ();
send_value(writer, tag, &mut data, write_tags) send_value(writer, tag, &mut data, write_tags)
@ -328,25 +326,28 @@ unsafe fn send_value<W: ProtoWrite>(
struct Object { struct Object {
id: u32, id: u32,
} }
consume_value!(*const Object, |ptr| writer.write_u32::<NativeEndian>((**ptr).id)) consume_value!(*const Object, |ptr| writer.write_u32((**ptr).id))
} }
} }
} }
pub fn send_args<W: ProtoWrite>( pub fn send_args<W>(
writer: &mut W, writer: &mut W,
service: u32, service: u32,
tag_bytes: &[u8], tag_bytes: &[u8],
data: *const *const (), data: *const *const (),
write_tags: bool, write_tags: bool,
) -> Result<(), Error> { ) -> Result<(), Error>
where
W: Write + ?Sized,
{
let (arg_tags_bytes, return_tag_bytes) = split_tag(tag_bytes); let (arg_tags_bytes, return_tag_bytes) = split_tag(tag_bytes);
let mut args_it = TagIterator::new(arg_tags_bytes); let mut args_it = TagIterator::new(arg_tags_bytes);
let return_it = TagIterator::new(return_tag_bytes); let return_it = TagIterator::new(return_tag_bytes);
trace!("send<{}>({})->{}", service, args_it, return_it); trace!("send<{}>({})->{}", service, args_it, return_it);
writer.write_u32::<NativeEndian>(service)?; writer.write_u32(service)?;
for index in 0.. { for index in 0.. {
if let Some(arg_tag) = args_it.next() { if let Some(arg_tag) = args_it.next() {
let mut data = unsafe { *data.offset(index) }; let mut data = unsafe { *data.offset(index) };
@ -356,7 +357,7 @@ pub fn send_args<W: ProtoWrite>(
} }
} }
writer.write_u8(0)?; writer.write_u8(0)?;
writer.write_bytes::<NativeEndian>(return_tag_bytes)?; writer.write_bytes(return_tag_bytes)?;
Ok(()) Ok(())
} }

View File

@ -4,8 +4,6 @@ use cslice::CSlice;
use libcortex_a9::asm; use libcortex_a9::asm;
use vcell::VolatileCell; use vcell::VolatileCell;
#[cfg(has_drtio)]
use super::{Message, KERNEL_CHANNEL_1TO0};
use crate::{artiq_raise, pl::csr, resolve_channel_name, rtio_core}; use crate::{artiq_raise, pl::csr, resolve_channel_name, rtio_core};
pub const RTIO_O_STATUS_WAIT: i32 = 1; pub const RTIO_O_STATUS_WAIT: i32 = 1;
@ -58,10 +56,6 @@ pub extern "C" fn init() {
csr::rtio::engine_addr_base_write(&TRANSACTION_BUFFER as *const Transaction as u32); csr::rtio::engine_addr_base_write(&TRANSACTION_BUFFER as *const Transaction as u32);
csr::rtio::enable_write(1); csr::rtio::enable_write(1);
} }
#[cfg(has_drtio)]
unsafe {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::RtioInitRequest);
}
} }
pub extern "C" fn get_counter() -> i64 { pub extern "C" fn get_counter() -> i64 {

View File

@ -2,8 +2,6 @@ use core::ptr::{read_volatile, write_volatile};
use cslice::CSlice; use cslice::CSlice;
#[cfg(has_drtio)]
use super::{Message, KERNEL_CHANNEL_1TO0};
use crate::{artiq_raise, pl::csr, resolve_channel_name, rtio_core}; use crate::{artiq_raise, pl::csr, resolve_channel_name, rtio_core};
pub const RTIO_O_STATUS_WAIT: u8 = 1; pub const RTIO_O_STATUS_WAIT: u8 = 1;
@ -24,10 +22,6 @@ pub extern "C" fn init() {
unsafe { unsafe {
rtio_core::reset_write(1); rtio_core::reset_write(1);
} }
#[cfg(has_drtio)]
unsafe {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::RtioInitRequest);
}
} }
pub extern "C" fn get_counter() -> i64 { pub extern "C" fn get_counter() -> i64 {

View File

@ -1,6 +1,8 @@
#![no_std] #![no_std]
#![feature(link_cfg)] #![feature(link_cfg)]
#![feature(nll)]
#![feature(c_unwind)] #![feature(c_unwind)]
#![feature(static_nobundle)]
#![cfg_attr(not(target_env = "msvc"), feature(libc))] #![cfg_attr(not(target_env = "msvc"), feature(libc))]
cfg_if::cfg_if! { cfg_if::cfg_if! {
@ -22,12 +24,7 @@ cfg_if::cfg_if! {
extern "C" {} extern "C" {}
#[cfg(target_os = "redox")] #[cfg(target_os = "redox")]
#[link( #[link(name = "gcc_eh", kind = "static-nobundle", cfg(target_feature = "crt-static"))]
name = "gcc_eh",
kind = "static",
modifiers = "-bundle",
cfg(target_feature = "crt-static")
)]
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
extern "C" {} extern "C" {}

View File

@ -16,7 +16,7 @@ build_zynq = { path = "../libbuild_zynq" }
[dependencies] [dependencies]
num-traits = { version = "0.2", default-features = false } num-traits = { version = "0.2", default-features = false }
num-derive = "0.4" num-derive = "0.3"
cslice = "0.3" cslice = "0.3"
log = "0.4" log = "0.4"
embedded-hal = "0.2" embedded-hal = "0.2"
@ -25,7 +25,7 @@ crc = { version = "1.7", default-features = false }
byteorder = { version = "1.3", default-features = false } byteorder = { version = "1.3", default-features = false }
void = { version = "1", default-features = false } void = { version = "1", default-features = false }
futures = { version = "0.3", default-features = false, features = ["async-await"] } futures = { version = "0.3", default-features = false, features = ["async-await"] }
async-recursion = "1.1" async-recursion = "0.3"
log_buffer = { version = "1.2" } log_buffer = { version = "1.2" }
vcell = "0.1" vcell = "0.1"

View File

@ -397,42 +397,6 @@ async fn handle_run_kernel(
control.borrow_mut().tx.async_send(reply).await; control.borrow_mut().tx.async_send(reply).await;
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
kernel::Message::I2cStartRequest(busno)
| kernel::Message::I2cRestartRequest(busno)
| kernel::Message::I2cStopRequest(busno)
| kernel::Message::I2cSwitchSelectRequest { busno, .. } => {
let result = rtio_mgt::drtio::i2c_send_basic(aux_mutex, routing_table, timer, &reply, busno).await;
let reply = match result {
Ok(succeeded) => kernel::Message::I2cBasicReply(succeeded),
Err(_) => kernel::Message::I2cBasicReply(false),
};
control.borrow_mut().tx.async_send(reply).await;
}
#[cfg(has_drtio)]
kernel::Message::I2cWriteRequest { busno, data } => {
let result = rtio_mgt::drtio::i2c_send_write(aux_mutex, routing_table, timer, busno, data).await;
let reply = match result {
Ok((succeeded, ack)) => kernel::Message::I2cWriteReply { succeeded, ack },
Err(_) => kernel::Message::I2cWriteReply {
succeeded: false,
ack: false,
},
};
control.borrow_mut().tx.async_send(reply).await;
}
#[cfg(has_drtio)]
kernel::Message::I2cReadRequest { busno, ack } => {
let result = rtio_mgt::drtio::i2c_send_read(aux_mutex, routing_table, timer, busno, ack).await;
let reply = match result {
Ok((succeeded, data)) => kernel::Message::I2cReadReply { succeeded, data },
Err(_) => kernel::Message::I2cReadReply {
succeeded: false,
data: 0xFF,
},
};
control.borrow_mut().tx.async_send(reply).await;
}
#[cfg(has_drtio)]
kernel::Message::SubkernelLoadRunRequest { kernel::Message::SubkernelLoadRunRequest {
id, id,
destination: _, destination: _,
@ -557,10 +521,6 @@ async fn handle_run_kernel(
.async_send(kernel::Message::UpDestinationsReply(result)) .async_send(kernel::Message::UpDestinationsReply(result))
.await; .await;
} }
#[cfg(has_drtio)]
kernel::Message::RtioInitRequest => {
rtio_mgt::drtio::reset(aux_mutex, routing_table, timer).await;
}
_ => { _ => {
panic!("unexpected message from core1 while kernel was running: {:?}", reply); panic!("unexpected message from core1 while kernel was running: {:?}", reply);
} }

View File

@ -2,10 +2,8 @@
#![no_main] #![no_main]
#![recursion_limit = "1024"] // for futures_util::select! #![recursion_limit = "1024"] // for futures_util::select!
#![feature(alloc_error_handler)] #![feature(alloc_error_handler)]
#![feature(const_btree_len)] #![feature(const_btree_new)]
#![feature(panic_info_message)] #![feature(panic_info_message)]
#![allow(internal_features)]
#![feature(lang_items)]
#[macro_use] #[macro_use]
extern crate alloc; extern crate alloc;
@ -13,9 +11,8 @@ extern crate alloc;
#[cfg(all(feature = "target_kasli_soc", has_virtual_leds))] #[cfg(all(feature = "target_kasli_soc", has_virtual_leds))]
use core::cell::RefCell; use core::cell::RefCell;
use ksupport;
use libasync::task; use libasync::task;
#[cfg(has_cxp_grabber)]
use libboard_artiq::cxp_phys;
#[cfg(has_drtio_eem)] #[cfg(has_drtio_eem)]
use libboard_artiq::drtio_eem; use libboard_artiq::drtio_eem;
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
@ -81,23 +78,6 @@ mod grabber {
} }
} }
#[cfg(has_cxp_grabber)]
mod cxp {
use libasync::delay;
use libboard_artiq::cxp_grabber;
use libboard_zynq::time::Milliseconds;
use crate::GlobalTimer;
pub async fn grabber_thread(timer: GlobalTimer) {
let mut countdown = timer.countdown();
loop {
cxp_grabber::tick(timer);
delay(&mut countdown, Milliseconds(200)).await;
}
}
}
static mut LOG_BUFFER: [u8; 1 << 17] = [0; 1 << 17]; static mut LOG_BUFFER: [u8; 1 << 17] = [0; 1 << 17];
#[no_mangle] #[no_mangle]
@ -120,10 +100,10 @@ pub fn main_core0() {
info!("gateware ident: {}", identifier_read(&mut [0; 64])); info!("gateware ident: {}", identifier_read(&mut [0; 64]));
ksupport::kernel::i2c::init(); ksupport::i2c::init();
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
{ {
let i2c_bus = ksupport::kernel::i2c::get_bus(); let i2c_bus = unsafe { (ksupport::i2c::I2C_BUS).as_mut().unwrap() };
let mut io_expander0 = io_expander::IoExpander::new(i2c_bus, 0).unwrap(); let mut io_expander0 = io_expander::IoExpander::new(i2c_bus, 0).unwrap();
let mut io_expander1 = io_expander::IoExpander::new(i2c_bus, 1).unwrap(); let mut io_expander1 = io_expander::IoExpander::new(i2c_bus, 1).unwrap();
io_expander0 io_expander0
@ -170,11 +150,5 @@ pub fn main_core0() {
task::spawn(ksupport::report_async_rtio_errors()); task::spawn(ksupport::report_async_rtio_errors());
#[cfg(has_cxp_grabber)]
{
cxp_phys::setup();
task::spawn(cxp::grabber_thread(timer));
}
comms::main(timer, cfg); comms::main(timer, cfg);
} }

View File

@ -99,7 +99,7 @@ async fn read_log_level_filter(stream: &mut TcpStream) -> Result<log::LevelFilte
async fn get_logger_buffer_pred<F>(f: F) -> LogBufferRef<'static> async fn get_logger_buffer_pred<F>(f: F) -> LogBufferRef<'static>
where F: Fn(&LogBufferRef) -> bool { where F: Fn(&LogBufferRef) -> bool {
poll_fn(|ctx| { poll_fn(|ctx| {
let logger = BufferLogger::get_logger(); let logger = unsafe { BufferLogger::get_logger().as_mut().unwrap() };
match logger.buffer() { match logger.buffer() {
Some(buffer) if f(&buffer) => Poll::Ready(buffer), Some(buffer) if f(&buffer) => Poll::Ready(buffer),
_ => { _ => {
@ -435,8 +435,8 @@ mod remote_coremgmt {
_restart_idle: &Rc<Semaphore>, _restart_idle: &Rc<Semaphore>,
) -> Result<()> { ) -> Result<()> {
let mut message = Vec::with_capacity(key.len() + value.len() + 4 * 2); let mut message = Vec::with_capacity(key.len() + value.len() + 4 * 2);
message.write_string::<NativeEndian>(key).unwrap(); message.write_string(key).unwrap();
message.write_bytes::<NativeEndian>(&value).unwrap(); message.write_bytes(&value).unwrap();
match drtio::partition_data( match drtio::partition_data(
linkno, linkno,
@ -750,7 +750,7 @@ mod local_coremgmt {
write_chunk(stream, &bytes).await?; write_chunk(stream, &bytes).await?;
if log::max_level() == log::LevelFilter::Trace { if log::max_level() == log::LevelFilter::Trace {
// temporarily discard all trace level log // temporarily discard all trace level log
let logger = BufferLogger::get_logger(); let logger = unsafe { BufferLogger::get_logger().as_mut().unwrap() };
logger.set_buffer_log_level(log::LevelFilter::Debug); logger.set_buffer_log_level(log::LevelFilter::Debug);
stream.flush().await?; stream.flush().await?;
logger.set_buffer_log_level(log::LevelFilter::Trace); logger.set_buffer_log_level(log::LevelFilter::Trace);
@ -768,7 +768,9 @@ mod local_coremgmt {
pub async fn set_uart_log_filter(stream: &mut TcpStream, lvl: log::LevelFilter) -> Result<()> { pub async fn set_uart_log_filter(stream: &mut TcpStream, lvl: log::LevelFilter) -> Result<()> {
info!("Changing UART log level to {}", lvl); info!("Changing UART log level to {}", lvl);
BufferLogger::get_logger().set_uart_log_level(lvl); unsafe {
BufferLogger::get_logger().as_ref().unwrap().set_uart_log_level(lvl);
}
write_i8(stream, Reply::Success as i8).await?; write_i8(stream, Reply::Success as i8).await?;
Ok(()) Ok(())
} }
@ -901,7 +903,6 @@ macro_rules! process {
}} }}
} }
#[allow(dead_code)]
#[derive(Clone)] #[derive(Clone)]
pub struct DrtioContext(pub Rc<Mutex<bool>>, pub Rc<RefCell<RoutingTable>>, pub GlobalTimer); pub struct DrtioContext(pub Rc<Mutex<bool>>, pub Rc<RefCell<RoutingTable>>, pub GlobalTimer);

View File

@ -71,7 +71,3 @@ fn soft_panic(info: &core::panic::PanicInfo) -> ! {
}; };
soft_panic_main(timer, cfg); soft_panic_main(timer, cfg);
} }
#[lang = "eh_personality"]
#[no_mangle]
pub extern "C" fn rust_eh_personality() {}

View File

@ -38,7 +38,7 @@ where
let ptr = storage as *mut u32; let ptr = storage as *mut u32;
let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 4); let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 4);
proto_async::read_chunk(stream, dest).await?; proto_async::read_chunk(stream, dest).await?;
let _ = dest; drop(dest);
let dest = core::slice::from_raw_parts_mut(ptr, length); let dest = core::slice::from_raw_parts_mut(ptr, length);
NativeEndian::from_slice_u32(dest); NativeEndian::from_slice_u32(dest);
} }
@ -46,7 +46,7 @@ where
let ptr = storage as *mut u64; let ptr = storage as *mut u64;
let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 8); let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 8);
proto_async::read_chunk(stream, dest).await?; proto_async::read_chunk(stream, dest).await?;
let _ = dest; drop(dest);
let dest = core::slice::from_raw_parts_mut(ptr, length); let dest = core::slice::from_raw_parts_mut(ptr, length);
NativeEndian::from_slice_u64(dest); NativeEndian::from_slice_u64(dest);
} }

View File

@ -1,7 +1,7 @@
#[cfg(not(feature = "target_ebaz4205"))] #[cfg(not(feature = "target_ebaz4205"))]
use embedded_hal::blocking::delay::DelayMs; use embedded_hal::blocking::delay::DelayMs;
#[cfg(has_si5324)] #[cfg(has_si5324)]
use ksupport::kernel::i2c; use ksupport::i2c;
#[cfg(not(feature = "target_ebaz4205"))] #[cfg(not(feature = "target_ebaz4205"))]
use libboard_artiq::pl; use libboard_artiq::pl;
#[cfg(has_si5324)] #[cfg(has_si5324)]
@ -446,7 +446,7 @@ pub fn init(timer: &mut GlobalTimer, cfg: &Config) {
let clk = get_rtio_clock_cfg(cfg); let clk = get_rtio_clock_cfg(cfg);
#[cfg(has_si5324)] #[cfg(has_si5324)]
{ {
let i2c = i2c::get_bus(); let i2c = unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() };
match clk { match clk {
RtioClock::Ext0_Bypass => { RtioClock::Ext0_Bypass => {
info!("bypassing the PLL for RTIO clock"); info!("bypassing the PLL for RTIO clock");

View File

@ -144,7 +144,7 @@ pub mod remote_dma {
pub async fn playback_done(&mut self, source: u8, error: u8, channel: u32, timestamp: u64) { pub async fn playback_done(&mut self, source: u8, error: u8, channel: u32, timestamp: u64) {
let mut traces_locked = self.traces.async_lock().await; let mut traces_locked = self.traces.async_lock().await;
let trace = traces_locked.get_mut(&source).unwrap(); let mut trace = traces_locked.get_mut(&source).unwrap();
trace.state = RemoteState::PlaybackEnded { trace.state = RemoteState::PlaybackEnded {
error: error, error: error,
channel: channel, channel: channel,

View File

@ -15,8 +15,8 @@ pub mod drtio {
use embedded_hal::blocking::delay::DelayMs; use embedded_hal::blocking::delay::DelayMs;
#[cfg(has_drtio_eem)] #[cfg(has_drtio_eem)]
use embedded_hal::blocking::delay::DelayUs; use embedded_hal::blocking::delay::DelayUs;
use ksupport::{kernel::Message as KernelMessage, resolve_channel_name, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, use ksupport::{resolve_channel_name, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR,
ASYNC_ERROR_SEQUENCE_ERROR, SEEN_ASYNC_ERRORS}; SEEN_ASYNC_ERRORS};
use libasync::{delay, task}; use libasync::{delay, task};
#[cfg(has_drtio_eem)] #[cfg(has_drtio_eem)]
use libboard_artiq::drtio_eem; use libboard_artiq::drtio_eem;
@ -411,32 +411,29 @@ pub mod drtio {
} }
Ok(Packet::DestinationOkReply) => (), Ok(Packet::DestinationOkReply) => (),
Ok(Packet::DestinationSequenceErrorReply { channel }) => { Ok(Packet::DestinationSequenceErrorReply { channel }) => {
let global_ch = ((destination as u32) << 16) | channel as u32;
error!( error!(
"[DEST#{}] RTIO sequence error involving channel 0x{:04x}:{}", "[DEST#{}] RTIO sequence error involving channel 0x{:04x}:{}",
destination, destination,
channel, channel,
resolve_channel_name(global_ch) resolve_channel_name(channel as u32)
); );
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_SEQUENCE_ERROR }; unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_SEQUENCE_ERROR };
} }
Ok(Packet::DestinationCollisionReply { channel }) => { Ok(Packet::DestinationCollisionReply { channel }) => {
let global_ch = ((destination as u32) << 16) | channel as u32;
error!( error!(
"[DEST#{}] RTIO collision involving channel 0x{:04x}:{}", "[DEST#{}] RTIO collision involving channel 0x{:04x}:{}",
destination, destination,
channel, channel,
resolve_channel_name(global_ch) resolve_channel_name(channel as u32)
); );
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_COLLISION }; unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_COLLISION };
} }
Ok(Packet::DestinationBusyReply { channel }) => { Ok(Packet::DestinationBusyReply { channel }) => {
let global_ch = ((destination as u32) << 16) | channel as u32;
error!( error!(
"[DEST#{}] RTIO busy error involving channel 0x{:04x}:{}", "[DEST#{}] RTIO busy error involving channel 0x{:04x}:{}",
destination, destination,
channel, channel,
resolve_channel_name(global_ch) resolve_channel_name(channel as u32)
); );
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_BUSY }; unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_BUSY };
} }
@ -547,7 +544,8 @@ pub mod drtio {
} }
} }
pub async fn reset(aux_mutex: &Rc<Mutex<bool>>, routing_table: &RoutingTable, mut timer: GlobalTimer) { #[allow(dead_code)]
pub fn reset(aux_mutex: Rc<Mutex<bool>>, routing_table: &RoutingTable, mut timer: GlobalTimer) {
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
unsafe { unsafe {
(csr::DRTIO[linkno].reset_write)(1); (csr::DRTIO[linkno].reset_write)(1);
@ -562,8 +560,14 @@ pub mod drtio {
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
let linkno = linkno as u8; let linkno = linkno as u8;
if link_rx_up(linkno, &mut timer).await { if task::block_on(link_rx_up(linkno, &mut timer)) {
let reply = aux_transact(&aux_mutex, linkno, routing_table, &Packet::ResetRequest, timer).await; let reply = task::block_on(aux_transact(
&aux_mutex,
linkno,
routing_table,
&Packet::ResetRequest,
timer,
));
match reply { match reply {
Ok(Packet::ResetAck) => (), Ok(Packet::ResetAck) => (),
Ok(_) => error!("[LINK#{}] reset failed, received unexpected aux packet", linkno), Ok(_) => error!("[LINK#{}] reset failed, received unexpected aux packet", linkno),
@ -922,91 +926,6 @@ pub mod drtio {
) )
.await .await
} }
pub async fn i2c_send_basic(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer,
request: &KernelMessage,
busno: u32,
) -> Result<bool, Error> {
let destination = (busno >> 16) as u8;
let busno = busno as u8;
let packet = match request {
KernelMessage::I2cStartRequest(_) => Packet::I2cStartRequest { destination, busno },
KernelMessage::I2cRestartRequest(_) => Packet::I2cRestartRequest { destination, busno },
KernelMessage::I2cStopRequest(_) => Packet::I2cStopRequest { destination, busno },
KernelMessage::I2cSwitchSelectRequest { address, mask, .. } => Packet::I2cSwitchSelectRequest {
destination,
busno,
address: *address,
mask: *mask,
},
_ => unreachable!(),
};
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(aux_mutex, linkno, routing_table, &packet, timer).await?;
match reply {
Packet::I2cBasicReply { succeeded } => Ok(succeeded),
_ => Err(Error::UnexpectedReply),
}
}
pub async fn i2c_send_write(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer,
busno: u32,
data: u8,
) -> Result<(bool, bool), Error> {
let destination = (busno >> 16) as u8;
let busno = busno as u8;
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::I2cWriteRequest {
destination,
busno,
data,
},
timer,
)
.await?;
match reply {
Packet::I2cWriteReply { succeeded, ack } => Ok((succeeded, ack)),
_ => Err(Error::UnexpectedReply),
}
}
pub async fn i2c_send_read(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer,
busno: u32,
ack: bool,
) -> Result<(bool, u8), Error> {
let destination = (busno >> 16) as u8;
let busno = busno as u8;
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::I2cReadRequest {
destination,
busno,
ack,
},
timer,
)
.await?;
match reply {
Packet::I2cReadReply { succeeded, data } => Ok((succeeded, data)),
_ => Err(Error::UnexpectedReply),
}
}
} }
#[cfg(not(has_drtio))] #[cfg(not(has_drtio))]
@ -1060,3 +979,11 @@ pub fn startup(
csr::rtio_core::reset_phy_write(1); csr::rtio_core::reset_phy_write(1);
} }
} }
#[allow(dead_code)]
pub fn reset(aux_mutex: Rc<Mutex<bool>>, routing_table: &RoutingTable, timer: GlobalTimer) {
unsafe {
csr::rtio_core::reset_write(1);
}
drtio::reset(aux_mutex, routing_table, timer)
}

View File

@ -40,7 +40,6 @@ impl From<DrtioError> for Error {
} }
} }
#[allow(dead_code)]
pub struct SubkernelFinished { pub struct SubkernelFinished {
pub id: u32, pub id: u32,
pub status: FinishStatus, pub status: FinishStatus,

View File

@ -9,6 +9,7 @@ format_code_in_doc_comments = false
comment_width = 100 comment_width = 100
normalize_comments = false normalize_comments = false
normalize_doc_attributes = false normalize_doc_attributes = false
license_template_path = ""
format_strings = true format_strings = true
format_macro_matchers = true format_macro_matchers = true
format_macro_bodies = true format_macro_bodies = true
@ -18,7 +19,7 @@ fn_single_line = false
where_single_line = true where_single_line = true
imports_indent = "Visual" imports_indent = "Visual"
imports_layout = "Mixed" imports_layout = "Mixed"
imports_granularity = "Crate" merge_imports = true
group_imports = "StdExternalCrate" group_imports = "StdExternalCrate"
reorder_imports = true reorder_imports = true
reorder_modules = true reorder_modules = true
@ -36,7 +37,7 @@ enum_discrim_align_threshold = 0
match_arm_blocks = true match_arm_blocks = true
match_arm_leading_pipes = "Never" match_arm_leading_pipes = "Never"
force_multiline_blocks = false force_multiline_blocks = false
fn_params_layout = "Tall" fn_args_layout = "Tall"
brace_style = "SameLineWhere" brace_style = "SameLineWhere"
control_brace_style = "AlwaysSameLine" control_brace_style = "AlwaysSameLine"
trailing_semicolon = true trailing_semicolon = true
@ -53,13 +54,15 @@ use_field_init_shorthand = false
force_explicit_abi = true force_explicit_abi = true
condense_wildcard_suffixes = false condense_wildcard_suffixes = false
color = "Auto" color = "Auto"
required_version = "1.7.0" required_version = "1.4.37"
unstable_features = false unstable_features = false
disable_all_formatting = false disable_all_formatting = false
skip_children = false skip_children = false
hide_parse_errors = false hide_parse_errors = false
error_on_line_overflow = false error_on_line_overflow = false
error_on_unformatted = false error_on_unformatted = false
report_todo = "Never"
report_fixme = "Never"
ignore = [] ignore = []
emit_mode = "Files" emit_mode = "Files"
make_backup = false make_backup = false

View File

@ -1,8 +1,6 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![allow(internal_features)]
#![feature(alloc_error_handler, never_type, panic_info_message)] #![feature(alloc_error_handler, never_type, panic_info_message)]
#![feature(lang_items)]
#[macro_use] #[macro_use]
extern crate log; extern crate log;
@ -28,8 +26,6 @@ extern crate alloc;
use analyzer::Analyzer; use analyzer::Analyzer;
use dma::Manager as DmaManager; use dma::Manager as DmaManager;
use embedded_hal::blocking::delay::DelayUs; use embedded_hal::blocking::delay::DelayUs;
#[cfg(has_drtio_eem)]
use libboard_artiq::drtio_eem;
#[cfg(has_grabber)] #[cfg(has_grabber)]
use libboard_artiq::grabber; use libboard_artiq::grabber;
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
@ -44,10 +40,7 @@ use libboard_artiq::{drtio_routing, drtioaux,
pl::csr}; pl::csr};
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
use libboard_zynq::error_led::ErrorLED; use libboard_zynq::error_led::ErrorLED;
use libboard_zynq::{i2c::{Error as I2cError, I2c}, use libboard_zynq::{i2c::I2c, print, println, slcr, time::Milliseconds, timer::GlobalTimer};
print, println, slcr,
time::Milliseconds,
timer::GlobalTimer};
use libconfig::Config; use libconfig::Config;
use libcortex_a9::{l2c::enable_l2_cache, regs::MPIDR}; use libcortex_a9::{l2c::enable_l2_cache, regs::MPIDR};
use libregister::RegisterR; use libregister::RegisterR;
@ -438,18 +431,11 @@ fn process_aux_packet(
timer timer
); );
match i2c.write(data) { match i2c.write(data) {
Ok(()) => drtioaux::send( Ok(ack) => drtioaux::send(
0, 0,
&drtioaux::Packet::I2cWriteReply { &drtioaux::Packet::I2cWriteReply {
succeeded: true, succeeded: true,
ack: true, ack: ack,
},
),
Err(I2cError::Nack) => drtioaux::send(
0,
&drtioaux::Packet::I2cWriteReply {
succeeded: true,
ack: false,
}, },
), ),
Err(_) => drtioaux::send( Err(_) => drtioaux::send(
@ -1111,7 +1097,12 @@ fn process_aux_packet(
if let Ok(level_filter) = mgmt::byte_to_level_filter(log_level) { if let Ok(level_filter) = mgmt::byte_to_level_filter(log_level) {
info!("Changing UART log level to {}", level_filter); info!("Changing UART log level to {}", level_filter);
logger::BufferLogger::get_logger().set_uart_log_level(level_filter); unsafe {
logger::BufferLogger::get_logger()
.as_ref()
.unwrap()
.set_uart_log_level(level_filter);
}
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true })
} else { } else {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
@ -1349,12 +1340,6 @@ fn process_aux_packet(
unsafe { unsafe {
csr::gt_drtio::txenable_write(0); csr::gt_drtio::txenable_write(0);
} }
#[cfg(has_drtio_eem)]
unsafe {
csr::eem_transceiver::txenable_write(0);
}
core_manager.write_image(); core_manager.write_image();
info!("reboot imminent"); info!("reboot imminent");
slcr::reboot(); slcr::reboot();
@ -1538,20 +1523,20 @@ pub extern "C" fn main_core0() -> i32 {
ram::init_alloc_core0(); ram::init_alloc_core0();
ksupport::kernel::i2c::init(); ksupport::i2c::init();
let i2c = ksupport::kernel::i2c::get_bus(); let mut i2c = unsafe { (ksupport::i2c::I2C_BUS).as_mut().unwrap() };
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
let (mut io_expander0, mut io_expander1); let (mut io_expander0, mut io_expander1);
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
{ {
io_expander0 = io_expander::IoExpander::new(i2c, 0).unwrap(); io_expander0 = io_expander::IoExpander::new(&mut i2c, 0).unwrap();
io_expander1 = io_expander::IoExpander::new(i2c, 1).unwrap(); io_expander1 = io_expander::IoExpander::new(&mut i2c, 1).unwrap();
io_expander0 io_expander0
.init(i2c) .init(&mut i2c)
.expect("I2C I/O expander #0 initialization failed"); .expect("I2C I/O expander #0 initialization failed");
io_expander1 io_expander1
.init(i2c) .init(&mut i2c)
.expect("I2C I/O expander #1 initialization failed"); .expect("I2C I/O expander #1 initialization failed");
// Drive CLK_SEL to true // Drive CLK_SEL to true
@ -1563,12 +1548,12 @@ pub extern "C" fn main_core0() -> i32 {
io_expander1.set(0, 1, false); io_expander1.set(0, 1, false);
io_expander0.set(1, 1, false); io_expander0.set(1, 1, false);
io_expander1.set(1, 1, false); io_expander1.set(1, 1, false);
io_expander0.service(i2c).unwrap(); io_expander0.service(&mut i2c).unwrap();
io_expander1.service(i2c).unwrap(); io_expander1.service(&mut i2c).unwrap();
} }
#[cfg(has_si5324)] #[cfg(has_si5324)]
si5324::setup(i2c, &SI5324_SETTINGS, si5324::Input::Ckin1, &mut timer).expect("cannot initialize Si5324"); si5324::setup(&mut i2c, &SI5324_SETTINGS, si5324::Input::Ckin1, &mut timer).expect("cannot initialize Si5324");
#[cfg(has_si549)] #[cfg(has_si549)]
si549::main_setup(&mut timer, &SI549_SETTINGS).expect("cannot initialize main Si549"); si549::main_setup(&mut timer, &SI549_SETTINGS).expect("cannot initialize main Si549");
@ -1588,12 +1573,6 @@ pub extern "C" fn main_core0() -> i32 {
unsafe { unsafe {
csr::gt_drtio::txenable_write(0xffffffffu32 as _); csr::gt_drtio::txenable_write(0xffffffffu32 as _);
} }
#[cfg(has_drtio_eem)]
unsafe {
csr::eem_transceiver::txenable_write(0xffffffffu32 as _);
}
#[cfg(has_si549)] #[cfg(has_si549)]
si549::helper_setup(&mut timer, &SI549_SETTINGS).expect("cannot initialize helper Si549"); si549::helper_setup(&mut timer, &SI549_SETTINGS).expect("cannot initialize helper Si549");
@ -1619,12 +1598,6 @@ pub extern "C" fn main_core0() -> i32 {
toggle_sed_spread(0); toggle_sed_spread(0);
} }
#[cfg(has_drtio_eem)]
{
drtio_eem::init(&mut timer, &cfg);
unsafe { csr::eem_transceiver::rx_ready_write(1) }
}
#[cfg(has_drtio_routing)] #[cfg(has_drtio_routing)]
let mut repeaters = [repeater::Repeater::default(); csr::DRTIOREP.len()]; let mut repeaters = [repeater::Repeater::default(); csr::DRTIOREP.len()];
#[cfg(not(has_drtio_routing))] #[cfg(not(has_drtio_routing))]
@ -1651,8 +1624,12 @@ pub extern "C" fn main_core0() -> i32 {
} }
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
{ {
io_expander0.service(i2c).expect("I2C I/O expander #0 service failed"); io_expander0
io_expander1.service(i2c).expect("I2C I/O expander #1 service failed"); .service(&mut i2c)
.expect("I2C I/O expander #0 service failed");
io_expander1
.service(&mut i2c)
.expect("I2C I/O expander #1 service failed");
} }
hardware_tick(&mut hardware_tick_ts, &mut timer); hardware_tick(&mut hardware_tick_ts, &mut timer);
@ -1661,7 +1638,7 @@ pub extern "C" fn main_core0() -> i32 {
info!("uplink is up, switching to recovered clock"); info!("uplink is up, switching to recovered clock");
#[cfg(has_siphaser)] #[cfg(has_siphaser)]
{ {
si5324::siphaser::select_recovered_clock(i2c, true, &mut timer).expect("failed to switch clocks"); si5324::siphaser::select_recovered_clock(&mut i2c, true, &mut timer).expect("failed to switch clocks");
si5324::siphaser::calibrate_skew(&mut timer).expect("failed to calibrate skew"); si5324::siphaser::calibrate_skew(&mut timer).expect("failed to calibrate skew");
} }
@ -1688,7 +1665,7 @@ pub extern "C" fn main_core0() -> i32 {
&mut rank, &mut rank,
&mut destination, &mut destination,
&mut timer, &mut timer,
i2c, &mut i2c,
&mut dma_manager, &mut dma_manager,
&mut analyzer, &mut analyzer,
&mut kernel_manager, &mut kernel_manager,
@ -1701,8 +1678,12 @@ pub extern "C" fn main_core0() -> i32 {
} }
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
{ {
io_expander0.service(i2c).expect("I2C I/O expander #0 service failed"); io_expander0
io_expander1.service(i2c).expect("I2C I/O expander #1 service failed"); .service(&mut i2c)
.expect("I2C I/O expander #0 service failed");
io_expander1
.service(&mut i2c)
.expect("I2C I/O expander #1 service failed");
} }
hardware_tick(&mut hardware_tick_ts, &mut timer); hardware_tick(&mut hardware_tick_ts, &mut timer);
if drtiosat_tsc_loaded() { if drtiosat_tsc_loaded() {
@ -1762,7 +1743,7 @@ pub extern "C" fn main_core0() -> i32 {
drtiosat_tsc_loaded(); drtiosat_tsc_loaded();
info!("uplink is down, switching to local oscillator clock"); info!("uplink is down, switching to local oscillator clock");
#[cfg(has_siphaser)] #[cfg(has_siphaser)]
si5324::siphaser::select_recovered_clock(i2c, false, &mut timer).expect("failed to switch clocks"); si5324::siphaser::select_recovered_clock(&mut i2c, false, &mut timer).expect("failed to switch clocks");
#[cfg(has_wrpll)] #[cfg(has_wrpll)]
si549::wrpll::select_recovered_clock(false, &mut timer); si549::wrpll::select_recovered_clock(false, &mut timer);
} }
@ -1829,7 +1810,3 @@ pub fn panic_fmt(info: &core::panic::PanicInfo) -> ! {
loop {} loop {}
} }
#[lang = "eh_personality"]
#[no_mangle]
pub extern "C" fn rust_eh_personality() {}

View File

@ -1,9 +1,8 @@
use alloc::vec::Vec; use alloc::vec::Vec;
use byteorder::{ByteOrder, NativeEndian}; use byteorder::{ByteOrder, NativeEndian};
use core_io::Write;
use crc::crc32; use crc::crc32;
use io::ProtoRead; use io::{ProtoRead, ProtoWrite};
use libboard_artiq::{drtioaux_proto::SAT_PAYLOAD_MAX_SIZE, use libboard_artiq::{drtioaux_proto::SAT_PAYLOAD_MAX_SIZE,
logger::{BufferLogger, LogBufferRef}}; logger::{BufferLogger, LogBufferRef}};
use libconfig::Config; use libconfig::Config;
@ -29,7 +28,7 @@ pub fn byte_to_level_filter(level_byte: u8) -> Result<LevelFilter> {
} }
fn get_logger_buffer() -> LogBufferRef<'static> { fn get_logger_buffer() -> LogBufferRef<'static> {
let logger = BufferLogger::get_logger(); let logger = unsafe { BufferLogger::get_logger().as_mut().unwrap() };
loop { loop {
if let Some(buffer_ref) = logger.buffer() { if let Some(buffer_ref) = logger.buffer() {
return buffer_ref; return buffer_ref;
@ -98,11 +97,9 @@ impl<'a> Manager<'_> {
pub fn write_config(&mut self) -> Result<()> { pub fn write_config(&mut self) -> Result<()> {
let mut payload = &self.config_payload[..]; let mut payload = &self.config_payload[..];
let key = payload let key = payload.read_string().map_err(|_err| error!("error on reading key"))?;
.read_string::<NativeEndian>()
.map_err(|_err| error!("error on reading key"))?;
debug!("write key: {}", key); debug!("write key: {}", key);
let value = payload.read_bytes::<NativeEndian>().unwrap(); let value = payload.read_bytes().unwrap();
self.cfg self.cfg
.write(&key, value) .write(&key, value)

View File

@ -4,12 +4,11 @@ use alloc::{collections::BTreeMap,
vec::Vec}; vec::Vec};
use core::{slice, str}; use core::{slice, str};
use byteorder::NativeEndian; use core_io::{Error as IoError, Write};
use core_io::Error as IoError;
use cslice::AsCSlice; use cslice::AsCSlice;
use dma::{Error as DmaError, Manager as DmaManager}; use dma::{Error as DmaError, Manager as DmaManager};
use io::{Cursor, ProtoWrite}; use io::{Cursor, ProtoWrite};
use ksupport::{eh_artiq, kernel, kernel::rtio, rpc}; use ksupport::{eh_artiq, kernel, rpc, rtio};
use libboard_artiq::{drtio_routing::RoutingTable, use libboard_artiq::{drtio_routing::RoutingTable,
drtioaux, drtioaux,
drtioaux_proto::{PayloadStatus, MASTER_PAYLOAD_MAX_SIZE}, drtioaux_proto::{PayloadStatus, MASTER_PAYLOAD_MAX_SIZE},
@ -53,7 +52,6 @@ enum KernelState {
}, },
} }
#[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
Load(String), Load(String),
@ -846,8 +844,6 @@ impl<'a> Manager<'_> {
destination == (self_destination as i32), destination == (self_destination as i32),
)); ));
} }
/* core.reset() on satellites only affects the satellite, ignore the request */
kernel::Message::RtioInitRequest => {}
_ => { _ => {
unexpected!("unexpected message from core1 while kernel was running: {:?}", reply); unexpected!("unexpected message from core1 while kernel was running: {:?}", reply);
} }
@ -984,24 +980,27 @@ impl<'a> Manager<'_> {
} }
} }
fn write_exception<W: ProtoWrite>( fn write_exception<W>(
writer: &mut W, writer: &mut W,
exceptions: &[Option<eh_artiq::Exception>], exceptions: &[Option<eh_artiq::Exception>],
stack_pointers: &[eh_artiq::StackPointerBacktrace], stack_pointers: &[eh_artiq::StackPointerBacktrace],
backtrace: &[(usize, usize)], backtrace: &[(usize, usize)],
async_errors: u8, async_errors: u8,
) -> Result<(), Error> { ) -> Result<(), Error>
where
W: Write + ?Sized,
{
/* header */ /* header */
writer.write_bytes::<NativeEndian>(&[0x5a, 0x5a, 0x5a, 0x5a, /*Reply::KernelException*/ 9])?; writer.write_bytes(&[0x5a, 0x5a, 0x5a, 0x5a, /*Reply::KernelException*/ 9])?;
writer.write_u32::<NativeEndian>(exceptions.len() as u32)?; writer.write_u32(exceptions.len() as u32)?;
for exception in exceptions.iter() { for exception in exceptions.iter() {
let exception = exception.as_ref().unwrap(); let exception = exception.as_ref().unwrap();
writer.write_u32::<NativeEndian>(exception.id)?; writer.write_u32(exception.id)?;
if exception.message.len() == usize::MAX { if exception.message.len() == usize::MAX {
// exception with host string // exception with host string
writer.write_u32::<NativeEndian>(u32::MAX)?; writer.write_u32(u32::MAX)?;
writer.write_u32::<NativeEndian>(exception.message.as_ptr() as u32)?; writer.write_u32(exception.message.as_ptr() as u32)?;
} else { } else {
let msg = let msg =
str::from_utf8(unsafe { slice::from_raw_parts(exception.message.as_ptr(), exception.message.len()) }) str::from_utf8(unsafe { slice::from_raw_parts(exception.message.as_ptr(), exception.message.len()) })
@ -1014,26 +1013,26 @@ fn write_exception<W: ProtoWrite>(
ksupport::resolve_channel_name(exception.param[0] as u32) ksupport::resolve_channel_name(exception.param[0] as u32)
), ),
); );
writer.write_string::<NativeEndian>(&msg)?; writer.write_string(&msg)?;
} }
writer.write_u64::<NativeEndian>(exception.param[0] as u64)?; writer.write_u64(exception.param[0] as u64)?;
writer.write_u64::<NativeEndian>(exception.param[1] as u64)?; writer.write_u64(exception.param[1] as u64)?;
writer.write_u64::<NativeEndian>(exception.param[2] as u64)?; writer.write_u64(exception.param[2] as u64)?;
writer.write_bytes::<NativeEndian>(exception.file.as_ref())?; writer.write_bytes(exception.file.as_ref())?;
writer.write_u32::<NativeEndian>(exception.line)?; writer.write_u32(exception.line)?;
writer.write_u32::<NativeEndian>(exception.column)?; writer.write_u32(exception.column)?;
writer.write_bytes::<NativeEndian>(exception.function.as_ref())?; writer.write_bytes(exception.function.as_ref())?;
} }
for sp in stack_pointers.iter() { for sp in stack_pointers.iter() {
writer.write_u32::<NativeEndian>(sp.stack_pointer as u32)?; writer.write_u32(sp.stack_pointer as u32)?;
writer.write_u32::<NativeEndian>(sp.initial_backtrace_size as u32)?; writer.write_u32(sp.initial_backtrace_size as u32)?;
writer.write_u32::<NativeEndian>(sp.current_backtrace_size as u32)?; writer.write_u32(sp.current_backtrace_size as u32)?;
} }
writer.write_u32::<NativeEndian>(backtrace.len() as u32)?; writer.write_u32(backtrace.len() as u32)?;
for &(addr, sp) in backtrace { for &(addr, sp) in backtrace {
writer.write_u32::<NativeEndian>(addr as u32)?; writer.write_u32(addr as u32)?;
writer.write_u32::<NativeEndian>(sp as u32)?; writer.write_u32(sp as u32)?;
} }
writer.write_u8(async_errors as u8)?; writer.write_u8(async_errors as u8)?;
Ok(()) Ok(())