Skip to content

Commit

Permalink
capsules: i2c_master: Use I2CMux
Browse files Browse the repository at this point in the history
To allow an I2C bus to have devices created by the board and still be
exposed to userspace let's convert the I2CMasterDriver to use an
I2CDevice instead of a I2C hardware.

This allows muxing an I2C bus with both userspace and devices in the
kernel.

This commit also adds a I2CMasterDriverComponent to help in creating the
I2CMasterDriver.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
  • Loading branch information
alistair23 committed Feb 19, 2024
1 parent 1a605d6 commit 9f1436a
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 95 deletions.
34 changes: 11 additions & 23 deletions boards/apollo3/lora_things_plus/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ use capsules_core::virtualizers::virtual_alarm::MuxAlarm;
use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
use components::bme280::Bme280Component;
use components::ccs811::Ccs811Component;
use components::i2c::I2CMasterDriverComponent;
use kernel::capabilities;
use kernel::component::Component;
use kernel::hil::i2c::I2CMaster;
use kernel::hil::led::LedHigh;
use kernel::hil::spi::SpiMaster;
use kernel::hil::time::Counter;
Expand Down Expand Up @@ -125,8 +125,10 @@ struct LoRaThingsPlus {
>,
gpio: &'static capsules_core::gpio::GPIO<'static, apollo3::gpio::GpioPin<'static>>,
console: &'static capsules_core::console::Console<'static>,
i2c_master:
&'static capsules_core::i2c_master::I2CMasterDriver<'static, apollo3::iom::Iom<'static>>,
i2c_master: &'static capsules_core::i2c_master::I2CMasterDriver<
'static,
capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
>,
external_spi_controller: &'static capsules_core::spi_controller::Spi<
'static,
capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
Expand Down Expand Up @@ -234,7 +236,6 @@ unsafe fn setup() -> (

// initialize capabilities
let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);

let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES));

Expand Down Expand Up @@ -327,29 +328,16 @@ unsafe fn setup() -> (
PROCESS_PRINTER = Some(process_printer);

// Init the I2C device attached via Qwiic
let i2c_master_buffer = static_init!(
[u8; capsules_core::i2c_master::BUFFER_LENGTH],
[0; capsules_core::i2c_master::BUFFER_LENGTH]
);
let i2c_master = static_init!(
capsules_core::i2c_master::I2CMasterDriver<'static, apollo3::iom::Iom<'static>>,
capsules_core::i2c_master::I2CMasterDriver::new(
&peripherals.iom0,
i2c_master_buffer,
board_kernel.create_grant(
capsules_core::i2c_master::DRIVER_NUM,
&memory_allocation_cap
)
)
);

peripherals.iom0.set_master_client(i2c_master);
peripherals.iom0.enable();

let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.iom0, None).finalize(
components::i2c_mux_component_static!(apollo3::iom::Iom<'static>),
);

let i2c_master =
I2CMasterDriverComponent::new(mux_i2c, board_kernel, capsules_core::i2c_master::DRIVER_NUM)
.finalize(components::i2c_master_component_static!(
apollo3::iom::Iom<'static>
));

let bme280 = Bme280Component::new(mux_i2c, 0x77).finalize(
components::bme280_component_static!(apollo3::iom::Iom<'static>),
);
Expand Down
35 changes: 12 additions & 23 deletions boards/apollo3/redboard_artemis_nano/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ use capsules_core::virtualizers::virtual_alarm::MuxAlarm;
use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
use components::bme280::Bme280Component;
use components::ccs811::Ccs811Component;
use components::i2c::I2CMasterDriverComponent;
use kernel::capabilities;
use kernel::component::Component;
use kernel::hil::i2c::I2CMaster;
use kernel::hil::led::LedHigh;
use kernel::hil::time::Counter;
use kernel::platform::{KernelResources, SyscallDriverLookup};
Expand Down Expand Up @@ -97,8 +97,10 @@ struct RedboardArtemisNano {
>,
gpio: &'static capsules_core::gpio::GPIO<'static, apollo3::gpio::GpioPin<'static>>,
console: &'static capsules_core::console::Console<'static>,
i2c_master:
&'static capsules_core::i2c_master::I2CMasterDriver<'static, apollo3::iom::Iom<'static>>,
i2c_master: &'static capsules_core::i2c_master::I2CMasterDriver<
'static,
capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
>,
spi_controller: &'static capsules_core::spi_controller::Spi<
'static,
capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
Expand Down Expand Up @@ -196,7 +198,6 @@ unsafe fn setup() -> (

// initialize capabilities
let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);

let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES));

Expand Down Expand Up @@ -289,27 +290,15 @@ unsafe fn setup() -> (
PROCESS_PRINTER = Some(process_printer);

// Init the I2C device attached via Qwiic
let i2c_master_buffer = static_init!(
[u8; capsules_core::i2c_master::BUFFER_LENGTH],
[0; capsules_core::i2c_master::BUFFER_LENGTH]
let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.iom2, None).finalize(
components::i2c_mux_component_static!(apollo3::iom::Iom<'static>),
);
let i2c_master = static_init!(
capsules_core::i2c_master::I2CMasterDriver<'static, apollo3::iom::Iom<'static>>,
capsules_core::i2c_master::I2CMasterDriver::new(
&peripherals.iom2,
i2c_master_buffer,
board_kernel.create_grant(
capsules_core::i2c_master::DRIVER_NUM,
&memory_allocation_cap
)
)
);

peripherals.iom2.set_master_client(i2c_master);
peripherals.iom2.enable();

let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.iom2, None)
.finalize(components::i2c_mux_component_static!(apollo3::iom::Iom));
let i2c_master =
I2CMasterDriverComponent::new(mux_i2c, board_kernel, capsules_core::i2c_master::DRIVER_NUM)
.finalize(components::i2c_master_component_static!(
apollo3::iom::Iom<'static>
));

let bme280 = Bme280Component::new(mux_i2c, 0x77)
.finalize(components::bme280_component_static!(apollo3::iom::Iom));
Expand Down
72 changes: 72 additions & 0 deletions boards/components/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,24 @@ macro_rules! i2c_master_slave_component_static {
};};
}

