beginnings of cramium hardware target integration

the hardware driver is compile-clean, but everything is just
a stub. But at least we have the API thunks laid bare which
gives us a roadmap for the next steps.
This commit is contained in:
bunnie 2024-06-06 17:58:11 +08:00
parent bc626f46aa
commit a5e45a2078
5 changed files with 100 additions and 20 deletions

View file

@ -21,17 +21,23 @@ rkyv = { version = "0.4.3", default-features = false, features = [
] }
susres = { package = "xous-api-susres", version = "0.9.57" }
modals = { path = "../modals" }
keyboard = { path = "../keyboard", features = ["inject-api"] }
keyboard = { path = "../keyboard", features = ["inject-api"], optional = true }
bitfield = "0.13.2"
vcell = "0.1.3"
xous-semver = "0.1.2"
utralib = { version = "0.1.24", optional = true, default-features = false }
trng = { path = "../trng" }
xous-usb-hid = { git = "https://github.com/betrusted-io/xous-usb-hid.git", branch="main" }
embedded-time = "0.12.1" # required by the keyboard interface
packed_struct = { version = "0.10", default-features = false } # used by the xous-usb-hid crate
num_enum = { version = "0.5", default-features = false } # used by the xous-usb-hid crate
xous-usb-hid = { git = "https://github.com/betrusted-io/xous-usb-hid.git", branch = "main" }
embedded-time = "0.12.1" # required by the keyboard interface
packed_struct = { version = "0.10", default-features = false } # used by the xous-usb-hid crate
num_enum = { version = "0.5", default-features = false } # used by the xous-usb-hid crate
cramium-hal = { path = "../../libs/cramium-hal", features = [
"std",
], optional = true }
cram-hal-service = { path = "../cram-hal-service", optional = true }
# Mass storage support
usbd_scsi = { path = "../../libs/mass-storage/usbd_scsi", optional = true }
@ -54,9 +60,15 @@ rand = "0.8.5"
rand_chacha = "0.3.1"
[features]
precursor = ["utralib/precursor", "utralib/std"]
hosted = ["utralib/hosted", "utralib/std"]
renode = ["utralib/renode", "utralib/std"]
precursor = ["utralib/precursor", "utralib/std", "keyboard"]
hosted = ["utralib/hosted", "utralib/std", "keyboard"]
renode = ["utralib/renode", "utralib/std", "keyboard"]
cramium-soc = [
"utralib/cramium-soc",
"utralib/std",
"cramium-hal",
"cram-hal-service",
]
minimal = ["mass-storage"]
mass-storage = ["usbd_scsi", "usbd_mass_storage"]
mjolnir = [

View file

@ -78,6 +78,7 @@ pub(crate) enum Opcode {
/// Handle the USB interrupt
UsbIrqHandler = 2048,
/// Suspend/resume callback
#[cfg(any(feature = "renode", feature = "precursor", feature = "hosted"))]
SuspendResume = 2049,
/// Exits the server
Quit = 4096,

View file

@ -3,7 +3,7 @@
#[cfg(not(target_os = "xous"))]
mod main_hosted;
#[cfg(any(feature = "precursor", feature = "renode"))]
#[cfg(any(feature = "precursor", feature = "renode", feature = "cramium-soc"))]
mod main_hw;
mod api;
@ -21,10 +21,10 @@ mod spinal_udc;
use packed_struct::PackedStructSlice;
#[cfg(any(feature = "precursor", feature = "renode"))]
use spinal_udc::*;
#[cfg(all(any(feature = "precursor", feature = "renode"), feature = "mass-storage"))]
#[cfg(all(any(feature = "precursor", feature = "renode", feature = "corigine"), feature = "mass-storage"))]
mod apps_block_device;
#[cfg(any(feature = "precursor", feature = "renode"))]
#[cfg(any(feature = "precursor", feature = "renode", feature = "cramium-soc"))]
mod hid;
#[cfg(not(target_os = "xous"))]
mod hosted;
@ -36,7 +36,7 @@ use hosted::*;
use num_traits::*;
fn main() -> ! {
#[cfg(any(feature = "precursor", feature = "renode"))]
#[cfg(any(feature = "precursor", feature = "renode", feature = "cramium-soc"))]
main_hw::main_hw();
#[cfg(not(target_os = "xous"))]
main_hosted::main_hosted();

View file

@ -4,18 +4,27 @@ use std::collections::VecDeque;
use std::convert::TryInto;
use std::sync::Arc;
#[cfg(not(feature = "minimal"))]
#[cfg(all(not(feature = "minimal"), any(feature = "cramium-soc")))]
use cram_hal_service::api::KeyMap;
#[cfg(feature = "cramium-soc")]
use cram_hal_service::keyboard;
use cramium_hal::usb::driver::CorigineUsb;
#[cfg(all(not(feature = "minimal"), any(feature = "renode", feature = "precursor")))]
use keyboard::KeyMap;
use num_traits::*;
#[cfg(feature = "cramium-soc")]
use packed_struct::PackedStructSlice;
use usb_device::class_prelude::*;
use usb_device::prelude::*;
use usb_device_xous::KeyboardLedsReport;
use usb_device_xous::UsbDeviceType;
use usbd_serial::SerialPort;
#[cfg(any(feature = "precursor", feature = "renode"))]
use utralib::generated::*;
use utralib::AtomicCsr;
use xous::{msg_blocking_scalar_unpack, msg_scalar_unpack};
use xous_ipc::Buffer;
#[cfg(not(feature = "minimal"))]
#[cfg(all(not(feature = "minimal"), any(feature = "precursor", feature = "renode")))]
use xous_semver::SemVer;
use xous_usb_hid::device::fido::RawFido;
use xous_usb_hid::device::fido::RawFidoConfig;
@ -79,16 +88,21 @@ pub(crate) fn main_hw() -> ! {
let xns = xous_names::XousNames::new().unwrap();
let usbdev_sid = xns.register_name(api::SERVER_NAME_USB_DEVICE, None).expect("can't register server");
let cid = xous::connect(usbdev_sid).expect("couldn't create suspend callback connection");
log::trace!("registered with NS -- {:?}", usbdev_sid);
#[cfg(not(feature = "minimal"))]
#[cfg(any(feature = "precursor", feature = "renode"))]
let llio = llio::Llio::new(&xns);
let tt = ticktimer_server::Ticktimer::new().unwrap();
#[cfg(not(feature = "minimal"))]
let native_kbd = keyboard::Keyboard::new(&xns).unwrap();
#[cfg(not(feature = "minimal"))]
#[cfg(all(not(feature = "minimal"), any(feature = "precursor", feature = "renode")))]
let serial_number = format!("{:x}", llio.soc_dna().unwrap());
#[cfg(not(feature = "minimal"))]
#[cfg(all(not(feature = "minimal"), any(feature = "cramium-soc")))]
let serial_number = format!("TODO!!"); // implement in cramium-hal once we have a serial number API
#[cfg(all(not(feature = "minimal"), any(feature = "precursor", feature = "renode")))]
{
let minimum_ver = SemVer { maj: 0, min: 9, rev: 8, extra: 20, commit: None };
let soc_ver = llio.soc_gitrev().unwrap();
@ -161,6 +175,7 @@ pub(crate) fn main_hw() -> ! {
}
// Allocate memory range and CSR for sharing between all the views.
#[cfg(any(feature = "precursor", feature = "renode"))]
let usb = xous::syscall::map_memory(
xous::MemoryAddress::new(utralib::HW_USBDEV_MEM),
None,
@ -168,6 +183,7 @@ pub(crate) fn main_hw() -> ! {
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map USB device memory range");
#[cfg(any(feature = "precursor", feature = "renode"))]
let csr = xous::syscall::map_memory(
xous::MemoryAddress::new(utra::usbdev::HW_USBDEV_BASE),
None,
@ -176,33 +192,78 @@ pub(crate) fn main_hw() -> ! {
)
.expect("couldn't map USB CSR range");
#[cfg(feature = "cramium-soc")]
let usb_mapping = xous::syscall::map_memory(
xous::MemoryAddress::new(cramium_hal::usb::utra::CORIGINE_USB_BASE),
None,
cramium_hal::usb::utra::CORIGINE_USB_LEN,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't reserve register pages");
#[cfg(feature = "cramium-soc")]
let ifram_range = xous::syscall::map_memory(
xous::MemoryAddress::new(cramium_hal::usb::driver::CRG_UDC_MEMBASE),
xous::MemoryAddress::new(cramium_hal::usb::driver::CRG_UDC_MEMBASE), // make P & V addresses line up
cramium_hal::usb::driver::CRG_IFRAM_PAGES * 0x1000,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't allocate IFRAM pages");
#[cfg(feature = "cramium-soc")]
let usb = AtomicCsr::new(usb_mapping.as_ptr() as *mut u32);
// Notes:
// - Most drivers would `Box()` the hardware management structure to make sure the compiler doesn't move
// its location. However, we can't do this here because we are trying to maintain compatibility with
// another crate that implements the USB stack which can't handle Box'd structures.
// - It is safe to call `.init()` repeatedly because within `init()` we have an atomic bool that tracks
// if the interrupt handler has been hooked, and ignores further requests to hook it.
#[cfg(any(feature = "renode", feature = "precursor"))]
let usb_fidokbd_dev = SpinalUsbDevice::new(usbdev_sid, usb.clone(), csr.clone());
#[cfg(feature = "cramium-soc")]
// safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses
let usb_fidokbd_dev = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) };
#[cfg(any(feature = "renode", feature = "precursor"))]
usb_fidokbd_dev.init();
#[cfg(any(feature = "renode", feature = "precursor"))]
let mut usbmgmt = usb_fidokbd_dev.get_iface();
#[cfg(feature = "cramium-soc")]
// safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses
let mut usbmgmt = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) };
// before doing any allocs, clone a copy of the hardware access structure so we can build a second
// view into the hardware with only FIDO descriptors
#[cfg(any(feature = "renode", feature = "precursor"))]
let usb_fido_dev: SpinalUsbDevice = SpinalUsbDevice::new(usbdev_sid, usb.clone(), csr.clone());
#[cfg(feature = "cramium-soc")]
// safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses
let usb_fido_dev = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) };
#[cfg(any(feature = "renode", feature = "precursor"))]
usb_fido_dev.init();
// do the same thing for mass storage
#[cfg(feature = "mass-storage")]
#[cfg(all(feature = "mass-storage", any(feature = "precursor", feature = "renode")))]
let ums_dev = SpinalUsbDevice::new(usbdev_sid, usb.clone(), csr.clone());
#[cfg(all(feature = "mass-storage", any(feature = "cramium-soc")))]
// safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses
let ums_dev = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) };
#[cfg(feature = "mass-storage")]
#[cfg(any(feature = "renode", feature = "precursor"))]
ums_dev.init();
#[cfg(any(feature = "renode", feature = "precursor"))]
let serial_dev = SpinalUsbDevice::new(usbdev_sid, usb.clone(), csr.clone());
#[cfg(feature = "cramium-soc")]
// safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses
let serial_dev = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) };
#[cfg(any(feature = "renode", feature = "precursor"))]
serial_dev.init();
#[cfg(feature = "cramium-soc")]
usbmgmt.init(); // for the cramium target, call init only once via management structure
// track which view is visible on the device core
#[cfg(not(feature = "minimal"))]
let mut view = Views::FidoWithKbd;
// register a suspend/resume listener
let cid = xous::connect(usbdev_sid).expect("couldn't create suspend callback connection");
#[cfg(any(feature = "renode", feature = "precursor", feature = "hosted"))]
let mut susres = susres::Susres::new(None, &xns, api::Opcode::SuspendResume as u32, cid)
.expect("couldn't create suspend/resume object");
@ -282,7 +343,12 @@ pub(crate) fn main_hw() -> ! {
const TRNG_BACKOFF_MS: u32 = 1;
const TRNG_BACKOFF_MAX_MS: u32 = 1000; // cap on how far we backoff the polling rate
#[cfg(any(feature = "renode", feature = "precursor"))]
let usb_hidv2_dev = SpinalUsbDevice::new(usbdev_sid, usb.clone(), csr.clone());
#[cfg(feature = "cramium-soc")]
// safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses
let usb_hidv2_dev = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) };
let hidv2_alloc = UsbBusAllocator::new(usb_hidv2_dev);
let mut hidv2 = hid::AppHID::new(
@ -468,6 +534,7 @@ pub(crate) fn main_hw() -> ! {
.unwrap();
xous::return_scalar(msg.sender, 0).unwrap();
}),
#[cfg(any(feature = "renode", feature = "precursor", feature = "hosted"))]
Some(Opcode::SuspendResume) => msg_scalar_unpack!(msg, token, _, _, _, {
usbmgmt.xous_suspend();
susres.suspend_until_resume(token).expect("couldn't execute suspend/resume");

View file

@ -1,7 +1,7 @@
#![allow(unused_imports)]
pub use xous_usb_hid::page::Keyboard as UsbKeyCode;
#[cfg(any(feature="precursor", feature="renode"))]
#[cfg(any(feature = "precursor", feature = "renode", feature = "cramium-soc"))]
#[rustfmt::skip]
pub fn char_to_hid_code_us101(key: char) -> Vec<UsbKeyCode> {
let mut code = vec![];
@ -120,7 +120,7 @@ pub fn char_to_hid_code_us101(key: char) -> Vec<UsbKeyCode> {
}
/// auto-generated using tools/kbd_layout.py + `usb kbdtest` on device for dvorak layout on US101
#[cfg(any(feature="precursor", feature="renode"))]
#[cfg(any(feature = "precursor", feature = "renode", feature = "cramium-soc"))]
#[rustfmt::skip]
pub fn char_to_hid_code_dvorak(key: char) -> Vec<UsbKeyCode> {
let mut code = vec![];