atsamd_hal/sercom/i2c/
reg.rs
1use super::flags::{BusState, Error};
4use super::InactiveTimeout;
5use super::{Flags, Status};
6use crate::pac;
7use crate::sercom::Sercom;
8use crate::time::Hertz;
9use atsamd_hal_macros::hal_cfg;
10
11const MASTER_ACT_READ: u8 = 2;
12const MASTER_ACT_STOP: u8 = 3;
13const MASTER_ACT_REPEATED_START: u8 = 1;
14
15#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
16type DataReg = u8;
17
18#[hal_cfg("sercom0-d5x")]
19type DataReg = u32;
20
21pub(in super::super) struct Registers<S: Sercom> {
22 pub sercom: S,
23}
24
25unsafe impl<S: Sercom> Sync for Registers<S> {}
28
29impl<S: Sercom> Registers<S> {
30 #[inline]
32 pub(super) fn new(sercom: S) -> Self {
33 Self { sercom }
34 }
35
36 #[inline]
38 pub(in super::super) fn i2c_master(&self) -> &pac::sercom0::I2cm {
39 self.sercom.i2cm()
40 }
41
42 pub(super) fn data_ptr<T>(&self) -> *mut T {
44 self.i2c_master().data().as_ptr() as *mut _
45 }
46
47 #[inline]
49 pub(super) fn free(self) -> S {
50 self.sercom
51 }
52
53 #[inline]
55 pub(super) fn swrst(&mut self) {
56 self.i2c_master().ctrla().write(|w| w.swrst().set_bit());
57 while self.i2c_master().syncbusy().read().swrst().bit_is_set() {}
58 }
59
60 #[inline]
62 pub(super) fn set_op_mode(&mut self, mode: pac::sercom0::i2cm::ctrla::Modeselect) {
63 self.i2c_master()
64 .ctrla()
65 .modify(|_, w| w.mode().variant(mode));
66 }
67
68 pub(super) fn set_baud(&mut self, clock_freq: impl Into<Hertz>, baud: impl Into<Hertz>) {
70 let baud = (clock_freq.into().to_Hz() / (2 * baud.into().to_Hz()) - 1) as u8;
73
74 unsafe {
75 self.i2c_master().baud().modify(|_, w| w.baud().bits(baud));
76 }
77 }
78
79 #[inline]
81 pub(super) fn get_baud(&self) -> u32 {
82 self.i2c_master().baud().read().bits()
83 }
84
85 #[inline]
93 pub(super) fn set_low_timeout(&mut self, set: bool) {
94 self.i2c_master()
95 .ctrla()
96 .modify(|_, w| w.lowtouten().bit(set));
97 }
98
99 #[inline]
107 pub(super) fn get_low_timeout(&mut self) -> bool {
108 self.i2c_master().ctrla().read().lowtouten().bit()
109 }
110
111 #[inline]
114 pub(super) fn set_inactive_timeout(&mut self, timeout: super::InactiveTimeout) {
115 #[allow(unused_unsafe)]
118 self.i2c_master()
119 .ctrla()
120 .modify(|_, w| unsafe { w.inactout().bits(timeout as u8) })
121 }
122
123 #[inline]
125 pub(super) fn get_inactive_timeout(&mut self) -> InactiveTimeout {
126 let timeout = self.i2c_master().ctrla().read().inactout().bits();
127
128 match timeout {
129 0 => InactiveTimeout::Disabled,
130 1 => InactiveTimeout::Us55,
131 2 => InactiveTimeout::Us105,
132 3 => InactiveTimeout::Us205,
133 _ => unreachable!(),
134 }
135 }
136
137 #[inline]
142 pub(super) fn set_run_in_standby(&mut self, set: bool) {
143 self.i2c_master()
144 .ctrla()
145 .modify(|_, w| w.runstdby().bit(set));
146 }
147
148 #[inline]
150 pub(super) fn get_run_in_standby(&self) -> bool {
151 self.i2c_master().ctrla().read().runstdby().bit()
152 }
153
154 #[inline]
156 pub(super) fn set_smart_mode(&mut self, set: bool) {
157 self.i2c_master().ctrlb().modify(|_, w| w.smen().bit(set));
158 }
159
160 #[inline]
162 pub(super) fn get_smart_mode(&self) -> bool {
163 self.i2c_master().ctrlb().read().smen().bit()
164 }
165
166 #[inline]
168 pub(super) fn clear_flags(&mut self, flags: Flags) {
169 self.i2c_master()
170 .intflag()
171 .modify(|_, w| unsafe { w.bits(flags.bits()) });
172 }
173
174 #[inline]
176 pub(super) fn read_flags(&self) -> Flags {
177 Flags::from_bits_truncate(self.i2c_master().intflag().read().bits())
178 }
179
180 #[inline]
182 pub(super) fn enable_interrupts(&mut self, flags: Flags) {
183 self.i2c_master()
184 .intenset()
185 .write(|w| unsafe { w.bits(flags.bits()) });
186 }
187
188 #[inline]
190 pub(super) fn disable_interrupts(&mut self, flags: Flags) {
191 self.i2c_master()
192 .intenclr()
193 .write(|w| unsafe { w.bits(flags.bits()) });
194 }
195
196 #[inline]
198 pub(super) fn clear_status(&mut self, status: Status) {
199 self.i2c_master()
200 .status()
201 .modify(|_, w| unsafe { w.bits(status.into()) });
202 }
203
204 #[inline]
206 pub(super) fn read_status(&self) -> Status {
207 self.i2c_master().status().read().bits().into()
208 }
209
210 pub(super) fn check_bus_status(&self) -> Result<(), Error> {
211 let status = self.read_status();
212 if status.busstate() == BusState::Busy
213 || (status.arblost() && status.busstate() != BusState::Idle)
214 || status.busstate() == BusState::Unknown
215 {
216 Err(Error::BusError)
217 } else {
218 Ok(())
219 }
220 }
221
222 #[inline]
225 pub(super) fn start_write(&mut self, addr: u8) -> Result<(), Error> {
226 if self.get_smart_mode() {
227 self.disable();
228 self.set_smart_mode(false);
229 self.enable();
230 }
231
232 self.check_bus_status()?;
233
234 unsafe {
237 self.i2c_master()
238 .addr()
239 .write(|w| w.addr().bits(encode_write_address(addr)));
240 }
241
242 Ok(())
243 }
244
245 #[inline]
247 pub(super) fn start_write_blocking(&mut self, addr: u8) -> Result<(), Error> {
248 self.start_write(addr)?;
249
250 while !self.i2c_master().intflag().read().mb().bit_is_set() {}
252 self.read_status().check_bus_error()
253 }
254
255 pub(super) fn start_read(&mut self, addr: u8) -> Result<(), Error> {
258 if self.get_smart_mode() {
259 self.disable();
260 self.set_smart_mode(false);
261 self.enable();
262 }
263
264 self.check_bus_status()?;
265
266 self.i2c_master()
267 .intflag()
268 .modify(|_, w| w.error().clear_bit());
269
270 unsafe {
273 self.i2c_master()
274 .addr()
275 .write(|w| w.addr().bits(encode_read_address(addr)));
276 }
277
278 Ok(())
279 }
280
281 #[inline]
283 pub(super) fn start_read_blocking(&mut self, addr: u8) -> Result<(), Error> {
284 self.start_read(addr)?;
285
286 loop {
288 let intflag = self.i2c_master().intflag().read();
289 if intflag.mb().bit_is_set() {
291 return Err(Error::ArbitrationLost);
292 }
293 if intflag.sb().bit_is_set() || intflag.error().bit_is_set() {
294 break;
295 }
296 }
297
298 self.read_status().check_bus_error()
299 }
300
301 #[cfg(feature = "dma")]
309 #[inline]
310 pub(in super::super) fn start_dma_write(&mut self, address: u8, xfer_len: u8) {
311 if !self.get_smart_mode() {
312 self.disable();
313 self.set_smart_mode(true);
314 self.enable();
315 }
316
317 self.i2c_master().addr().write(|w| unsafe {
318 w.addr().bits(encode_write_address(address));
319 w.len().bits(xfer_len);
320 w.lenen().set_bit()
321 });
322
323 self.sync_sysop();
324 }
325
326 #[cfg(feature = "dma")]
334 #[inline]
335 pub(in super::super) fn start_dma_read(&mut self, address: u8, xfer_len: u8) {
336 if !self.get_smart_mode() {
337 self.disable();
338 self.set_smart_mode(true);
339 self.enable();
340 }
341
342 self.i2c_master().addr().write(|w| unsafe {
343 w.addr().bits(encode_read_address(address));
344 w.len().bits(xfer_len);
345 w.lenen().set_bit()
346 });
347
348 self.sync_sysop();
349 }
350
351 #[inline]
354 pub(super) fn cmd_stop(&mut self) {
355 unsafe {
356 self.i2c_master().ctrlb().modify(|_, w| {
357 w.ackact().set_bit();
359 w.cmd().bits(MASTER_ACT_STOP)
360 });
361 }
362 self.sync_sysop();
363 }
364
365 #[inline]
368 pub(super) fn cmd_repeated_start(&mut self) {
369 unsafe {
370 self.i2c_master().ctrlb().modify(|_, w| {
371 w.ackact().set_bit();
373 w.cmd().bits(MASTER_ACT_REPEATED_START)
374 });
375 }
376 self.sync_sysop();
377 }
378
379 #[inline]
380 pub(super) fn cmd_read(&mut self) {
381 unsafe {
382 self.i2c_master().ctrlb().modify(|_, w| {
383 w.ackact().clear_bit();
385 w.cmd().bits(MASTER_ACT_READ)
386 });
387 }
388 self.sync_sysop();
389 }
390
391 #[inline]
392 pub(super) fn write_one(&mut self, byte: u8) {
393 unsafe {
394 self.i2c_master().data().write(|w| w.bits(byte as DataReg));
395 }
396 }
397
398 #[inline]
399 pub(super) fn send_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
400 for b in bytes {
401 self.write_one(*b);
402
403 loop {
404 let intflag = self.i2c_master().intflag().read();
405 if intflag.mb().bit_is_set() || intflag.error().bit_is_set() {
406 break;
407 }
408 }
409 self.read_status().check_bus_error()?;
410 }
411 Ok(())
412 }
413
414 #[inline]
415 #[allow(clippy::unnecessary_cast)]
416 pub(super) fn read_one(&mut self) -> u8 {
417 self.i2c_master().data().read().bits() as u8
420 }
421
422 #[inline]
423 pub(super) fn read_one_blocking(&mut self) -> u8 {
424 while !self.i2c_master().intflag().read().sb().bit_is_set() {
425 core::hint::spin_loop();
426 }
427 self.read_one()
428 }
429
430 #[inline]
431 pub(super) fn fill_buffer(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
432 let mut iter = buffer.iter_mut();
434 *iter.next().expect("buffer len is at least 1") = self.read_one_blocking();
435
436 loop {
437 match iter.next() {
438 None => break,
439 Some(dest) => {
440 self.cmd_read();
442 *dest = self.read_one_blocking();
443 }
444 }
445 }
446
447 self.i2c_master()
450 .ctrlb()
451 .modify(|_, w| w.ackact().set_bit());
452
453 Ok(())
454 }
455
456 #[inline]
457 pub(super) fn do_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
458 self.start_write_blocking(addr)?;
459 self.send_bytes(bytes)
460 }
461
462 #[inline]
466 pub(super) fn continue_write(&mut self, bytes: &[u8]) -> Result<(), Error> {
467 self.send_bytes(bytes)
468 }
469
470 #[inline]
471 pub(super) fn do_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
472 self.start_read_blocking(addr)?;
473 self.fill_buffer(buffer)
474 }
475
476 #[inline]
480 pub(super) fn continue_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
481 self.fill_buffer(buffer)
482 }
483
484 #[inline]
485 pub(super) fn do_write_read(
486 &mut self,
487 addr: u8,
488 bytes: &[u8],
489 buffer: &mut [u8],
490 ) -> Result<(), Error> {
491 self.start_write_blocking(addr)?;
492 self.send_bytes(bytes)?;
493 self.start_read_blocking(addr)?;
494 self.fill_buffer(buffer)?;
495 Ok(())
496 }
497
498 #[inline]
500 pub(super) fn bus_idle(&mut self) {
501 self.i2c_master()
503 .status()
504 .modify(|_, w| unsafe { w.busstate().bits(BusState::Idle as u8) });
505 self.sync_sysop();
507 }
508
509 #[inline]
510 fn sync_sysop(&mut self) {
511 while self.i2c_master().syncbusy().read().sysop().bit_is_set() {}
512 }
513
514 #[inline]
518 pub(super) fn enable(&mut self) {
519 self.enable_peripheral(true);
521 self.bus_idle();
523 }
524
525 #[inline]
526 pub(super) fn disable(&mut self) {
527 self.enable_peripheral(false);
528 }
529
530 #[inline]
533 pub(super) fn enable_peripheral(&mut self, enable: bool) {
534 self.i2c_master()
535 .ctrla()
536 .modify(|_, w| w.enable().bit(enable));
537 while self.i2c_master().syncbusy().read().enable().bit_is_set() {}
538 }
539}
540
541fn encode_write_address(addr_7_bits: u8) -> u16 {
542 (addr_7_bits as u16) << 1
543}
544
545fn encode_read_address(addr_7_bits: u8) -> u16 {
546 ((addr_7_bits as u16) << 1) | 1
547}