1
0
Fork 0

Compare commits

...

8 Commits

Author SHA1 Message Date
Simon Renblad 4d3895094d use C ABI for attribute writeback typeinfo 2024-10-25 14:38:14 +08:00
Simon Renblad 3b52d3e765 cargo lockfile 2024-10-24 17:58:07 +08:00
Simon Renblad 5365b02159 fix errors 2024-10-24 17:49:54 +08:00
Simon Renblad ec4cea7cd2 added eh_rust 2024-10-24 13:17:47 +08:00
Simon Renblad ee0c59d23a removing core_io dependency 2024-10-24 13:17:44 +08:00
Sébastien Bourdeauducq 9ce3aadb15 cargo fmt 2024-10-18 17:43:39 +08:00
mwojcik 3390abd5a1 subkernels: pass now_mu when calling subkernels 2024-10-18 13:51:48 +08:00
newell a410c40b50 ADD SPI to EBAZ4205 for AD9834 (#331)
Co-authored-by: newell <newell.jensen@gmail.com>
Co-committed-by: newell <newell.jensen@gmail.com>
2024-10-17 15:06:11 +08:00
39 changed files with 756 additions and 313 deletions

View File

@ -0,0 +1,70 @@
core_addr = "192.168.1.57"
device_db = {
"core": {
"type": "local",
"module": "artiq.coredevice.core",
"class": "Core",
"arguments": {
"host": core_addr,
"ref_period": 1e-9,
"target": "cortexa9",
},
},
"core_log": {
"type": "controller",
"host": "::1",
"port": 1068,
"command": "aqctl_corelog -p {port} --bind {bind} " + core_addr,
},
"core_moninj": {
"type": "controller",
"host": "::1",
"port_proxy": 1383,
"port": 1384,
"command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} "
+ core_addr,
},
"core_analyzer": {
"type": "controller",
"host": "::1",
"port_proxy": 1385,
"port": 1386,
"command": "aqctl_coreanalyzer_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} "
+ core_addr,
},
"core_cache": {
"type": "local",
"module": "artiq.coredevice.cache",
"class": "CoreCache",
},
"core_dma": {"type": "local", "module": "artiq.coredevice.dma", "class": "CoreDMA"},
"led0": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 0},
},
"led1": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 1},
},
}
device_db.update(
spi0={
"type": "local",
"module": "artiq.coredevice.spi2",
"class": "SPIMaster",
"arguments": {"channel": 2},
},
dds0={
"type": "local",
"module": "artiq.coredevice.ad9834",
"class": "AD9834",
"arguments": {"spi_device": "spi0"},
},
)

View File

@ -11,11 +11,11 @@
"src-pythonparser": "src-pythonparser" "src-pythonparser": "src-pythonparser"
}, },
"locked": { "locked": {
"lastModified": 1727765117, "lastModified": 1729249162,
"narHash": "sha256-P4PgnsXNL4kXjSAhRpXzkq17j8bEaJAqNLSH2Vt+DY0=", "narHash": "sha256-o3UROeulca0x5LQ6PlVILKEnZfhLElUA6qnNJ4Uwjmk=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "333623e24bdec00783bc89c1e8b6b49a74bc9e1c", "rev": "02235b2d80780de2ce0bb3cea09fe05be191fa5b",
"revCount": 9020, "revCount": 9039,
"type": "git", "type": "git",
"url": "https://github.com/m-labs/artiq.git" "url": "https://github.com/m-labs/artiq.git"
}, },
@ -102,11 +102,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1727348695, "lastModified": 1728492678,
"narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=", "narHash": "sha256-9UTxR8eukdg+XZeHgxW5hQA9fIKHsKCdOIUycTryeVw=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784", "rev": "5633bcff0c6162b9e4b5f1264264611e950c8ec7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -153,11 +153,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1724921939, "lastModified": 1728371104,
"narHash": "sha256-/S5iip1LHLiCP2VY7PwClDteP9ZMRZvzzKR1LZuV3fs=", "narHash": "sha256-PPnAyDedUQ7Og/Cby9x5OT9wMkNGTP8GS53V6N/dk4w=",
"owner": "m-labs", "owner": "m-labs",
"repo": "sipyco", "repo": "sipyco",
"rev": "32ddd78ff3641b75054793ea0d5681c951766754", "rev": "094a6cd63ffa980ef63698920170e50dc9ba77fd",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -185,11 +185,11 @@
"src-misoc": { "src-misoc": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1715647536, "lastModified": 1728978817,
"narHash": "sha256-q+USDcaKHABwW56Jzq8u94iGPWlyLXMyVt0j/Gyg+IE=", "narHash": "sha256-b4633jrhh4i+KunZq4kNlyhdm9BCsEJwKs+6KINKV2o=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "fea9de558c730bc394a5936094ae95bb9d6fa726", "rev": "386b544776b66cea148da67d06a4b3a4151179f9",
"revCount": 2455, "revCount": 2459,
"submodules": true, "submodules": true,
"type": "git", "type": "git",
"url": "https://github.com/m-labs/misoc.git" "url": "https://github.com/m-labs/misoc.git"

View File

@ -11,7 +11,6 @@
pkgs = import artiq.inputs.nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) ]; }; pkgs = import artiq.inputs.nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) ]; };
zynqpkgs = zynq-rs.packages.x86_64-linux; zynqpkgs = zynq-rs.packages.x86_64-linux;
artiqpkgs = artiq.packages.x86_64-linux; artiqpkgs = artiq.packages.x86_64-linux;
llvmPackages_11 = zynq-rs.llvmPackages_11;
rust = zynq-rs.rust; rust = zynq-rs.rust;
rustPlatform = zynq-rs.rustPlatform; rustPlatform = zynq-rs.rustPlatform;
@ -126,7 +125,7 @@
lockFile = src/Cargo.lock; lockFile = src/Cargo.lock;
outputHashes = { outputHashes = {
"tar-no-std-0.1.8" = "sha256-xm17108v4smXOqxdLvHl9CxTCJslmeogjm4Y87IXFuM="; "tar-no-std-0.1.8" = "sha256-xm17108v4smXOqxdLvHl9CxTCJslmeogjm4Y87IXFuM=";
"nalgebra-0.32.6" = "sha256-L/YudkVOtfGYoNQKBD7LMk/sMYgRDzPDdpGL5rO7G2I="; "fatfs-0.4.0" = "sha256-P7IgvhwTPXtNhcyv8cFqwO2UdaEcCGJY7UBG6+yBFSg=";
}; };
}; };
@ -134,12 +133,12 @@
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 ]))
zynqpkgs.cargo-xbuild zynqpkgs.cargo-xbuild
llvmPackages_11.llvm pkgs.llvmPackages_18.llvm
llvmPackages_11.clang-unwrapped pkgs.llvmPackages_18.clang-unwrapped
]; ];
buildPhase = '' buildPhase = ''
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="${llvmPackages_11.clang-unwrapped.lib}/lib/clang/11.1.0/include" export CLANG_EXTRA_INCLUDE_DIR="${pkgs.llvmPackages_18.clang-unwrapped.lib}/lib/clang/18/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}
@ -373,8 +372,8 @@
name = "artiq-zynq-dev-shell"; name = "artiq-zynq-dev-shell";
buildInputs = with pkgs; [ buildInputs = with pkgs; [
rust rust
llvmPackages_11.llvm llvmPackages_18.llvm
llvmPackages_11.clang-unwrapped llvmPackages_18.clang-unwrapped
gnumake gnumake
cacert cacert
zynqpkgs.cargo-xbuild zynqpkgs.cargo-xbuild
@ -388,7 +387,7 @@
pre-commit pre-commit
]; ];
XARGO_RUST_SRC = "${rust}/lib/rustlib/src/rust/library"; XARGO_RUST_SRC = "${rust}/lib/rustlib/src/rust/library";
CLANG_EXTRA_INCLUDE_DIR = "${llvmPackages_11.clang-unwrapped.lib}/lib/clang/11.1.0/include"; CLANG_EXTRA_INCLUDE_DIR = "${pkgs.llvmPackages_18.clang-unwrapped.lib}/lib/clang/18/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}";

62
src/Cargo.lock generated
View File

