Skip to content

Commit

Permalink
[opentitanlib] Add ftdi transport for voyager board
Browse files Browse the repository at this point in the history
Signed-off-by: Douglas Reis <[email protected]>
  • Loading branch information
engdoreis committed Dec 13, 2024
1 parent 4077374 commit 06cd198
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 0 deletions.
6 changes: 6 additions & 0 deletions sw/host/opentitanlib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ rust_library(
"src/app/mod.rs",
"src/app/spi.rs",
"src/backend/chip_whisperer.rs",
"src/backend/ftdi.rs",
"src/backend/hyperdebug.rs",
"src/backend/mod.rs",
"src/backend/proxy.rs",
Expand Down Expand Up @@ -181,6 +182,8 @@ rust_library(
"src/transport/dediprog/mod.rs",
"src/transport/dediprog/spi.rs",
"src/transport/errors.rs",
"src/transport/ftdi/chip.rs",
"src/transport/ftdi/mod.rs",
"src/transport/hyperdebug/c2d2.rs",
"src/transport/hyperdebug/dfu.rs",
"src/transport/hyperdebug/gpio.rs",
Expand Down Expand Up @@ -297,9 +300,12 @@ rust_library(
"@crate_index//:deser-hjson",
"@crate_index//:directories",
"@crate_index//:ecdsa",
"@crate_index//:embedded-hal",
"@crate_index//:env_logger",
"@crate_index//:erased-serde",
"@crate_index//:ftdi",
"@crate_index//:ftdi-embedded-hal",
"@crate_index//:ftdi-mpsse",
"@crate_index//:hex",
"@crate_index//:humantime",
"@crate_index//:humantime-serde",
Expand Down
1 change: 1 addition & 0 deletions sw/host/opentitanlib/src/app/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static BUILTINS: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
"/__builtin__/ti50emulator.json" => include_str!("ti50emulator.json"),
"/__builtin__/opentitan_cw310.json" => include_str!("opentitan_cw310.json"),
"/__builtin__/opentitan_cw340.json" => include_str!("opentitan_cw340.json"),
"/__builtin__/opentitan_ftdi_voyager.json" => include_str!("opentitan_ftdi_voyager.json"),
"/__builtin__/opentitan.json" => include_str!("opentitan.json"),
"/__builtin__/hyperdebug.json" => include_str!("hyperdebug.json"),
"/__builtin__/hyperdebug_chipwhisperer.json" => include_str!("hyperdebug_chipwhisperer.json"),
Expand Down
82 changes: 82 additions & 0 deletions sw/host/opentitanlib/src/app/config/opentitan_ftdi_voyager.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"includes": ["/__builtin__/opentitan.json"],
"interface": "ftdi",
"pins": [
{
"name": "RESET",
"mode": "PushPull",
"invert": false,
"alias_of": "adbus5",
"pull_mode": "None"
},
{
"name": "TRST",
"mode": "PushPull",
"level": false,
"alias_of": "adbus4",
"pull_mode": "None"
},
{
"name": "IOC0",
"alias_of": "bdbus4"
},
{
"name": "IOC1",
"alias_of": "bdbus5"
},
{
"name": "IOC2",
"alias_of": "bdbus6"
},
{
"name": "MUX_FTDI",
"alias_of": "bdbus7"
},
{
"name": "IOC8",
"alias_of": "adbus6"
},
{
"name": "IOC5",
"alias_of": "adbus7"
}
],
"spi": [
{
"name": "BOOTSTRAP"
}
],
"uarts": [
{
"name": "console",
"alias_of": "0"
},
{
"name": "dut",
"alias_of": "3"
}
],
"strappings": [
{
"name": "ROM_BOOTSTRAP",
"pins": [
{
"name": "SW_STRAP0",
"level": true
},
{
"name": "SW_STRAP1",
"level": true
},
{
"name": "SW_STRAP2",
"level": true
},
{
"name": "MUX_FTDI",
"level": true
}
]
}
]
}
14 changes: 14 additions & 0 deletions sw/host/opentitanlib/src/backend/ftdi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;

use crate::backend::BackendOpts;
use crate::transport::ftdi::chip::Chip;
use crate::transport::ftdi::Ftdi;
use crate::transport::Transport;

pub fn create<C: Chip + 'static>(_args: &BackendOpts) -> Result<Box<dyn Transport>> {
Ok(Box::new(Ftdi::<C>::new()?))
}
6 changes: 6 additions & 0 deletions sw/host/opentitanlib/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ use crate::app::config::process_config_file;
use crate::app::{TransportWrapper, TransportWrapperBuilder};
use crate::transport::chip_whisperer::board::{Cw310, Cw340};
use crate::transport::dediprog::Dediprog;
use crate::transport::ftdi::chip::Ft4232hq;
use crate::transport::hyperdebug::{
C2d2Flavor, ChipWhispererFlavor, ServoMicroFlavor, StandardFlavor, Ti50Flavor,
};
use crate::transport::{EmptyTransport, Transport};
use crate::util::parse_int::ParseInt;

mod chip_whisperer;
mod ftdi;
mod hyperdebug;
mod proxy;
mod ti50emulator;
Expand Down Expand Up @@ -131,6 +133,10 @@ pub fn create(args: &BackendOpts) -> Result<TransportWrapper> {
chip_whisperer::create::<Cw340>(args)?,
Some(Path::new("/__builtin__/opentitan_cw340.json")),
),
"ftdi" => (
ftdi::create::<Ft4232hq>(args)?,
Some(Path::new("/__builtin__/opentitan_ftdi_voyager.json")),
),
"dediprog" => {
let dediprog: Box<dyn Transport> = Box::new(Dediprog::new(
args.usb_vid,
Expand Down
24 changes: 24 additions & 0 deletions sw/host/opentitanlib/src/transport/ftdi/chip.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

pub trait Chip {
const VENDOR_ID: u16 = 0x0403;
const PRODUCT_ID: u16;

const UART_BAUD: u32 = 115200;

const INTERFACES: &'static [ftdi::Interface];
}

pub struct Ft4232hq {}

impl Chip for Ft4232hq {
const PRODUCT_ID: u16 = 0x6011;
const INTERFACES: &'static [ftdi::Interface] = &[
ftdi::Interface::A,
ftdi::Interface::B,
// ftdi::Interface::C,
ftdi::Interface::D,
];
}
120 changes: 120 additions & 0 deletions sw/host/opentitanlib/src/transport/ftdi/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use serde_annotate::Annotate;
use std::any::Any;
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::rc::Rc;

use crate::io::gpio::GpioPin;
use crate::io::spi::Target;
use crate::io::uart::Uart;
use crate::io::uart::UartError;
use crate::transport::common::uart::SerialPortUart;
use crate::transport::{
Capabilities, Capability, Transport, TransportError, TransportInterfaceType,
};
use crate::util::parse_int::ParseInt;
use serialport::SerialPortType;

use chip::Chip;
use ftdi_embedded_hal as ftdi_hal;

pub mod chip;

#[derive(Default)]
struct Inner {
spi: Option<Rc<dyn Target>>,
gpio: HashMap<String, Rc<dyn GpioPin>>,
uart: HashMap<u32, Rc<dyn Uart>>,
}

pub struct Ftdi<C: Chip> {
pub(crate) ftdi_interfaces: HashMap<ftdi::Interface, ftdi_hal::FtHal<ftdi::Device>>,
inner: RefCell<Inner>,
phantom: std::marker::PhantomData<C>,
}

impl<C: Chip> Ftdi<C> {
pub fn new() -> anyhow::Result<Self> {
let mut ftdi_interfaces = HashMap::new();
for interface in C::INTERFACES {
let device = ftdi::find_by_vid_pid(C::VENDOR_ID, C::PRODUCT_ID)
.interface(*interface)
.open()?;
ftdi_interfaces.insert(*interface, ftdi_hal::FtHal::init_freq(device, 8_000_000)?);
}

let ftdi_dev = Ftdi {
ftdi_interfaces,
inner: RefCell::default(),
phantom: std::marker::PhantomData,
};
Ok(ftdi_dev)
}

fn open_uart(&self, instance: u32) -> Result<SerialPortUart> {
let mut ports = serialport::available_ports()
.map_err(|e| UartError::EnumerationError(e.to_string()))?;

ports.retain(|port| {
if let SerialPortType::UsbPort(info) = &port.port_type {
if info.vid == C::VENDOR_ID && info.pid == C::PRODUCT_ID {
return true;
}
}
false
});

let port = ports.get(instance as usize).ok_or_else(|| {
TransportError::InvalidInstance(TransportInterfaceType::Uart, instance.to_string())
})?;

SerialPortUart::open(&port.port_name, C::UART_BAUD)
}
}

impl<C: Chip> Transport for Ftdi<C> {
fn capabilities(&self) -> Result<Capabilities> {
Ok(Capabilities::new(
Capability::SPI | Capability::GPIO | Capability::UART | Capability::UART_NONBLOCKING,
))
}

fn uart(&self, instance: &str) -> Result<Rc<dyn Uart>> {
let mut inner = self.inner.borrow_mut();
let instance = u32::from_str(instance).ok().ok_or_else(|| {
TransportError::InvalidInstance(TransportInterfaceType::Uart, instance.to_string())
})?;
let uart = match inner.uart.entry(instance) {
Entry::Vacant(v) => {
let u = v.insert(Rc::new(self.open_uart(instance)?));
Rc::clone(u)
}
Entry::Occupied(o) => Rc::clone(o.get()),
};
Ok(uart)
}

fn gpio_pin(&self, pinname: &str) -> Result<Rc<dyn GpioPin>> {
Err(TransportError::UnsupportedOperation.into())
}

fn spi(&self, _instance: &str) -> Result<Rc<dyn Target>> {
Err(TransportError::UnsupportedOperation.into())
}

fn dispatch(&self, _action: &dyn Any) -> Result<Option<Box<dyn Annotate>>> {
Err(TransportError::UnsupportedOperation.into())
}
}

/// Command for Transport::dispatch().
pub struct SetPll {}

/// Command for Transport::dispatch(). Resets the Chip whisperer board's SAM3X chip.
pub struct ResetSam3x {}
1 change: 1 addition & 0 deletions sw/host/opentitanlib/src/transport/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::io::uart::Uart;
pub mod chip_whisperer;
pub mod common;
pub mod dediprog;
pub mod ftdi;
pub mod hyperdebug;
pub mod ioexpander;
pub mod proxy;
Expand Down

0 comments on commit 06cd198

Please sign in to comment.