#[macro_export]
macro_rules! i2c_master_component_static {
($I:ty $(,)?) => {{
let i2c_master_buffer = kernel::static_buf!([u8; capsules_core::i2c_master::BUFFER_LENGTH]);
let i2c_device =
kernel::static_buf!(capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, $I>);

let driver = kernel::static_buf!(
capsules_core::i2c_master::I2CMasterDriver<
'static,
capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, $I>,
>
);

(i2c_device, i2c_master_buffer, driver)
};};
}

pub struct I2CMuxComponent<
I: 'static + i2c::I2CMaster<'static>,
S: 'static + i2c::SMBusMaster<'static> = NoSMBus,
Expand Down Expand Up @@ -173,3 +191,57 @@ impl<I: 'static + i2c::I2CMasterSlave<'static>> Component for I2CMasterSlaveDriv
i2c_master_slave_driver
}
}

pub struct I2CMasterDriverComponent<I: 'static + i2c::I2CMaster<'static>> {
i2c_mux: &'static MuxI2C<'static, I>,
board_kernel: &'static kernel::Kernel,
driver_num: usize,
}

impl<I: 'static + i2c::I2CMaster<'static>> I2CMasterDriverComponent<I> {
pub fn new(
i2c: &'static MuxI2C<'static, I>,
board_kernel: &'static kernel::Kernel,
driver_num: usize,
) -> Self {
I2CMasterDriverComponent {
i2c_mux: i2c,
board_kernel,
driver_num,
}
}
}

impl<I: 'static + i2c::I2CMaster<'static>> Component for I2CMasterDriverComponent<I> {
type StaticInput = (
&'static mut MaybeUninit<I2CDevice<'static, I>>,
&'static mut MaybeUninit<[u8; capsules_core::i2c_master::BUFFER_LENGTH]>,
&'static mut MaybeUninit<
capsules_core::i2c_master::I2CMasterDriver<'static, I2CDevice<'static, I>>,
>,
);
type Output =
&'static capsules_core::i2c_master::I2CMasterDriver<'static, I2CDevice<'static, I>>;

fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);

let userspace_device = static_buffer.0.write(I2CDevice::new(self.i2c_mux, 0x00));
let i2c_master_buffer = static_buffer
.1
.write([0; capsules_core::i2c_master::BUFFER_LENGTH]);

let i2c_master = static_buffer
.2
.write(capsules_core::i2c_master::I2CMasterDriver::new(
userspace_device,
i2c_master_buffer,
self.board_kernel.create_grant(self.driver_num, &grant_cap),
));

userspace_device.set_client(i2c_master);
i2c::I2CDevice::enable(userspace_device);

