diff options
| -rw-r--r-- | embassy-stm32/src/i2c/config.rs | 149 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/mod.rs | 161 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 442 |
3 files changed, 681 insertions, 71 deletions
diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs new file mode 100644 index 000000000..eba14f6e0 --- /dev/null +++ b/embassy-stm32/src/i2c/config.rs | |||
| @@ -0,0 +1,149 @@ | |||
| 1 | use stm32_metapac::i2c::vals::Oamsk; | ||
| 2 | |||
| 3 | use crate::gpio::Pull; | ||
| 4 | |||
| 5 | #[repr(u8)] | ||
| 6 | #[derive(Copy, Clone)] | ||
| 7 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 8 | pub enum AddrMask { | ||
| 9 | NOMASK, | ||
| 10 | MASK1, | ||
| 11 | MASK2, | ||
| 12 | MASK3, | ||
| 13 | MASK4, | ||
| 14 | MASK5, | ||
| 15 | MASK6, | ||
| 16 | MASK7, | ||
| 17 | } | ||
| 18 | impl From<AddrMask> for Oamsk { | ||
| 19 | fn from(value: AddrMask) -> Self { | ||
| 20 | match value { | ||
| 21 | AddrMask::NOMASK => Oamsk::NOMASK, | ||
| 22 | AddrMask::MASK1 => Oamsk::MASK1, | ||
| 23 | AddrMask::MASK2 => Oamsk::MASK2, | ||
| 24 | AddrMask::MASK3 => Oamsk::MASK3, | ||
| 25 | AddrMask::MASK4 => Oamsk::MASK4, | ||
| 26 | AddrMask::MASK5 => Oamsk::MASK5, | ||
| 27 | AddrMask::MASK6 => Oamsk::MASK6, | ||
| 28 | AddrMask::MASK7 => Oamsk::MASK7, | ||
| 29 | } | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||
| 34 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 35 | pub enum Address { | ||
| 36 | SevenBit(u8), | ||
| 37 | TenBit(u16), | ||
| 38 | } | ||
| 39 | impl From<u8> for Address { | ||
| 40 | fn from(value: u8) -> Self { | ||
| 41 | Address::SevenBit(value) | ||
| 42 | } | ||
| 43 | } | ||
| 44 | impl From<u16> for Address { | ||
| 45 | fn from(value: u16) -> Self { | ||
| 46 | assert!(value < 0x400, "Ten bit address must be less than 0x400"); | ||
| 47 | Address::TenBit(value) | ||
| 48 | } | ||
| 49 | } | ||
| 50 | impl Address { | ||
| 51 | pub(super) fn add_mode(&self) -> stm32_metapac::i2c::vals::Addmode { | ||
| 52 | match self { | ||
| 53 | Address::SevenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT7, | ||
| 54 | Address::TenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT10, | ||
| 55 | } | ||
| 56 | } | ||
| 57 | pub fn addr(&self) -> u16 { | ||
| 58 | match self { | ||
| 59 | Address::SevenBit(addr) => *addr as u16, | ||
| 60 | Address::TenBit(addr) => *addr, | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | #[derive(Copy, Clone)] | ||
| 66 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 67 | pub struct OA2 { | ||
| 68 | pub addr: u8, | ||
| 69 | pub mask: AddrMask, | ||
| 70 | } | ||
| 71 | |||
| 72 | #[derive(Copy, Clone)] | ||
| 73 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 74 | pub enum OwnAddresses { | ||
| 75 | OA1(Address), | ||
| 76 | OA2(OA2), | ||
| 77 | Both { oa1: Address, oa2: OA2 }, | ||
| 78 | } | ||
| 79 | |||
| 80 | /// Slave Configuration | ||
| 81 | #[derive(Copy, Clone)] | ||
| 82 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 83 | pub struct SlaveAddrConfig { | ||
| 84 | /// Target Address(es) | ||
| 85 | pub addr: OwnAddresses, | ||
| 86 | /// Control if the peripheral should respond to the general call address | ||
| 87 | pub general_call: bool, | ||
| 88 | } | ||
| 89 | impl SlaveAddrConfig { | ||
| 90 | pub fn new_oa1(addr: Address, general_call: bool) -> Self { | ||
| 91 | Self { | ||
| 92 | addr: OwnAddresses::OA1(addr), | ||
| 93 | general_call, | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | pub fn basic(addr: Address) -> Self { | ||
| 98 | Self { | ||
| 99 | addr: OwnAddresses::OA1(addr), | ||
| 100 | general_call: false, | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | /// I2C config | ||
| 106 | #[non_exhaustive] | ||
| 107 | #[derive(Copy, Clone)] | ||
| 108 | pub struct Config { | ||
| 109 | /// Enable internal pullup on SDA. | ||
| 110 | /// | ||
| 111 | /// Using external pullup resistors is recommended for I2C. If you do | ||
| 112 | /// have external pullups you should not enable this. | ||
| 113 | pub sda_pullup: bool, | ||
| 114 | /// Enable internal pullup on SCL. | ||
| 115 | /// | ||
| 116 | /// Using external pullup resistors is recommended for I2C. If you do | ||
| 117 | /// have external pullups you should not enable this. | ||
| 118 | pub scl_pullup: bool, | ||
| 119 | /// Timeout. | ||
| 120 | #[cfg(feature = "time")] | ||
| 121 | pub timeout: embassy_time::Duration, | ||
| 122 | } | ||
| 123 | |||
| 124 | impl Default for Config { | ||
| 125 | fn default() -> Self { | ||
| 126 | Self { | ||
| 127 | sda_pullup: false, | ||
| 128 | scl_pullup: false, | ||
| 129 | #[cfg(feature = "time")] | ||
| 130 | timeout: embassy_time::Duration::from_millis(1000), | ||
| 131 | } | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | impl Config { | ||
| 136 | pub(super) fn scl_pull_mode(&self) -> Pull { | ||
| 137 | match self.scl_pullup { | ||
| 138 | true => Pull::Up, | ||
| 139 | false => Pull::Down, | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | pub(super) fn sda_pull_mode(&self) -> Pull { | ||
| 144 | match self.sda_pullup { | ||
| 145 | true => Pull::Up, | ||
| 146 | false => Pull::Down, | ||
| 147 | } | ||
| 148 | } | ||
| 149 | } | ||
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 739e960b9..0457595d2 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -5,14 +5,18 @@ | |||
| 5 | #[cfg_attr(any(i2c_v2, i2c_v3), path = "v2.rs")] | 5 | #[cfg_attr(any(i2c_v2, i2c_v3), path = "v2.rs")] |
| 6 | mod _version; | 6 | mod _version; |
| 7 | 7 | ||
| 8 | mod config; | ||
| 9 | |||
| 8 | use core::future::Future; | 10 | use core::future::Future; |
| 9 | use core::iter; | 11 | use core::iter; |
| 10 | use core::marker::PhantomData; | 12 | use core::marker::PhantomData; |
| 11 | 13 | ||
| 14 | pub use config::*; | ||
| 12 | use embassy_hal_internal::{Peripheral, PeripheralRef}; | 15 | use embassy_hal_internal::{Peripheral, PeripheralRef}; |
| 13 | use embassy_sync::waitqueue::AtomicWaker; | 16 | use embassy_sync::waitqueue::AtomicWaker; |
| 14 | #[cfg(feature = "time")] | 17 | #[cfg(feature = "time")] |
| 15 | use embassy_time::{Duration, Instant}; | 18 | use embassy_time::{Duration, Instant}; |
| 19 | use mode::{Master, MasterMode, MultiMaster}; | ||
| 16 | 20 | ||
| 17 | use crate::dma::ChannelAndRequest; | 21 | use crate::dma::ChannelAndRequest; |
| 18 | #[cfg(gpio_v2)] | 22 | #[cfg(gpio_v2)] |
| @@ -108,8 +112,56 @@ impl Config { | |||
| 108 | } | 112 | } |
| 109 | } | 113 | } |
| 110 | 114 | ||
| 115 | /// I2C modes | ||
| 116 | pub mod mode { | ||
| 117 | trait SealedMode {} | ||
| 118 | |||
| 119 | /// Trait for I2C master operations. | ||
| 120 | #[allow(private_bounds)] | ||
| 121 | pub trait MasterMode: SealedMode {} | ||
| 122 | |||
| 123 | /// Mode allowing for I2C master operations. | ||
| 124 | pub struct Master; | ||
| 125 | /// Mode allowing for I2C master and slave operations. | ||
| 126 | pub struct MultiMaster; | ||
| 127 | |||
| 128 | impl SealedMode for Master {} | ||
| 129 | impl MasterMode for Master {} | ||
| 130 | |||
| 131 | impl SealedMode for MultiMaster {} | ||
| 132 | impl MasterMode for MultiMaster {} | ||
| 133 | } | ||
| 134 | |||
| 135 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
| 136 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 137 | /// The command kind to the slave from the master | ||
| 138 | pub enum CommandKind { | ||
| 139 | /// Write to the slave | ||
| 140 | SlaveReceive, | ||
| 141 | /// Read from the slave | ||
| 142 | SlaveSend, | ||
| 143 | } | ||
| 144 | |||
| 145 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
| 146 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 147 | /// The command kind to the slave from the master and the address that the slave matched | ||
| 148 | pub struct Command { | ||
| 149 | pub kind: CommandKind, | ||
| 150 | pub address: Address, | ||
| 151 | } | ||
| 152 | |||
| 153 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
| 154 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 155 | /// The status of the slave send operation | ||
| 156 | pub enum SendStatus { | ||
| 157 | /// The slave send operation is done, all bytes have been sent and the master is not requesting more | ||
| 158 | Done, | ||
| 159 | /// The slave send operation is done, but there are leftover bytes that the master did not read | ||
| 160 | LeftoverBytes(usize), | ||
| 161 | } | ||
| 162 | |||
| 111 | /// I2C driver. | 163 | /// I2C driver. |
| 112 | pub struct I2c<'d, M: Mode> { | 164 | pub struct I2c<'d, M: Mode, IM: MasterMode> { |
| 113 | info: &'static Info, | 165 | info: &'static Info, |
| 114 | state: &'static State, | 166 | state: &'static State, |
| 115 | kernel_clock: Hertz, | 167 | kernel_clock: Hertz, |
| @@ -120,9 +172,10 @@ pub struct I2c<'d, M: Mode> { | |||
| 120 | #[cfg(feature = "time")] | 172 | #[cfg(feature = "time")] |
| 121 | timeout: Duration, | 173 | timeout: Duration, |
| 122 | _phantom: PhantomData<M>, | 174 | _phantom: PhantomData<M>, |
| 175 | _phantom2: PhantomData<IM>, | ||
| 123 | } | 176 | } |
| 124 | 177 | ||
| 125 | impl<'d> I2c<'d, Async> { | 178 | impl<'d> I2c<'d, Async, Master> { |
| 126 | /// Create a new I2C driver. | 179 | /// Create a new I2C driver. |
| 127 | pub fn new<T: Instance>( | 180 | pub fn new<T: Instance>( |
| 128 | peri: impl Peripheral<P = T> + 'd, | 181 | peri: impl Peripheral<P = T> + 'd, |
| @@ -148,7 +201,7 @@ impl<'d> I2c<'d, Async> { | |||
| 148 | } | 201 | } |
| 149 | } | 202 | } |
| 150 | 203 | ||
| 151 | impl<'d> I2c<'d, Blocking> { | 204 | impl<'d> I2c<'d, Blocking, Master> { |
| 152 | /// Create a new blocking I2C driver. | 205 | /// Create a new blocking I2C driver. |
| 153 | pub fn new_blocking<T: Instance>( | 206 | pub fn new_blocking<T: Instance>( |
| 154 | peri: impl Peripheral<P = T> + 'd, | 207 | peri: impl Peripheral<P = T> + 'd, |
| @@ -169,7 +222,7 @@ impl<'d> I2c<'d, Blocking> { | |||
| 169 | } | 222 | } |
| 170 | } | 223 | } |
| 171 | 224 | ||
| 172 | impl<'d, M: Mode> I2c<'d, M> { | 225 | impl<'d, M: Mode> I2c<'d, M, Master> { |
| 173 | /// Create a new I2C driver. | 226 | /// Create a new I2C driver. |
| 174 | fn new_inner<T: Instance>( | 227 | fn new_inner<T: Instance>( |
| 175 | _peri: impl Peripheral<P = T> + 'd, | 228 | _peri: impl Peripheral<P = T> + 'd, |
| @@ -194,8 +247,10 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 194 | #[cfg(feature = "time")] | 247 | #[cfg(feature = "time")] |
| 195 | timeout: config.timeout, | 248 | timeout: config.timeout, |
| 196 | _phantom: PhantomData, | 249 | _phantom: PhantomData, |
| 250 | _phantom2: PhantomData, | ||
| 197 | }; | 251 | }; |
| 198 | this.enable_and_init(freq, config); | 252 | this.enable_and_init(freq, config); |
| 253 | |||
| 199 | this | 254 | this |
| 200 | } | 255 | } |
| 201 | 256 | ||
| @@ -203,7 +258,9 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 203 | self.info.rcc.enable_and_reset(); | 258 | self.info.rcc.enable_and_reset(); |
| 204 | self.init(freq, config); | 259 | self.init(freq, config); |
| 205 | } | 260 | } |
| 261 | } | ||
| 206 | 262 | ||
| 263 | impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | ||
| 207 | fn timeout(&self) -> Timeout { | 264 | fn timeout(&self) -> Timeout { |
| 208 | Timeout { | 265 | Timeout { |
| 209 | #[cfg(feature = "time")] | 266 | #[cfg(feature = "time")] |
| @@ -211,8 +268,28 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 211 | } | 268 | } |
| 212 | } | 269 | } |
| 213 | } | 270 | } |
| 271 | impl<'d, M: Mode> I2c<'d, M, Master> { | ||
| 272 | /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster) | ||
| 273 | pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> { | ||
| 274 | let mut slave = I2c { | ||
| 275 | info: self.info, | ||
| 276 | state: self.state, | ||
| 277 | kernel_clock: self.kernel_clock, | ||
| 278 | scl: self.scl.take(), | ||
| 279 | sda: self.sda.take(), | ||
| 280 | tx_dma: self.tx_dma.take(), | ||
| 281 | rx_dma: self.rx_dma.take(), | ||
| 282 | #[cfg(feature = "time")] | ||
| 283 | timeout: self.timeout, | ||
| 284 | _phantom: PhantomData, | ||
| 285 | _phantom2: PhantomData, | ||
| 286 | }; | ||
| 287 | slave.init_slave(slave_addr_config); | ||
| 288 | slave | ||
| 289 | } | ||
| 290 | } | ||
| 214 | 291 | ||
| 215 | impl<'d, M: Mode> Drop for I2c<'d, M> { | 292 | impl<'d, M: Mode, IM: MasterMode> Drop for I2c<'d, M, IM> { |
| 216 | fn drop(&mut self) { | 293 | fn drop(&mut self) { |
| 217 | self.scl.as_ref().map(|x| x.set_as_disconnected()); | 294 | self.scl.as_ref().map(|x| x.set_as_disconnected()); |
| 218 | self.sda.as_ref().map(|x| x.set_as_disconnected()); | 295 | self.sda.as_ref().map(|x| x.set_as_disconnected()); |
| @@ -329,27 +406,39 @@ foreach_peripheral!( | |||
| 329 | }; | 406 | }; |
| 330 | ); | 407 | ); |
| 331 | 408 | ||
| 332 | impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M> { | 409 | impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> |
| 410 | embedded_hal_02::blocking::i2c::Read<A> for I2c<'d, M, IM> | ||
| 411 | where | ||
| 412 | A: Into<Address>, | ||
| 413 | { | ||
| 333 | type Error = Error; | 414 | type Error = Error; |
| 334 | 415 | ||
| 335 | fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { | 416 | fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> { |
| 336 | self.blocking_read(address, buffer) | 417 | self.blocking_read(address.into(), buffer) |
| 337 | } | 418 | } |
| 338 | } | 419 | } |
| 339 | 420 | ||
| 340 | impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M> { | 421 | impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> |
| 422 | embedded_hal_02::blocking::i2c::Write<A> for I2c<'d, M, IM> | ||
| 423 | where | ||
| 424 | A: Into<Address>, | ||
| 425 | { | ||
| 341 | type Error = Error; | 426 | type Error = Error; |
| 342 | 427 | ||
| 343 | fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { | 428 | fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { |
| 344 | self.blocking_write(address, write) | 429 | self.blocking_write(address.into(), write) |
| 345 | } | 430 | } |
| 346 | } | 431 | } |
| 347 | 432 | ||
| 348 | impl<'d, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M> { | 433 | impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> |
| 434 | embedded_hal_02::blocking::i2c::WriteRead<A> for I2c<'d, M, IM> | ||
| 435 | where | ||
| 436 | A: Into<Address>, | ||
| 437 | { | ||
| 349 | type Error = Error; | 438 | type Error = Error; |
| 350 | 439 | ||
| 351 | fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { | 440 | fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { |
| 352 | self.blocking_write_read(address, write, read) | 441 | self.blocking_write_read(address.into(), write, read) |
| 353 | } | 442 | } |
| 354 | } | 443 | } |
| 355 | 444 | ||
| @@ -369,51 +458,57 @@ impl embedded_hal_1::i2c::Error for Error { | |||
| 369 | } | 458 | } |
| 370 | } | 459 | } |
| 371 | 460 | ||
| 372 | impl<'d, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, M> { | 461 | impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::ErrorType for I2c<'d, M, IM> { |
| 373 | type Error = Error; | 462 | type Error = Error; |
| 374 | } | 463 | } |
| 375 | 464 | ||
| 376 | impl<'d, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, M> { | 465 | impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_1::i2c::AddressMode> embedded_hal_1::i2c::I2c<A> for I2c<'d, M, IM> |
| 377 | fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { | 466 | where |
| 378 | self.blocking_read(address, read) | 467 | Address: From<A>, |
| 468 | { | ||
| 469 | fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { | ||
| 470 | self.blocking_read(address.into(), read) | ||
| 379 | } | 471 | } |
| 380 | 472 | ||
| 381 | fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { | 473 | fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { |
| 382 | self.blocking_write(address, write) | 474 | self.blocking_write(address.into(), write) |
| 383 | } | 475 | } |
| 384 | 476 | ||
| 385 | fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { | 477 | fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { |
| 386 | self.blocking_write_read(address, write, read) | 478 | self.blocking_write_read(address.into(), write, read) |
| 387 | } | 479 | } |
| 388 | 480 | ||
| 389 | fn transaction( | 481 | fn transaction( |
| 390 | &mut self, | 482 | &mut self, |
| 391 | address: u8, | 483 | address: A, |
| 392 | operations: &mut [embedded_hal_1::i2c::Operation<'_>], | 484 | operations: &mut [embedded_hal_1::i2c::Operation<'_>], |
| 393 | ) -> Result<(), Self::Error> { | 485 | ) -> Result<(), Self::Error> { |
| 394 | self.blocking_transaction(address, operations) | 486 | self.blocking_transaction(address.into(), operations) |
| 395 | } | 487 | } |
| 396 | } | 488 | } |
| 397 | 489 | ||
| 398 | impl<'d> embedded_hal_async::i2c::I2c for I2c<'d, Async> { | 490 | impl<'d, IM: MasterMode, A: embedded_hal_async::i2c::AddressMode> embedded_hal_async::i2c::I2c<A> for I2c<'d, Async, IM> |
| 399 | async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { | 491 | where |
| 400 | self.read(address, read).await | 492 | Address: From<A>, |
| 493 | { | ||
| 494 | async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { | ||
| 495 | self.read(address.into(), read).await | ||
| 401 | } | 496 | } |
| 402 | 497 | ||
| 403 | async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { | 498 | async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { |
| 404 | self.write(address, write).await | 499 | self.write(address.into(), write).await |
| 405 | } | 500 | } |
| 406 | 501 | ||
| 407 | async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { | 502 | async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { |
| 408 | self.write_read(address, write, read).await | 503 | self.write_read(address.into(), write, read).await |
| 409 | } | 504 | } |
| 410 | 505 | ||
| 411 | async fn transaction( | 506 | async fn transaction( |
| 412 | &mut self, | 507 | &mut self, |
| 413 | address: u8, | 508 | address: A, |
| 414 | operations: &mut [embedded_hal_1::i2c::Operation<'_>], | 509 | operations: &mut [embedded_hal_1::i2c::Operation<'_>], |
| 415 | ) -> Result<(), Self::Error> { | 510 | ) -> Result<(), Self::Error> { |
| 416 | self.transaction(address, operations).await | 511 | self.transaction(address.into(), operations).await |
| 417 | } | 512 | } |
| 418 | } | 513 | } |
| 419 | 514 | ||
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 8c8df79dd..c2560d819 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -2,9 +2,12 @@ use core::cmp; | |||
| 2 | use core::future::poll_fn; | 2 | use core::future::poll_fn; |
| 3 | use core::task::Poll; | 3 | use core::task::Poll; |
| 4 | 4 | ||
| 5 | use config::{Address, OwnAddresses, OA2}; | ||
| 5 | use embassy_embedded_hal::SetConfig; | 6 | use embassy_embedded_hal::SetConfig; |
| 6 | use embassy_hal_internal::drop::OnDrop; | 7 | use embassy_hal_internal::drop::OnDrop; |
| 7 | use embedded_hal_1::i2c::Operation; | 8 | use embedded_hal_1::i2c::Operation; |
| 9 | use mode::Master; | ||
| 10 | use stm32_metapac::i2c::vals::Addmode; | ||
| 8 | 11 | ||
| 9 | use super::*; | 12 | use super::*; |
| 10 | use crate::pac::i2c; | 13 | use crate::pac::i2c; |
| @@ -13,17 +16,21 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() { | |||
| 13 | let regs = T::info().regs; | 16 | let regs = T::info().regs; |
| 14 | let isr = regs.isr().read(); | 17 | let isr = regs.isr().read(); |
| 15 | 18 | ||
| 16 | if isr.tcr() || isr.tc() { | 19 | if isr.tcr() || isr.tc() || isr.addr() || isr.stopf() { |
| 17 | T::state().waker.wake(); | 20 | T::state().waker.wake(); |
| 18 | } | 21 | } |
| 19 | // The flag can only be cleared by writting to nbytes, we won't do that here, so disable | 22 | |
| 20 | // the interrupt | ||
| 21 | critical_section::with(|_| { | 23 | critical_section::with(|_| { |
| 22 | regs.cr1().modify(|w| w.set_tcie(false)); | 24 | regs.cr1().modify(|w| { |
| 25 | w.set_addrie(false); | ||
| 26 | // The flag can only be cleared by writting to nbytes, we won't do that here, so disable | ||
| 27 | // the interrupt | ||
| 28 | w.set_tcie(false); | ||
| 29 | }); | ||
| 23 | }); | 30 | }); |
| 24 | } | 31 | } |
| 25 | 32 | ||
| 26 | impl<'d, M: Mode> I2c<'d, M> { | 33 | impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { |
| 27 | pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { | 34 | pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { |
| 28 | self.info.regs.cr1().modify(|reg| { | 35 | self.info.regs.cr1().modify(|reg| { |
| 29 | reg.set_pe(false); | 36 | reg.set_pe(false); |
| @@ -51,7 +58,7 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 51 | 58 | ||
| 52 | fn master_read( | 59 | fn master_read( |
| 53 | info: &'static Info, | 60 | info: &'static Info, |
| 54 | address: u8, | 61 | address: Address, |
| 55 | length: usize, | 62 | length: usize, |
| 56 | stop: Stop, | 63 | stop: Stop, |
| 57 | reload: bool, | 64 | reload: bool, |
| @@ -80,8 +87,8 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 80 | }; | 87 | }; |
| 81 | 88 | ||
| 82 | info.regs.cr2().modify(|w| { | 89 | info.regs.cr2().modify(|w| { |
| 83 | w.set_sadd((address << 1 | 0) as u16); | 90 | w.set_sadd(address.addr() << 1); |
| 84 | w.set_add10(i2c::vals::Addmode::BIT7); | 91 | w.set_add10(address.add_mode()); |
| 85 | w.set_dir(i2c::vals::Dir::READ); | 92 | w.set_dir(i2c::vals::Dir::READ); |
| 86 | w.set_nbytes(length as u8); | 93 | w.set_nbytes(length as u8); |
| 87 | w.set_start(true); | 94 | w.set_start(true); |
| @@ -94,7 +101,7 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 94 | 101 | ||
| 95 | fn master_write( | 102 | fn master_write( |
| 96 | info: &'static Info, | 103 | info: &'static Info, |
| 97 | address: u8, | 104 | address: Address, |
| 98 | length: usize, | 105 | length: usize, |
| 99 | stop: Stop, | 106 | stop: Stop, |
| 100 | reload: bool, | 107 | reload: bool, |
| @@ -124,8 +131,8 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 124 | // START bit can be set even if the bus is BUSY or | 131 | // START bit can be set even if the bus is BUSY or |
| 125 | // I2C is in slave mode. | 132 | // I2C is in slave mode. |
| 126 | info.regs.cr2().modify(|w| { | 133 | info.regs.cr2().modify(|w| { |
| 127 | w.set_sadd((address << 1 | 0) as u16); | 134 | w.set_sadd(address.addr() << 1); |
| 128 | w.set_add10(i2c::vals::Addmode::BIT7); | 135 | w.set_add10(address.add_mode()); |
| 129 | w.set_dir(i2c::vals::Dir::WRITE); | 136 | w.set_dir(i2c::vals::Dir::WRITE); |
| 130 | w.set_nbytes(length as u8); | 137 | w.set_nbytes(length as u8); |
| 131 | w.set_start(true); | 138 | w.set_start(true); |
| @@ -136,14 +143,14 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 136 | Ok(()) | 143 | Ok(()) |
| 137 | } | 144 | } |
| 138 | 145 | ||
| 139 | fn master_continue(info: &'static Info, length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> { | 146 | fn reload(info: &'static Info, length: usize, will_reload: bool, timeout: Timeout) -> Result<(), Error> { |
| 140 | assert!(length < 256 && length > 0); | 147 | assert!(length < 256 && length > 0); |
| 141 | 148 | ||
| 142 | while !info.regs.isr().read().tcr() { | 149 | while !info.regs.isr().read().tcr() { |
| 143 | timeout.check()?; | 150 | timeout.check()?; |
| 144 | } | 151 | } |
| 145 | 152 | ||
| 146 | let reload = if reload { | 153 | let will_reload = if will_reload { |
| 147 | i2c::vals::Reload::NOTCOMPLETED | 154 | i2c::vals::Reload::NOTCOMPLETED |
| 148 | } else { | 155 | } else { |
| 149 | i2c::vals::Reload::COMPLETED | 156 | i2c::vals::Reload::COMPLETED |
| @@ -151,7 +158,7 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 151 | 158 | ||
| 152 | info.regs.cr2().modify(|w| { | 159 | info.regs.cr2().modify(|w| { |
| 153 | w.set_nbytes(length as u8); | 160 | w.set_nbytes(length as u8); |
| 154 | w.set_reload(reload); | 161 | w.set_reload(will_reload); |
| 155 | }); | 162 | }); |
| 156 | 163 | ||
| 157 | Ok(()) | 164 | Ok(()) |
| @@ -229,7 +236,13 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 229 | } | 236 | } |
| 230 | } | 237 | } |
| 231 | 238 | ||
| 232 | fn read_internal(&mut self, address: u8, read: &mut [u8], restart: bool, timeout: Timeout) -> Result<(), Error> { | 239 | fn read_internal( |
| 240 | &mut self, | ||
| 241 | address: Address, | ||
| 242 | read: &mut [u8], | ||
| 243 | restart: bool, | ||
| 244 | timeout: Timeout, | ||
| 245 | ) -> Result<(), Error> { | ||
| 233 | let completed_chunks = read.len() / 255; | 246 | let completed_chunks = read.len() / 255; |
| 234 | let total_chunks = if completed_chunks * 255 == read.len() { | 247 | let total_chunks = if completed_chunks * 255 == read.len() { |
| 235 | completed_chunks | 248 | completed_chunks |
| @@ -250,7 +263,7 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 250 | 263 | ||
| 251 | for (number, chunk) in read.chunks_mut(255).enumerate() { | 264 | for (number, chunk) in read.chunks_mut(255).enumerate() { |
| 252 | if number != 0 { | 265 | if number != 0 { |
| 253 | Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?; | 266 | Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; |
| 254 | } | 267 | } |
| 255 | 268 | ||
| 256 | for byte in chunk { | 269 | for byte in chunk { |
| @@ -263,7 +276,13 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 263 | Ok(()) | 276 | Ok(()) |
| 264 | } | 277 | } |
| 265 | 278 | ||
| 266 | fn write_internal(&mut self, address: u8, write: &[u8], send_stop: bool, timeout: Timeout) -> Result<(), Error> { | 279 | fn write_internal( |
| 280 | &mut self, | ||
| 281 | address: Address, | ||
| 282 | write: &[u8], | ||
| 283 | send_stop: bool, | ||
| 284 | timeout: Timeout, | ||
| 285 | ) -> Result<(), Error> { | ||
| 267 | let completed_chunks = write.len() / 255; | 286 | let completed_chunks = write.len() / 255; |
| 268 | let total_chunks = if completed_chunks * 255 == write.len() { | 287 | let total_chunks = if completed_chunks * 255 == write.len() { |
| 269 | completed_chunks | 288 | completed_chunks |
| @@ -291,7 +310,7 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 291 | 310 | ||
| 292 | for (number, chunk) in write.chunks(255).enumerate() { | 311 | for (number, chunk) in write.chunks(255).enumerate() { |
| 293 | if number != 0 { | 312 | if number != 0 { |
| 294 | Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?; | 313 | Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; |
| 295 | } | 314 | } |
| 296 | 315 | ||
| 297 | for byte in chunk { | 316 | for byte in chunk { |
| @@ -320,18 +339,18 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 320 | // Blocking public API | 339 | // Blocking public API |
| 321 | 340 | ||
| 322 | /// Blocking read. | 341 | /// Blocking read. |
| 323 | pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { | 342 | pub fn blocking_read(&mut self, address: Address, read: &mut [u8]) -> Result<(), Error> { |
| 324 | self.read_internal(address, read, false, self.timeout()) | 343 | self.read_internal(address, read, false, self.timeout()) |
| 325 | // Automatic Stop | 344 | // Automatic Stop |
| 326 | } | 345 | } |
| 327 | 346 | ||
| 328 | /// Blocking write. | 347 | /// Blocking write. |
| 329 | pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { | 348 | pub fn blocking_write(&mut self, address: Address, write: &[u8]) -> Result<(), Error> { |
| 330 | self.write_internal(address, write, true, self.timeout()) | 349 | self.write_internal(address, write, true, self.timeout()) |
| 331 | } | 350 | } |
| 332 | 351 | ||
| 333 | /// Blocking write, restart, read. | 352 | /// Blocking write, restart, read. |
| 334 | pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { | 353 | pub fn blocking_write_read(&mut self, address: Address, write: &[u8], read: &mut [u8]) -> Result<(), Error> { |
| 335 | let timeout = self.timeout(); | 354 | let timeout = self.timeout(); |
| 336 | self.write_internal(address, write, false, timeout)?; | 355 | self.write_internal(address, write, false, timeout)?; |
| 337 | self.read_internal(address, read, true, timeout) | 356 | self.read_internal(address, read, true, timeout) |
| @@ -343,7 +362,7 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 343 | /// Consecutive operations of same type are merged. See [transaction contract] for details. | 362 | /// Consecutive operations of same type are merged. See [transaction contract] for details. |
| 344 | /// | 363 | /// |
| 345 | /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction | 364 | /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction |
| 346 | pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { | 365 | pub fn blocking_transaction(&mut self, addr: Address, operations: &mut [Operation<'_>]) -> Result<(), Error> { |
| 347 | let _ = addr; | 366 | let _ = addr; |
| 348 | let _ = operations; | 367 | let _ = operations; |
| 349 | todo!() | 368 | todo!() |
| @@ -352,7 +371,7 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 352 | /// Blocking write multiple buffers. | 371 | /// Blocking write multiple buffers. |
| 353 | /// | 372 | /// |
| 354 | /// The buffers are concatenated in a single write transaction. | 373 | /// The buffers are concatenated in a single write transaction. |
| 355 | pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { | 374 | pub fn blocking_write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> { |
| 356 | if write.is_empty() { | 375 | if write.is_empty() { |
| 357 | return Err(Error::ZeroLengthTransfer); | 376 | return Err(Error::ZeroLengthTransfer); |
| 358 | } | 377 | } |
| @@ -385,7 +404,7 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 385 | let last_chunk_idx = total_chunks.saturating_sub(1); | 404 | let last_chunk_idx = total_chunks.saturating_sub(1); |
| 386 | 405 | ||
| 387 | if idx != 0 { | 406 | if idx != 0 { |
| 388 | if let Err(err) = Self::master_continue( | 407 | if let Err(err) = Self::reload( |
| 389 | self.info, | 408 | self.info, |
| 390 | slice_len.min(255), | 409 | slice_len.min(255), |
| 391 | (idx != last_slice_index) || (slice_len > 255), | 410 | (idx != last_slice_index) || (slice_len > 255), |
| @@ -398,7 +417,7 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 398 | 417 | ||
| 399 | for (number, chunk) in slice.chunks(255).enumerate() { | 418 | for (number, chunk) in slice.chunks(255).enumerate() { |
| 400 | if number != 0 { | 419 | if number != 0 { |
| 401 | if let Err(err) = Self::master_continue( | 420 | if let Err(err) = Self::reload( |
| 402 | self.info, | 421 | self.info, |
| 403 | chunk.len(), | 422 | chunk.len(), |
| 404 | (number != last_chunk_idx) || (idx != last_slice_index), | 423 | (number != last_chunk_idx) || (idx != last_slice_index), |
| @@ -431,10 +450,10 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 431 | } | 450 | } |
| 432 | } | 451 | } |
| 433 | 452 | ||
| 434 | impl<'d> I2c<'d, Async> { | 453 | impl<'d, IM: MasterMode> I2c<'d, Async, IM> { |
| 435 | async fn write_dma_internal( | 454 | async fn write_dma_internal( |
| 436 | &mut self, | 455 | &mut self, |
| 437 | address: u8, | 456 | address: Address, |
| 438 | write: &[u8], | 457 | write: &[u8], |
| 439 | first_slice: bool, | 458 | first_slice: bool, |
| 440 | last_slice: bool, | 459 | last_slice: bool, |
| @@ -482,7 +501,7 @@ impl<'d> I2c<'d, Async> { | |||
| 482 | timeout, | 501 | timeout, |
| 483 | )?; | 502 | )?; |
| 484 | } else { | 503 | } else { |
| 485 | Self::master_continue(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?; | 504 | Self::reload(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?; |
| 486 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); | 505 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); |
| 487 | } | 506 | } |
| 488 | } else if !(isr.tcr() || isr.tc()) { | 507 | } else if !(isr.tcr() || isr.tc()) { |
| @@ -493,7 +512,7 @@ impl<'d> I2c<'d, Async> { | |||
| 493 | } else { | 512 | } else { |
| 494 | let last_piece = (remaining_len <= 255) && last_slice; | 513 | let last_piece = (remaining_len <= 255) && last_slice; |
| 495 | 514 | ||
| 496 | if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { | 515 | if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) { |
| 497 | return Poll::Ready(Err(e)); | 516 | return Poll::Ready(Err(e)); |
| 498 | } | 517 | } |
| 499 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); | 518 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); |
| @@ -519,7 +538,7 @@ impl<'d> I2c<'d, Async> { | |||
| 519 | 538 | ||
| 520 | async fn read_dma_internal( | 539 | async fn read_dma_internal( |
| 521 | &mut self, | 540 | &mut self, |
| 522 | address: u8, | 541 | address: Address, |
| 523 | buffer: &mut [u8], | 542 | buffer: &mut [u8], |
| 524 | restart: bool, | 543 | restart: bool, |
| 525 | timeout: Timeout, | 544 | timeout: Timeout, |
| @@ -569,7 +588,7 @@ impl<'d> I2c<'d, Async> { | |||
| 569 | } else { | 588 | } else { |
| 570 | let last_piece = remaining_len <= 255; | 589 | let last_piece = remaining_len <= 255; |
| 571 | 590 | ||
| 572 | if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { | 591 | if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) { |
| 573 | return Poll::Ready(Err(e)); | 592 | return Poll::Ready(Err(e)); |
| 574 | } | 593 | } |
| 575 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); | 594 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); |
| @@ -590,12 +609,11 @@ impl<'d> I2c<'d, Async> { | |||
| 590 | 609 | ||
| 591 | Ok(()) | 610 | Ok(()) |
| 592 | } | 611 | } |
| 593 | |||
| 594 | // ========================= | 612 | // ========================= |
| 595 | // Async public API | 613 | // Async public API |
| 596 | 614 | ||
| 597 | /// Write. | 615 | /// Write. |
| 598 | pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { | 616 | pub async fn write(&mut self, address: Address, write: &[u8]) -> Result<(), Error> { |
| 599 | let timeout = self.timeout(); | 617 | let timeout = self.timeout(); |
| 600 | if write.is_empty() { | 618 | if write.is_empty() { |
| 601 | self.write_internal(address, write, true, timeout) | 619 | self.write_internal(address, write, true, timeout) |
| @@ -609,7 +627,7 @@ impl<'d> I2c<'d, Async> { | |||
| 609 | /// Write multiple buffers. | 627 | /// Write multiple buffers. |
| 610 | /// | 628 | /// |
| 611 | /// The buffers are concatenated in a single write transaction. | 629 | /// The buffers are concatenated in a single write transaction. |
| 612 | pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { | 630 | pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> { |
| 613 | let timeout = self.timeout(); | 631 | let timeout = self.timeout(); |
| 614 | 632 | ||
| 615 | if write.is_empty() { | 633 | if write.is_empty() { |
| @@ -632,7 +650,7 @@ impl<'d> I2c<'d, Async> { | |||
| 632 | } | 650 | } |
| 633 | 651 | ||
| 634 | /// Read. | 652 | /// Read. |
| 635 | pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { | 653 | pub async fn read(&mut self, address: Address, buffer: &mut [u8]) -> Result<(), Error> { |
| 636 | let timeout = self.timeout(); | 654 | let timeout = self.timeout(); |
| 637 | 655 | ||
| 638 | if buffer.is_empty() { | 656 | if buffer.is_empty() { |
| @@ -644,7 +662,7 @@ impl<'d> I2c<'d, Async> { | |||
| 644 | } | 662 | } |
| 645 | 663 | ||
| 646 | /// Write, restart, read. | 664 | /// Write, restart, read. |
| 647 | pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { | 665 | pub async fn write_read(&mut self, address: Address, write: &[u8], read: &mut [u8]) -> Result<(), Error> { |
| 648 | let timeout = self.timeout(); | 666 | let timeout = self.timeout(); |
| 649 | 667 | ||
| 650 | if write.is_empty() { | 668 | if write.is_empty() { |
| @@ -669,13 +687,343 @@ impl<'d> I2c<'d, Async> { | |||
| 669 | /// Consecutive operations of same type are merged. See [transaction contract] for details. | 687 | /// Consecutive operations of same type are merged. See [transaction contract] for details. |
| 670 | /// | 688 | /// |
| 671 | /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction | 689 | /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction |
| 672 | pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { | 690 | pub async fn transaction(&mut self, addr: Address, operations: &mut [Operation<'_>]) -> Result<(), Error> { |
| 673 | let _ = addr; | 691 | let _ = addr; |
| 674 | let _ = operations; | 692 | let _ = operations; |
| 675 | todo!() | 693 | todo!() |
| 676 | } | 694 | } |
| 677 | } | 695 | } |
| 678 | 696 | ||
| 697 | impl<'d, M: Mode> I2c<'d, M, MultiMaster> { | ||
| 698 | pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) { | ||
| 699 | self.info.regs.cr1().modify(|reg| { | ||
| 700 | reg.set_pe(false); | ||
| 701 | }); | ||
| 702 | |||
| 703 | self.info.regs.cr1().modify(|reg| { | ||
| 704 | reg.set_nostretch(false); | ||
| 705 | reg.set_gcen(config.general_call); | ||
| 706 | reg.set_sbc(true); | ||
| 707 | reg.set_pe(true); | ||
| 708 | }); | ||
| 709 | |||
| 710 | self.reconfigure_addresses(config.addr); | ||
| 711 | } | ||
| 712 | |||
| 713 | /// Configure the slave address. | ||
| 714 | pub fn reconfigure_addresses(&mut self, addresses: OwnAddresses) { | ||
| 715 | match addresses { | ||
| 716 | OwnAddresses::OA1(oa1) => self.configure_oa1(oa1), | ||
| 717 | OwnAddresses::OA2(oa2) => self.configure_oa2(oa2), | ||
| 718 | OwnAddresses::Both { oa1, oa2 } => { | ||
| 719 | self.configure_oa1(oa1); | ||
| 720 | self.configure_oa2(oa2); | ||
| 721 | } | ||
| 722 | } | ||
| 723 | } | ||
| 724 | |||
| 725 | fn configure_oa1(&mut self, oa1: Address) { | ||
| 726 | match oa1 { | ||
| 727 | Address::SevenBit(addr) => self.info.regs.oar1().write(|reg| { | ||
| 728 | reg.set_oa1en(false); | ||
| 729 | reg.set_oa1((addr << 1) as u16); | ||
| 730 | reg.set_oa1mode(Addmode::BIT7); | ||
| 731 | reg.set_oa1en(true); | ||
| 732 | }), | ||
| 733 | Address::TenBit(addr) => self.info.regs.oar1().write(|reg| { | ||
| 734 | reg.set_oa1en(false); | ||
| 735 | reg.set_oa1(addr); | ||
| 736 | reg.set_oa1mode(Addmode::BIT10); | ||
| 737 | reg.set_oa1en(true); | ||
| 738 | }), | ||
| 739 | } | ||
| 740 | } | ||
| 741 | |||
| 742 | fn configure_oa2(&mut self, oa2: OA2) { | ||
| 743 | self.info.regs.oar2().write(|reg| { | ||
| 744 | reg.set_oa2en(false); | ||
| 745 | reg.set_oa2msk(oa2.mask.into()); | ||
| 746 | reg.set_oa2(oa2.addr << 1); | ||
| 747 | reg.set_oa2en(true); | ||
| 748 | }); | ||
| 749 | } | ||
| 750 | |||
| 751 | fn determine_matched_address(&self) -> Result<Address, Error> { | ||
| 752 | let matched = self.info.regs.isr().read().addcode(); | ||
| 753 | |||
| 754 | if matched >> 3 == 0b11110 { | ||
| 755 | // is 10-bit address and we need to get the other 8 bits from the rxdr | ||
| 756 | // we do this by doing a blocking read of 1 byte | ||
| 757 | let mut buffer = [0]; | ||
| 758 | self.slave_read_internal(&mut buffer, self.timeout())?; | ||
| 759 | Ok(Address::TenBit((matched as u16) << 6 | buffer[0] as u16)) | ||
| 760 | } else { | ||
| 761 | Ok(Address::SevenBit(matched)) | ||
| 762 | } | ||
| 763 | } | ||
| 764 | } | ||
| 765 | |||
| 766 | impl<'d, M: Mode> I2c<'d, M, MultiMaster> { | ||
| 767 | /// # Safety | ||
| 768 | /// This function will clear the address flag which will stop the clock stretching. | ||
| 769 | /// This should only be done after the dma transfer has been set up. | ||
| 770 | fn slave_start(info: &'static Info, length: usize, reload: bool) { | ||
| 771 | assert!(length < 256); | ||
| 772 | |||
| 773 | let reload = if reload { | ||
| 774 | i2c::vals::Reload::NOTCOMPLETED | ||
| 775 | } else { | ||
| 776 | i2c::vals::Reload::COMPLETED | ||
| 777 | }; | ||
| 778 | |||
| 779 | info.regs.cr2().modify(|w| { | ||
| 780 | w.set_nbytes(length as u8); | ||
| 781 | w.set_reload(reload); | ||
| 782 | }); | ||
| 783 | |||
| 784 | // clear the address flag, will stop the clock stretching. | ||
| 785 | // this should only be done after the dma transfer has been set up. | ||
| 786 | info.regs.icr().modify(|reg| reg.set_addrcf(true)); | ||
| 787 | } | ||
| 788 | |||
| 789 | // A blocking read operation | ||
| 790 | fn slave_read_internal(&self, read: &mut [u8], timeout: Timeout) -> Result<(), Error> { | ||
| 791 | let completed_chunks = read.len() / 255; | ||
| 792 | let total_chunks = if completed_chunks * 255 == read.len() { | ||
| 793 | completed_chunks | ||
| 794 | } else { | ||
| 795 | completed_chunks + 1 | ||
| 796 | }; | ||
| 797 | let last_chunk_idx = total_chunks.saturating_sub(1); | ||
| 798 | for (number, chunk) in read.chunks_mut(255).enumerate() { | ||
| 799 | if number != 0 { | ||
| 800 | Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; | ||
| 801 | } | ||
| 802 | |||
| 803 | for byte in chunk { | ||
| 804 | // Wait until we have received something | ||
| 805 | self.wait_rxne(timeout)?; | ||
| 806 | |||
| 807 | *byte = self.info.regs.rxdr().read().rxdata(); | ||
| 808 | } | ||
| 809 | } | ||
| 810 | |||
| 811 | Ok(()) | ||
| 812 | } | ||
| 813 | |||
| 814 | // A blocking write operation | ||
| 815 | fn slave_write_internal(&mut self, write: &[u8], timeout: Timeout) -> Result<(), Error> { | ||
| 816 | let completed_chunks = write.len() / 255; | ||
| 817 | let total_chunks = if completed_chunks * 255 == write.len() { | ||
| 818 | completed_chunks | ||
| 819 | } else { | ||
| 820 | completed_chunks + 1 | ||
| 821 | }; | ||
| 822 | let last_chunk_idx = total_chunks.saturating_sub(1); | ||
| 823 | |||
| 824 | for (number, chunk) in write.chunks(255).enumerate() { | ||
| 825 | if number != 0 { | ||
| 826 | Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; | ||
| 827 | } | ||
| 828 | |||
| 829 | for byte in chunk { | ||
| 830 | // Wait until we are allowed to send data | ||
| 831 | // (START has been ACKed or last byte when | ||
| 832 | // through) | ||
| 833 | self.wait_txe(timeout)?; | ||
| 834 | |||
| 835 | self.info.regs.txdr().write(|w| w.set_txdata(*byte)); | ||
| 836 | } | ||
| 837 | } | ||
| 838 | Ok(()) | ||
| 839 | } | ||
| 840 | |||
| 841 | /// Listen for incoming I2C messages. | ||
| 842 | /// | ||
| 843 | /// The listen method is an asynchronous method but it does not require DMA to be asynchronous. | ||
| 844 | pub async fn listen(&mut self) -> Result<Command, Error> { | ||
| 845 | let state = self.state; | ||
| 846 | self.info.regs.cr1().modify(|reg| { | ||
| 847 | reg.set_addrie(true); | ||
| 848 | }); | ||
| 849 | |||
| 850 | poll_fn(|cx| { | ||
| 851 | state.waker.register(cx.waker()); | ||
| 852 | let isr = self.info.regs.isr().read(); | ||
| 853 | if !isr.addr() { | ||
| 854 | Poll::Pending | ||
| 855 | } else { | ||
| 856 | // we do not clear the address flag here as it will be cleared by the dma read/write | ||
| 857 | // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it | ||
| 858 | match isr.dir() { | ||
| 859 | i2c::vals::Dir::WRITE => Poll::Ready(Ok(Command { | ||
| 860 | kind: CommandKind::SlaveReceive, | ||
| 861 | address: self.determine_matched_address()?, | ||
| 862 | })), | ||
| 863 | i2c::vals::Dir::READ => Poll::Ready(Ok(Command { | ||
| 864 | kind: CommandKind::SlaveSend, | ||
| 865 | address: self.determine_matched_address()?, | ||
| 866 | })), | ||
| 867 | } | ||
| 868 | } | ||
| 869 | }) | ||
| 870 | .await | ||
| 871 | } | ||
| 872 | |||
| 873 | /// Respond to a receive command. | ||
| 874 | pub fn blocking_respond_to_receive(&self, read: &mut [u8]) -> Result<(), Error> { | ||
| 875 | let timeout = self.timeout(); | ||
| 876 | self.slave_read_internal(read, timeout) | ||
| 877 | } | ||
| 878 | |||
| 879 | /// Respond to a send command. | ||
| 880 | pub fn blocking_respond_to_send(&mut self, write: &[u8]) -> Result<(), Error> { | ||
| 881 | let timeout = self.timeout(); | ||
| 882 | self.slave_write_internal(write, timeout) | ||
| 883 | } | ||
| 884 | } | ||
| 885 | |||
| 886 | impl<'d> I2c<'d, Async, MultiMaster> { | ||
| 887 | /// Respond to a receive command. | ||
| 888 | pub async fn respond_to_receive(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { | ||
| 889 | let timeout = self.timeout(); | ||
| 890 | timeout.with(self.read_dma_internal_slave(buffer, timeout)).await | ||
| 891 | } | ||
| 892 | |||
| 893 | /// Respond to a send request from an I2C master. | ||
| 894 | pub async fn respond_to_send(&mut self, write: &[u8]) -> Result<SendStatus, Error> { | ||
| 895 | let timeout = self.timeout(); | ||
| 896 | timeout.with(self.write_dma_internal_slave(write, timeout)).await | ||
| 897 | } | ||
| 898 | |||
| 899 | // for data reception in slave mode | ||
| 900 | async fn read_dma_internal_slave(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> { | ||
| 901 | let total_len = buffer.len(); | ||
| 902 | let mut remaining_len = total_len; | ||
| 903 | |||
| 904 | let regs = self.info.regs; | ||
| 905 | |||
| 906 | let dma_transfer = unsafe { | ||
| 907 | regs.cr1().modify(|w| { | ||
| 908 | w.set_rxdmaen(true); | ||
| 909 | w.set_stopie(true); | ||
| 910 | w.set_tcie(true); | ||
| 911 | }); | ||
| 912 | let src = regs.rxdr().as_ptr() as *mut u8; | ||
| 913 | |||
| 914 | self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default()) | ||
| 915 | }; | ||
| 916 | |||
| 917 | let state = self.state; | ||
| 918 | |||
| 919 | let on_drop = OnDrop::new(|| { | ||
| 920 | regs.cr1().modify(|w| { | ||
| 921 | w.set_rxdmaen(false); | ||
| 922 | w.set_stopie(false); | ||
| 923 | w.set_tcie(false); | ||
| 924 | }) | ||
| 925 | }); | ||
| 926 | |||
| 927 | let total_received = poll_fn(|cx| { | ||
| 928 | state.waker.register(cx.waker()); | ||
| 929 | |||
| 930 | let isr = regs.isr().read(); | ||
| 931 | |||
| 932 | if remaining_len == total_len { | ||
| 933 | Self::slave_start(self.info, total_len.min(255), total_len > 255); | ||
| 934 | remaining_len = remaining_len.saturating_sub(255); | ||
| 935 | Poll::Pending | ||
| 936 | } else if isr.tcr() { | ||
| 937 | let is_last_slice = remaining_len <= 255; | ||
| 938 | if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) { | ||
| 939 | return Poll::Ready(Err(e)); | ||
| 940 | } | ||
| 941 | remaining_len = remaining_len.saturating_sub(255); | ||
| 942 | regs.cr1().modify(|w| w.set_tcie(true)); | ||
| 943 | Poll::Pending | ||
| 944 | } else if isr.stopf() { | ||
| 945 | regs.icr().write(|reg| reg.set_stopcf(true)); | ||
| 946 | let poll = Poll::Ready(Ok(remaining_len)); | ||
| 947 | poll | ||
| 948 | } else { | ||
| 949 | Poll::Pending | ||
| 950 | } | ||
| 951 | }) | ||
| 952 | .await?; | ||
| 953 | |||
| 954 | dma_transfer.await; | ||
| 955 | |||
| 956 | drop(on_drop); | ||
| 957 | |||
| 958 | Ok(total_received) | ||
| 959 | } | ||
| 960 | |||
| 961 | async fn write_dma_internal_slave(&mut self, buffer: &[u8], timeout: Timeout) -> Result<SendStatus, Error> { | ||
| 962 | let total_len = buffer.len(); | ||
| 963 | let mut remaining_len = total_len; | ||
| 964 | |||
| 965 | let mut dma_transfer = unsafe { | ||
| 966 | let regs = self.info.regs; | ||
| 967 | regs.cr1().modify(|w| { | ||
| 968 | w.set_txdmaen(true); | ||
| 969 | w.set_stopie(true); | ||
| 970 | w.set_tcie(true); | ||
| 971 | }); | ||
| 972 | let dst = regs.txdr().as_ptr() as *mut u8; | ||
| 973 | |||
| 974 | self.tx_dma.as_mut().unwrap().write(buffer, dst, Default::default()) | ||
| 975 | }; | ||
| 976 | |||
| 977 | let on_drop = OnDrop::new(|| { | ||
| 978 | let regs = self.info.regs; | ||
| 979 | regs.cr1().modify(|w| { | ||
| 980 | w.set_txdmaen(false); | ||
| 981 | w.set_stopie(false); | ||
| 982 | w.set_tcie(false); | ||
| 983 | }) | ||
| 984 | }); | ||
| 985 | |||
| 986 | let state = self.state; | ||
| 987 | |||
| 988 | let size = poll_fn(|cx| { | ||
| 989 | state.waker.register(cx.waker()); | ||
| 990 | |||
| 991 | let isr = self.info.regs.isr().read(); | ||
| 992 | |||
| 993 | if remaining_len == total_len { | ||
| 994 | Self::slave_start(self.info, total_len.min(255), total_len > 255); | ||
| 995 | remaining_len = remaining_len.saturating_sub(255); | ||
| 996 | Poll::Pending | ||
| 997 | } else if isr.tcr() { | ||
| 998 | let is_last_slice = remaining_len <= 255; | ||
| 999 | if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) { | ||
| 1000 | return Poll::Ready(Err(e)); | ||
| 1001 | } | ||
| 1002 | remaining_len = remaining_len.saturating_sub(255); | ||
| 1003 | self.info.regs.cr1().modify(|w| w.set_tcie(true)); | ||
| 1004 | Poll::Pending | ||
| 1005 | } else if isr.stopf() { | ||
| 1006 | self.info.regs.icr().write(|reg| reg.set_stopcf(true)); | ||
| 1007 | if remaining_len > 0 { | ||
| 1008 | dma_transfer.request_stop(); | ||
| 1009 | Poll::Ready(Ok(SendStatus::LeftoverBytes(remaining_len as usize))) | ||
| 1010 | } else { | ||
| 1011 | Poll::Ready(Ok(SendStatus::Done)) | ||
| 1012 | } | ||
| 1013 | } else { | ||
| 1014 | Poll::Pending | ||
| 1015 | } | ||
| 1016 | }) | ||
| 1017 | .await?; | ||
| 1018 | |||
| 1019 | dma_transfer.await; | ||
| 1020 | |||
| 1021 | drop(on_drop); | ||
| 1022 | |||
| 1023 | Ok(size) | ||
| 1024 | } | ||
| 1025 | } | ||
| 1026 | |||
| 679 | /// I2C Stop Configuration | 1027 | /// I2C Stop Configuration |
| 680 | /// | 1028 | /// |
| 681 | /// Peripheral options for generating the STOP condition | 1029 | /// Peripheral options for generating the STOP condition |
| @@ -800,7 +1148,7 @@ impl Timings { | |||
| 800 | } | 1148 | } |
| 801 | } | 1149 | } |
| 802 | 1150 | ||
| 803 | impl<'d, M: Mode> SetConfig for I2c<'d, M> { | 1151 | impl<'d, M: Mode> SetConfig for I2c<'d, M, Master> { |
| 804 | type Config = Hertz; | 1152 | type Config = Hertz; |
| 805 | type ConfigError = (); | 1153 | type ConfigError = (); |
| 806 | fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { | 1154 | fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { |
| @@ -816,3 +1164,21 @@ impl<'d, M: Mode> SetConfig for I2c<'d, M> { | |||
| 816 | Ok(()) | 1164 | Ok(()) |
| 817 | } | 1165 | } |
| 818 | } | 1166 | } |
| 1167 | |||
| 1168 | impl<'d, M: Mode> SetConfig for I2c<'d, M, MultiMaster> { | ||
| 1169 | type Config = (Hertz, SlaveAddrConfig); | ||
| 1170 | type ConfigError = (); | ||
| 1171 | fn set_config(&mut self, (config, addr_config): &Self::Config) -> Result<(), ()> { | ||
| 1172 | let timings = Timings::new(self.kernel_clock, *config); | ||
| 1173 | self.info.regs.timingr().write(|reg| { | ||
| 1174 | reg.set_presc(timings.prescale); | ||
| 1175 | reg.set_scll(timings.scll); | ||
| 1176 | reg.set_sclh(timings.sclh); | ||
| 1177 | reg.set_sdadel(timings.sdadel); | ||
| 1178 | reg.set_scldel(timings.scldel); | ||
| 1179 | }); | ||
| 1180 | self.init_slave(*addr_config); | ||
| 1181 | |||
| 1182 | Ok(()) | ||
| 1183 | } | ||
| 1184 | } | ||
