1use core::cmp;
2use core::future::poll_fn;
3use core::task::Poll;
4
5use embassy_embedded_hal::SetConfig;
6use embassy_hal_internal::drop::OnDrop;
7use embedded_hal_1::i2c::Operation;
8
9use super::*;
10use crate::pac::i2c;
11
12pub(crate) unsafe fn on_interrupt<T: Instance>() {
13 let regs: I2c = T::info().regs;
14 let isr: Isr = regs.isr().read();
15
16 if isr.tcr() || isr.tc() {
17 T::state().waker.wake();
18 }
19 // The flag can only be cleared by writting to nbytes, we won't do that here, so disable
20 // the interrupt
21 critical_section::with(|_| {
22 regs.cr1().modify(|w: &mut Cr1| w.set_tcie(val:false));
23 });
24}
25
26impl<'d, M: Mode> I2c<'d, M> {
27 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
28 self.info.regs.cr1().modify(|reg| {
29 reg.set_pe(false);
30 reg.set_anfoff(false);
31 });
32
33 let timings = Timings::new(self.kernel_clock, freq.into());
34
35 self.info.regs.timingr().write(|reg| {
36 reg.set_presc(timings.prescale);
37 reg.set_scll(timings.scll);
38 reg.set_sclh(timings.sclh);
39 reg.set_sdadel(timings.sdadel);
40 reg.set_scldel(timings.scldel);
41 });
42
43 self.info.regs.cr1().modify(|reg| {
44 reg.set_pe(true);
45 });
46 }
47
48 fn master_stop(&mut self) {
49 self.info.regs.cr2().write(|w| w.set_stop(true));
50 }
51
52 fn master_read(
53 info: &'static Info,
54 address: u8,
55 length: usize,
56 stop: Stop,
57 reload: bool,
58 restart: bool,
59 timeout: Timeout,
60 ) -> Result<(), Error> {
61 assert!(length < 256);
62
63 if !restart {
64 // Wait for any previous address sequence to end
65 // automatically. This could be up to 50% of a bus
66 // cycle (ie. up to 0.5/freq)
67 while info.regs.cr2().read().start() {
68 timeout.check()?;
69 }
70 }
71
72 // Set START and prepare to receive bytes into
73 // `buffer`. The START bit can be set even if the bus
74 // is BUSY or I2C is in slave mode.
75
76 let reload = if reload {
77 i2c::vals::Reload::NOT_COMPLETED
78 } else {
79 i2c::vals::Reload::COMPLETED
80 };
81
82 info.regs.cr2().modify(|w| {
83 w.set_sadd((address << 1 | 0) as u16);
84 w.set_add10(i2c::vals::Addmode::BIT7);
85 w.set_dir(i2c::vals::Dir::READ);
86 w.set_nbytes(length as u8);
87 w.set_start(true);
88 w.set_autoend(stop.autoend());
89 w.set_reload(reload);
90 });
91
92 Ok(())
93 }
94
95 fn master_write(
96 info: &'static Info,
97 address: u8,
98 length: usize,
99 stop: Stop,
100 reload: bool,
101 timeout: Timeout,
102 ) -> Result<(), Error> {
103 assert!(length < 256);
104
105 // Wait for any previous address sequence to end
106 // automatically. This could be up to 50% of a bus
107 // cycle (ie. up to 0.5/freq)
108 while info.regs.cr2().read().start() {
109 timeout.check()?;
110 }
111
112 // Wait for the bus to be free
113 while info.regs.isr().read().busy() {
114 timeout.check()?;
115 }
116
117 let reload = if reload {
118 i2c::vals::Reload::NOT_COMPLETED
119 } else {
120 i2c::vals::Reload::COMPLETED
121 };
122
123 // Set START and prepare to send `bytes`. The
124 // START bit can be set even if the bus is BUSY or
125 // I2C is in slave mode.
126 info.regs.cr2().modify(|w| {
127 w.set_sadd((address << 1 | 0) as u16);
128 w.set_add10(i2c::vals::Addmode::BIT7);
129 w.set_dir(i2c::vals::Dir::WRITE);
130 w.set_nbytes(length as u8);
131 w.set_start(true);
132 w.set_autoend(stop.autoend());
133 w.set_reload(reload);
134 });
135
136 Ok(())
137 }
138
139 fn master_continue(info: &'static Info, length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> {
140 assert!(length < 256 && length > 0);
141
142 while !info.regs.isr().read().tcr() {
143 timeout.check()?;
144 }
145
146 let reload = if reload {
147 i2c::vals::Reload::NOT_COMPLETED
148 } else {
149 i2c::vals::Reload::COMPLETED
150 };
151
152 info.regs.cr2().modify(|w| {
153 w.set_nbytes(length as u8);
154 w.set_reload(reload);
155 });
156
157 Ok(())
158 }
159
160 fn flush_txdr(&self) {
161 if self.info.regs.isr().read().txis() {
162 self.info.regs.txdr().write(|w| w.set_txdata(0));
163 }
164 if !self.info.regs.isr().read().txe() {
165 self.info.regs.isr().modify(|w| w.set_txe(true))
166 }
167 }
168
169 fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> {
170 loop {
171 let isr = self.info.regs.isr().read();
172 if isr.txe() {
173 return Ok(());
174 } else if isr.berr() {
175 self.info.regs.icr().write(|reg| reg.set_berrcf(true));
176 return Err(Error::Bus);
177 } else if isr.arlo() {
178 self.info.regs.icr().write(|reg| reg.set_arlocf(true));
179 return Err(Error::Arbitration);
180 } else if isr.nackf() {
181 self.info.regs.icr().write(|reg| reg.set_nackcf(true));
182 self.flush_txdr();
183 return Err(Error::Nack);
184 }
185
186 timeout.check()?;
187 }
188 }
189
190 fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> {
191 loop {
192 let isr = self.info.regs.isr().read();
193 if isr.rxne() {
194 return Ok(());
195 } else if isr.berr() {
196 self.info.regs.icr().write(|reg| reg.set_berrcf(true));
197 return Err(Error::Bus);
198 } else if isr.arlo() {
199 self.info.regs.icr().write(|reg| reg.set_arlocf(true));
200 return Err(Error::Arbitration);
201 } else if isr.nackf() {
202 self.info.regs.icr().write(|reg| reg.set_nackcf(true));
203 self.flush_txdr();
204 return Err(Error::Nack);
205 }
206
207 timeout.check()?;
208 }
209 }
210
211 fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> {
212 loop {
213 let isr = self.info.regs.isr().read();
214 if isr.tc() {
215 return Ok(());
216 } else if isr.berr() {
217 self.info.regs.icr().write(|reg| reg.set_berrcf(true));
218 return Err(Error::Bus);
219 } else if isr.arlo() {
220 self.info.regs.icr().write(|reg| reg.set_arlocf(true));
221 return Err(Error::Arbitration);
222 } else if isr.nackf() {
223 self.info.regs.icr().write(|reg| reg.set_nackcf(true));
224 self.flush_txdr();
225 return Err(Error::Nack);
226 }
227
228 timeout.check()?;
229 }
230 }
231
232 fn read_internal(&mut self, address: u8, read: &mut [u8], restart: bool, timeout: Timeout) -> Result<(), Error> {
233 let completed_chunks = read.len() / 255;
234 let total_chunks = if completed_chunks * 255 == read.len() {
235 completed_chunks
236 } else {
237 completed_chunks + 1
238 };
239 let last_chunk_idx = total_chunks.saturating_sub(1);
240
241 Self::master_read(
242 self.info,
243 address,
244 read.len().min(255),
245 Stop::Automatic,
246 last_chunk_idx != 0,
247 restart,
248 timeout,
249 )?;
250
251 for (number, chunk) in read.chunks_mut(255).enumerate() {
252 if number != 0 {
253 Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
254 }
255
256 for byte in chunk {
257 // Wait until we have received something
258 self.wait_rxne(timeout)?;
259
260 *byte = self.info.regs.rxdr().read().rxdata();
261 }
262 }
263 Ok(())
264 }
265
266 fn write_internal(&mut self, address: u8, write: &[u8], send_stop: bool, timeout: Timeout) -> Result<(), Error> {
267 let completed_chunks = write.len() / 255;
268 let total_chunks = if completed_chunks * 255 == write.len() {
269 completed_chunks
270 } else {
271 completed_chunks + 1
272 };
273 let last_chunk_idx = total_chunks.saturating_sub(1);
274
275 // I2C start
276 //
277 // ST SAD+W
278 if let Err(err) = Self::master_write(
279 self.info,
280 address,
281 write.len().min(255),
282 Stop::Software,
283 last_chunk_idx != 0,
284 timeout,
285 ) {
286 if send_stop {
287 self.master_stop();
288 }
289 return Err(err);
290 }
291
292 for (number, chunk) in write.chunks(255).enumerate() {
293 if number != 0 {
294 Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
295 }
296
297 for byte in chunk {
298 // Wait until we are allowed to send data
299 // (START has been ACKed or last byte when
300 // through)
301 if let Err(err) = self.wait_txe(timeout) {
302 if send_stop {
303 self.master_stop();
304 }
305 return Err(err);
306 }
307
308 self.info.regs.txdr().write(|w| w.set_txdata(*byte));
309 }
310 }
311 // Wait until the write finishes
312 let result = self.wait_tc(timeout);
313 if send_stop {
314 self.master_stop();
315 }
316 result
317 }
318
319 // =========================
320 // Blocking public API
321
322 /// Blocking read.
323 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
324 self.read_internal(address, read, false, self.timeout())
325 // Automatic Stop
326 }
327
328 /// Blocking write.
329 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
330 self.write_internal(address, write, true, self.timeout())
331 }
332
333 /// Blocking write, restart, read.
334 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
335 let timeout = self.timeout();
336 self.write_internal(address, write, false, timeout)?;
337 self.read_internal(address, read, true, timeout)
338 // Automatic Stop
339 }
340
341 /// Blocking transaction with operations.
342 ///
343 /// Consecutive operations of same type are merged. See [transaction contract] for details.
344 ///
345 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
346 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
347 let _ = addr;
348 let _ = operations;
349 todo!()
350 }
351
352 /// Blocking write multiple buffers.
353 ///
354 /// The buffers are concatenated in a single write transaction.
355 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
356 if write.is_empty() {
357 return Err(Error::ZeroLengthTransfer);
358 }
359
360 let timeout = self.timeout();
361
362 let first_length = write[0].len();
363 let last_slice_index = write.len() - 1;
364
365 if let Err(err) = Self::master_write(
366 self.info,
367 address,
368 first_length.min(255),
369 Stop::Software,
370 (first_length > 255) || (last_slice_index != 0),
371 timeout,
372 ) {
373 self.master_stop();
374 return Err(err);
375 }
376
377 for (idx, slice) in write.iter().enumerate() {
378 let slice_len = slice.len();
379 let completed_chunks = slice_len / 255;
380 let total_chunks = if completed_chunks * 255 == slice_len {
381 completed_chunks
382 } else {
383 completed_chunks + 1
384 };
385 let last_chunk_idx = total_chunks.saturating_sub(1);
386
387 if idx != 0 {
388 if let Err(err) = Self::master_continue(
389 self.info,
390 slice_len.min(255),
391 (idx != last_slice_index) || (slice_len > 255),
392 timeout,
393 ) {
394 self.master_stop();
395 return Err(err);
396 }
397 }
398
399 for (number, chunk) in slice.chunks(255).enumerate() {
400 if number != 0 {
401 if let Err(err) = Self::master_continue(
402 self.info,
403 chunk.len(),
404 (number != last_chunk_idx) || (idx != last_slice_index),
405 timeout,
406 ) {
407 self.master_stop();
408 return Err(err);
409 }
410 }
411
412 for byte in chunk {
413 // Wait until we are allowed to send data
414 // (START has been ACKed or last byte when
415 // through)
416 if let Err(err) = self.wait_txe(timeout) {
417 self.master_stop();
418 return Err(err);
419 }
420
421 // Put byte on the wire
422 //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
423 self.info.regs.txdr().write(|w| w.set_txdata(*byte));
424 }
425 }
426 }
427 // Wait until the write finishes
428 let result = self.wait_tc(timeout);
429 self.master_stop();
430 result
431 }
432}
433
434impl<'d> I2c<'d, Async> {
435 async fn write_dma_internal(
436 &mut self,
437 address: u8,
438 write: &[u8],
439 first_slice: bool,
440 last_slice: bool,
441 timeout: Timeout,
442 ) -> Result<(), Error> {
443 let total_len = write.len();
444
445 let dma_transfer = unsafe {
446 let regs = self.info.regs;
447 regs.cr1().modify(|w| {
448 w.set_txdmaen(true);
449 if first_slice {
450 w.set_tcie(true);
451 }
452 });
453 let dst = regs.txdr().as_ptr() as *mut u8;
454
455 self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
456 };
457
458 let mut remaining_len = total_len;
459
460 let on_drop = OnDrop::new(|| {
461 let regs = self.info.regs;
462 regs.cr1().modify(|w| {
463 if last_slice {
464 w.set_txdmaen(false);
465 }
466 w.set_tcie(false);
467 })
468 });
469
470 poll_fn(|cx| {
471 self.state.waker.register(cx.waker());
472
473 let isr = self.info.regs.isr().read();
474 if remaining_len == total_len {
475 if first_slice {
476 Self::master_write(
477 self.info,
478 address,
479 total_len.min(255),
480 Stop::Software,
481 (total_len > 255) || !last_slice,
482 timeout,
483 )?;
484 } else {
485 Self::master_continue(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
486 self.info.regs.cr1().modify(|w| w.set_tcie(true));
487 }
488 } else if !(isr.tcr() || isr.tc()) {
489 // poll_fn was woken without an interrupt present
490 return Poll::Pending;
491 } else if remaining_len == 0 {
492 return Poll::Ready(Ok(()));
493 } else {
494 let last_piece = (remaining_len <= 255) && last_slice;
495
496 if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) {
497 return Poll::Ready(Err(e));
498 }
499 self.info.regs.cr1().modify(|w| w.set_tcie(true));
500 }
501
502 remaining_len = remaining_len.saturating_sub(255);
503 Poll::Pending
504 })
505 .await?;
506
507 dma_transfer.await;
508
509 if last_slice {
510 // This should be done already
511 self.wait_tc(timeout)?;
512 self.master_stop();
513 }
514
515 drop(on_drop);
516
517 Ok(())
518 }
519
520 async fn read_dma_internal(
521 &mut self,
522 address: u8,
523 buffer: &mut [u8],
524 restart: bool,
525 timeout: Timeout,
526 ) -> Result<(), Error> {
527 let total_len = buffer.len();
528
529 let dma_transfer = unsafe {
530 let regs = self.info.regs;
531 regs.cr1().modify(|w| {
532 w.set_rxdmaen(true);
533 w.set_tcie(true);
534 });
535 let src = regs.rxdr().as_ptr() as *mut u8;
536
537 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
538 };
539
540 let mut remaining_len = total_len;
541
542 let on_drop = OnDrop::new(|| {
543 let regs = self.info.regs;
544 regs.cr1().modify(|w| {
545 w.set_rxdmaen(false);
546 w.set_tcie(false);
547 })
548 });
549
550 poll_fn(|cx| {
551 self.state.waker.register(cx.waker());
552
553 let isr = self.info.regs.isr().read();
554 if remaining_len == total_len {
555 Self::master_read(
556 self.info,
557 address,
558 total_len.min(255),
559 Stop::Software,
560 total_len > 255,
561 restart,
562 timeout,
563 )?;
564 } else if !(isr.tcr() || isr.tc()) {
565 // poll_fn was woken without an interrupt present
566 return Poll::Pending;
567 } else if remaining_len == 0 {
568 return Poll::Ready(Ok(()));
569 } else {
570 let last_piece = remaining_len <= 255;
571
572 if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) {
573 return Poll::Ready(Err(e));
574 }
575 self.info.regs.cr1().modify(|w| w.set_tcie(true));
576 }
577
578 remaining_len = remaining_len.saturating_sub(255);
579 Poll::Pending
580 })
581 .await?;
582
583 dma_transfer.await;
584
585 // This should be done already
586 self.wait_tc(timeout)?;
587 self.master_stop();
588
589 drop(on_drop);
590
591 Ok(())
592 }
593
594 // =========================
595 // Async public API
596
597 /// Write.
598 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
599 let timeout = self.timeout();
600 if write.is_empty() {
601 self.write_internal(address, write, true, timeout)
602 } else {
603 timeout
604 .with(self.write_dma_internal(address, write, true, true, timeout))
605 .await
606 }
607 }
608
609 /// Write multiple buffers.
610 ///
611 /// The buffers are concatenated in a single write transaction.
612 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
613 let timeout = self.timeout();
614
615 if write.is_empty() {
616 return Err(Error::ZeroLengthTransfer);
617 }
618 let mut iter = write.iter();
619
620 let mut first = true;
621 let mut current = iter.next();
622 while let Some(c) = current {
623 let next = iter.next();
624 let is_last = next.is_none();
625
626 let fut = self.write_dma_internal(address, c, first, is_last, timeout);
627 timeout.with(fut).await?;
628 first = false;
629 current = next;
630 }
631 Ok(())
632 }
633
634 /// Read.
635 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
636 let timeout = self.timeout();
637
638 if buffer.is_empty() {
639 self.read_internal(address, buffer, false, timeout)
640 } else {
641 let fut = self.read_dma_internal(address, buffer, false, timeout);
642 timeout.with(fut).await
643 }
644 }
645
646 /// Write, restart, read.
647 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
648 let timeout = self.timeout();
649
650 if write.is_empty() {
651 self.write_internal(address, write, false, timeout)?;
652 } else {
653 let fut = self.write_dma_internal(address, write, true, true, timeout);
654 timeout.with(fut).await?;
655 }
656
657 if read.is_empty() {
658 self.read_internal(address, read, true, timeout)?;
659 } else {
660 let fut = self.read_dma_internal(address, read, true, timeout);
661 timeout.with(fut).await?;
662 }
663
664 Ok(())
665 }
666
667 /// Transaction with operations.
668 ///
669 /// Consecutive operations of same type are merged. See [transaction contract] for details.
670 ///
671 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
672 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
673 let _ = addr;
674 let _ = operations;
675 todo!()
676 }
677}
678
679/// I2C Stop Configuration
680///
681/// Peripheral options for generating the STOP condition
682#[derive(Copy, Clone, PartialEq)]
683enum Stop {
684 /// Software end mode: Must write register to generate STOP condition
685 Software,
686 /// Automatic end mode: A STOP condition is automatically generated once the
687 /// configured number of bytes have been transferred
688 Automatic,
689}
690
691impl Stop {
692 fn autoend(&self) -> i2c::vals::Autoend {
693 match self {
694 Stop::Software => i2c::vals::Autoend::SOFTWARE,
695 Stop::Automatic => i2c::vals::Autoend::AUTOMATIC,
696 }
697 }
698}
699
700struct Timings {
701 prescale: u8,
702 scll: u8,
703 sclh: u8,
704 sdadel: u8,
705 scldel: u8,
706}
707
708impl Timings {
709 fn new(i2cclk: Hertz, freq: Hertz) -> Self {
710 let i2cclk = i2cclk.0;
711 let freq = freq.0;
712 // Refer to RM0433 Rev 7 Figure 539 for setup and hold timing:
713 //
714 // t_I2CCLK = 1 / PCLK1
715 // t_PRESC = (PRESC + 1) * t_I2CCLK
716 // t_SCLL = (SCLL + 1) * t_PRESC
717 // t_SCLH = (SCLH + 1) * t_PRESC
718 //
719 // t_SYNC1 + t_SYNC2 > 4 * t_I2CCLK
720 // t_SCL ~= t_SYNC1 + t_SYNC2 + t_SCLL + t_SCLH
721 let ratio = i2cclk / freq;
722
723 // For the standard-mode configuration method, we must have a ratio of 4
724 // or higher
725 assert!(ratio >= 4, "The I2C PCLK must be at least 4 times the bus frequency!");
726
727 let (presc_reg, scll, sclh, sdadel, scldel) = if freq > 100_000 {
728 // Fast-mode (Fm) or Fast-mode Plus (Fm+)
729 // here we pick SCLL + 1 = 2 * (SCLH + 1)
730
731 // Prescaler, 384 ticks for sclh/scll. Round up then subtract 1
732 let presc_reg = ((ratio - 1) / 384) as u8;
733 // ratio < 1200 by pclk 120MHz max., therefore presc < 16
734
735 // Actual precale value selected
736 let presc = (presc_reg + 1) as u32;
737
738 let sclh = ((ratio / presc) - 3) / 3;
739 let scll = (2 * (sclh + 1)) - 1;
740
741 let (sdadel, scldel) = if freq > 400_000 {
742 // Fast-mode Plus (Fm+)
743 assert!(i2cclk >= 17_000_000); // See table in datsheet
744
745 let sdadel = i2cclk / 8_000_000 / presc;
746 let scldel = i2cclk / 4_000_000 / presc - 1;
747
748 (sdadel, scldel)
749 } else {
750 // Fast-mode (Fm)
751 assert!(i2cclk >= 8_000_000); // See table in datsheet
752
753 let sdadel = i2cclk / 4_000_000 / presc;
754 let scldel = i2cclk / 2_000_000 / presc - 1;
755
756 (sdadel, scldel)
757 };
758
759 (presc_reg, scll as u8, sclh as u8, sdadel as u8, scldel as u8)
760 } else {
761 // Standard-mode (Sm)
762 // here we pick SCLL = SCLH
763 assert!(i2cclk >= 2_000_000); // See table in datsheet
764
765 // Prescaler, 512 ticks for sclh/scll. Round up then
766 // subtract 1
767 let presc = (ratio - 1) / 512;
768 let presc_reg = cmp::min(presc, 15) as u8;
769
770 // Actual prescale value selected
771 let presc = (presc_reg + 1) as u32;
772
773 let sclh = ((ratio / presc) - 2) / 2;
774 let scll = sclh;
775
776 // Speed check
777 assert!(sclh < 256, "The I2C PCLK is too fast for this bus frequency!");
778
779 let sdadel = i2cclk / 2_000_000 / presc;
780 let scldel = i2cclk / 500_000 / presc - 1;
781
782 (presc_reg, scll as u8, sclh as u8, sdadel as u8, scldel as u8)
783 };
784
785 // Sanity check
786 assert!(presc_reg < 16);
787
788 // Keep values within reasonable limits for fast per_ck
789 let sdadel = cmp::max(sdadel, 2);
790 let scldel = cmp::max(scldel, 4);
791
792 //(presc_reg, scll, sclh, sdadel, scldel)
793 Self {
794 prescale: presc_reg,
795 scll,
796 sclh,
797 sdadel,
798 scldel,
799 }
800 }
801}
802
803impl<'d, M: Mode> SetConfig for I2c<'d, M> {
804 type Config = Hertz;
805 type ConfigError = ();
806 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
807 let timings: Timings = Timings::new(self.kernel_clock, *config);
808 self.info.regs.timingr().write(|reg: &mut Timingr| {
809 reg.set_presc(val:timings.prescale);
810 reg.set_scll(val:timings.scll);
811 reg.set_sclh(val:timings.sclh);
812 reg.set_sdadel(val:timings.sdadel);
813 reg.set_scldel(val:timings.scldel);
814 });
815
816 Ok(())
817 }
818}
819