| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| use anyhow::{anyhow, Result}; |
| use bitflags::bitflags; |
| use erased_serde::Serialize; |
| use std::any::Any; |
| use std::path::PathBuf; |
| use std::rc::Rc; |
| use thiserror::Error; |
| |
| use crate::io::gpio::GpioPin; |
| use crate::io::spi::Target; |
| use crate::io::uart::Uart; |
| |
| pub mod cw310; |
| pub mod hyperdebug; |
| pub mod ultradebug; |
| pub mod verilator; |
| |
| bitflags! { |
| /// A bitmap of capabilities which may be provided by a transport. |
| pub struct Capability: u32 { |
| const NONE = 0x00000000; |
| const UART = 0x00000001; |
| const SPI = 0x00000002; |
| const GPIO = 0x00000004; |
| } |
| } |
| |
| /// A struct which can check that needed capability requirements are met. |
| pub struct Capabilities { |
| capabilities: Capability, |
| needed: Capability, |
| } |
| |
| impl Capabilities { |
| /// Create a new Capabilities object representing a provider of |
| /// capabilities specified by `cap`. |
| pub fn new(cap: Capability) -> Self { |
| Self { |
| capabilities: cap, |
| needed: Capability::NONE, |
| } |
| } |
| |
| /// Request the capabilities specified by `cap`. |
| pub fn request(&mut self, cap: Capability) -> &mut Self { |
| self.needed |= cap; |
| self |
| } |
| |
| /// Checks that the requested capabilities are provided. |
| pub fn ok(&self) -> Result<()> { |
| if self.capabilities & self.needed != self.needed { |
| Err(anyhow!( |
| "Requested capabilities {:?}, but capabilities {:?} are supplied", |
| self.needed, |
| self.capabilities |
| )) |
| } else { |
| Ok(()) |
| } |
| } |
| } |
| |
| /// Errors related to the SPI interface and SPI transactions. |
| #[derive(Error, Debug)] |
| pub enum TransportError { |
| #[error("This transport does not support {0} instance {1}")] |
| InvalidInstance(&'static str, String), |
| #[error("This transport does not support the requested operation")] |
| UnsupportedOperation, |
| } |
| |
| /// A transport object is a factory for the low-level interfaces provided |
| /// by a given communications backend. |
| pub trait Transport { |
| /// Returns a `Capabilities` object to check the capabilities of this |
| /// transport object. |
| fn capabilities(&self) -> Capabilities; |
| |
| /// Returns a SPI [`Target`] implementation. |
| fn spi(&self, _instance: &str) -> Result<Rc<dyn Target>> { |
| unimplemented!(); |
| } |
| /// Returns a [`Uart`] implementation. |
| fn uart(&self, _instance: &str) -> Result<Rc<dyn Uart>> { |
| unimplemented!(); |
| } |
| /// Returns a [`GpioPin`] implementation. |
| fn gpio_pin(&self, _instance: &str) -> Result<Rc<dyn GpioPin>> { |
| unimplemented!(); |
| } |
| /// Invoke non-standard functionality of some Transport implementations. |
| fn dispatch(&self, _action: &dyn Any) -> Result<Option<Box<dyn Serialize>>> { |
| Err(TransportError::UnsupportedOperation.into()) |
| } |
| } |
| |
| /// Used by Transport implementations dealing with emulated OpenTitan |
| /// chips, allowing e.g. more efficient direct means of programming |
| /// emulated flash storage. (As opposed to running an actual |
| /// bootloater on the emulated target, which would receive data via |
| /// SPI to be flashed.) |
| pub struct Bootstrap { |
| pub image_path: PathBuf, |
| } |
| |
| /// An `EmptyTransport` provides no communications backend. |
| pub struct EmptyTransport; |
| |
| impl Transport for EmptyTransport { |
| fn capabilities(&self) -> Capabilities { |
| Capabilities::new(Capability::NONE) |
| } |
| } |
| |
| #[cfg(test)] |
| pub mod tests { |
| use super::*; |
| |
| #[test] |
| fn test_capabilities_met() -> Result<()> { |
| let mut cap = Capabilities::new(Capability::UART | Capability::SPI); |
| assert!(cap.request(Capability::UART).ok().is_ok()); |
| Ok(()) |
| } |
| |
| #[test] |
| fn test_capabilities_not_met() -> Result<()> { |
| let mut cap = Capabilities::new(Capability::UART | Capability::SPI); |
| assert!(cap.request(Capability::GPIO).ok().is_err()); |
| Ok(()) |
| } |
| } |