1 | //! Inter-Integrated-Circuit (I2C) |
2 | #![macro_use ] |
3 | |
4 | #[cfg_attr (i2c_v1, path = "v1.rs" )] |
5 | #[cfg_attr (any(i2c_v2, i2c_v3), path = "v2.rs" )] |
6 | mod _version; |
7 | |
8 | use core::future::Future; |
9 | use core::iter; |
10 | use core::marker::PhantomData; |
11 | |
12 | use embassy_hal_internal::{Peripheral, PeripheralRef}; |
13 | use embassy_sync::waitqueue::AtomicWaker; |
14 | #[cfg (feature = "time" )] |
15 | use embassy_time::{Duration, Instant}; |
16 | |
17 | use crate::dma::ChannelAndRequest; |
18 | #[cfg (gpio_v2)] |
19 | use crate::gpio::Pull; |
20 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin as _, Speed}; |
21 | use crate::interrupt::typelevel::Interrupt; |
22 | use crate::mode::{Async, Blocking, Mode}; |
23 | use crate::rcc::{RccInfo, SealedRccPeripheral}; |
24 | use crate::time::Hertz; |
25 | use crate::{interrupt, peripherals}; |
26 | |
27 | /// I2C error. |
28 | #[derive (Debug, PartialEq, Eq, Copy, Clone)] |
29 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
30 | pub enum Error { |
31 | /// Bus error |
32 | Bus, |
33 | /// Arbitration lost |
34 | Arbitration, |
35 | /// ACK not received (either to the address or to a data byte) |
36 | Nack, |
37 | /// Timeout |
38 | Timeout, |
39 | /// CRC error |
40 | Crc, |
41 | /// Overrun error |
42 | Overrun, |
43 | /// Zero-length transfers are not allowed. |
44 | ZeroLengthTransfer, |
45 | } |
46 | |
47 | /// I2C config |
48 | #[non_exhaustive ] |
49 | #[derive (Copy, Clone)] |
50 | pub struct Config { |
51 | /// Enable internal pullup on SDA. |
52 | /// |
53 | /// Using external pullup resistors is recommended for I2C. If you do |
54 | /// have external pullups you should not enable this. |
55 | #[cfg (gpio_v2)] |
56 | pub sda_pullup: bool, |
57 | /// Enable internal pullup on SCL. |
58 | /// |
59 | /// Using external pullup resistors is recommended for I2C. If you do |
60 | /// have external pullups you should not enable this. |
61 | #[cfg (gpio_v2)] |
62 | pub scl_pullup: bool, |
63 | /// Timeout. |
64 | #[cfg (feature = "time" )] |
65 | pub timeout: embassy_time::Duration, |
66 | } |
67 | |
68 | impl Default for Config { |
69 | fn default() -> Self { |
70 | Self { |
71 | #[cfg (gpio_v2)] |
72 | sda_pullup: false, |
73 | #[cfg (gpio_v2)] |
74 | scl_pullup: false, |
75 | #[cfg (feature = "time" )] |
76 | timeout: embassy_time::Duration::from_millis(1000), |
77 | } |
78 | } |
79 | } |
80 | |
81 | impl Config { |
82 | fn scl_af(&self) -> AfType { |
83 | #[cfg (gpio_v1)] |
84 | return AfType::output(OutputType::OpenDrain, Speed::Medium); |
85 | #[cfg (gpio_v2)] |
86 | return AfType::output_pull( |
87 | OutputType::OpenDrain, |
88 | Speed::Medium, |
89 | match self.scl_pullup { |
90 | true => Pull::Up, |
91 | false => Pull::None, |
92 | }, |
93 | ); |
94 | } |
95 | |
96 | fn sda_af(&self) -> AfType { |
97 | #[cfg (gpio_v1)] |
98 | return AfType::output(OutputType::OpenDrain, Speed::Medium); |
99 | #[cfg (gpio_v2)] |
100 | return AfType::output_pull( |
101 | OutputType::OpenDrain, |
102 | Speed::Medium, |
103 | match self.sda_pullup { |
104 | true => Pull::Up, |
105 | false => Pull::None, |
106 | }, |
107 | ); |
108 | } |
109 | } |
110 | |
111 | /// I2C driver. |
112 | pub struct I2c<'d, M: Mode> { |
113 | info: &'static Info, |
114 | state: &'static State, |
115 | kernel_clock: Hertz, |
116 | scl: Option<PeripheralRef<'d, AnyPin>>, |
117 | sda: Option<PeripheralRef<'d, AnyPin>>, |
118 | tx_dma: Option<ChannelAndRequest<'d>>, |
119 | rx_dma: Option<ChannelAndRequest<'d>>, |
120 | #[cfg (feature = "time" )] |
121 | timeout: Duration, |
122 | _phantom: PhantomData<M>, |
123 | } |
124 | |
125 | impl<'d> I2c<'d, Async> { |
126 | /// Create a new I2C driver. |
127 | pub fn new<T: Instance>( |
128 | peri: impl Peripheral<P = T> + 'd, |
129 | scl: impl Peripheral<P = impl SclPin<T>> + 'd, |
130 | sda: impl Peripheral<P = impl SdaPin<T>> + 'd, |
131 | _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>> |
132 | + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>> |
133 | + 'd, |
134 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
135 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
136 | freq: Hertz, |
137 | config: Config, |
138 | ) -> Self { |
139 | Self::new_inner( |
140 | peri, |
141 | new_pin!(scl, config.scl_af()), |
142 | new_pin!(sda, config.sda_af()), |
143 | new_dma!(tx_dma), |
144 | new_dma!(rx_dma), |
145 | freq, |
146 | config, |
147 | ) |
148 | } |
149 | } |
150 | |
151 | impl<'d> I2c<'d, Blocking> { |
152 | /// Create a new blocking I2C driver. |
153 | pub fn new_blocking<T: Instance>( |
154 | peri: impl Peripheral<P = T> + 'd, |
155 | scl: impl Peripheral<P = impl SclPin<T>> + 'd, |
156 | sda: impl Peripheral<P = impl SdaPin<T>> + 'd, |
157 | freq: Hertz, |
158 | config: Config, |
159 | ) -> Self { |
160 | Self::new_inner( |
161 | peri, |
162 | scl:new_pin!(scl, config.scl_af()), |
163 | sda:new_pin!(sda, config.sda_af()), |
164 | tx_dma:None, |
165 | rx_dma:None, |
166 | freq, |
167 | config, |
168 | ) |
169 | } |
170 | } |
171 | |
172 | impl<'d, M: Mode> I2c<'d, M> { |
173 | /// Create a new I2C driver. |
174 | fn new_inner<T: Instance>( |
175 | _peri: impl Peripheral<P = T> + 'd, |
176 | scl: Option<PeripheralRef<'d, AnyPin>>, |
177 | sda: Option<PeripheralRef<'d, AnyPin>>, |
178 | tx_dma: Option<ChannelAndRequest<'d>>, |
179 | rx_dma: Option<ChannelAndRequest<'d>>, |
180 | freq: Hertz, |
181 | config: Config, |
182 | ) -> Self { |
183 | unsafe { T::EventInterrupt::enable() }; |
184 | unsafe { T::ErrorInterrupt::enable() }; |
185 | |
186 | let mut this = Self { |
187 | info: T::info(), |
188 | state: T::state(), |
189 | kernel_clock: T::frequency(), |
190 | scl, |
191 | sda, |
192 | tx_dma, |
193 | rx_dma, |
194 | #[cfg (feature = "time" )] |
195 | timeout: config.timeout, |
196 | _phantom: PhantomData, |
197 | }; |
198 | this.enable_and_init(freq, config); |
199 | this |
200 | } |
201 | |
202 | fn enable_and_init(&mut self, freq: Hertz, config: Config) { |
203 | self.info.rcc.enable_and_reset(); |
204 | self.init(freq, config); |
205 | } |
206 | |
207 | fn timeout(&self) -> Timeout { |
208 | Timeout { |
209 | #[cfg (feature = "time" )] |
210 | deadline: Instant::now() + self.timeout, |
211 | } |
212 | } |
213 | } |
214 | |
215 | impl<'d, M: Mode> Drop for I2c<'d, M> { |
216 | fn drop(&mut self) { |
217 | self.scl.as_ref().map(|x: &PeripheralRef<'_, AnyPin>| x.set_as_disconnected()); |
218 | self.sda.as_ref().map(|x: &PeripheralRef<'_, AnyPin>| x.set_as_disconnected()); |
219 | |
220 | self.info.rcc.disable() |
221 | } |
222 | } |
223 | |
224 | #[derive (Copy, Clone)] |
225 | struct Timeout { |
226 | #[cfg (feature = "time" )] |
227 | deadline: Instant, |
228 | } |
229 | |
230 | #[allow (dead_code)] |
231 | impl Timeout { |
232 | #[inline ] |
233 | fn check(self) -> Result<(), Error> { |
234 | #[cfg (feature = "time" )] |
235 | if Instant::now() > self.deadline { |
236 | return Err(Error::Timeout); |
237 | } |
238 | |
239 | Ok(()) |
240 | } |
241 | |
242 | #[inline ] |
243 | fn with<R>(self, fut: impl Future<Output = Result<R, Error>>) -> impl Future<Output = Result<R, Error>> { |
244 | #[cfg (feature = "time" )] |
245 | { |
246 | use futures_util::FutureExt; |
247 | |
248 | embassy_futures::select::select(embassy_time::Timer::at(self.deadline), fut).map(|r| match r { |
249 | embassy_futures::select::Either::First(_) => Err(Error::Timeout), |
250 | embassy_futures::select::Either::Second(r) => r, |
251 | }) |
252 | } |
253 | |
254 | #[cfg (not(feature = "time" ))] |
255 | fut |
256 | } |
257 | } |
258 | |
259 | struct State { |
260 | #[allow (unused)] |
261 | waker: AtomicWaker, |
262 | } |
263 | |
264 | impl State { |
265 | const fn new() -> Self { |
266 | Self { |
267 | waker: AtomicWaker::new(), |
268 | } |
269 | } |
270 | } |
271 | |
272 | struct Info { |
273 | regs: crate::pac::i2c::I2c, |
274 | rcc: RccInfo, |
275 | } |
276 | |
277 | peri_trait!( |
278 | irqs: [EventInterrupt, ErrorInterrupt], |
279 | ); |
280 | |
281 | pin_trait!(SclPin, Instance); |
282 | pin_trait!(SdaPin, Instance); |
283 | dma_trait!(RxDma, Instance); |
284 | dma_trait!(TxDma, Instance); |
285 | |
286 | /// Event interrupt handler. |
287 | pub struct EventInterruptHandler<T: Instance> { |
288 | _phantom: PhantomData<T>, |
289 | } |
290 | |
291 | impl<T: Instance> interrupt::typelevel::Handler<T::EventInterrupt> for EventInterruptHandler<T> { |
292 | unsafe fn on_interrupt() { |
293 | _version::on_interrupt::<T>() |
294 | } |
295 | } |
296 | |
297 | /// Error interrupt handler. |
298 | pub struct ErrorInterruptHandler<T: Instance> { |
299 | _phantom: PhantomData<T>, |
300 | } |
301 | |
302 | impl<T: Instance> interrupt::typelevel::Handler<T::ErrorInterrupt> for ErrorInterruptHandler<T> { |
303 | unsafe fn on_interrupt() { |
304 | _version::on_interrupt::<T>() |
305 | } |
306 | } |
307 | |
308 | foreach_peripheral!( |
309 | (i2c, $inst:ident) => { |
310 | #[allow(private_interfaces)] |
311 | impl SealedInstance for peripherals::$inst { |
312 | fn info() -> &'static Info { |
313 | static INFO: Info = Info{ |
314 | regs: crate::pac::$inst, |
315 | rcc: crate::peripherals::$inst::RCC_INFO, |
316 | }; |
317 | &INFO |
318 | } |
319 | fn state() -> &'static State { |
320 | static STATE: State = State::new(); |
321 | &STATE |
322 | } |
323 | } |
324 | |
325 | impl Instance for peripherals::$inst { |
326 | type EventInterrupt = crate::_generated::peripheral_interrupts::$inst::EV; |
327 | type ErrorInterrupt = crate::_generated::peripheral_interrupts::$inst::ER; |
328 | } |
329 | }; |
330 | ); |
331 | |
332 | impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M> { |
333 | type Error = Error; |
334 | |
335 | fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { |
336 | self.blocking_read(address, read:buffer) |
337 | } |
338 | } |
339 | |
340 | impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M> { |
341 | type Error = Error; |
342 | |
343 | fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { |
344 | self.blocking_write(address, write) |
345 | } |
346 | } |
347 | |
348 | impl<'d, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M> { |
349 | type Error = Error; |
350 | |
351 | fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { |
352 | self.blocking_write_read(address, write, read) |
353 | } |
354 | } |
355 | |
356 | impl embedded_hal_1::i2c::Error for Error { |
357 | fn kind(&self) -> embedded_hal_1::i2c::ErrorKind { |
358 | match *self { |
359 | Self::Bus => embedded_hal_1::i2c::ErrorKind::Bus, |
360 | Self::Arbitration => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss, |
361 | Self::Nack => { |
362 | embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Unknown) |
363 | } |
364 | Self::Timeout => embedded_hal_1::i2c::ErrorKind::Other, |
365 | Self::Crc => embedded_hal_1::i2c::ErrorKind::Other, |
366 | Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun, |
367 | Self::ZeroLengthTransfer => embedded_hal_1::i2c::ErrorKind::Other, |
368 | } |
369 | } |
370 | } |
371 | |
372 | impl<'d, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, M> { |
373 | type Error = Error; |
374 | } |
375 | |
376 | impl<'d, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, M> { |
377 | fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { |
378 | self.blocking_read(address, read) |
379 | } |
380 | |
381 | fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { |
382 | self.blocking_write(address, write) |
383 | } |
384 | |
385 | fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { |
386 | self.blocking_write_read(address, write, read) |
387 | } |
388 | |
389 | fn transaction( |
390 | &mut self, |
391 | address: u8, |
392 | operations: &mut [embedded_hal_1::i2c::Operation<'_>], |
393 | ) -> Result<(), Self::Error> { |
394 | self.blocking_transaction(addr:address, operations) |
395 | } |
396 | } |
397 | |
398 | impl<'d> embedded_hal_async::i2c::I2c for I2c<'d, Async> { |
399 | async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { |
400 | self.read(address, buffer:read).await |
401 | } |
402 | |
403 | async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { |
404 | self.write(address, write).await |
405 | } |
406 | |
407 | async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { |
408 | self.write_read(address, write, read).await |
409 | } |
410 | |
411 | async fn transaction( |
412 | &mut self, |
413 | address: u8, |
414 | operations: &mut [embedded_hal_1::i2c::Operation<'_>], |
415 | ) -> Result<(), Self::Error> { |
416 | self.transaction(addr:address, operations).await |
417 | } |
418 | } |
419 | |
420 | /// Frame type in I2C transaction. |
421 | /// |
422 | /// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST |
423 | /// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an |
424 | /// ACK or NACK after the last byte received. |
425 | /// |
426 | /// For write operations, the following options are identical because they differ only in the (N)ACK |
427 | /// treatment relevant for read operations: |
428 | /// |
429 | /// - `FirstFrame` and `FirstAndNextFrame` |
430 | /// - `NextFrame` and `LastFrameNoStop` |
431 | /// |
432 | /// Abbreviations used below: |
433 | /// |
434 | /// - `ST` = start condition |
435 | /// - `SR` = repeated start condition |
436 | /// - `SP` = stop condition |
437 | /// - `ACK`/`NACK` = last byte in read operation |
438 | #[derive (Copy, Clone)] |
439 | #[allow (dead_code)] |
440 | enum FrameOptions { |
441 | /// `[ST/SR]+[NACK]+[SP]` First frame (of this type) in transaction and also last frame overall. |
442 | FirstAndLastFrame, |
443 | /// `[ST/SR]+[NACK]` First frame of this type in transaction, last frame in a read operation but |
444 | /// not the last frame overall. |
445 | FirstFrame, |
446 | /// `[ST/SR]+[ACK]` First frame of this type in transaction, neither last frame overall nor last |
447 | /// frame in a read operation. |
448 | FirstAndNextFrame, |
449 | /// `[ACK]` Middle frame in a read operation (neither first nor last). |
450 | NextFrame, |
451 | /// `[NACK]+[SP]` Last frame overall in this transaction but not the first frame. |
452 | LastFrame, |
453 | /// `[NACK]` Last frame in a read operation but not last frame overall in this transaction. |
454 | LastFrameNoStop, |
455 | } |
456 | |
457 | #[allow (dead_code)] |
458 | impl FrameOptions { |
459 | /// Sends start or repeated start condition before transfer. |
460 | fn send_start(self) -> bool { |
461 | match self { |
462 | Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true, |
463 | Self::NextFrame | Self::LastFrame | Self::LastFrameNoStop => false, |
464 | } |
465 | } |
466 | |
467 | /// Sends stop condition after transfer. |
468 | fn send_stop(self) -> bool { |
469 | match self { |
470 | Self::FirstAndLastFrame | Self::LastFrame => true, |
471 | Self::FirstFrame | Self::FirstAndNextFrame | Self::NextFrame | Self::LastFrameNoStop => false, |
472 | } |
473 | } |
474 | |
475 | /// Sends NACK after last byte received, indicating end of read operation. |
476 | fn send_nack(self) -> bool { |
477 | match self { |
478 | Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true, |
479 | Self::FirstAndNextFrame | Self::NextFrame => false, |
480 | } |
481 | } |
482 | } |
483 | |
484 | /// Iterates over operations in transaction. |
485 | /// |
486 | /// Returns necessary frame options for each operation to uphold the [transaction contract] and have |
487 | /// the right start/stop/(N)ACK conditions on the wire. |
488 | /// |
489 | /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction |
490 | #[allow (dead_code)] |
491 | fn operation_frames<'a, 'b: 'a>( |
492 | operations: &'a mut [embedded_hal_1::i2c::Operation<'b>], |
493 | ) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, FrameOptions)>, Error> { |
494 | use embedded_hal_1::i2c::Operation::{Read, Write}; |
495 | |
496 | // Check empty read buffer before starting transaction. Otherwise, we would risk halting with an |
497 | // error in the middle of the transaction. |
498 | // |
499 | // In principle, we could allow empty read frames within consecutive read operations, as long as |
500 | // at least one byte remains in the final (merged) read operation, but that makes the logic more |
501 | // complicated and error-prone. |
502 | if operations.iter().any(|op| match op { |
503 | Read(read) => read.is_empty(), |
504 | Write(_) => false, |
505 | }) { |
506 | return Err(Error::Overrun); |
507 | } |
508 | |
509 | let mut operations = operations.iter_mut().peekable(); |
510 | |
511 | let mut next_first_frame = true; |
512 | |
513 | Ok(iter::from_fn(move || { |
514 | let Some(op) = operations.next() else { |
515 | return None; |
516 | }; |
517 | |
518 | // Is `op` first frame of its type? |
519 | let first_frame = next_first_frame; |
520 | let next_op = operations.peek(); |
521 | |
522 | // Get appropriate frame options as combination of the following properties: |
523 | // |
524 | // - For each first operation of its type, generate a (repeated) start condition. |
525 | // - For the last operation overall in the entire transaction, generate a stop condition. |
526 | // - For read operations, check the next operation: if it is also a read operation, we merge |
527 | // these and send ACK for all bytes in the current operation; send NACK only for the final |
528 | // read operation's last byte (before write or end of entire transaction) to indicate last |
529 | // byte read and release the bus for transmission of the bus master's next byte (or stop). |
530 | // |
531 | // We check the third property unconditionally, i.e. even for write opeartions. This is okay |
532 | // because the resulting frame options are identical for write operations. |
533 | let frame = match (first_frame, next_op) { |
534 | (true, None) => FrameOptions::FirstAndLastFrame, |
535 | (true, Some(Read(_))) => FrameOptions::FirstAndNextFrame, |
536 | (true, Some(Write(_))) => FrameOptions::FirstFrame, |
537 | // |
538 | (false, None) => FrameOptions::LastFrame, |
539 | (false, Some(Read(_))) => FrameOptions::NextFrame, |
540 | (false, Some(Write(_))) => FrameOptions::LastFrameNoStop, |
541 | }; |
542 | |
543 | // Pre-calculate if `next_op` is the first operation of its type. We do this here and not at |
544 | // the beginning of the loop because we hand out `op` as iterator value and cannot access it |
545 | // anymore in the next iteration. |
546 | next_first_frame = match (&op, next_op) { |
547 | (_, None) => false, |
548 | (Read(_), Some(Write(_))) | (Write(_), Some(Read(_))) => true, |
549 | (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false, |
550 | }; |
551 | |
552 | Some((op, frame)) |
553 | })) |
554 | } |
555 | |