i2c_master
}
}
30 changes: 12 additions & 18 deletions boards/opentitan/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::pinmux_layout::BoardPinmuxLayout;
use capsules_aes_gcm::aes_gcm;
use capsules_core::virtualizers::virtual_aes_ccm;
use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
use components::i2c::I2CMasterDriverComponent;
use earlgrey::chip::EarlGreyDefaultPeripherals;
use earlgrey::chip_config::EarlGreyConfig;
use earlgrey::pinmux_config::EarlGreyPinmuxConfig;
Expand All @@ -28,7 +29,6 @@ use kernel::component::Component;
use kernel::hil;
use kernel::hil::entropy::Entropy32;
use kernel::hil::hasher::Hasher;
use kernel::hil::i2c::I2CMaster;
use kernel::hil::led::LedHigh;
use kernel::hil::rng::Rng;
use kernel::hil::symmetric_encryption::AES128;
Expand Down Expand Up @@ -186,8 +186,10 @@ struct EarlGrey {
'static,
capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
>,
i2c_master:
&'static capsules_core::i2c_master::I2CMasterDriver<'static, lowrisc::i2c::I2c<'static>>,
i2c_master: &'static capsules_core::i2c_master::I2CMasterDriver<
'static,
capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, lowrisc::i2c::I2c<'static>>,
>,
spi_controller: &'static capsules_core::spi_controller::Spi<
'static,
capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
Expand Down Expand Up @@ -522,23 +524,15 @@ unsafe fn setup() -> (
)
.finalize(components::hmac_component_static!(lowrisc::hmac::Hmac, 32));

let i2c_master_buffer = static_init!(
[u8; capsules_core::i2c_master::BUFFER_LENGTH],
[0; capsules_core::i2c_master::BUFFER_LENGTH]
);
let i2c_master = static_init!(
capsules_core::i2c_master::I2CMasterDriver<'static, lowrisc::i2c::I2c<'static>>,
capsules_core::i2c_master::I2CMasterDriver::new(
&peripherals.i2c0,
i2c_master_buffer,
board_kernel.create_grant(
capsules_core::i2c_master::DRIVER_NUM,
&memory_allocation_cap
)
)
let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.i2c0, None).finalize(
components::i2c_mux_component_static!(lowrisc::i2c::I2c<'static>),
);

peripherals.i2c0.set_master_client(i2c_master);
let i2c_master =
I2CMasterDriverComponent::new(mux_i2c, board_kernel, capsules_core::i2c_master::DRIVER_NUM)
.finalize(components::i2c_master_component_static!(
lowrisc::i2c::I2c<'static>
));

//SPI
let mux_spi = components::spi::SpiMuxComponent::new(&peripherals.spi_host0).finalize(
Expand Down
39 changes: 16 additions & 23 deletions boards/raspberry_pi_pico/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,16 @@
#![cfg_attr(not(doc), no_main)]
#![deny(missing_docs)]

use core::arch::global_asm;

use capsules_core::i2c_master::I2CMasterDriver;
use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
use components::date_time_component_static;
use components::gpio::GpioComponent;
use components::i2c::I2CMasterDriverComponent;
use components::led::LedsComponent;
use core::arch::global_asm;
use enum_primitive::cast::FromPrimitive;
use kernel::component::Component;
use kernel::debug;
use kernel::hil::gpio::{Configure, FloatingState};
use kernel::hil::i2c::I2CMaster;
use kernel::hil::led::LedHigh;
use kernel::hil::usb::Client;
use kernel::platform::{KernelResources, SyscallDriverLookup};
Expand Down Expand Up @@ -88,7 +86,10 @@ pub struct RaspberryPiPico {
led: &'static capsules_core::led::LedDriver<'static, LedHigh<'static, RPGpioPin<'static>>, 1>,
adc: &'static capsules_core::adc::AdcVirtualized<'static>,
temperature: &'static TemperatureDriver,
i2c: &'static capsules_core::i2c_master::I2CMasterDriver<'static, I2c<'static, 'static>>,
i2c: &'static capsules_core::i2c_master::I2CMasterDriver<
'static,
capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, I2c<'static, 'static>>,
>,

date_time:
&'static capsules_extra::date_time::DateTimeCapsule<'static, rp2040::rtc::Rtc<'static>>,
Expand Down Expand Up @@ -521,24 +522,16 @@ pub unsafe fn main() {
sda_pin.set_floating_state(FloatingState::PullUp);
scl_pin.set_floating_state(FloatingState::PullUp);

let i2c_master_buffer = static_init!(
[u8; capsules_core::i2c_master::BUFFER_LENGTH],
[0; capsules_core::i2c_master::BUFFER_LENGTH]
);
let i2c0 = &peripherals.i2c0;
let i2c = static_init!(
I2CMasterDriver<I2c<'static, 'static>>,
I2CMasterDriver::new(
i2c0,
i2c_master_buffer,
board_kernel.create_grant(
capsules_core::i2c_master::DRIVER_NUM,
&memory_allocation_capability
),
)
);
i2c0.init(10 * 1000);
i2c0.set_master_client(i2c);
let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.i2c0, None)
.finalize(components::i2c_mux_component_static!(I2c<'static, 'static>));

let i2c =
I2CMasterDriverComponent::new(mux_i2c, board_kernel, capsules_core::i2c_master::DRIVER_NUM)
.finalize(components::i2c_master_component_static!(
I2c<'static, 'static>
));

peripherals.i2c0.init(10 * 1000);

let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES)
.finalize(components::round_robin_component_static!(NUM_PROCS));
Expand Down
Loading

0 comments on commit 9f1436a

Please sign in to comment.