@ -46,6 +46,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]] [[package]]
name = "build_const" name = "build_const"
version = "0.2.2" version = "0.2.2"
@ -82,18 +88,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "compiler_builtins" name = "compiler_builtins"
version = "0.1.39" version = "0.1.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3748f82c7d366a0b4950257d19db685d4958d2fa27c6d164a3f069fec42b748b" checksum = "f11973008a8cf741fe6d22f339eba21fd0ca81e2760a769ba8243ed6c21edd7e"
[[package]]
name = "core_io"
version = "0.1.20210325"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97f8932064288cc79feb4d343a399d353a6f6f001e586ece47fe518a9e8507df"
dependencies = [
"rustc_version",
]
[[package]] [[package]]
name = "crc" name = "crc"
@ -141,13 +138,10 @@ dependencies = [
[[package]] [[package]]
name = "fatfs" name = "fatfs"
version = "0.3.5" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/rafalh/rust-fatfs?rev=85f06e0#85f06e08edbd3368e1b0562f2fc1b6d178bf7b8a"
checksum = "e18f80a87439240dac45d927fd8f8081b6f1e34c03e97271189fa8a8c2e96c8f"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.6.0",
"byteorder",
"core_io",
"log", "log",
] ]
@ -229,7 +223,6 @@ name = "io"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"core_io",
"libsupport_zynq", "libsupport_zynq",
] ]
@ -239,7 +232,6 @@ version = "0.1.0"
dependencies = [ dependencies = [
"build_zynq", "build_zynq",
"byteorder", "byteorder",
"core_io",
"cslice", "cslice",
"dwarf", "dwarf",
"dyld", "dyld",
@ -278,7 +270,6 @@ name = "libboard_artiq"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"build_zynq", "build_zynq",
"core_io",
"crc", "crc",
"embedded-hal", "embedded-hal",
"io", "io",
@ -322,7 +313,6 @@ dependencies = [
name = "libconfig" name = "libconfig"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"core_io",
"fatfs", "fatfs",
"libboard_zynq", "libboard_zynq",
"log", "log",
@ -394,8 +384,9 @@ checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577"
[[package]] [[package]]
name = "nalgebra" name = "nalgebra"
version = "0.32.6" version = "0.33.1"
source = "git+https://git.m-labs.hk/M-Labs/nalgebra.git?rev=dd00f9b#dd00f9b46046e0b931d1b470166db02fd29591be" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf139e93ad757869338ad85239cb1d6c067b23b94e5846e637ca6328ee4be60"
dependencies = [ dependencies = [
"approx", "approx",
"num-complex", "num-complex",
@ -519,7 +510,6 @@ dependencies = [
"async-recursion", "async-recursion",
"build_zynq", "build_zynq",
"byteorder", "byteorder",
"core_io",
"cslice", "cslice",
"dwarf", "dwarf",
"dyld", "dyld",
@ -545,21 +535,11 @@ dependencies = [
"void", "void",
] ]
[[package]]
name = "rustc_version"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "satman" name = "satman"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"build_zynq", "build_zynq",
"core_io",
"cslice", "cslice",
"embedded-hal", "embedded-hal",
"io", "io",
@ -576,17 +556,11 @@ dependencies = [
"unwind", "unwind",
] ]
[[package]]
name = "semver"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
[[package]] [[package]]
name = "simba" name = "simba"
version = "0.8.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50582927ed6f77e4ac020c057f37a268fc6aebc29225050365aacbb9deeeddc4" checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa"
dependencies = [ dependencies = [
"approx", "approx",
"num-complex", "num-complex",
@ -600,7 +574,7 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e4a069bef843d170df47e7c0a8bf8d037f217d9f5b325865acc3e466ffe40d3" checksum = "3e4a069bef843d170df47e7c0a8bf8d037f217d9f5b325865acc3e466ffe40d3"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"byteorder", "byteorder",
"managed", "managed",
] ]
@ -622,7 +596,7 @@ version = "0.1.8"
source = "git+https://git.m-labs.hk/M-Labs/tar-no-std?rev=2ab6dc5#2ab6dc58e5249c59c4eb03eaf3a119bcdd678d32" source = "git+https://git.m-labs.hk/M-Labs/tar-no-std?rev=2ab6dc5#2ab6dc58e5249c59c4eb03eaf3a119bcdd678d32"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"bitflags", "bitflags 1.3.2",
"log", "log",
] ]

View File

@ -1,23 +1,19 @@
#!/usr/bin/env python #!/usr/bin/env python
import argparse import argparse
from operator import itemgetter
import analyzer
import dma
from artiq.gateware import rtio
from artiq.gateware.rtio.phy import dds, spi2, ttl_simple
from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path
from config import write_csr_file, write_mem_file, write_rustc_cfg_file
from migen import * from migen import *
from migen.build.generic_platform import IOStandard, Misc, Pins, Subsignal
from migen.build.platforms import ebaz4205 from migen.build.platforms import ebaz4205
from migen.build.generic_platform import Pins, Subsignal, IOStandard, Misc
from migen_axi.integration.soc_core import SoCCore from migen_axi.integration.soc_core import SoCCore
from misoc.interconnect.csr import * from misoc.interconnect.csr import *
from artiq.gateware import rtio
from artiq.gateware.rtio.phy import ttl_simple
from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path
import dma
import analyzer
from config import write_csr_file, write_mem_file, write_rustc_cfg_file
_ps = [ _ps = [
( (
"ps", "ps",
@ -83,6 +79,17 @@ _i2c = [
) )
] ]
_spi = [
(
"spi",
0,
Subsignal("clk", Pins("V20")),
Subsignal("mosi", Pins("U20")),
Subsignal("cs_n", Pins("P19")),
IOStandard("LVCMOS33"),
)
]
class EBAZ4205(SoCCore): class EBAZ4205(SoCCore):
def __init__(self, rtio_clk=125e6, acpki=False): def __init__(self, rtio_clk=125e6, acpki=False):
@ -97,6 +104,7 @@ class EBAZ4205(SoCCore):
platform.add_extension(_ps) platform.add_extension(_ps)
platform.add_extension(_ddr) platform.add_extension(_ddr)
platform.add_extension(_i2c) platform.add_extension(_i2c)
platform.add_extension(_spi)
gmii = platform.request("gmii") gmii = platform.request("gmii")
platform.add_period_constraint(gmii.rx_clk, 10) platform.add_period_constraint(gmii.rx_clk, 10)
@ -171,6 +179,11 @@ class EBAZ4205(SoCCore):
phy = ttl_simple.Output(user_led) phy = ttl_simple.Output(user_led)
self.submodules += phy self.submodules += phy
self.rtio_channels.append(rtio.Channel.from_phy(phy)) self.rtio_channels.append(rtio.Channel.from_phy(phy))
print("SPI at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
spi_phy = spi2.SPIMaster(platform.request("spi"))
self.submodules += spi_phy
self.rtio_channels.append(rtio.Channel.from_phy(spi_phy, ififo_depth=4))
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels) self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
self.rtio_channels.append(rtio.LogChannel()) self.rtio_channels.append(rtio.LogChannel())

View File

@ -20,7 +20,6 @@ build_zynq = { path = "../libbuild_zynq" }
log = "0.4" log = "0.4"
log_buffer = { version = "1.2" } log_buffer = { version = "1.2" }
crc = { version = "1.7", default-features = false } crc = { version = "1.7", default-features = false }
core_io = { version = "0.1", features = ["collections"] }
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 }

View File

@ -1,16 +1,15 @@
use core::slice; use core::slice;
use core_io::{Error as IoError, ErrorKind as IoErrorKind};
use crc; use crc;
use io::{proto::{ProtoRead, ProtoWrite}, use io::{proto::{ProtoRead, ProtoWrite},
Cursor}; Cursor, Error as IoError};
use libboard_zynq::{time::Milliseconds, timer::GlobalTimer}; use libboard_zynq::{time::Milliseconds, timer::GlobalTimer};
pub use crate::drtioaux_proto::Packet; pub use crate::drtioaux_proto::Packet;
use crate::{drtioaux_proto::Error as ProtocolError, mem::mem::DRTIOAUX_MEM, pl::csr::DRTIOAUX}; use crate::{drtioaux_proto::Error as ProtocolError, mem::mem::DRTIOAUX_MEM, pl::csr::DRTIOAUX};
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error<T> {
GatewareError, GatewareError,
CorruptedPacket, CorruptedPacket,
@ -20,17 +19,17 @@ pub enum Error {
RoutingError, RoutingError,
Protocol(ProtocolError), Protocol(ProtocolError<T>),
} }
impl From<ProtocolError> for Error { impl<T> From<ProtocolError<T>> for Error<T> {
fn from(value: ProtocolError) -> Error { fn from(value: ProtocolError<T>) -> Error<T> {
Error::Protocol(value) Error::Protocol(value)
} }
} }
impl From<IoError> for Error { impl<T> From<IoError<T>> for Error<T> {
fn from(value: IoError) -> Error { fn from(value: IoError<T>) -> Error<T> {
Error::Protocol(ProtocolError::Io(value)) Error::Protocol(ProtocolError::Io(value))
} }
} }
@ -57,8 +56,8 @@ pub fn has_rx_error(linkno: u8) -> bool {
} }
} }
fn receive<F, T>(linkno: u8, f: F) -> Result<Option<T>, Error> fn receive<F, T>(linkno: u8, f: F) -> Result<Option<T>, Error<!>>
where F: FnOnce(&[u8]) -> Result<T, Error> { where F: FnOnce(&[u8]) -> Result<T, Error<!>> {
let linkidx = linkno as usize; let linkidx = linkno as usize;
unsafe { unsafe {
if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 { if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 {
@ -73,14 +72,14 @@ where F: FnOnce(&[u8]) -> Result<T, Error> {
} }
} }
pub fn recv(linkno: u8) -> Result<Option<Packet>, Error> { pub fn recv(linkno: u8) -> Result<Option<Packet>, Error<!>> {
if has_rx_error(linkno) { if has_rx_error(linkno) {
return Err(Error::GatewareError); return Err(Error::GatewareError);
} }
receive(linkno, |buffer| { receive(linkno, |buffer| {
if buffer.len() < 8 { if buffer.len() < 8 {
return Err(IoError::new(IoErrorKind::UnexpectedEof, "Unexpected end").into()); return Err(IoError::UnexpectedEnd.into());
} }
let mut reader = Cursor::new(buffer); let mut reader = Cursor::new(buffer);
@ -97,7 +96,7 @@ pub fn recv(linkno: u8) -> Result<Option<Packet>, Error> {
}) })
} }
pub fn recv_timeout(linkno: u8, timeout_ms: Option<u64>, timer: GlobalTimer) -> Result<Packet, Error> { pub fn recv_timeout(linkno: u8, timeout_ms: Option<u64>, timer: GlobalTimer) -> Result<Packet, Error<!>> {
let timeout_ms = Milliseconds(timeout_ms.unwrap_or(10)); let timeout_ms = Milliseconds(timeout_ms.unwrap_or(10));
let limit = timer.get_time() + timeout_ms; let limit = timer.get_time() + timeout_ms;
while timer.get_time() < limit { while timer.get_time() < limit {
@ -109,8 +108,8 @@ pub fn recv_timeout(linkno: u8, timeout_ms: Option<u64>, timer: GlobalTimer) ->
Err(Error::TimedOut) Err(Error::TimedOut)
} }
fn transmit<F>(linkno: u8, f: F) -> Result<(), Error> fn transmit<F>(linkno: u8, f: F) -> Result<(), Error<!>>
where F: FnOnce(&mut [u8]) -> Result<usize, Error> { where F: FnOnce(&mut [u8]) -> Result<usize, Error<!>> {
let linkno = linkno as usize; let linkno = linkno as usize;
unsafe { unsafe {
while (DRTIOAUX[linkno].aux_tx_read)() != 0 {} while (DRTIOAUX[linkno].aux_tx_read)() != 0 {}
@ -122,7 +121,7 @@ where F: FnOnce(&mut [u8]) -> Result<usize, Error> {
} }
} }
pub fn send(linkno: u8, packet: &Packet) -> Result<(), Error> { pub fn send(linkno: u8, packet: &Packet) -> Result<(), Error<!>> {
transmit(linkno, |buffer| { transmit(linkno, |buffer| {
let mut writer = Cursor::new(buffer); let mut writer = Cursor::new(buffer);

View File

@ -1,9 +1,8 @@
use core::slice; use core::slice;
use core_io::{Error as IoError, ErrorKind as IoErrorKind};
use crc; use crc;
use io::{proto::{ProtoRead, ProtoWrite}, use io::{proto::{ProtoRead, ProtoWrite},
Cursor}; Cursor, Error as IoError};
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 nb;
@ -35,8 +34,8 @@ fn tx_ready(linkno: usize) -> nb::Result<(), Void> {
} }
} }
async fn receive<F, T>(linkno: u8, f: F) -> Result<Option<T>, Error> async fn receive<F, T>(linkno: u8, f: F) -> Result<Option<T>, Error<!>>
where F: FnOnce(&[u8]) -> Result<T, Error> { where F: FnOnce(&[u8]) -> Result<T, Error<!>> {
let linkidx = linkno as usize; let linkidx = linkno as usize;
unsafe { unsafe {
if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 { if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 {
@ -51,14 +50,14 @@ where F: FnOnce(&[u8]) -> Result<T, Error> {
} }
} }
pub async fn recv(linkno: u8) -> Result<Option<Packet>, Error> { pub async fn recv(linkno: u8) -> Result<Option<Packet>, Error<!>> {
if has_rx_error(linkno) { if has_rx_error(linkno) {
return Err(Error::GatewareError); return Err(Error::GatewareError);
} }
receive(linkno, |buffer| { receive(linkno, |buffer| {
if buffer.len() < 8 { if buffer.len() < 8 {
return Err(IoError::new(IoErrorKind::UnexpectedEof, "Unexpected end").into()); return Err(IoError::UnexpectedEnd.into());
} }
let mut reader = Cursor::new(buffer); let mut reader = Cursor::new(buffer);
@ -76,7 +75,7 @@ pub async fn recv(linkno: u8) -> Result<Option<Packet>, Error> {
.await .await
} }
pub async fn recv_timeout(linkno: u8, timeout_ms: Option<u64>, timer: GlobalTimer) -> Result<Packet, Error> { pub async fn recv_timeout(linkno: u8, timeout_ms: Option<u64>, timer: GlobalTimer) -> Result<Packet, Error<!>> {
let timeout_ms = Milliseconds(timeout_ms.unwrap_or(10)); let timeout_ms = Milliseconds(timeout_ms.unwrap_or(10));
let limit = timer.get_time() + timeout_ms; let limit = timer.get_time() + timeout_ms;
let mut would_block = false; let mut would_block = false;
@ -96,8 +95,8 @@ pub async fn recv_timeout(linkno: u8, timeout_ms: Option<u64>, timer: GlobalTime
Err(Error::TimedOut) Err(Error::TimedOut)
} }
async fn transmit<F>(linkno: u8, f: F) -> Result<(), Error> async fn transmit<F>(linkno: u8, f: F) -> Result<(), Error<!>>
where F: FnOnce(&mut [u8]) -> Result<usize, Error> { where F: FnOnce(&mut [u8]) -> Result<usize, Error<!>> {
let linkno = linkno as usize; let linkno = linkno as usize;
unsafe { unsafe {
let _ = block_async!(tx_ready(linkno)).await; let _ = block_async!(tx_ready(linkno)).await;
@ -109,7 +108,7 @@ where F: FnOnce(&mut [u8]) -> Result<usize, Error> {
} }
} }
pub async fn send(linkno: u8, packet: &Packet) -> Result<(), Error> { pub async fn send(linkno: u8, packet: &Packet) -> Result<(), Error<!>> {
transmit(linkno, |buffer| { transmit(linkno, |buffer| {
let mut writer = Cursor::new(buffer); let mut writer = Cursor::new(buffer);

View File

@ -1,4 +1,4 @@
use core_io::{Error as IoError, Read, Write}; use io::{Error as IoError, Read, Write};
use io::proto::{ProtoRead, ProtoWrite}; use io::proto::{ProtoRead, ProtoWrite};
const MAX_PACKET: usize = 1024; const MAX_PACKET: usize = 1024;
@ -10,13 +10,13 @@ pub const SAT_PAYLOAD_MAX_SIZE: usize = /*max size*/MAX_PACKET - /*CRC*/4 - /*p
pub const MASTER_PAYLOAD_MAX_SIZE: usize = SAT_PAYLOAD_MAX_SIZE - /*source*/1 - /*destination*/1 - /*ID*/4; pub const MASTER_PAYLOAD_MAX_SIZE: usize = SAT_PAYLOAD_MAX_SIZE - /*source*/1 - /*destination*/1 - /*ID*/4;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error<T> {
UnknownPacket(u8), UnknownPacket(u8),
Io(IoError), Io(IoError<T>),
} }
impl From<IoError> for Error { impl<T> From<IoError<T>> for Error<T> {
fn from(value: IoError) -> Error { fn from(value: IoError<T>) -> Error<T> {
Error::Io(value) Error::Io(value)
} }
} }
@ -255,6 +255,7 @@ pub enum Packet {
destination: u8, destination: u8,
id: u32, id: u32,
run: bool, run: bool,
timestamp: u64,
}, },
SubkernelLoadRunReply { SubkernelLoadRunReply {
destination: u8, destination: u8,
@ -290,7 +291,7 @@ pub enum Packet {
} }
impl Packet { impl Packet {
pub fn read_from<R>(reader: &mut R) -> Result<Self, Error> pub fn read_from<R>(reader: &mut R) -> Result<Self, Error<R::ReadError>>
where R: Read + ?Sized { where R: Read + ?Sized {
Ok(match reader.read_u8()? { Ok(match reader.read_u8()? {
0x00 => Packet::EchoRequest, 0x00 => Packet::EchoRequest,
@ -514,6 +515,7 @@ impl Packet {
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32()?, id: reader.read_u32()?,
run: reader.read_bool()?, run: reader.read_bool()?,
timestamp: reader.read_u64()?,
}, },
0xc5 => Packet::SubkernelLoadRunReply { 0xc5 => Packet::SubkernelLoadRunReply {
destination: reader.read_u8()?, destination: reader.read_u8()?,
@ -567,7 +569,7 @@ impl Packet {
}) })
} }
pub fn write_to<W>(&self, writer: &mut W) -> Result<(), IoError> pub fn write_to<W>(&self, writer: &mut W) -> Result<(), IoError<W::WriteError>>
where W: Write + ?Sized { where W: Write + ?Sized {
match *self { match *self {
Packet::EchoRequest => writer.write_u8(0x00)?, Packet::EchoRequest => writer.write_u8(0x00)?,
@ -877,12 +879,14 @@ impl Packet {
destination, destination,
id, id,
run, run,
timestamp,
} => { } => {
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(id)?; writer.write_u32(id)?;
writer.write_bool(run)?; writer.write_bool(run)?;
writer.write_u64(timestamp)?;
} }
Packet::SubkernelLoadRunReply { destination, succeeded } => { Packet::SubkernelLoadRunReply { destination, succeeded } => {
writer.write_u8(0xc5)?; writer.write_u8(0xc5)?;

View File

@ -1,5 +1,6 @@
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 core::arch::asm;
use libregister::RegisterR; use libregister::RegisterR;
#[cfg(has_si549)] #[cfg(has_si549)]

View File

@ -1,9 +1,8 @@
#![no_std] #![no_std]
#![feature(never_type)] #![feature(never_type)]
#![feature(naked_functions)] #![feature(naked_functions)]
#![feature(asm)] #![allow(unexpected_cfgs)]
extern crate core_io;
extern crate crc; extern crate crc;
extern crate embedded_hal; extern crate embedded_hal;
extern crate io; extern crate io;

View File

@ -1,3 +1,5 @@
#![allow(unexpected_cfgs)]
use std::{env, use std::{env,
fs::File, fs::File,
io::{BufRead, BufReader, Write}, io::{BufRead, BufReader, Write},

View File

@ -8,7 +8,6 @@ name = "io"
path = "lib.rs" path = "lib.rs"
[dependencies] [dependencies]
core_io = { version = "0.1", features = ["collections"] }
byteorder = { version = "1.0", default-features = false, optional = true } byteorder = { version = "1.0", default-features = false, optional = true }
libsupport_zynq = { path = "@@ZYNQ_RS@@/libsupport_zynq", default-features = false, features = ["alloc_core"] } libsupport_zynq = { path = "@@ZYNQ_RS@@/libsupport_zynq", default-features = false, features = ["alloc_core"] }

View File

@ -1,7 +1,7 @@
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use alloc::vec::Vec; use alloc::vec::Vec;
use core_io::{Error as IoError, Read, Write}; use crate::{Read, Write};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Cursor<T> { pub struct Cursor<T> {
@ -42,7 +42,9 @@ impl<T> Cursor<T> {
} }
impl<T: AsRef<[u8]>> Read for Cursor<T> { impl<T: AsRef<[u8]>> Read for Cursor<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, IoError> { type ReadError = !;
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::ReadError> {
let data = &self.inner.as_ref()[self.pos..]; let data = &self.inner.as_ref()[self.pos..];
let len = buf.len().min(data.len()); let len = buf.len().min(data.len());
// ``copy_from_slice`` generates AXI bursts, use a regular loop instead // ``copy_from_slice`` generates AXI bursts, use a regular loop instead
@ -55,7 +57,10 @@ impl<T: AsRef<[u8]>> Read for Cursor<T> {
} }
impl Write for Cursor<&mut [u8]> { impl Write for Cursor<&mut [u8]> {
fn write(&mut self, buf: &[u8]) -> Result<usize, IoError> { type WriteError = !;
type FlushError = !;
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
let data = &mut self.inner[self.pos..]; let data = &mut self.inner[self.pos..];
let len = buf.len().min(data.len()); let len = buf.len().min(data.len());
for i in 0..len { for i in 0..len {
@ -66,20 +71,23 @@ impl Write for Cursor<&mut [u8]> {
} }
#[inline] #[inline]
fn flush(&mut self) -> Result<(), IoError> { fn flush(&mut self) -> Result<(), Self::FlushError> {
Ok(()) Ok(())
} }
} }
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
impl Write for Cursor<Vec<u8>> { impl Write for Cursor<Vec<u8>> {
fn write(&mut self, buf: &[u8]) -> Result<usize, IoError> { type WriteError = !;
type FlushError = !;
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
self.inner.extend_from_slice(buf); self.inner.extend_from_slice(buf);
Ok(buf.len()) Ok(buf.len())
} }
#[inline] #[inline]
fn flush(&mut self) -> Result<(), IoError> { fn flush(&mut self) -> Result<(), Self::FlushError> {
Ok(()) Ok(())
} }
} }

View File

@ -1,9 +1,9 @@
#![no_std] #![no_std]
#![feature(never_type)] #![feature(never_type)]
#![allow(unexpected_cfgs)]
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;
extern crate core_io;
#[cfg(feature = "byteorder")] #[cfg(feature = "byteorder")]
extern crate byteorder; extern crate byteorder;
@ -12,8 +12,142 @@ pub mod cursor;
#[cfg(feature = "byteorder")] #[cfg(feature = "byteorder")]
pub mod proto; pub mod proto;
use core::fmt::{Display, Formatter};
pub use cursor::Cursor; pub use cursor::Cursor;
#[cfg(all(feature = "byteorder", feature = "alloc"))] #[cfg(all(feature = "byteorder", feature = "alloc"))]
pub use proto::ReadStringError; pub use proto::ReadStringError;
#[cfg(feature = "byteorder")] #[cfg(feature = "byteorder")]
pub use proto::{ProtoRead, ProtoWrite}; pub use proto::{ProtoRead, ProtoWrite};
#[derive(Debug, Clone, PartialEq)]
pub enum Error<T> {
UnexpectedEnd,
Other(T),
}
impl<T> From<T> for Error<T> {
fn from(value: T) -> Error<T> {
Error::Other(value)
}
}
impl<T: Display> Display for Error<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
match self {
Error::UnexpectedEnd => write!(f, "unexpected end of stream"),
Error::Other(other) => write!(f, "other IO error: {}", other),
}
}
}
pub trait Read {
type ReadError;
/// Pull some bytes from this source into the specified buffer, returning
/// how many bytes were read.
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::ReadError>;
/// Read the exact number of bytes required to fill `buf`.
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), Error<Self::ReadError>> {
while !buf.is_empty() {
let read_bytes = self.read(buf)?;
if read_bytes == 0 {
return Err(Error::UnexpectedEnd);
}
buf = &mut { buf }[read_bytes..];
}
Ok(())
}
}
impl<'a, T: Read> Read for &'a mut T {
type ReadError = T::ReadError;
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::ReadError> {
T::read(self, buf)
}
}
pub trait Write {
type WriteError;
type FlushError;
/// Write a buffer into this object, returning how many bytes were written.
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError>;
/// Flush this output stream, ensuring that all intermediately buffered contents
/// reach their destination.
fn flush(&mut self) -> Result<(), Self::FlushError>;
/// Attempts to write an entire buffer into `self`.
fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Error<Self::WriteError>> {
while buf.len() > 0 {
let written_bytes = self.write(buf)?;
if written_bytes == 0 {
return Err(Error::UnexpectedEnd);
}
buf = &buf[written_bytes..];
}
Ok(())
}
/// Hints the writer how much bytes will be written after call to this function.
///
/// At least `min` bytes should be written after the call to this function and
/// if `max` is `Some(x)` than at most `x` bytes should be written.
fn size_hint(&mut self, _min: usize, _max: Option<usize>) {}
}
impl<'a, T: Write> Write for &'a mut T {
type WriteError = T::WriteError;
type FlushError = T::FlushError;
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
T::write(self, buf)
}
fn flush(&mut self) -> Result<(), Self::FlushError> {
T::flush(self)
}
fn size_hint(&mut self, min: usize, max: Option<usize>) {
T::size_hint(self, min, max)
}
}
impl<'a> Write for &'a mut [u8] {
type WriteError = !;
type FlushError = !;
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
let len = buf.len().min(self.len());
self[..len].copy_from_slice(&buf[..len]);
Ok(len)
}
#[inline]
fn flush(&mut self) -> Result<(), Self::FlushError> {
Ok(())
}
}
#[cfg(feature = "alloc")]
impl<'a> Write for alloc::vec::Vec<u8> {
type WriteError = !;
type FlushError = !;
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
self.extend_from_slice(buf);
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> Result<(), Self::FlushError> {
Ok(())
}
}

View File

@ -3,7 +3,9 @@ use alloc::{string::String, vec};
use core::str::Utf8Error; use core::str::Utf8Error;
use byteorder::{ByteOrder, NativeEndian}; use byteorder::{ByteOrder, NativeEndian};
use core_io::{Error as IoError, Read, Write}; use Error as IoError;
use Read;
use Write;
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -147,7 +149,7 @@ pub trait ProtoWrite {
impl<T> ProtoRead for T impl<T> ProtoRead for T
where T: Read + ?Sized where T: Read + ?Sized
{ {
type ReadError = IoError; type ReadError = IoError<T::ReadError>;
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::ReadError> { fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::ReadError> {
T::read_exact(self, buf) T::read_exact(self, buf)
@ -157,7 +159,7 @@ where T: Read + ?Sized
impl<T> ProtoWrite for T impl<T> ProtoWrite for T
where T: Write + ?Sized where T: Write + ?Sized
{ {
type WriteError = IoError; type WriteError = IoError<T::WriteError>;
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::WriteError> { fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::WriteError> {
T::write_all(self, buf) T::write_all(self, buf)

View File

@ -12,12 +12,12 @@ build_zynq = { path = "../libbuild_zynq" }
cslice = "0.3" cslice = "0.3"
log = "0.4" log = "0.4"
nb = "0.1" nb = "0.1"
core_io = { version = "0.1", features = ["collections"] }
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 }
log_buffer = { version = "1.2" } log_buffer = { version = "1.2" }
libm = { version = "0.2", features = ["unstable"] } libm = { version = "0.2", features = ["unstable"] }
vcell = "0.1" vcell = "0.1"
nalgebra = { version = "0.33.0", default-features = false, features = ["libm", "alloc"]}
libboard_zynq = { path = "@@ZYNQ_RS@@/libboard_zynq", features = ["ipv6"]} libboard_zynq = { path = "@@ZYNQ_RS@@/libboard_zynq", features = ["ipv6"]}
libsupport_zynq = { path = "@@ZYNQ_RS@@/libsupport_zynq", default-features = false, features = ["alloc_core"] } libsupport_zynq = { path = "@@ZYNQ_RS@@/libsupport_zynq", default-features = false, features = ["alloc_core"] }
@ -32,9 +32,3 @@ unwind = { path = "../libunwind" }
libc = { path = "../libc" } libc = { path = "../libc" }
io = { path = "../libio" } io = { path = "../libio" }
libboard_artiq = { path = "../libboard_artiq" } libboard_artiq = { path = "../libboard_artiq" }
[dependencies.nalgebra]
git = "https://git.m-labs.hk/M-Labs/nalgebra.git"
rev = "dd00f9b"
default-features = false
features = ["libm", "alloc"]

View File

@ -14,10 +14,9 @@
use core::mem; use core::mem;
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};
use io::{Cursor, ProtoRead}; use io::{Cursor, Error as ReadError, ProtoRead, Read};
use libc::{c_int, c_void, uintptr_t}; use libc::{c_int, c_void, uintptr_t};
use log::{error, trace}; use log::{error, trace};
use unwind as uw; use unwind as uw;
@ -96,30 +95,30 @@ struct ExceptionBuffer {
} }
static mut EXCEPTION_BUFFER: ExceptionBuffer = ExceptionBuffer { static mut EXCEPTION_BUFFER: ExceptionBuffer = ExceptionBuffer {
uw_exceptions: [uw::_Unwind_Exception { uw_exceptions: [ const { uw::_Unwind_Exception {
exception_class: EXCEPTION_CLASS, exception_class: EXCEPTION_CLASS,
exception_cleanup: cleanup, exception_cleanup: cleanup,
private: [0; uw::unwinder_private_data_size], private: [0; uw::unwinder_private_data_size],
}; MAX_INFLIGHT_EXCEPTIONS], } }; MAX_INFLIGHT_EXCEPTIONS],
exceptions: [None; MAX_INFLIGHT_EXCEPTIONS + 1], exceptions: [None; MAX_INFLIGHT_EXCEPTIONS + 1],
exception_stack: [-1; MAX_INFLIGHT_EXCEPTIONS + 1], exception_stack: [-1; MAX_INFLIGHT_EXCEPTIONS + 1],
backtrace: [(0, 0); MAX_BACKTRACE_SIZE], backtrace: [(0, 0); MAX_BACKTRACE_SIZE],
backtrace_size: 0, backtrace_size: 0,
stack_pointers: [StackPointerBacktrace { stack_pointers: [ const { StackPointerBacktrace {
stack_pointer: 0, stack_pointer: 0,
initial_backtrace_size: 0, initial_backtrace_size: 0,
current_backtrace_size: 0, current_backtrace_size: 0,
}; MAX_INFLIGHT_EXCEPTIONS + 1], } }; MAX_INFLIGHT_EXCEPTIONS + 1],
exception_count: 0, exception_count: 0,
}; };
pub unsafe extern "C" fn reset_exception_buffer() { pub unsafe extern "C" fn reset_exception_buffer() {
trace!("reset exception buffer"); trace!("reset exception buffer");
EXCEPTION_BUFFER.uw_exceptions = [uw::_Unwind_Exception { EXCEPTION_BUFFER.uw_exceptions = [ const { uw::_Unwind_Exception {
exception_class: EXCEPTION_CLASS, exception_class: EXCEPTION_CLASS,
exception_cleanup: cleanup, exception_cleanup: cleanup,
private: [0; uw::unwinder_private_data_size], private: [0; uw::unwinder_private_data_size],
}; MAX_INFLIGHT_EXCEPTIONS]; } }; MAX_INFLIGHT_EXCEPTIONS];
EXCEPTION_BUFFER.exceptions = [None; MAX_INFLIGHT_EXCEPTIONS + 1]; EXCEPTION_BUFFER.exceptions = [None; MAX_INFLIGHT_EXCEPTIONS + 1];
EXCEPTION_BUFFER.exception_stack = [-1; MAX_INFLIGHT_EXCEPTIONS + 1]; EXCEPTION_BUFFER.exception_stack = [-1; MAX_INFLIGHT_EXCEPTIONS + 1];
EXCEPTION_BUFFER.backtrace_size = 0; EXCEPTION_BUFFER.backtrace_size = 0;
@ -295,7 +294,9 @@ pub unsafe extern "C" fn raise(exception: *const Exception) -> ! {
unreachable!(); unreachable!();
} }
fn read_exception_string<'a>(reader: &mut Cursor<&[u8]>) -> Result<CSlice<'a, u8>, ReadError> { fn read_exception_string<'a, 'b>(
reader: &mut Cursor<&'b [u8]>,
) -> Result<CSlice<'a, u8>, ReadError<<Cursor<&'b [u8]> as Read>::ReadError>> {
let len = reader.read_u32()? as usize; let len = reader.read_u32()? as usize;
if len == usize::MAX { if len == usize::MAX {
let data = reader.read_u32()?; let data = reader.read_u32()?;
@ -311,7 +312,7 @@ fn read_exception_string<'a>(reader: &mut Cursor<&[u8]>) -> Result<CSlice<'a, u8
} }
} }
fn read_exception(raw_exception: &[u8]) -> Result<Exception, ReadError> { fn read_exception(raw_exception: &[u8]) -> Result<Exception, ReadError<<Cursor<&[u8]> as Read>::ReadError>> {
let mut reader = Cursor::new(raw_exception); let mut reader = Cursor::new(raw_exception);
let mut byte = reader.read_u8()?; let mut byte = reader.read_u8()?;

View File

@ -0,0 +1,149 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// This is the Rust personality function, adapted for use in ARTIQ. We never actually panic
// from Rust or recover from Rust exceptions (there's nothing to catch the panics), but we
// need a personality function to step back through Rust frames in order to make a backtrace.
//
// By design, this personality function is only ever called in the search phase, although
// to keep things simple and close to upstream, it is not modified
use unwind as uw;
use libc::c_int;
use dwarf::eh::{EHAction, EHContext};
// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
// and TargetLowering::getExceptionSelectorRegister() for each architecture,
// then mapped to DWARF register numbers via register definition tables
// (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
// See also http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
#[cfg(target_arch = "x86")]
const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
#[cfg(target_arch = "x86_64")]
const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
#[cfg(any(target_arch = "riscv32"))]
const UNWIND_DATA_REG: (i32, i32) = (10, 11); // X10, X11
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1
// The following code is based on GCC's C and C++ personality routines. For reference, see:
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
#[lang = "eh_personality"]
#[no_mangle]
unsafe extern "C" fn rust_eh_personality(
state: uw::_Unwind_State,
exception_object: *mut uw::_Unwind_Exception,
context: *mut uw::_Unwind_Context,
) -> uw::_Unwind_Reason_Code {
let state = state as c_int;
let action = state & uw::_US_ACTION_MASK as c_int;
let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int {
// Backtraces on ARM will call the personality routine with
// state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
// we want to continue unwinding the stack, otherwise all our backtraces
// would end at __rust_try
if state & uw::_US_FORCE_UNWIND as c_int != 0 {
return continue_unwind(exception_object, context);
}
true
} else if action == uw::_US_UNWIND_FRAME_STARTING as c_int {
false
} else if action == uw::_US_UNWIND_FRAME_RESUME as c_int {
return continue_unwind(exception_object, context);
} else {
return uw::_URC_FAILURE;
};
// The DWARF unwinder assumes that _Unwind_Context holds things like the function
// and LSDA pointers, however ARM EHABI places them into the exception object.
// To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which
// take only the context pointer, GCC personality routines stash a pointer to
// exception_object in the context, using location reserved for ARM's
// "scratch register" (r12).
uw::_Unwind_SetGR(context, uw::UNWIND_POINTER_REG, exception_object as uw::_Unwind_Ptr);
// ...A more principled approach would be to provide the full definition of ARM's
// _Unwind_Context in our libunwind bindings and fetch the required data from there
// directly, bypassing DWARF compatibility functions.
let eh_action = match find_eh_action(context) {
Ok(action) => action,
Err(_) => return uw::_URC_FAILURE,
};
if search_phase {
match eh_action {
EHAction::None | EHAction::Cleanup(_) => {
return continue_unwind(exception_object, context);
}
EHAction::Catch(_) => {
// EHABI requires the personality routine to update the
// SP value in the barrier cache of the exception object.
(*exception_object).private[5] =
uw::_Unwind_GetGR(context, uw::UNWIND_SP_REG);
return uw::_URC_HANDLER_FOUND;
}
EHAction::Terminate => return uw::_URC_FAILURE,
}
} else {
match eh_action {
EHAction::None => return continue_unwind(exception_object, context),
EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
uw::_Unwind_SetGR(
context,
UNWIND_DATA_REG.0,
exception_object as uw::_Unwind_Ptr,
);
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
uw::_Unwind_SetIP(context, lpad);
return uw::_URC_INSTALL_CONTEXT;
}
EHAction::Terminate => return uw::_URC_FAILURE,
}
}
// On ARM EHABI the personality routine is responsible for actually
// unwinding a single stack frame before returning (ARM EHABI Sec. 6.1).
unsafe fn continue_unwind(
exception_object: *mut uw::_Unwind_Exception,
context: *mut uw::_Unwind_Context,
) -> uw::_Unwind_Reason_Code {
if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON {
uw::_URC_CONTINUE_UNWIND
} else {
uw::_URC_FAILURE
}
}
// defined in libgcc
extern "C" {
fn __gnu_unwind_frame(
exception_object: *mut uw::_Unwind_Exception,
context: *mut uw::_Unwind_Context,
) -> uw::_Unwind_Reason_Code;
}
}
unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result<EHAction, ()> {
let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
let mut ip_before_instr: c_int = 0;
let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);
let eh_context = EHContext {
// The return address points 1 byte past the call instruction,
// which could be in the next IP range in LSDA range table.
ip: if ip_before_instr != 0 { ip } else { ip - 1 },
func_start: uw::_Unwind_GetRegionStart(context),
get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
};
dwarf::eh::find_eh_action(lsda, &eh_context, false,0)
}

View File

@ -1,5 +1,5 @@
use core::sync::atomic::{AtomicBool, Ordering}; use core::sync::atomic::{AtomicBool, Ordering};
use core::arch::asm;
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};
use libregister::RegisterR; use libregister::RegisterR;

View File

@ -25,12 +25,14 @@ 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 (),

View File

@ -81,6 +81,7 @@ pub enum Message {
id: u32, id: u32,
destination: u8, destination: u8,
run: bool, run: bool,
timestamp: u64,
}, },
#[cfg(has_drtio)] #[cfg(has_drtio)]
SubkernelLoadRunReply { SubkernelLoadRunReply {

View File

@ -3,7 +3,7 @@ use alloc::vec::Vec;
use cslice::CSlice; use cslice::CSlice;
use super::{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 {
@ -14,6 +14,7 @@ pub extern "C" fn load_run(id: u32, destination: u8, run: bool) {
id: id, id: id,
destination: destination, destination: destination,
run: run, run: run,
timestamp: now_mu() as u64,
}); });
} }
match unsafe { KERNEL_CHANNEL_0TO1.as_mut().unwrap() }.recv() { match unsafe { KERNEL_CHANNEL_0TO1.as_mut().unwrap() }.recv() {

View File

@ -1,9 +1,10 @@
#![no_std] #![no_std]
#![feature(c_variadic)] #![feature(c_variadic)]
#![feature(const_btree_new)] #![feature(lang_items)]
#![feature(const_in_array_repeat_expressions)] #![feature(const_btree_len)]
#![feature(generic_const_exprs)]
#![feature(naked_functions)] #![feature(naked_functions)]
#![feature(asm)] #![allow(unexpected_cfgs)]
#[macro_use] #[macro_use]
extern crate alloc; extern crate alloc;
@ -21,6 +22,7 @@ pub use pl::csr::rtio_core;
use void::Void; use void::Void;
pub mod eh_artiq; pub mod eh_artiq;
pub mod eh_rust;
pub mod i2c; pub mod i2c;
pub mod irq; pub mod irq;
pub mod kernel; pub mod kernel;

View File

@ -1,9 +1,8 @@
use core::str; use core::str;
use byteorder::{ByteOrder, NativeEndian}; use byteorder::{ByteOrder, NativeEndian};
use core_io::{Error, Read, Write};
use cslice::{CMutSlice, CSlice}; use cslice::{CMutSlice, CSlice};
use io::{ProtoRead, ProtoWrite}; use io::{Error, ProtoRead, ProtoWrite, Read, Write};
use log::trace; use log::trace;
use self::tag::{split_tag, Tag, TagIterator}; use self::tag::{split_tag, Tag, TagIterator};
@ -37,16 +36,17 @@ 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>( unsafe fn recv_elements<F, R, E>(
reader: &mut R, reader: &mut R,
elt_tag: Tag, elt_tag: Tag,
length: usize, length: usize,
storage: *mut (), storage: *mut (),
alloc: &mut F, alloc: &mut F,
) -> Result<(), Error> ) -> Result<(), E>
where where
F: FnMut(usize) -> *mut (), F: FnMut(usize) -> Result<*mut (), E>,
R: Read + ?Sized, R: Read + ?Sized,
E: From<Error<R::ReadError>>,
{ {
match elt_tag { match elt_tag {
Tag::Bool => { Tag::Bool => {
@ -57,7 +57,6 @@ 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)?;
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);
} }
@ -65,7 +64,6 @@ 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)?;
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);
} }
@ -79,10 +77,11 @@ where
Ok(()) Ok(())
} }
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, E>(reader: &mut R, tag: Tag, data: &mut *mut (), alloc: &mut F) -> Result<(), E>
where where
F: FnMut(usize) -> *mut (), F: FnMut(usize) -> Result<*mut (), E>,
R: Read + ?Sized, R: Read + ?Sized,
E: From<Error<R::ReadError>>,
{ {
macro_rules! consume_value { macro_rules! consume_value {
($ty:ty, | $ptr:ident | $map:expr) => {{ ($ty:ty, | $ptr:ident | $map:expr) => {{
@ -109,7 +108,7 @@ where
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()? 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(())
}) })
@ -139,7 +138,7 @@ where
let storage_offset = round_up(list_size, tag.alignment()); let storage_offset = round_up(list_size, tag.alignment());
let storage_size = tag.size() * length; let storage_size = tag.size() * length;
let allocation = alloc(storage_offset + storage_size) as *mut u8; let allocation = alloc(storage_offset + storage_size)? as *mut u8;
*ptr_to_list = allocation as *mut List; *ptr_to_list = allocation as *mut List;
let storage = allocation.offset(storage_offset as isize) as *mut (); let storage = allocation.offset(storage_offset as isize) as *mut ();
@ -158,7 +157,7 @@ where
} }
let elt_tag = it.clone().next().expect("truncated tag"); let elt_tag = it.clone().next().expect("truncated tag");
*buffer = alloc(elt_tag.size() * total_len); *buffer = alloc(elt_tag.size() * total_len)?;
recv_elements(reader, elt_tag, total_len, *buffer, alloc) recv_elements(reader, elt_tag, total_len, *buffer, alloc)
}) })
} }
@ -175,15 +174,16 @@ where
} }
} }
pub fn recv_return<'a, F, R>( pub fn recv_return<'a, F, R, E>(
reader: &mut R, reader: &mut R,
tag_bytes: &'a [u8], tag_bytes: &'a [u8],
data: *mut (), data: *mut (),
alloc: &mut F, alloc: &mut F,
) -> Result<&'a [u8], Error> ) -> Result<&'a [u8], E>
where where
F: FnMut(usize) -> *mut (), F: FnMut(usize) -> Result<*mut (), E>,
R: Read + ?Sized, R: Read + ?Sized,
E: From<Error<R::ReadError>>,
{ {
let mut it = TagIterator::new(tag_bytes); let mut it = TagIterator::new(tag_bytes);
trace!("recv ...->{}", it); trace!("recv ...->{}", it);
@ -201,7 +201,7 @@ unsafe fn send_elements<W>(
length: usize, length: usize,
data: *const (), data: *const (),
write_tags: bool, write_tags: bool,
) -> Result<(), Error> ) -> Result<(), Error<W::WriteError>>
where where
W: Write + ?Sized, W: Write + ?Sized,
{ {
@ -233,8 +233,15 @@ where
Ok(()) Ok(())
} }
unsafe fn send_value<W>(writer: &mut W, tag: Tag, data: &mut *const (), write_tags: bool) -> Result<(), Error> unsafe fn send_value<W>(
where W: Write + ?Sized { writer: &mut W,
tag: Tag,
data: &mut *const (),
write_tags: bool,
) -> Result<(), Error<W::WriteError>>
where
W: Write + ?Sized,
{
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);
@ -337,7 +344,7 @@ pub fn send_args<W>(
tag_bytes: &[u8], tag_bytes: &[u8],
data: *const *const (), data: *const *const (),
write_tags: bool, write_tags: bool,
) -> Result<(), Error> ) -> Result<(), Error<W::WriteError>>
where where
W: Write + ?Sized, W: Write + ?Sized,
{ {

View File

@ -1,8 +1,5 @@
#![no_std] #![no_std]
#![feature(link_cfg)] #![feature(link_cfg)]
#![feature(nll)]
#![feature(unwind_attributes)]
#![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! {
@ -17,17 +14,3 @@ cfg_if::cfg_if! {
pub use backtrace::backtrace; pub use backtrace::backtrace;
} }
} }
#[cfg(target_env = "musl")]
#[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))]
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
extern "C" {}
#[cfg(target_os = "redox")]
#[link(name = "gcc_eh", kind = "static-nobundle", cfg(target_feature = "crt-static"))]
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
extern "C" {}
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
#[link(name = "unwind", kind = "static-nobundle")]
extern "C" {}

View File

@ -77,8 +77,7 @@ pub type _Unwind_Exception_Cleanup_Fn =
all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
link(name = "unwind", kind = "static") link(name = "unwind", kind = "static")
)] )]
extern "C" { extern "C-unwind" {
#[unwind(allowed)]
pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !; pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception); pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void; pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
@ -226,8 +225,7 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
#[cfg_attr(all(feature = "llvm-libunwind", #[cfg_attr(all(feature = "llvm-libunwind",
any(target_os = "fuchsia", target_os = "linux")), any(target_os = "fuchsia", target_os = "linux")),
link(name = "unwind", kind = "static"))] link(name = "unwind", kind = "static"))]
extern "C" { extern "C-unwind" {
#[unwind(allowed)]
pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code; pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
trace_argument: *mut c_void) trace_argument: *mut c_void)
@ -238,8 +236,7 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
#[cfg_attr(all(feature = "llvm-libunwind", #[cfg_attr(all(feature = "llvm-libunwind",
any(target_os = "fuchsia", target_os = "linux")), any(target_os = "fuchsia", target_os = "linux")),
link(name = "unwind", kind = "static"))] link(name = "unwind", kind = "static"))]
extern "C" { extern "C-unwind" {
#[unwind(allowed)]
pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
} }

View File

@ -20,7 +20,6 @@ num-derive = "0.3"
cslice = "0.3" cslice = "0.3"
log = "0.4" log = "0.4"
embedded-hal = "0.2" embedded-hal = "0.2"
core_io = { version = "0.1", features = ["collections"] }
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"] }

View File

@ -1,3 +1,4 @@
#![allow(unexpected_cfgs)]
extern crate build_zynq; extern crate build_zynq;
fn main() { fn main() {

View File

@ -1,12 +1,12 @@
use alloc::{collections::BTreeMap, rc::Rc, string::String, vec, vec::Vec}; use alloc::{collections::BTreeMap, rc::Rc, string::String, vec, vec::Vec};
use core::{cell::RefCell, fmt, slice, str}; use core::{cell::RefCell, fmt, slice, str};
use core_io::Error as IoError;
use cslice::CSlice; use cslice::CSlice;
use dyld::elf; use dyld::elf;
use futures::{future::FutureExt, select_biased}; use futures::{future::FutureExt, select_biased};
#[cfg(has_drtio)] #[cfg(has_drtio)]
use io::Cursor; use io::Cursor;
use io::Error as IoError;
#[cfg(has_drtio)] #[cfg(has_drtio)]
use ksupport::rpc; use ksupport::rpc;
use ksupport::{kernel, resolve_channel_name}; use ksupport::{kernel, resolve_channel_name};
@ -78,8 +78,8 @@ impl From<smoltcp::Error> for Error {
} }
} }
impl From<IoError> for Error { impl<T> From<IoError<T>> for Error {
fn from(_error: IoError) -> Self { fn from(_error: IoError<T>) -> Self {
Error::IoError Error::IoError
} }
} }
@ -405,8 +405,9 @@ async fn handle_run_kernel(
id, id,
destination: _, destination: _,
run, run,
timestamp,
} => { } => {
let succeeded = match subkernel::load(aux_mutex, routing_table, timer, id, run).await { let succeeded = match subkernel::load(aux_mutex, routing_table, timer, id, run, timestamp).await {
Ok(()) => true, Ok(()) => true,
Err(e) => { Err(e) => {
error!("Error loading subkernel: {:?}", e); error!("Error loading subkernel: {:?}", e);

View File

@ -1,9 +1,9 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![recursion_limit = "1024"] // for futures_util::select! #![recursion_limit = "1024"] // for futures_util::select!
#![allow(unexpected_cfgs)]
#![feature(alloc_error_handler)] #![feature(alloc_error_handler)]
#![feature(const_btree_new)] #![feature(const_btree_len)]
#![feature(panic_info_message)]
#[macro_use] #[macro_use]
extern crate alloc; extern crate alloc;

View File

@ -22,7 +22,7 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
} else { } else {
print!("unknown location"); print!("unknown location");
} }
if let Some(message) = info.message() { if let Some(message) = info.message().as_str() {
println!(": {}", message); println!(": {}", message);
} else { } else {
println!(""); println!("");
@ -61,7 +61,7 @@ fn soft_panic(info: &core::panic::PanicInfo) -> ! {
} else { } else {
error!("panic at unknown location"); error!("panic at unknown location");
} }
if let Some(message) = info.message() { if let Some(message) = info.message().as_str() {
error!("panic message: {}", message); error!("panic message: {}", message);
} }
let timer = GlobalTimer::start(); let timer = GlobalTimer::start();

View File

@ -792,6 +792,7 @@ pub mod drtio {
id: u32, id: u32,
destination: u8, destination: u8,
run: bool, run: bool,
timestamp: u64,
) -> Result<(), Error> { ) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact( let reply = aux_transact(
@ -803,6 +804,7 @@ pub mod drtio {
source: 0, source: 0,
destination: destination, destination: destination,
run: run, run: run,
timestamp,
}, },
timer, timer,
) )

View File

@ -100,12 +100,22 @@ pub async fn load(
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
run: bool, run: bool,
timestamp: u64,
) -> Result<(), Error> { ) -> Result<(), Error> {
if let Some(subkernel) = SUBKERNELS.async_lock().await.get_mut(&id) { if let Some(subkernel) = SUBKERNELS.async_lock().await.get_mut(&id) {
if subkernel.state != SubkernelState::Uploaded { if subkernel.state != SubkernelState::Uploaded {
return Err(Error::IncorrectState); return Err(Error::IncorrectState);
} }
drtio::subkernel_load(aux_mutex, routing_table, timer, id, subkernel.destination, run).await?; drtio::subkernel_load(
aux_mutex,
routing_table,
timer,
id,
subkernel.destination,
run,
timestamp,
)
.await?;
if run { if run {
subkernel.state = SubkernelState::Running; subkernel.state = SubkernelState::Running;
} }

View File

@ -15,7 +15,6 @@ build_zynq = { path = "../libbuild_zynq" }
[dependencies] [dependencies]
log = { version = "0.4", default-features = false } log = { version = "0.4", default-features = false }
core_io = { version = "0.1", features = ["collections"] }
cslice = "0.3" cslice = "0.3"
embedded-hal = "0.2" embedded-hal = "0.2"

View File

@ -1,10 +1,10 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![feature(alloc_error_handler, try_trait, never_type, panic_info_message)] #![feature(alloc_error_handler, never_type)]
#![allow(unexpected_cfgs)]
#[macro_use] #[macro_use]
extern crate log; extern crate log;
extern crate core_io;
extern crate cslice; extern crate cslice;
extern crate embedded_hal; extern crate embedded_hal;
@ -150,7 +150,7 @@ fn process_aux_packet(
analyzer: &mut Analyzer, analyzer: &mut Analyzer,
kernel_manager: &mut KernelManager, kernel_manager: &mut KernelManager,
router: &mut Router, router: &mut Router,
) -> Result<(), drtioaux::Error> { ) -> Result<(), drtioaux::Error<!>> {
// In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels, // In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels,
// and u16 otherwise; hence the `as _` conversion. // and u16 otherwise; hence the `as _` conversion.
match packet { match packet {
@ -826,6 +826,7 @@ fn process_aux_packet(
destination: _destination, destination: _destination,
id, id,
run, run,
timestamp,
} => { } => {
forward!( forward!(
router, router,
@ -844,7 +845,7 @@ fn process_aux_packet(
// cannot run kernel while DDMA is running // cannot run kernel while DDMA is running
succeeded = false; succeeded = false;
} else { } else {
succeeded |= kernel_manager.run(source, id).is_ok(); succeeded |= kernel_manager.run(source, id, timestamp).is_ok();
} }
} }
router.send( router.send(
@ -1458,7 +1459,7 @@ pub fn panic_fmt(info: &core::panic::PanicInfo) -> ! {
} else { } else {
print!("unknown location"); print!("unknown location");
} }
if let Some(message) = info.message() { if let Some(message) = info.message().as_str() {
println!(": {}", message); println!(": {}", message);
} else { } else {
println!(""); println!("");

View File

@ -191,7 +191,7 @@ impl Repeater {
} }
} }
fn recv_aux_timeout(&self, timeout: u32, timer: &mut GlobalTimer) -> Result<drtioaux::Packet, drtioaux::Error> { fn recv_aux_timeout(&self, timeout: u32, timer: &mut GlobalTimer) -> Result<drtioaux::Packet, drtioaux::Error<!>> {
let max_time = timer.get_time() + Milliseconds(timeout.into()); let max_time = timer.get_time() + Milliseconds(timeout.into());
loop { loop {
if !rep_link_rx_up(self.repno) { if !rep_link_rx_up(self.repno) {
@ -216,7 +216,7 @@ impl Repeater {
rank: u8, rank: u8,
self_destination: u8, self_destination: u8,
timer: &mut GlobalTimer, timer: &mut GlobalTimer,
) -> Result<(), drtioaux::Error> { ) -> Result<(), drtioaux::Error<!>> {
self.aux_send(request)?; self.aux_send(request)?;
loop { loop {
let reply = self.recv_aux_timeout(200, timer)?; let reply = self.recv_aux_timeout(200, timer)?;
@ -242,14 +242,14 @@ impl Repeater {
Ok(()) Ok(())
} }
pub fn aux_send(&self, request: &drtioaux::Packet) -> Result<(), drtioaux::Error> { pub fn aux_send(&self, request: &drtioaux::Packet) -> Result<(), drtioaux::Error<!>> {
if self.state != RepeaterState::Up { if self.state != RepeaterState::Up {
return Err(drtioaux::Error::LinkDown); return Err(drtioaux::Error::LinkDown);
} }
drtioaux::send(self.auxno, request) drtioaux::send(self.auxno, request)
} }
pub fn sync_tsc(&self, timer: &mut GlobalTimer) -> Result<(), drtioaux::Error> { pub fn sync_tsc(&self, timer: &mut GlobalTimer) -> Result<(), drtioaux::Error<!>> {
if self.state != RepeaterState::Up { if self.state != RepeaterState::Up {
return Ok(()); return Ok(());
} }
@ -275,7 +275,7 @@ impl Repeater {
destination: u8, destination: u8,
hops: &[u8; drtio_routing::MAX_HOPS], hops: &[u8; drtio_routing::MAX_HOPS],
timer: &mut GlobalTimer, timer: &mut GlobalTimer,
) -> Result<(), drtioaux::Error> { ) -> Result<(), drtioaux::Error<!>> {
if self.state != RepeaterState::Up { if self.state != RepeaterState::Up {
return Ok(()); return Ok(());
} }
@ -299,14 +299,14 @@ impl Repeater {
&self, &self,
routing_table: &drtio_routing::RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: &mut GlobalTimer, timer: &mut GlobalTimer,
) -> Result<(), drtioaux::Error> { ) -> Result<(), drtioaux::Error<!>> {
for i in 0..drtio_routing::DEST_COUNT { for i in 0..drtio_routing::DEST_COUNT {
self.set_path(i as u8, &routing_table.0[i], timer)?; self.set_path(i as u8, &routing_table.0[i], timer)?;
} }
Ok(()) Ok(())
} }
pub fn set_rank(&self, rank: u8, timer: &mut GlobalTimer) -> Result<(), drtioaux::Error> { pub fn set_rank(&self, rank: u8, timer: &mut GlobalTimer) -> Result<(), drtioaux::Error<!>> {
if self.state != RepeaterState::Up { if self.state != RepeaterState::Up {
return Ok(()); return Ok(());
} }
@ -318,7 +318,7 @@ impl Repeater {
Ok(()) Ok(())
} }
pub fn rtio_reset(&self, timer: &mut GlobalTimer) -> Result<(), drtioaux::Error> { pub fn rtio_reset(&self, timer: &mut GlobalTimer) -> Result<(), drtioaux::Error<!>> {
let repno = self.repno as usize; let repno = self.repno as usize;
unsafe { unsafe {
(csr::DRTIOREP[repno].reset_write)(1); (csr::DRTIOREP[repno].reset_write)(1);
@ -361,11 +361,11 @@ impl Repeater {
) { ) {
} }
pub fn sync_tsc(&self, _timer: &mut GlobalTimer) -> Result<(), drtioaux::Error> { pub fn sync_tsc(&self, _timer: &mut GlobalTimer) -> Result<(), drtioaux::Error<!>> {
Ok(()) Ok(())
} }
pub fn rtio_reset(&self, _timer: &mut GlobalTimer) -> Result<(), drtioaux::Error> { pub fn rtio_reset(&self, _timer: &mut GlobalTimer) -> Result<(), drtioaux::Error<!>> {
Ok(()) Ok(())
} }
} }

View File

@ -129,7 +129,7 @@ impl Router {
_routing_table: &drtio_routing::RoutingTable, _routing_table: &drtio_routing::RoutingTable,
_rank: u8, _rank: u8,
_destination: u8, _destination: u8,
) -> Result<(), drtioaux::Error> { ) -> Result<(), drtioaux::Error<!>> {
#[cfg(has_drtio_routing)] #[cfg(has_drtio_routing)]
{ {
let destination = packet.routable_destination(); let destination = packet.routable_destination();

View File

@ -1,18 +1,21 @@
use alloc::{collections::BTreeMap, use alloc::{
collections::BTreeMap,
format, format,
string::{String, ToString}, string::{String, ToString},
vec::Vec}; vec::Vec,
use core::{option::NoneError, slice, str}; };
use core::{slice, str};
use core_io::{Error as IoError, Write};
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, Error as IoError, ProtoWrite, Write};
use ksupport::{eh_artiq, kernel, rpc}; use ksupport::{eh_artiq, kernel, rpc};
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},
pl::csr}; pl::csr,
};
use libboard_zynq::{time::Milliseconds, timer::GlobalTimer}; use libboard_zynq::{time::Milliseconds, timer::GlobalTimer};
use libcortex_a9::sync_channel::Receiver; use libcortex_a9::sync_channel::Receiver;
use log::warn; use log::warn;
@ -52,6 +55,7 @@ enum KernelState {
}, },
} }
#[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
Load(String), Load(String),
@ -65,14 +69,8 @@ pub enum Error {
DmaError(DmaError), DmaError(DmaError),
} }
impl From<NoneError> for Error { impl<T> From<IoError<T>> for Error {
fn from(_: NoneError) -> Error { fn from(_value: IoError<T>) -> Error {
Error::KernelNotFound
}
}
impl From<IoError> for Error {
fn from(_value: IoError) -> Error {
Error::SubkernelIoError Error::SubkernelIoError
} }
} }
@ -89,8 +87,8 @@ impl From<()> for Error {
} }
} }
impl From<drtioaux::Error> for Error { impl<T> From<drtioaux::Error<T>> for Error {
fn from(_value: drtioaux::Error) -> Error { fn from(_value: drtioaux::Error<T>) -> Error {
Error::DrtioError Error::DrtioError
} }
} }
@ -222,7 +220,10 @@ impl MessageManager {
} }
} }
pub fn get_outgoing_slice(&mut self, data_slice: &mut [u8; MASTER_PAYLOAD_MAX_SIZE]) -> Option<SliceMeta> { pub fn get_outgoing_slice(
&mut self,
data_slice: &mut [u8; MASTER_PAYLOAD_MAX_SIZE],
) -> Option<SliceMeta> {
if self.out_state != OutMessageState::MessageBeingSent { if self.out_state != OutMessageState::MessageBeingSent {
return None; return None;
} }
@ -303,7 +304,13 @@ impl<'a> Manager<'_> {
} }
} }
pub fn add(&mut self, id: u32, status: PayloadStatus, data: &[u8], data_len: usize) -> Result<(), Error> { pub fn add(
&mut self,
id: u32,
status: PayloadStatus,
data: &[u8],
data_len: usize,
) -> Result<(), Error> {
let kernel = match self.kernels.get_mut(&id) { let kernel = match self.kernels.get_mut(&id) {
Some(kernel) => { Some(kernel) => {
if kernel.complete || status.is_first() { if kernel.complete || status.is_first() {
@ -316,7 +323,7 @@ impl<'a> Manager<'_> {
complete: false, complete: false,
}, },
); );
self.kernels.get_mut(&id)? self.kernels.get_mut(&id).ok_or(Error::KernelNotFound)?
} else { } else {
kernel kernel
} }
@ -329,7 +336,7 @@ impl<'a> Manager<'_> {
complete: false, complete: false,
}, },
); );
self.kernels.get_mut(&id)? self.kernels.get_mut(&id).ok_or(Error::KernelNotFound)?
} }
}; };
kernel.library.extend(&data[0..data_len]); kernel.library.extend(&data[0..data_len]);
@ -349,7 +356,7 @@ impl<'a> Manager<'_> {
} }
} }
pub fn run(&mut self, source: u8, id: u32) -> Result<(), Error> { pub fn run(&mut self, source: u8, id: u32, timestamp: u64) -> Result<(), Error> {
if self.session.kernel_state != KernelState::Loaded || self.session.id != id { if self.session.kernel_state != KernelState::Loaded || self.session.id != id {
self.load(id)?; self.load(id)?;
} }
@ -359,6 +366,7 @@ impl<'a> Manager<'_> {
csr::cri_con::selected_write(2); csr::cri_con::selected_write(2);
} }
rtio::at_mu(timestamp as i64);
self.control.tx.send(kernel::Message::StartRequest); self.control.tx.send(kernel::Message::StartRequest);
Ok(()) Ok(())
} }
@ -373,10 +381,15 @@ impl<'a> Manager<'_> {
if !self.running() { if !self.running() {
return; return;
} }
self.session.messages.handle_incoming(status, id, length, slice); self.session
.messages
.handle_incoming(status, id, length, slice);
} }
pub fn message_get_slice(&mut self, slice: &mut [u8; MASTER_PAYLOAD_MAX_SIZE]) -> Option<SliceMeta> { pub fn message_get_slice(
&mut self,
slice: &mut [u8; MASTER_PAYLOAD_MAX_SIZE],
) -> Option<SliceMeta> {
if !self.running() { if !self.running() {
return None; return None;
} }
@ -395,15 +408,19 @@ impl<'a> Manager<'_> {
if self.session.id == id && self.session.kernel_state == KernelState::Loaded { if self.session.id == id && self.session.kernel_state == KernelState::Loaded {
return Ok(()); return Ok(());
} }
if !self.kernels.get(&id)?.complete { if !self.kernels.get(&id).ok_or(Error::KernelNotFound)?.complete {
return Err(Error::KernelNotFound); return Err(Error::KernelNotFound);
} }
self.session = Session::new(id); self.session = Session::new(id);
self.control.restart(); self.control.restart();
self.control self.control.tx.send(kernel::Message::LoadRequest(
.tx self.kernels
.send(kernel::Message::LoadRequest(self.kernels.get(&id)?.library.clone())); .get(&id)
.ok_or(Error::KernelNotFound)?
.library
.clone(),
));
let reply = self.control.rx.recv(); let reply = self.control.rx.recv();
match reply { match reply {
kernel::Message::LoadCompleted => Ok(()), kernel::Message::LoadCompleted => Ok(()),
@ -415,7 +432,10 @@ impl<'a> Manager<'_> {
} }
} }
pub fn exception_get_slice(&mut self, data_slice: &mut [u8; MASTER_PAYLOAD_MAX_SIZE]) -> SliceMeta { pub fn exception_get_slice(
&mut self,
data_slice: &mut [u8; MASTER_PAYLOAD_MAX_SIZE],
) -> SliceMeta {
match self.session.last_exception.as_mut() { match self.session.last_exception.as_mut() {
Some(exception) => exception.get_slice_master(data_slice), Some(exception) => exception.get_slice_master(data_slice),
None => SliceMeta { None => SliceMeta {
@ -569,7 +589,14 @@ impl<'a> Manager<'_> {
} }
} }
match self.process_kern_message(router, routing_table, rank, destination, dma_manager, timer) { match self.process_kern_message(
router,
routing_table,
rank,
destination,
dma_manager,
timer,
) {
Ok(true) => { Ok(true) => {
self.last_finished = Some(SubkernelFinished { self.last_finished = Some(SubkernelFinished {
id: self.session.id, id: self.session.id,
@ -612,7 +639,9 @@ impl<'a> Manager<'_> {
for (i, (status, exception_source)) in self.session.subkernels_finished.iter().enumerate() { for (i, (status, exception_source)) in self.session.subkernels_finished.iter().enumerate() {
if *status == id { if *status == id {
if exception_source.is_none() { if exception_source.is_none() {
self.control.tx.send(kernel::Message::SubkernelAwaitFinishReply); self.control
.tx
.send(kernel::Message::SubkernelAwaitFinishReply);
self.session.kernel_state = KernelState::Running; self.session.kernel_state = KernelState::Running;
self.session.subkernels_finished.swap_remove(i); self.session.subkernels_finished.swap_remove(i);
} else { } else {
@ -640,15 +669,26 @@ impl<'a> Manager<'_> {
if self.session.kernel_state == KernelState::SubkernelAwaitLoad { if self.session.kernel_state == KernelState::SubkernelAwaitLoad {
self.control self.control
.tx .tx
.send(kernel::Message::SubkernelLoadRunReply { succeeded: succeeded }); .send(kernel::Message::SubkernelLoadRunReply {
succeeded: succeeded,
});
self.session.kernel_state = KernelState::Running; self.session.kernel_state = KernelState::Running;
} else { } else {
warn!("received unsolicited SubkernelLoadRunReply"); warn!("received unsolicited SubkernelLoadRunReply");
} }
} }
pub fn remote_subkernel_finished(&mut self, id: u32, with_exception: bool, exception_source: u8) { pub fn remote_subkernel_finished(
let exception_src = if with_exception { Some(exception_source) } else { None }; &mut self,
id: u32,
with_exception: bool,
exception_source: u8,
) {
let exception_src = if with_exception {
Some(exception_source)
} else {
None
};
self.session.subkernels_finished.push((id, exception_src)); self.session.subkernels_finished.push((id, exception_src));
} }
@ -661,18 +701,19 @@ impl<'a> Manager<'_> {
rank: u8, rank: u8,
self_destination: u8, self_destination: u8,
) { ) {
if let KernelState::SubkernelRetrievingException { destination } = self.session.kernel_state { if let KernelState::SubkernelRetrievingException { destination } = self.session.kernel_state
{
self.session self.session
.external_exception .external_exception
.as_mut() .as_mut()
.unwrap() .unwrap()
.extend_from_slice(exception_data); .extend_from_slice(exception_data);
if last { if last {
self.control self.control.tx.send(kernel::Message::SubkernelError(
.tx kernel::SubkernelStatus::Exception(
.send(kernel::Message::SubkernelError(kernel::SubkernelStatus::Exception(
self.session.external_exception.take().unwrap(), self.session.external_exception.take().unwrap(),
))); ),
));
self.session.kernel_state = KernelState::Running; self.session.kernel_state = KernelState::Running;
} else { } else {
/* fetch another slice */ /* fetch another slice */
@ -707,7 +748,12 @@ impl<'a> Manager<'_> {
dma_manager.cleanup(router, rank, self_destination, routing_table); dma_manager.cleanup(router, rank, self_destination, routing_table);
return Ok(true); return Ok(true);
} }
kernel::Message::KernelException(exceptions, stack_pointers, backtrace, async_errors) => { kernel::Message::KernelException(
exceptions,
stack_pointers,
backtrace,
async_errors,
) => {
error!("exception in kernel"); error!("exception in kernel");
for exception in exceptions { for exception in exceptions {
error!("{:?}", exception.unwrap()); error!("{:?}", exception.unwrap());
@ -716,12 +762,21 @@ impl<'a> Manager<'_> {
error!("backtrace: {:?}", backtrace); error!("backtrace: {:?}", backtrace);
let buf: Vec<u8> = Vec::new(); let buf: Vec<u8> = Vec::new();
let mut writer = Cursor::new(buf); let mut writer = Cursor::new(buf);
match write_exception(&mut writer, exceptions, stack_pointers, backtrace, async_errors) { match write_exception(
&mut writer,
exceptions,
stack_pointers,
backtrace,
async_errors,
) {
Ok(()) => (), Ok(()) => (),
Err(_) => error!("Error writing exception data"), Err(_) => error!("Error writing exception data"),
} }
self.kernel_stop(); self.kernel_stop();
return Err(Error::KernelException(Sliceable::new(0, writer.into_inner()))); return Err(Error::KernelException(Sliceable::new(
0,
writer.into_inner(),
)));
} }
kernel::Message::CachePutRequest(key, value) => { kernel::Message::CachePutRequest(key, value) => {
self.cache.insert(key, value); self.cache.insert(key, value);
@ -769,11 +824,13 @@ impl<'a> Manager<'_> {
let max_time = timer.get_time() + Milliseconds(10000); let max_time = timer.get_time() + Milliseconds(10000);
self.session.kernel_state = match self.session.kernel_state { self.session.kernel_state = match self.session.kernel_state {
// if we are still waiting for the traces to be uploaded, extend the state by timeout // if we are still waiting for the traces to be uploaded, extend the state by timeout
KernelState::DmaPendingPlayback { id, timestamp } => KernelState::DmaPendingAwait { KernelState::DmaPendingPlayback { id, timestamp } => {
KernelState::DmaPendingAwait {
id: id, id: id,
timestamp: timestamp, timestamp: timestamp,
max_time: max_time, max_time: max_time,
}, }
}
_ => KernelState::DmaAwait { max_time: max_time }, _ => KernelState::DmaAwait { max_time: max_time },
}; };
} }
@ -812,6 +869,7 @@ impl<'a> Manager<'_> {
id, id,
destination: sk_destination, destination: sk_destination,
run, run,
timestamp,
} => { } => {
self.session.kernel_state = KernelState::SubkernelAwaitLoad; self.session.kernel_state = KernelState::SubkernelAwaitLoad;
router.route( router.route(
@ -820,6 +878,7 @@ impl<'a> Manager<'_> {
destination: sk_destination, destination: sk_destination,
id: id, id: id,
run: run, run: run,
timestamp,
}, },
routing_table, routing_table,
rank, rank,
@ -844,7 +903,10 @@ impl<'a> Manager<'_> {
)); ));
} }
_ => { _ => {
unexpected!("unexpected message from core1 while kernel was running: {:?}", reply); unexpected!(
"unexpected message from core1 while kernel was running: {:?}",
reply
);
} }
} }
Ok(false) Ok(false)
@ -862,9 +924,9 @@ impl<'a> Manager<'_> {
KernelState::MsgAwait { max_time, id, tags } => { KernelState::MsgAwait { max_time, id, tags } => {
if let Some(max_time) = *max_time { if let Some(max_time) = *max_time {
if timer.get_time() > max_time { if timer.get_time() > max_time {
self.control self.control.tx.send(kernel::Message::SubkernelError(
.tx kernel::SubkernelStatus::Timeout,
.send(kernel::Message::SubkernelError(kernel::SubkernelStatus::Timeout)); ));
self.session.kernel_state = KernelState::Running; self.session.kernel_state = KernelState::Running;
return Ok(()); return Ok(());
} }
@ -872,7 +934,9 @@ impl<'a> Manager<'_> {
if let Some(message) = self.session.messages.get_incoming(*id) { if let Some(message) = self.session.messages.get_incoming(*id) {
self.control self.control
.tx .tx
.send(kernel::Message::SubkernelMsgRecvReply { count: message.count }); .send(kernel::Message::SubkernelMsgRecvReply {
count: message.count,
});
let tags = tags.clone(); let tags = tags.clone();
self.session.kernel_state = KernelState::Running; self.session.kernel_state = KernelState::Running;
self.pass_message_to_kernel(&message, tags, timer) self.pass_message_to_kernel(&message, tags, timer)
@ -894,9 +958,9 @@ impl<'a> Manager<'_> {
KernelState::SubkernelAwaitFinish { max_time, id } => { KernelState::SubkernelAwaitFinish { max_time, id } => {
if let Some(max_time) = *max_time { if let Some(max_time) = *max_time {
if timer.get_time() > max_time { if timer.get_time() > max_time {
self.control self.control.tx.send(kernel::Message::SubkernelError(
.tx kernel::SubkernelStatus::Timeout,
.send(kernel::Message::SubkernelError(kernel::SubkernelStatus::Timeout)); ));
self.session.kernel_state = KernelState::Running; self.session.kernel_state = KernelState::Running;
return Ok(()); return Ok(());
} }
@ -922,7 +986,12 @@ impl<'a> Manager<'_> {
} }
} }
fn pass_message_to_kernel(&mut self, message: &Message, tags: Vec<u8>, timer: &GlobalTimer) -> Result<(), Error> { fn pass_message_to_kernel(
&mut self,
message: &Message,
tags: Vec<u8>,
timer: &GlobalTimer,
) -> Result<(), Error> {
let mut reader = Cursor::new(&message.data); let mut reader = Cursor::new(&message.data);
let mut current_tags: &[u8] = &tags; let mut current_tags: &[u8] = &tags;
let mut i = message.count; let mut i = message.count;
@ -933,29 +1002,50 @@ impl<'a> Manager<'_> {
}; };
let mut exception: Option<Sliceable> = None; let mut exception: Option<Sliceable> = None;
let mut unexpected: Option<String> = None; let mut unexpected: Option<String> = None;
let remaining_tags = rpc::recv_return(&mut reader, current_tags, slot, &mut |size| { let remaining_tags =
rpc::recv_return(&mut reader, current_tags, slot, &mut |size| -> Result<
_,
Error,
> {
if size == 0 { if size == 0 {
0 as *mut () Ok(0 as *mut ())
} else { } else {
self.control.tx.send(kernel::Message::RpcRecvReply(Ok(size))); self.control
.tx
.send(kernel::Message::RpcRecvReply(Ok(size)));
match recv_w_timeout(&mut self.control.rx, timer, 100) { match recv_w_timeout(&mut self.control.rx, timer, 100) {
Ok(kernel::Message::RpcRecvRequest(slot)) => slot, Ok(kernel::Message::RpcRecvRequest(slot)) => Ok(slot),
Ok(kernel::Message::KernelException(exceptions, stack_pointers, backtrace, async_errors)) => { Ok(kernel::Message::KernelException(
exceptions,
stack_pointers,
backtrace,
async_errors,
)) => {
let buf: Vec<u8> = Vec::new(); let buf: Vec<u8> = Vec::new();
let mut writer = Cursor::new(buf); let mut writer = Cursor::new(buf);
match write_exception(&mut writer, exceptions, stack_pointers, backtrace, async_errors) { match write_exception(
&mut writer,
exceptions,
stack_pointers,
backtrace,
async_errors,
) {
Ok(()) => { Ok(()) => {
exception = Some(Sliceable::new(0, writer.into_inner())); exception = Some(Sliceable::new(0, writer.into_inner()));
} }
Err(_) => { Err(_) => {
unexpected = Some("Error writing exception data".to_string()); unexpected =
Some("Error writing exception data".to_string());
} }
}; };
0 as *mut () Ok(0 as *mut ())
} }
other => { other => {
unexpected = Some(format!("expected nested value slot from kernel CPU, not {:?}", other)); unexpected = Some(format!(
0 as *mut () "expected nested value slot from kernel CPU, not {:?}",
other
));
Ok(0 as *mut ())
} }
} }
} }
@ -1001,8 +1091,9 @@ where
writer.write_u32(u32::MAX)?; writer.write_u32(u32::MAX)?;
writer.write_u32(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 {
str::from_utf8(unsafe { slice::from_raw_parts(exception.message.as_ptr(), exception.message.len()) }) slice::from_raw_parts(exception.message.as_ptr(), exception.message.len())
})
.unwrap() .unwrap()
.replace( .replace(
"{rtio_channel_info:0}", "{rtio_channel_info:0}",