diff --git a/examples/rt685s-evk/Cargo.lock b/examples/rt685s-evk/Cargo.lock index 9f65e26e..a88ad7bf 100644 --- a/examples/rt685s-evk/Cargo.lock +++ b/examples/rt685s-evk/Cargo.lock @@ -32,25 +32,6 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "bincode" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" -dependencies = [ - "bincode_derive", - "unty", -] - -[[package]] -name = "bincode_derive" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" -dependencies = [ - "virtue", -] - [[package]] name = "bit-register" version = "0.1.0" @@ -85,26 +66,6 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f798d2d157e547aa99aab0967df39edd0b70307312b6f8bd2848e6abe40896e0" -[[package]] -name = "bitfield" -version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ba6517c6b0f2bf08be60e187ab64b038438f22dd755614d8fe4d4098c46419" -dependencies = [ - "bitfield-macros", -] - -[[package]] -name = "bitfield-macros" -version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48d6ace212fdf1b45fd6b566bb40808415344642b76c3224c07c8df9da81e97" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "bitfield-struct" version = "0.12.1" @@ -156,20 +117,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfu-service" -version = "0.1.0" -dependencies = [ - "defmt 0.3.100", - "embassy-futures", - "embassy-sync", - "embassy-time", - "embedded-cfu-protocol", - "embedded-services", - "fw-update-interface", - "heapless", -] - [[package]] name = "cordyceps" version = "0.3.4" @@ -326,17 +273,6 @@ dependencies = [ "defmt 0.3.100", ] -[[package]] -name = "device-driver" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e4547bd66511372d2a38ac3c1b2892c7ebf83cf0d5411c3406e496c85a1d96" -dependencies = [ - "defmt 0.3.100", - "embedded-io 0.6.1", - "embedded-io-async 0.6.1", -] - [[package]] name = "document-features" version = "0.2.12" @@ -358,7 +294,6 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0641612053b2f34fc250bb63f6630ae75de46e02ade7f457268447081d709ce" dependencies = [ - "defmt 1.1.0", "embassy-futures", "embassy-hal-internal 0.4.0", "embassy-sync", @@ -460,7 +395,7 @@ dependencies = [ "embedded-mcu-hal", "embedded-storage", "fixed", - "itertools 0.11.0", + "itertools", "mimxrt600-fcb 0.2.2", "mimxrt633s-pac", "mimxrt685s-pac", @@ -534,26 +469,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "embedded-batteries-async" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3bf0e4be67770cfc31f1cea8b73baf98c0baf2c57d6bd8c3a4c315acb1d8bd4" -dependencies = [ - "bitfield-struct", - "embedded-batteries", - "embedded-hal 1.0.0", -] - -[[package]] -name = "embedded-cfu-protocol" -version = "0.2.0" -source = "git+https://github.com/OpenDevicePartnership/embedded-cfu#523a83919c3535e8ccead031d80b715d77395f81" -dependencies = [ - "defmt 0.3.100", - "embedded-io-async 0.6.1", -] - [[package]] name = "embedded-crc-macros" version = "1.0.0" @@ -604,9 +519,6 @@ name = "embedded-io" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" -dependencies = [ - "defmt 0.3.100", -] [[package]] name = "embedded-io" @@ -680,17 +592,6 @@ dependencies = [ "embedded-storage", ] -[[package]] -name = "embedded-usb-pd" -version = "0.1.0" -source = "git+https://github.com/OpenDevicePartnership/embedded-usb-pd#071f163395e3eaea3094b817e3d943ab7265be3d" -dependencies = [ - "bincode", - "bitfield 0.19.4", - "defmt 0.3.100", - "embedded-hal-async", -] - [[package]] name = "espi-device" version = "0.1.0" @@ -740,14 +641,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" -[[package]] -name = "fw-update-interface" -version = "0.1.0" -dependencies = [ - "defmt 0.3.100", - "embedded-services", -] - [[package]] name = "generator" version = "0.8.8" @@ -842,15 +735,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -1079,29 +963,6 @@ dependencies = [ "embedded-hal-async", ] -[[package]] -name = "power-policy-interface" -version = "0.1.0" -dependencies = [ - "defmt 0.3.100", - "embassy-sync", - "embedded-batteries-async", - "embedded-services", -] - -[[package]] -name = "power-policy-service" -version = "0.1.0" -dependencies = [ - "defmt 0.3.100", - "embassy-futures", - "embassy-sync", - "embassy-time", - "embedded-services", - "heapless", - "power-policy-interface", -] - [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -1169,22 +1030,18 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" name = "rt685s-evk-example" version = "0.1.0" dependencies = [ - "cfu-service", "cortex-m", "cortex-m-rt", "crc", "defmt 0.3.100", "defmt-rtt", - "embassy-embedded-hal", "embassy-executor", "embassy-futures", "embassy-imxrt", "embassy-sync", "embassy-time", - "embedded-cfu-protocol", "embedded-mcu-hal", "embedded-services", - "embedded-usb-pd", "hidi2c-target-service", "mimxrt600-fcb 0.1.0", "num_enum", @@ -1192,15 +1049,10 @@ dependencies = [ "panic-probe", "platform-service", "power-button-service", - "power-policy-interface", - "power-policy-service", "static_cell", "time-alarm-service", "time-alarm-service-interface", "time-alarm-service-relay", - "tps6699x", - "type-c-interface", - "type-c-service", "typenum", "zerocopy", ] @@ -1422,31 +1274,6 @@ dependencies = [ "time-alarm-service-interface", ] -[[package]] -name = "tps6699x" -version = "0.1.0" -source = "git+https://github.com/OpenDevicePartnership/tps6699x#3001309250c68ef383412614845a9e7360c18710" -dependencies = [ - "bincode", - "bitfield 0.19.4", - "bitflags 2.11.1", - "defmt 0.3.100", - "device-driver", - "embassy-sync", - "embassy-time", - "embedded-hal 1.0.0", - "embedded-hal-async", - "embedded-io-async 0.6.1", - "embedded-services", - "embedded-usb-pd", - "fw-update-interface", - "heapless", - "itertools 0.14.0", - "power-policy-interface", - "type-c-interface", - "type-c-service", -] - [[package]] name = "tracing" version = "0.1.44" @@ -1508,34 +1335,6 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "type-c-interface" -version = "0.1.0" -dependencies = [ - "bitfield 0.17.0", - "defmt 0.3.100", - "embedded-services", - "embedded-usb-pd", - "heapless", - "power-policy-interface", -] - -[[package]] -name = "type-c-service" -version = "0.1.0" -dependencies = [ - "defmt 0.3.100", - "embassy-futures", - "embassy-sync", - "embassy-time", - "embedded-services", - "embedded-usb-pd", - "fw-update-interface", - "heapless", - "power-policy-interface", - "type-c-interface", -] - [[package]] name = "typenum" version = "1.20.0" @@ -1548,12 +1347,6 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" -[[package]] -name = "unty" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" - [[package]] name = "valuable" version = "0.1.1" @@ -1566,12 +1359,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" -[[package]] -name = "virtue" -version = "0.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" - [[package]] name = "void" version = "1.0.2" diff --git a/examples/rt685s-evk/Cargo.toml b/examples/rt685s-evk/Cargo.toml index 15bfac73..850805f0 100644 --- a/examples/rt685s-evk/Cargo.toml +++ b/examples/rt685s-evk/Cargo.toml @@ -32,7 +32,6 @@ embassy-imxrt = { git = "https://github.com/OpenDevicePartnership/embassy-imxrt" "mimxrt685s", ] } -embassy-embedded-hal = { version = "0.6.0", features = ["defmt"] } embedded-mcu-hal = { version = "0.3.0", features = ["defmt"] } embassy-sync = { version = "0.8", features = ["defmt"] } embassy-executor = { version = "0.10.0", features = [ @@ -48,7 +47,6 @@ embassy-time = { version = "0.5.1", features = [ ] } mimxrt600-fcb = "0.1.0" -embedded-cfu-protocol = { git = "https://github.com/OpenDevicePartnership/embedded-cfu" } embedded-services = { path = "../../embedded-service", features = ["defmt"] } hidi2c-target-service = { path = "../../hidi2c-target-service", features = [ "defmt", @@ -59,22 +57,6 @@ odp-service-common = { path = "../../odp-service-common" } power-button-service = { path = "../../power-button-service", features = [ "defmt", ] } -power-policy-interface = { path = "../../power-policy-interface", features = [ - "defmt", -] } -power-policy-service = { path = "../../power-policy-service", features = [ - "defmt", -] } -tps6699x = { git = "https://github.com/OpenDevicePartnership/tps6699x", features = [ - "defmt", - "odp-type-c-service", - "odp-fw-update-interface", -] } -embedded-usb-pd = { git = "https://github.com/OpenDevicePartnership/embedded-usb-pd", default-features = false, features = [ - "defmt", -] } -type-c-service = { path = "../../type-c-service", features = ["defmt"] } -type-c-interface = { path = "../../type-c-interface", features = ["defmt"] } time-alarm-service = { path = "../../time-alarm-service", features = ["defmt"] } time-alarm-service-interface = { path = "../../time-alarm-service-interface", features = [ "defmt", @@ -92,13 +74,6 @@ platform-service = { path = "../../platform-service", features = [ ] } zerocopy = "0.8" -cfu-service = { path = "../../cfu-service", features = ["defmt"] } - # Needed otherwise cargo will pull from git [patch."https://github.com/OpenDevicePartnership/embedded-services"] embedded-services = { path = "../../embedded-service" } -type-c-service = { path = "../../type-c-service" } -type-c-interface = { path = "../../type-c-interface" } -power-policy-service = { path = "../../power-policy-service" } -power-policy-interface = { path = "../../power-policy-interface" } -fw-update-interface = { path = "../../fw-update-interface" } diff --git a/examples/rt685s-evk/src/bin/type_c.rs b/examples/rt685s-evk/src/bin/type_c.rs deleted file mode 100644 index bc04122a..00000000 --- a/examples/rt685s-evk/src/bin/type_c.rs +++ /dev/null @@ -1,298 +0,0 @@ -#![no_std] -#![no_main] -use ::tps6699x::ADDR1; -use ::tps6699x::asynchronous::embassy::interrupt::InterruptReceiver; -use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice; -use embassy_executor::Spawner; -use embassy_imxrt::gpio::{Input, Inverter, Pull}; -use embassy_imxrt::i2c::Async; -use embassy_imxrt::i2c::master::{Config, I2cMaster}; -use embassy_imxrt::{bind_interrupts, peripherals}; -use embassy_sync::channel::{DynamicReceiver, DynamicSender}; -use embassy_sync::mutex::Mutex; -use embassy_sync::pubsub::{DynImmediatePublisher, DynSubscriber, PubSubChannel}; -use embassy_time::{self as _, Delay}; -use embedded_services::GlobalRawMutex; -use embedded_services::event::{MapSender, NoopSender}; -use embedded_services::{error, info}; -use embedded_usb_pd::LocalPortId; -use power_policy_interface::psu; -use power_policy_service::psu::PsuEventReceivers; -use power_policy_service::service::registration::ArrayRegistration; -use static_cell::StaticCell; -use tps6699x::odp::driver as tps6699x_drv; -use type_c_interface::port::event::PortEventBitfield; -use type_c_service::controller::Port; -use type_c_service::controller::event_receiver::{ - EventReceiver as PortEventReceiver, InterruptReceiver as _, PortEventSplitter, -}; -use type_c_service::controller::macros::PortComponents; -use type_c_service::controller::state::SharedState; -use type_c_service::define_controller_port_static_cell_channel; -use type_c_service::service::Service; -use type_c_service::service::registration::PortData; - -extern crate rt685s_evk_example; - -bind_interrupts!(struct Irqs { - FLEXCOMM2 => embassy_imxrt::i2c::InterruptHandler; -}); - -type PowerNotifier<'a> = - power_policy_interface::psu::event::NonBlockingSenderNotifier>; -type SharedStateType = Mutex; -type PortType = Mutex< - GlobalRawMutex, - Port< - 'static, - Tps6699xMutex<'static>, - SharedStateType, - type_c_interface::port::event::NonBlockingSenderNotifier< - DynamicSender<'static, type_c_interface::service::event::PortEventData>, - >, - PowerNotifier<'static>, - DynamicSender<'static, type_c_service::controller::event::Loopback>, - >, ->; -type ChargerType = power_policy_interface::charger::mock::ChargerType; - -type BusMaster<'a> = I2cMaster<'a, Async>; -type BusDevice<'a> = I2cDevice<'a, GlobalRawMutex, BusMaster<'a>>; -type Tps6699xMutex<'a> = Mutex>>; -type Controller<'a> = tps6699x::asynchronous::embassy::controller::Controller>; -type InterruptProcessor<'a> = - tps6699x::asynchronous::embassy::interrupt::InterruptProcessor<'a, GlobalRawMutex, BusDevice<'a>>; - -type PowerPolicySenderType = MapSender< - power_policy_interface::service::event::Event<'static, PortType>, - power_policy_interface::service::event::EventData, - DynImmediatePublisher<'static, power_policy_interface::service::event::EventData>, - fn( - power_policy_interface::service::event::Event<'static, PortType>, - ) -> power_policy_interface::service::event::EventData, ->; - -type PowerPolicyReceiverType = DynSubscriber<'static, power_policy_interface::service::event::EventData>; -type PowerPolicyNotifierType = - power_policy_interface::service::event::NonBlockingSenderNotifier<'static, PortType, PowerPolicySenderType>; -type PowerPolicyServiceType = Mutex< - GlobalRawMutex, - power_policy_service::service::Service< - 'static, - ArrayRegistration<'static, PortType, 2, PowerPolicyNotifierType, 1, ChargerType, 0>, - >, ->; - -const PORT_COUNT: usize = 2; -type PortReceiverType = DynamicReceiver<'static, type_c_interface::service::event::PortEventData>; -type TypeCServiceEventReceiverType = type_c_service::service::event_receiver::ArrayEventReceiver< - 'static, - PORT_COUNT, - PortType, - PortReceiverType, - PowerPolicyReceiverType, ->; - -type TypeCServiceNotifierType = - type_c_interface::service::event::NonBlockingSenderNotifier<'static, PortType, NoopSender>; -type TypeCRegistrationType = type_c_service::service::registration::ArrayRegistration< - 'static, - PortType, - PORT_COUNT, - TypeCServiceNotifierType, - 1, ->; -type TypeCServiceType = type_c_service::service::Service<'static, TypeCRegistrationType>; -type PortEventReceiverType = PortEventReceiver< - 'static, - SharedStateType, - DynamicReceiver<'static, PortEventBitfield>, - DynamicReceiver<'static, type_c_service::controller::event::Loopback>, ->; - -#[embassy_executor::task(pool_size = 2)] -async fn port_task(mut event_receiver: PortEventReceiverType, port: &'static PortType) { - port.lock().await.sync_state().await.unwrap(); - - loop { - let event = event_receiver.wait_event().await; - let output = port.lock().await.process_event(event).await; - if let Err(e) = output { - error!("Error processing event: {:?}", e); - } - } -} - -#[embassy_executor::task] -async fn interrupt_task(mut int_in: Input<'static>, mut interrupt: InterruptProcessor<'static>) { - tps6699x::asynchronous::embassy::task::interrupt_task(&mut int_in, &mut [&mut interrupt]).await; -} - -#[embassy_executor::task] -async fn interrupt_splitter_task( - mut interrupt_receiver: InterruptReceiver<'static, GlobalRawMutex, BusDevice<'static>>, - mut interrupt_splitter: PortEventSplitter<2, DynamicSender<'static, PortEventBitfield>>, -) -> ! { - loop { - let interrupts = interrupt_receiver.wait_interrupt().await; - interrupt_splitter.process_interrupts(interrupts).await; - } -} - -#[embassy_executor::task] -async fn power_policy_task( - psu_events: PsuEventReceivers<'static, 2, PortType, DynamicReceiver<'static, psu::event::EventData>>, - power_policy: &'static PowerPolicyServiceType, -) { - power_policy_service::service::task::psu_task(psu_events, power_policy).await; -} - -#[embassy_executor::task] -async fn type_c_service_task( - service: &'static Mutex, - event_receiver: TypeCServiceEventReceiverType, -) { - type_c_service::task::task(service, event_receiver).await; -} - -#[embassy_executor::main] -async fn main(spawner: Spawner) { - let p = embassy_imxrt::init(Default::default()); - - info!("Embedded service init"); - embedded_services::init().await; - - let int_in = Input::new(p.PIO1_7, Pull::Up, Inverter::Disabled); - static BUS: StaticCell>> = StaticCell::new(); - let bus = BUS.init(Mutex::new( - I2cMaster::new_async(p.FLEXCOMM2, p.PIO0_18, p.PIO0_17, Irqs, Config::default(), p.DMA0_CH5).unwrap(), - )); - - let device = I2cDevice::new(bus); - - static CONTROLLER: StaticCell> = StaticCell::new(); - let controller = CONTROLLER.init(Controller::new_tps66994(device, Default::default(), ADDR1).unwrap()); - let (mut tps6699x, interrupt_processor, interrupt_receiver) = controller.make_parts(); - - info!("Resetting PD controller"); - let mut delay = Delay; - tps6699x.reset(&mut delay).await.unwrap(); - - info!("Spawining interrupt task"); - spawner.spawn(interrupt_task(int_in, interrupt_processor).expect("Failed to spawn interrupt task")); - - // These aren't enabled by default - tps6699x - .modify_interrupt_mask_all(|mask| { - mask.set_am_entered(true); - mask.set_dp_sid_status_updated(true); - mask.set_intel_vid_status_updated(true); - mask.set_usb_status_updated(true); - mask.set_power_path_switch_changed(true); - mask.set_sink_ready(true); - *mask - }) - .await - .unwrap(); - - info!("Spawining PD controller task"); - static CONTROLLER_MUTEX: StaticCell> = StaticCell::new(); - let controller_mutex = CONTROLLER_MUTEX.init(Mutex::new(tps6699x_drv::tps66994( - tps6699x, - Default::default(), - Default::default(), - "tps6699x_0", - ))); - - define_controller_port_static_cell_channel!(pub(self), port0, GlobalRawMutex, Tps6699xMutex<'static>); - let PortComponents { - port: port0, - power_policy_receiver: policy_receiver0, - event_receiver: event_receiver0, - interrupt_sender: port0_interrupt_sender, - type_c_receiver: type_c_receiver0, - } = port0::create("PD0", LocalPortId(0), Default::default(), controller_mutex); - - define_controller_port_static_cell_channel!(pub(self), port1, GlobalRawMutex, Tps6699xMutex<'static>); - let PortComponents { - port: port1, - power_policy_receiver: policy_receiver1, - event_receiver: event_receiver1, - interrupt_sender: port1_interrupt_sender, - type_c_receiver: type_c_receiver1, - } = port1::create("PD1", LocalPortId(1), Default::default(), controller_mutex); - - let port_event_splitter = PortEventSplitter::new([port0_interrupt_sender, port1_interrupt_sender]); - - // The service is the only receiver and we only use a DynImmediatePublisher, which doesn't take a publisher slot - static POWER_POLICY_CHANNEL: StaticCell< - PubSubChannel, - > = StaticCell::new(); - - let power_policy_channel = POWER_POLICY_CHANNEL.init(PubSubChannel::new()); - let power_policy_sender: PowerPolicySenderType = - MapSender::new(power_policy_channel.dyn_immediate_publisher(), |e| e.into()); - // Guaranteed to not panic since we initialized the channel above - let power_policy_subscriber = power_policy_channel.dyn_subscriber().unwrap(); - - // Create power policy service - let power_policy_registration = ArrayRegistration { - psus: [port0, port1], - chargers: [], - service_notifiers: [power_policy_sender.into()], - }; - - static POWER_SERVICE: StaticCell = StaticCell::new(); - let power_service = POWER_SERVICE.init(Mutex::new(power_policy_service::service::Service::new( - power_policy_registration, - power_policy_service::service::config::Config::default(), - ))); - - static TYPE_C_SERVICE: StaticCell> = StaticCell::new(); - let type_c_service = TYPE_C_SERVICE.init(Mutex::new(Service::new( - Default::default(), - TypeCRegistrationType { - ports: [port0, port1], - service_notifiers: [NoopSender.into()], - port_data: [ - PortData { - local_port: Some(LocalPortId(0)), - }, - PortData { - local_port: Some(LocalPortId(1)), - }, - ], - }, - ))); - - info!("Spawining type-c service task"); - spawner.spawn( - type_c_service_task( - type_c_service, - TypeCServiceEventReceiverType::new( - [port0, port1], - [type_c_receiver0, type_c_receiver1], - power_policy_subscriber, - ), - ) - .expect("Failed to create type-c service task"), - ); - - info!("Spawining power policy task"); - spawner.spawn( - power_policy_task( - PsuEventReceivers::new([port0, port1], [policy_receiver0, policy_receiver1]), - power_service, - ) - .expect("Failed to create power policy task"), - ); - - spawner.spawn(port_task(event_receiver0, port0).expect("Failed to create controller0 task")); - - spawner.spawn(port_task(event_receiver1, port1).expect("Failed to create controller1 task")); - - spawner.spawn( - interrupt_splitter_task(interrupt_receiver, port_event_splitter) - .expect("Failed to spawn interrupt splitter task"), - ); -} diff --git a/examples/rt685s-evk/src/bin/type_c_cfu.rs b/examples/rt685s-evk/src/bin/type_c_cfu.rs deleted file mode 100644 index 5be1a476..00000000 --- a/examples/rt685s-evk/src/bin/type_c_cfu.rs +++ /dev/null @@ -1,440 +0,0 @@ -#![no_std] -#![no_main] - -use ::tps6699x::ADDR1; -use ::tps6699x::asynchronous::embassy::interrupt::InterruptReceiver; -use cfu_service::CfuClient; -use cfu_service::component::{CfuDevice, InternalResponseData, RequestData}; -use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice; -use embassy_executor::Spawner; -use embassy_imxrt::gpio::{Input, Inverter, Pull}; -use embassy_imxrt::i2c::Async; -use embassy_imxrt::i2c::master::{Config, I2cMaster}; -use embassy_imxrt::{bind_interrupts, peripherals}; -use embassy_sync::channel::{DynamicReceiver, DynamicSender}; -use embassy_sync::mutex::Mutex; -use embassy_sync::once_lock::OnceLock; -use embassy_sync::pubsub::{DynImmediatePublisher, DynSubscriber, PubSubChannel}; -use embassy_time::Timer; -use embassy_time::{self as _, Delay}; -use embedded_cfu_protocol::protocol_definitions::*; -use embedded_cfu_protocol::protocol_definitions::{FwUpdateOffer, FwUpdateOfferResponse, FwVersion}; -use embedded_services::GlobalRawMutex; -use embedded_services::event::{MapSender, NoopSender}; -use embedded_services::{error, info}; -use embedded_usb_pd::LocalPortId; -use power_policy_interface::psu; -use power_policy_service::psu::PsuEventReceivers; -use power_policy_service::service::registration::ArrayRegistration; -use static_cell::StaticCell; -use tps6699x::odp::driver as tps6699x_drv; -use type_c_interface::port::event::PortEventBitfield; -use type_c_service::controller::Port; -use type_c_service::controller::event_receiver::{ - EventReceiver as PortEventReceiver, InterruptReceiver as _, PortEventSplitter, -}; -use type_c_service::controller::macros::PortComponents; -use type_c_service::controller::state::SharedState as PortSharedState; -use type_c_service::define_controller_port_static_cell_channel; -use type_c_service::service::Service; -use type_c_service::service::registration::PortData; - -extern crate rt685s_evk_example; - -bind_interrupts!(struct Irqs { - FLEXCOMM2 => embassy_imxrt::i2c::InterruptHandler; -}); - -struct CfuCustomization; - -impl cfu_service::customization::Customization for CfuCustomization { - fn validate(&mut self, _current: FwVersion, _offer: &FwUpdateOffer) -> FwUpdateOfferResponse { - // For this example, we always accept the offer - FwUpdateOfferResponse::new_accept(HostToken::Driver) - } -} - -type PowerNotifier<'a> = - power_policy_interface::psu::event::NonBlockingSenderNotifier>; -type PortSharedStateType = Mutex; -type PortType = Mutex< - GlobalRawMutex, - Port< - 'static, - Tps6699xMutex<'static>, - PortSharedStateType, - type_c_interface::port::event::NonBlockingSenderNotifier< - DynamicSender<'static, type_c_interface::service::event::PortEventData>, - >, - PowerNotifier<'static>, - DynamicSender<'static, type_c_service::controller::event::Loopback>, - >, ->; -type ChargerType = power_policy_interface::charger::mock::ChargerType; - -type BusMaster<'a> = I2cMaster<'a, Async>; -type BusDevice<'a> = I2cDevice<'a, GlobalRawMutex, BusMaster<'a>>; -type Tps6699xMutex<'a> = Mutex>>; -type Controller<'a> = tps6699x::asynchronous::embassy::controller::Controller>; -type InterruptProcessor<'a> = - tps6699x::asynchronous::embassy::interrupt::InterruptProcessor<'a, GlobalRawMutex, BusDevice<'a>>; - -type PowerPolicySenderType = MapSender< - power_policy_interface::service::event::Event<'static, PortType>, - power_policy_interface::service::event::EventData, - DynImmediatePublisher<'static, power_policy_interface::service::event::EventData>, - fn( - power_policy_interface::service::event::Event<'static, PortType>, - ) -> power_policy_interface::service::event::EventData, ->; - -type PowerPolicyReceiverType = DynSubscriber<'static, power_policy_interface::service::event::EventData>; -type PowerPolicyNotifierType = - power_policy_interface::service::event::NonBlockingSenderNotifier<'static, PortType, PowerPolicySenderType>; -type PowerPolicyServiceType = Mutex< - GlobalRawMutex, - power_policy_service::service::Service< - 'static, - ArrayRegistration<'static, PortType, 2, PowerPolicyNotifierType, 1, ChargerType, 0>, - >, ->; - -const PORT_COUNT: usize = 2; -type PortReceiverType = DynamicReceiver<'static, type_c_interface::service::event::PortEventData>; -type TypeCServiceEventReceiverType = type_c_service::service::event_receiver::ArrayEventReceiver< - 'static, - PORT_COUNT, - PortType, - PortReceiverType, - PowerPolicyReceiverType, ->; - -type TypeCServiceNotifierType = - type_c_interface::service::event::NonBlockingSenderNotifier<'static, PortType, NoopSender>; -type TypeCRegistrationType = type_c_service::service::registration::ArrayRegistration< - 'static, - PortType, - PORT_COUNT, - TypeCServiceNotifierType, - 1, ->; -type TypeCServiceType = type_c_service::service::Service<'static, TypeCRegistrationType>; -type PortEventReceiverType = PortEventReceiver< - 'static, - PortSharedStateType, - DynamicReceiver<'static, PortEventBitfield>, - DynamicReceiver<'static, type_c_service::controller::event::Loopback>, ->; - -type CfuUpdaterSharedStateType = Mutex; -type CfuUpdaterType<'a> = - cfu_service::basic::Updater<'a, Tps6699xMutex<'a>, CfuUpdaterSharedStateType, CfuCustomization>; - -const CONTROLLER0_CFU_ID: ComponentId = 0x12; - -#[embassy_executor::task(pool_size = 2)] -async fn port_task(mut event_receiver: PortEventReceiverType, port: &'static PortType) { - port.lock().await.sync_state().await.unwrap(); - - loop { - let event = event_receiver.wait_event().await; - let output = port.lock().await.process_event(event).await; - if let Err(e) = output { - error!("Error processing event: {:?}", e); - } - } -} - -#[embassy_executor::task] -async fn cfu_updater_task( - mut event_receiver: cfu_service::basic::event_receiver::EventReceiver<'static, CfuUpdaterSharedStateType>, - mut updater: CfuUpdaterType<'static>, -) -> ! { - loop { - let event = event_receiver.wait_next().await; - let output = updater.process_event(event).await; - event_receiver.finalize(output).await; - } -} - -#[embassy_executor::task] -async fn interrupt_task(mut int_in: Input<'static>, mut interrupt: InterruptProcessor<'static>) { - tps6699x::asynchronous::embassy::task::interrupt_task(&mut int_in, &mut [&mut interrupt]).await; -} - -#[embassy_executor::task] -async fn interrupt_splitter_task( - mut interrupt_receiver: InterruptReceiver<'static, GlobalRawMutex, BusDevice<'static>>, - mut interrupt_splitter: PortEventSplitter<2, DynamicSender<'static, PortEventBitfield>>, -) -> ! { - loop { - let interrupts = interrupt_receiver.wait_interrupt().await; - interrupt_splitter.process_interrupts(interrupts).await; - } -} - -#[embassy_executor::task] -async fn fw_update_task(cfu_client: &'static CfuClient) { - Timer::after_millis(1000).await; - - info!("Getting FW version"); - let response = cfu_client - .route_request(CONTROLLER0_CFU_ID, RequestData::FwVersionRequest) - .await - .unwrap(); - let prev_version = match response { - InternalResponseData::FwVersionResponse(GetFwVersionResponse { component_info, .. }) => { - Into::::into(component_info[0].fw_version) - } - _ => panic!("Unexpected response"), - }; - info!("Got version: {:#x}", prev_version); - - info!("Giving offer"); - let offer = cfu_client - .route_request( - CONTROLLER0_CFU_ID, - RequestData::GiveOffer(FwUpdateOffer::new( - HostToken::Driver, - CONTROLLER0_CFU_ID, - FwVersion::new(0x211), - 0, - 0, - )), - ) - .await - .unwrap(); - info!("Got response: {:?}", offer); - - let fw = &[]; //include_bytes!("../../fw.bin"); - let num_chunks = fw.len() / DEFAULT_DATA_LENGTH + (fw.len() % DEFAULT_DATA_LENGTH != 0) as usize; - - for (i, chunk) in fw.chunks(DEFAULT_DATA_LENGTH).enumerate() { - let header = FwUpdateContentHeader { - data_length: chunk.len() as u8, - sequence_num: i as u16, - firmware_address: (i * DEFAULT_DATA_LENGTH) as u32, - flags: if i == 0 { - FW_UPDATE_FLAG_FIRST_BLOCK - } else if i == num_chunks - 1 { - FW_UPDATE_FLAG_LAST_BLOCK - } else { - 0 - }, - }; - - let mut chunk_data = [0u8; DEFAULT_DATA_LENGTH]; - chunk_data[..chunk.len()].copy_from_slice(chunk); - let request = FwUpdateContentCommand { - header, - data: chunk_data, - }; - - info!("Sending chunk {} of {}", i + 1, num_chunks); - let response = cfu_client - .route_request(CONTROLLER0_CFU_ID, RequestData::GiveContent(request)) - .await - .unwrap(); - info!("Got response: {:?}", response); - } - - Timer::after_millis(2000).await; - info!("Getting FW version"); - let response = cfu_client - .route_request(CONTROLLER0_CFU_ID, RequestData::FwVersionRequest) - .await - .unwrap(); - let version = match response { - InternalResponseData::FwVersionResponse(GetFwVersionResponse { component_info, .. }) => { - Into::::into(component_info[0].fw_version) - } - _ => panic!("Unexpected response"), - }; - info!("Got previous version: {:#x}", prev_version); - info!("Got version: {:#x}", version); -} - -#[embassy_executor::task] -async fn power_policy_task( - psu_events: PsuEventReceivers<'static, 2, PortType, DynamicReceiver<'static, psu::event::EventData>>, - power_policy: &'static PowerPolicyServiceType, -) { - power_policy_service::service::task::psu_task(psu_events, power_policy).await; -} - -#[embassy_executor::task] -async fn type_c_service_task( - service: &'static Mutex, - event_receiver: TypeCServiceEventReceiverType, -) { - type_c_service::task::task(service, event_receiver).await; -} - -#[embassy_executor::main] -async fn main(spawner: Spawner) { - let p = embassy_imxrt::init(Default::default()); - - info!("Embedded service init"); - embedded_services::init().await; - - let int_in = Input::new(p.PIO1_7, Pull::Up, Inverter::Disabled); - static BUS: StaticCell>> = StaticCell::new(); - let bus = BUS.init(Mutex::new( - I2cMaster::new_async(p.FLEXCOMM2, p.PIO0_18, p.PIO0_17, Irqs, Config::default(), p.DMA0_CH5).unwrap(), - )); - - let device = I2cDevice::new(bus); - - static CONTROLLER: StaticCell> = StaticCell::new(); - let controller = CONTROLLER.init(Controller::new_tps66994(device, Default::default(), ADDR1).unwrap()); - let (mut tps6699x, interrupt_processor, interrupt_receiver) = controller.make_parts(); - - info!("Resetting PD controller"); - let mut delay = Delay; - tps6699x.reset(&mut delay).await.unwrap(); - - info!("Spawining interrupt task"); - spawner.spawn(interrupt_task(int_in, interrupt_processor).expect("Failed to spawn interrupt task")); - - // These aren't enabled by default - tps6699x - .modify_interrupt_mask_all(|mask| { - mask.set_am_entered(true); - mask.set_dp_sid_status_updated(true); - mask.set_intel_vid_status_updated(true); - mask.set_usb_status_updated(true); - mask.set_power_path_switch_changed(true); - mask.set_sink_ready(true); - *mask - }) - .await - .unwrap(); - - info!("Spawining PD controller task"); - static CONTROLLER_MUTEX: StaticCell> = StaticCell::new(); - let controller_mutex = CONTROLLER_MUTEX.init(Mutex::new(tps6699x_drv::tps66994( - tps6699x, - Default::default(), - Default::default(), - "tps6699x_0", - ))); - - // Create controller CFU device and updater - static CFU_DEVICE: StaticCell = StaticCell::new(); - let cfu_device = CFU_DEVICE.init(CfuDevice::new(CONTROLLER0_CFU_ID)); - - static CFU_SHARED_STATE: StaticCell = StaticCell::new(); - let cfu_shared_state = CFU_SHARED_STATE.init(Mutex::new(cfu_service::basic::state::SharedState::new())); - - let cfu_event_receiver = - cfu_service::basic::event_receiver::EventReceiver::new(cfu_device, cfu_shared_state, Default::default()); - - let cfu_updater = cfu_service::basic::Updater::new( - controller_mutex, - cfu_shared_state, - Default::default(), - CONTROLLER0_CFU_ID, - CfuCustomization, - ); - - // Create CFU client - static CFU_CLIENT: OnceLock = OnceLock::new(); - let cfu_client = CfuClient::new(&CFU_CLIENT).await; - cfu_client.register_device(cfu_device).unwrap(); - - define_controller_port_static_cell_channel!(pub(self), port0, GlobalRawMutex, Tps6699xMutex<'static>); - let PortComponents { - port: port0, - power_policy_receiver: policy_receiver0, - event_receiver: event_receiver0, - interrupt_sender: port0_interrupt_sender, - type_c_receiver: type_c_receiver0, - } = port0::create("PD0", LocalPortId(0), Default::default(), controller_mutex); - - define_controller_port_static_cell_channel!(pub(self),port1, GlobalRawMutex, Tps6699xMutex<'static>); - let PortComponents { - port: port1, - power_policy_receiver: policy_receiver1, - event_receiver: event_receiver1, - interrupt_sender: port1_interrupt_sender, - type_c_receiver: type_c_receiver1, - } = port1::create("PD1", LocalPortId(1), Default::default(), controller_mutex); - - let port_event_splitter = PortEventSplitter::new([port0_interrupt_sender, port1_interrupt_sender]); - - // Create power policy service - // The service is the only receiver and we only use a DynImmediatePublisher, which doesn't take a publisher slot - static POWER_POLICY_CHANNEL: StaticCell< - PubSubChannel, - > = StaticCell::new(); - - let power_policy_channel = POWER_POLICY_CHANNEL.init(PubSubChannel::new()); - let power_policy_sender: PowerPolicySenderType = - MapSender::new(power_policy_channel.dyn_immediate_publisher(), |e| e.into()); - // Guaranteed to not panic since we initialized the channel above - let power_policy_subscriber = power_policy_channel.dyn_subscriber().unwrap(); - - let power_policy_registration = ArrayRegistration { - psus: [port0, port1], - chargers: [], - service_notifiers: [power_policy_sender.into()], - }; - - static POWER_SERVICE: StaticCell = StaticCell::new(); - let power_service = POWER_SERVICE.init(Mutex::new(power_policy_service::service::Service::new( - power_policy_registration, - power_policy_service::service::config::Config::default(), - ))); - - static TYPE_C_SERVICE: StaticCell> = StaticCell::new(); - let type_c_service = TYPE_C_SERVICE.init(Mutex::new(Service::new( - Default::default(), - TypeCRegistrationType { - ports: [port0, port1], - port_data: [ - PortData { - local_port: Some(LocalPortId(0)), - }, - PortData { - local_port: Some(LocalPortId(1)), - }, - ], - service_notifiers: [NoopSender.into()], - }, - ))); - - info!("Spawining type-c service task"); - spawner.spawn( - type_c_service_task( - type_c_service, - TypeCServiceEventReceiverType::new( - [port0, port1], - [type_c_receiver0, type_c_receiver1], - power_policy_subscriber, - ), - ) - .expect("Failed to spawn type-c service task"), - ); - - info!("Spawining power policy task"); - spawner.spawn( - power_policy_task( - PsuEventReceivers::new([port0, port1], [policy_receiver0, policy_receiver1]), - power_service, - ) - .expect("Failed to create power policy task"), - ); - - spawner.spawn(port_task(event_receiver0, port0).expect("Failed to create controller0 task")); - - spawner.spawn(port_task(event_receiver1, port1).expect("Failed to create controller1 task")); - - spawner.spawn( - interrupt_splitter_task(interrupt_receiver, port_event_splitter) - .expect("Failed to spawn interrupt splitter task"), - ); - - spawner.spawn(cfu_updater_task(cfu_event_receiver, cfu_updater).expect("Failed to create CFU updater task")); - - spawner.spawn(fw_update_task(cfu_client).expect("Failed to create fw update task")); -}