diff --git a/Cargo.lock b/Cargo.lock index 19dc1d4..c8b320e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,11 +147,16 @@ version = "0.1.0" name = "kaptan-drivers" version = "0.1.0" dependencies = [ + "kaptan-i2c", "kaptan-sensor", "kaptan-spi", "kaptan-time", ] +[[package]] +name = "kaptan-i2c" +version = "0.1.0" + [[package]] name = "kaptan-kakute-f7-mini-v3" version = "0.1.0" @@ -188,6 +193,7 @@ name = "kaptan-runtime" version = "0.1.0" dependencies = [ "kaptan-drivers", + "kaptan-i2c", "kaptan-sensor", "kaptan-spi", "kaptan-time", @@ -210,6 +216,7 @@ version = "0.1.0" dependencies = [ "cortex-m", "kaptan-dma", + "kaptan-i2c", "kaptan-spi", "kaptan-time", "stm32f7", diff --git a/Cargo.toml b/Cargo.toml index 4bb4a42..9d22a2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "libs/kaptan-actuator", "libs/kaptan-dma", "libs/kaptan-drivers", + "libs/kaptan-i2c", "libs/kaptan-mavlink", "libs/kaptan-runtime", "libs/kaptan-sensor", diff --git a/libs/kaptan-drivers/Cargo.toml b/libs/kaptan-drivers/Cargo.toml index 6361f79..871ba91 100644 --- a/libs/kaptan-drivers/Cargo.toml +++ b/libs/kaptan-drivers/Cargo.toml @@ -11,5 +11,6 @@ workspace = true [dependencies] kaptan-sensor = { path = "../kaptan-sensor" } +kaptan-i2c = { path = "../kaptan-i2c" } kaptan-spi = { path = "../kaptan-spi" } kaptan-time = { path = "../kaptan-time" } diff --git a/libs/kaptan-i2c/Cargo.toml b/libs/kaptan-i2c/Cargo.toml new file mode 100644 index 0000000..edf98fc --- /dev/null +++ b/libs/kaptan-i2c/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "kaptan-i2c" +edition.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[lints] +workspace = true diff --git a/libs/kaptan-i2c/src/lib.rs b/libs/kaptan-i2c/src/lib.rs new file mode 100644 index 0000000..ba3a20f --- /dev/null +++ b/libs/kaptan-i2c/src/lib.rs @@ -0,0 +1,50 @@ +//! Non-blocking I²C transaction contract. +//! +//! Controllers own in-flight transfer storage. Implementations may use +//! interrupts or DMA, but must never make a driver wait for a peripheral +//! status flag. + +#![no_std] + +/// Terminal outcome reported by an I²C controller. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum I2cCompletion { + /// The bound interrupt had no terminal transaction event. + NotPending, + /// The submitted transaction completed and read bytes are valid. + Complete, + /// The submitted transaction failed and read bytes are unusable. + TransferFault, +} + +/// Owns a non-blocking I²C controller route and its in-flight storage. +/// +/// Each operation sends a STOP on successful completion. Controllers copy a +/// submitted write into owned storage before returning. A completed read is +/// copied into the caller-provided destination only from +/// [`Self::complete_transaction`], after the hardware no longer accesses the +/// controller-owned storage. This avoids retaining pointers to caller slices +/// across interrupt boundaries. +pub trait I2cBus { + /// Failure to submit a transaction. + type StartError; + + /// Starts one address-scoped write transaction ending with a STOP. + fn start_write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::StartError>; + + /// Starts one address-scoped read transaction ending with a STOP. + fn start_read(&mut self, address: u8, length: usize) -> Result<(), Self::StartError>; + + /// Releases controller ownership after a hardware ISR acknowledged the + /// terminal event and, for a successful read, copies into `read`. + /// + /// This must not poll or wait. `read` must match the length submitted to + /// [`Self::start_read`] for the completed read transaction. + fn complete_transaction(&mut self, completion: I2cCompletion, read: Option<&mut [u8]>); + + /// Cancels an in-flight transaction after a board-selected timeout. + /// + /// Implementations must release controller-owned transaction state and + /// arrange for any required STOP or peripheral recovery without waiting. + fn cancel_transaction(&mut self); +} diff --git a/libs/kaptan-runtime/Cargo.toml b/libs/kaptan-runtime/Cargo.toml index 7e39dbe..072715b 100644 --- a/libs/kaptan-runtime/Cargo.toml +++ b/libs/kaptan-runtime/Cargo.toml @@ -11,6 +11,7 @@ workspace = true [dependencies] kaptan-drivers = { path = "../kaptan-drivers" } +kaptan-i2c = { path = "../kaptan-i2c" } kaptan-sensor = { path = "../kaptan-sensor" } kaptan-spi = { path = "../kaptan-spi" } kaptan-time = { path = "../kaptan-time" } diff --git a/libs/kaptan-stm32f7/Cargo.toml b/libs/kaptan-stm32f7/Cargo.toml index d753bf6..dccbec2 100644 --- a/libs/kaptan-stm32f7/Cargo.toml +++ b/libs/kaptan-stm32f7/Cargo.toml @@ -16,6 +16,7 @@ stm32f722 = ["stm32f7/stm32f722"] [dependencies] cortex-m = "0.7" kaptan-dma = { path = "../kaptan-dma" } +kaptan-i2c = { path = "../kaptan-i2c" } kaptan-spi = { path = "../kaptan-spi" } kaptan-time = { path = "../kaptan-time" } stm32f7 = { version = "0.16", default-features = false }