Merge #259 259: examples-features/ctap: Ensure the stack is created r=jrvanwhy a=alistair23 Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Co-authored-by: Alistair Francis <alistair.francis@wdc.com>
diff --git a/Cargo.toml b/Cargo.toml index caeae02..99543d9 100644 --- a/Cargo.toml +++ b/Cargo.toml
@@ -29,6 +29,7 @@ p256 = { version = "0.5.0" , default-features = false, features = ["arithmetic", "ecdsa", "ecdsa-core"] } subtle = { version = "2.3.0", default-features = false, features = ["i128"] } generic-array = { version = "0.14.3" } +libmctp = { version = "0.1.0" } # We need to override this to allow builds for targets that don't support atomics. # Once a version newer then 0.4.11 is released we can update to use that.
diff --git a/Makefile b/Makefile index e32decb..81829e2 100644 --- a/Makefile +++ b/Makefile
@@ -18,6 +18,7 @@ @echo " - nrf52" @echo " - imxrt1050" @echo " - apollo3" + @echo " - stm32f3discovery" @echo @echo "Run 'make setup' to setup Rust to build libtock-rs." @echo "Run 'make <board>' to build libtock-rs for that board" @@ -132,6 +133,14 @@ flash-nrf52840: PLATFORM=nrf52840 cargo run $(release) --target=thumbv7em-none-eabi --example $(EXAMPLE) $(features) +.PHONY: stm32f3discovery +stm32f3discovery: + PLATFORM=stm32f3discovery cargo build $(release) --target=thumbv7em-none-eabi --examples $(features) + +.PHONY: flash-stm32f3discovery +flash-stm32f3discovery: + PLATFORM=stm32f3discovery cargo run $(release) --target=thumbv7em-none-eabi --example $(EXAMPLE) $(features) + .PHONY: opentitan opentitan: PLATFORM=opentitan cargo build $(release) --target=riscv32imc-unknown-none-elf --examples $(features)
diff --git a/boards/layout_stm32f3discovery.ld b/boards/layout_stm32f3discovery.ld new file mode 100644 index 0000000..9368003 --- /dev/null +++ b/boards/layout_stm32f3discovery.ld
@@ -0,0 +1,11 @@ +/* Layout for the stm32f3discovery board, usable by the examples in this repository. */ + +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x08020040, LENGTH = 0x00020000 + SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 48K +} + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout_generic.ld
diff --git a/examples/libmctp.rs b/examples/libmctp.rs new file mode 100644 index 0000000..8623665 --- /dev/null +++ b/examples/libmctp.rs
@@ -0,0 +1,105 @@ +#![no_std] +/// This is a example of a MCTP master device +use libmctp::smbus::{MCTPSMBusContext, VendorIDFormat}; +use libtock::i2c_master::I2cBuffer; +use libtock::println; +use libtock::result::TockResult; +use libtock::syscalls; + +libtock_core::stack_size! {0x800} + +// The address of this device +const MY_ID: u8 = 0x23; +const DEST_ID: u8 = 0x10; +// Support vendor defined protocol 0x7E +const MSG_TYPES: [u8; 1] = [0x7E]; +// Specify a PCI vendor ID that we support +const VENDOR_IDS: [libmctp::smbus::VendorIDFormat; 1] = [VendorIDFormat { + // PCI Vendor ID + format: 0x00, + // PCI VID + data: 0x1414, + // Extra data + numeric_value: 4, +}]; + +#[libtock::main] +async fn main() -> TockResult<()> { + let mut drivers = libtock::retrieve_drivers()?; + drivers.console.create_console(); + println!("Starting libmctp example"); + let i2c_driver = drivers.i2c.init_driver()?; + + // Check that I2C exists + if i2c_driver.check_present().is_err() { + println!("No I2C device, yielding"); + loop { + unsafe { syscalls::raw::yieldk() }; + } + } + println!("Found the I2C device"); + + println!("Setting callback"); + let mut callback = |_, _| { + println!("I2C Callback"); + }; + + let _subscription = i2c_driver.subscribe(&mut callback)?; + println!("Creating MCTP SMBus Context"); + let ctx = MCTPSMBusContext::new(MY_ID, &MSG_TYPES, &VENDOR_IDS); + + let mut buf: [u8; 32] = [0; 32]; + + println!("Creating the request"); + let len = ctx + .get_request() + .get_vendor_defined_message_support(0xB, 0, &mut buf); + + println!("Creating master write buffer"); + let mut master_write_buffer = I2cBuffer::default(); + // Skip the first byte, as that is the destination address + for (i, d) in buf[1..].iter().enumerate() { + master_write_buffer[i] = *d; + } + let dest_buffer = i2c_driver.init_buffer(&mut master_write_buffer)?; + println!(" done"); + + let _ = i2c_driver.write(DEST_ID as usize, len.unwrap()); + + unsafe { syscalls::raw::yieldk() }; + + // Read 4 bytes for the SMBus header + let _ = i2c_driver.read(DEST_ID as usize, 4); + + unsafe { syscalls::raw::yieldk() }; + + // Copy into a temp buffer + let mut temp_buffer = [0; libtock::hmac::DEST_BUFFER_SIZE]; + dest_buffer.read_bytes(&mut temp_buffer[1..4]); + + // Determine the full length + let bytes = ctx.get_length(&temp_buffer).unwrap(); + + // Read the full packet. The slave will re-send the data, so do + // a full read + let _ = i2c_driver.read(DEST_ID as usize, bytes - 1); + + unsafe { syscalls::raw::yieldk() }; + + // Copy in the full packet, with space for the destination address + dest_buffer.read_bytes(&mut temp_buffer[1..bytes - 1]); + + // Set the destination address as this isn't filled in the buffer from + // the kernel + temp_buffer[0] = DEST_ID << 1; + + // Decode the response + let ret = ctx.decode_packet(&temp_buffer[0..bytes]); + + // Print the outcome of the decode + println!("ret: {:?}", ret); + + loop { + unsafe { syscalls::raw::yieldk() }; + } +}
diff --git a/examples/ninedof.rs b/examples/ninedof.rs new file mode 100644 index 0000000..ec0724c --- /dev/null +++ b/examples/ninedof.rs
@@ -0,0 +1,23 @@ +#![no_std] + +use libtock::println; +use libtock::result::TockResult; +use libtock::timer::Duration; + +libtock_core::stack_size! {0x800} + +#[libtock::main] +async fn main() -> TockResult<()> { + let mut drivers = libtock::retrieve_drivers()?; + + let mut timer_driver = drivers.timer.create_timer_driver(); + let timer_driver = timer_driver.activate()?; + drivers.console.create_console(); + + loop { + println!("Mag: {}\n", drivers.ninedof.read_magnetometer()?); + println!("Accel: {}\n", drivers.ninedof.read_acceleration()?); + println!("Gyro: {}\n", drivers.ninedof.read_gyroscope()?); + timer_driver.sleep(Duration::from_ms(500)).await?; + } +}
diff --git a/src/drivers.rs b/src/drivers.rs index 7df124b..8604691 100644 --- a/src/drivers.rs +++ b/src/drivers.rs
@@ -4,7 +4,8 @@ use crate::ctap::CtapDriverFactory; use crate::gpio::GpioDriverFactory; use crate::hmac::HmacDriverFactory; -use crate::i2c::I2cDriverFactory; +use crate::i2c_master::I2cDriverFactory; +use crate::i2c_master_slave::I2cMSDriverFactory; use crate::leds::LedsDriverFactory; use crate::result::OtherError; use crate::result::TockError; @@ -31,6 +32,7 @@ pub temperature: TemperatureDriverFactory, pub buttons: ButtonsDriverFactory, pub adc: AdcDriverFactory, + pub i2c_ms: I2cMSDriverFactory, pub i2c: I2cDriverFactory, pub rng: RngDriver, pub ble_advertising: BleAdvertisingDriverFactory, @@ -79,6 +81,7 @@ }, gpio: GpioDriverFactory, hmac: HmacDriverFactory, + i2c_ms: I2cMSDriverFactory, i2c: I2cDriverFactory, temperature: TemperatureDriverFactory, rng: RngDriver,
diff --git a/src/i2c_master.rs b/src/i2c_master.rs new file mode 100644 index 0000000..55f2ee1 --- /dev/null +++ b/src/i2c_master.rs
@@ -0,0 +1,112 @@ +use crate::callback::CallbackSubscription; +use crate::callback::Consumer; +use crate::result::TockResult; +use crate::syscalls; +use core::marker::PhantomData; +use core::ops::Deref; +use core::ops::DerefMut; +use libtock_core::shared_memory::SharedMemory; + +const DRIVER_NUMBER: usize = 0x20003; + +pub const BUFFER_SIZE: usize = 64; + +mod command_nr { + pub const CHECK_PRESENT: usize = 0; + pub const WRITE: usize = 1; + pub const READ: usize = 2; + pub const WRITE_READ: usize = 3; +} + +mod subscribe_nr { + pub const SUBSCRIBE_CALLBACK: usize = 1; +} + +mod allow_nr { + pub const BUFFER: usize = 1; +} + +#[non_exhaustive] +pub struct I2cDriverFactory; + +impl I2cDriverFactory { + pub fn init_driver(&mut self) -> TockResult<I2cDriver> { + let i2c = I2cDriver { + lifetime: PhantomData, + }; + Ok(i2c) + } +} + +struct I2cEventConsumer; + +impl<CB: FnMut(usize, usize)> Consumer<CB> for I2cEventConsumer { + fn consume(callback: &mut CB, _: usize, _: usize, _: usize) { + callback(0, 0); + } +} + +pub struct I2cBuffer { + buffer: [u8; BUFFER_SIZE], +} + +impl Default for I2cBuffer { + fn default() -> Self { + I2cBuffer { + buffer: [0; BUFFER_SIZE], + } + } +} + +impl Deref for I2cBuffer { + type Target = [u8; BUFFER_SIZE]; + + fn deref(&self) -> &Self::Target { + &self.buffer + } +} + +impl DerefMut for I2cBuffer { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.buffer + } +} + +pub struct I2cDriver<'a> { + lifetime: PhantomData<&'a ()>, +} + +impl<'a> I2cDriver<'a> { + pub fn init_buffer(&self, buffer: &'a mut I2cBuffer) -> TockResult<SharedMemory> { + syscalls::allow(DRIVER_NUMBER, allow_nr::BUFFER, &mut buffer.buffer).map_err(Into::into) + } + + pub fn subscribe<CB: FnMut(usize, usize)>( + &self, + callback: &'a mut CB, + ) -> TockResult<CallbackSubscription> { + syscalls::subscribe::<I2cEventConsumer, _>( + DRIVER_NUMBER, + subscribe_nr::SUBSCRIBE_CALLBACK, + callback, + ) + .map_err(Into::into) + } + + pub fn check_present(&self) -> TockResult<usize> { + syscalls::command(DRIVER_NUMBER, command_nr::CHECK_PRESENT, 0, 0).map_err(Into::into) + } + + pub fn write(&self, address: usize, length: usize) -> TockResult<usize> { + syscalls::command(DRIVER_NUMBER, command_nr::WRITE, address, length).map_err(Into::into) + } + + pub fn read(&self, address: usize, length: usize) -> TockResult<usize> { + syscalls::command(DRIVER_NUMBER, command_nr::READ, address, length).map_err(Into::into) + } + + pub fn write_read(&self, address: usize, length: usize) -> TockResult<usize> { + syscalls::command(DRIVER_NUMBER, command_nr::WRITE_READ, address, length) + .map_err(Into::into) + } +}
diff --git a/src/i2c.rs b/src/i2c_master_slave.rs similarity index 80% rename from src/i2c.rs rename to src/i2c_master_slave.rs index 8256af8..0e3cce6 100644 --- a/src/i2c.rs +++ b/src/i2c_master_slave.rs
@@ -35,38 +35,38 @@ } #[non_exhaustive] -pub struct I2cDriverFactory; +pub struct I2cMSDriverFactory; -impl I2cDriverFactory { - pub fn init_driver(&mut self) -> TockResult<I2cDriver> { - let i2c = I2cDriver { +impl I2cMSDriverFactory { + pub fn init_driver(&mut self) -> TockResult<I2cMSDriver> { + let i2c_ms = I2cMSDriver { lifetime: PhantomData, }; - Ok(i2c) + Ok(i2c_ms) } } -struct I2cEventConsumer; +struct I2cMSEventConsumer; -impl<CB: FnMut(usize, usize)> Consumer<CB> for I2cEventConsumer { +impl<CB: FnMut(usize, usize)> Consumer<CB> for I2cMSEventConsumer { fn consume(callback: &mut CB, _: usize, _: usize, _: usize) { callback(0, 0); } } -pub struct I2cMasterWriteBuffer { +pub struct I2cMSMasterWriteBuffer { buffer: [u8; MASTER_BUFFER_SIZE], } -impl Default for I2cMasterWriteBuffer { +impl Default for I2cMSMasterWriteBuffer { fn default() -> Self { - I2cMasterWriteBuffer { + I2cMSMasterWriteBuffer { buffer: [0; MASTER_BUFFER_SIZE], } } } -impl Deref for I2cMasterWriteBuffer { +impl Deref for I2cMSMasterWriteBuffer { type Target = [u8; MASTER_BUFFER_SIZE]; fn deref(&self) -> &Self::Target { @@ -74,25 +74,25 @@ } } -impl DerefMut for I2cMasterWriteBuffer { +impl DerefMut for I2cMSMasterWriteBuffer { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buffer } } -pub struct I2cMasterReadBuffer { +pub struct I2cMSMasterReadBuffer { buffer: [u8; MASTER_BUFFER_SIZE], } -impl Default for I2cMasterReadBuffer { +impl Default for I2cMSMasterReadBuffer { fn default() -> Self { - I2cMasterReadBuffer { + I2cMSMasterReadBuffer { buffer: [0; MASTER_BUFFER_SIZE], } } } -impl Deref for I2cMasterReadBuffer { +impl Deref for I2cMSMasterReadBuffer { type Target = [u8; MASTER_BUFFER_SIZE]; fn deref(&self) -> &Self::Target { @@ -100,25 +100,25 @@ } } -impl DerefMut for I2cMasterReadBuffer { +impl DerefMut for I2cMSMasterReadBuffer { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buffer } } -pub struct I2cSlaveReadBuffer { +pub struct I2cMSSlaveReadBuffer { buffer: [u8; SLAVE_BUFFER_SIZE], } -impl Default for I2cSlaveReadBuffer { +impl Default for I2cMSSlaveReadBuffer { fn default() -> Self { - I2cSlaveReadBuffer { + I2cMSSlaveReadBuffer { buffer: [0; SLAVE_BUFFER_SIZE], } } } -impl Deref for I2cSlaveReadBuffer { +impl Deref for I2cMSSlaveReadBuffer { type Target = [u8; SLAVE_BUFFER_SIZE]; fn deref(&self) -> &Self::Target { @@ -126,25 +126,25 @@ } } -impl DerefMut for I2cSlaveReadBuffer { +impl DerefMut for I2cMSSlaveReadBuffer { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buffer } } -pub struct I2cSlaveWriteBuffer { +pub struct I2cMSSlaveWriteBuffer { buffer: [u8; SLAVE_BUFFER_SIZE], } -impl Default for I2cSlaveWriteBuffer { +impl Default for I2cMSSlaveWriteBuffer { fn default() -> Self { - I2cSlaveWriteBuffer { + I2cMSSlaveWriteBuffer { buffer: [0; SLAVE_BUFFER_SIZE], } } } -impl Deref for I2cSlaveWriteBuffer { +impl Deref for I2cMSSlaveWriteBuffer { type Target = [u8; SLAVE_BUFFER_SIZE]; fn deref(&self) -> &Self::Target { @@ -152,20 +152,20 @@ } } -impl DerefMut for I2cSlaveWriteBuffer { +impl DerefMut for I2cMSSlaveWriteBuffer { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buffer } } -pub struct I2cDriver<'a> { +pub struct I2cMSDriver<'a> { lifetime: PhantomData<&'a ()>, } -impl<'a> I2cDriver<'a> { +impl<'a> I2cMSDriver<'a> { pub fn init_master_write_buffer( &self, - buffer: &'a mut I2cMasterWriteBuffer, + buffer: &'a mut I2cMSMasterWriteBuffer, ) -> TockResult<SharedMemory> { syscalls::allow(DRIVER_NUMBER, allow_nr::MASTER_WRIE, &mut buffer.buffer) .map_err(Into::into) @@ -173,7 +173,7 @@ pub fn init_master_read_buffer( &self, - buffer: &'a mut I2cMasterReadBuffer, + buffer: &'a mut I2cMSMasterReadBuffer, ) -> TockResult<SharedMemory> { syscalls::allow(DRIVER_NUMBER, allow_nr::MASTER_READ, &mut buffer.buffer) .map_err(Into::into) @@ -181,14 +181,14 @@ pub fn init_slave_read_buffer( &self, - buffer: &'a mut I2cSlaveReadBuffer, + buffer: &'a mut I2cMSSlaveReadBuffer, ) -> TockResult<SharedMemory> { syscalls::allow(DRIVER_NUMBER, allow_nr::SLAVE_READ, &mut buffer.buffer).map_err(Into::into) } pub fn init_slave_write_buffer( &self, - buffer: &'a mut I2cSlaveWriteBuffer, + buffer: &'a mut I2cMSSlaveWriteBuffer, ) -> TockResult<SharedMemory> { syscalls::allow(DRIVER_NUMBER, allow_nr::SLAVE_WRITE, &mut buffer.buffer) .map_err(Into::into) @@ -198,7 +198,7 @@ &self, callback: &'a mut CB, ) -> TockResult<CallbackSubscription> { - syscalls::subscribe::<I2cEventConsumer, _>( + syscalls::subscribe::<I2cMSEventConsumer, _>( DRIVER_NUMBER, subscribe_nr::SUBSCRIBE_CALLBACK, callback,
diff --git a/src/lib.rs b/src/lib.rs index 619c379..6f5be5a 100644 --- a/src/lib.rs +++ b/src/lib.rs
@@ -13,7 +13,8 @@ pub mod futures; pub mod gpio; pub mod hmac; -pub mod i2c; +pub mod i2c_master; +pub mod i2c_master_slave; pub mod leds; pub mod result; pub mod rng;