1#![no_std]
2use atsamd_hal::target_device::SDHC0;
3use bit_field::BitField;
4use core::hint::unreachable_unchecked;
5use embedded_error::mci::CommandOrDataError;
6use embedded_error::mci::MciError;
7use embedded_error::ImplError;
8use mci::command_arguments::mci_command::MciCommand;
9use mci::command_arguments::mmc::BusWidth;
10use mci::mci::Mci;
11
12pub struct AtsamdMci {
13 sdhc: SDHC0,
14 trans_pos: u64,
15 block_size: u16,
16 block_amount: u16,
17}
18
19impl AtsamdMci {
20 pub fn new(sdhc: SDHC0) -> AtsamdMci {
21 AtsamdMci {
22 sdhc,
23 trans_pos: 0,
24 block_size: 0,
25 block_amount: 0,
26 }
27 }
28
29 pub fn reset(&mut self) {
30 self.sdhc.srr.modify(|_, w| w.swrstcmd().set_bit());
31 }
32
33 pub fn wait_busy(&mut self) -> Result<(), MciError> {
34 for n in (0u32..=0xFFFF_FFFFu32).rev() {
35 if n == 0 {
36 self.reset();
37 return Err(MciError::Impl(ImplError::TimedOut));
38 }
39 if self.sdhc.psr.read().datll().bits() == 0x1 {
40 return Ok(());
41 }
42 }
43 unsafe { unreachable_unchecked() }
44 }
45
46 pub fn set_speed(&mut self, speed: u32, prog_clock_mode: u8) {
47 if self.sdhc.ccr.read().sdclken().bit_is_set() {
48 let mut psr = self.sdhc.psr.read();
49 while psr.cmdinhc().bit_is_set() || psr.cmdinhd().bit_is_set() {
50 psr = self.sdhc.psr.read();
51 }
52 }
53 let mut clk_base = self.sdhc.ca0r.read().baseclkf().bits();
55 let clk_mult = self.sdhc.ca1r.read().clkmult().bits();
56 let mut div: u32;
57
58 if clk_mult > 0 {
60 clk_base /= 2;
61 }
62
63 if prog_clock_mode == 0 {
64 self.sdhc.ccr.modify(|_, w| w.clkgsel().clear_bit());
66 div = ((clk_base as u32) / speed) / 2;
67 } else {
68 self.sdhc.ccr.modify(|_, w| w.clkgsel().set_bit());
70 div = ((clk_base as u32) * ((clk_mult as u32) + 1)) / speed;
73 div = if div > 0 { div - 1 } else { div };
74 }
75
76 div = if self.sdhc.hc1r().read().hsen().bit_is_set() && div == 0 {
79 1
80 } else {
81 div
82 };
83
84 self.sdhc.ccr.modify(|_, w| unsafe {
86 w.sdclkfsel()
87 .bits(div as u8)
88 .usdclkfsel()
89 .bits((div >> 8) as u8)
90 });
91
92 self.sdhc.ccr.modify(|_, w| w.intclken().set_bit());
93
94 while self.sdhc.ccr.read().intclks().bit_is_clear() {}
96
97 self.sdhc.ccr.modify(|_, w| w.sdclken().set_bit());
99 }
100
101 pub fn send_command_execute(
103 &mut self,
104 mut cmdr: u16,
105 cmd: u32,
106 arg: u32,
107 ) -> Result<(), MciError> {
108 cmdr.set_bits(8..16, cmd as u16);
109 let cmd: MciCommand = cmd.into();
110
111 if cmd.have_response() {
112 cmdr.set_bits(
113 0..2,
114 if cmd.have_136bit_response() {
115 0x1
116 } else if cmd.card_may_send_busy() {
117 0x3
118 } else {
119 0x2
120 },
121 );
122 }
123
124 self.sdhc.mc1r.modify(|_, w| {
125 if cmd.open_drain_broadcast_command() {
126 w.opd().set_bit()
127 } else {
128 w.opd().clear_bit()
129 }
130 });
131
132 self.sdhc.arg1r.write(|w| unsafe { w.bits(arg) });
133 self.sdhc.cr.write(|w| unsafe { w.bits(cmdr) });
134
135 loop {
136 let sr = self.sdhc.eister().read();
137 let error = error_from_eistr(
138 sr.cmdteo().bit_is_set(),
139 sr.cmdcrc().bit_is_set(),
140 sr.cmdend().bit_is_set(),
141 sr.cmdidx().bit_is_set(),
142 sr.datteo().bit_is_set(),
143 sr.datcrc().bit_is_set(),
144 sr.datend().bit_is_set(),
145 sr.adma().bit_is_set(),
146 cmd.expect_valid_crc(),
147 );
148 if error.is_some() {
149 self.reset();
150 self.sdhc.eister().write(|w| unsafe { w.bits(0x03FF) });
151 return Err(error.unwrap());
152 }
153 if self.sdhc.nistr().read().cmdc().bit_is_clear() {
154 break;
155 }
156 }
157
158 if !cmdr.get_bit(5) {
159 self.sdhc.nistr().write(|w| w.cmdc().set_bit());
160 }
161
162 if cmd.card_may_send_busy() {
163 return self.wait_busy();
164 }
165
166 Ok(())
167 }
168
169 pub fn eistr_err(&mut self) -> Result<(), MciError> {
170 let sr = self.sdhc.eistr().read();
171 let error = command_error_from_eistr(
172 sr.datteo().bit_is_set(),
173 sr.datcrc().bit_is_set(),
174 sr.datend().bit_is_set(),
175 );
176 if error.is_some() {
177 self.reset();
178 return Err(MciError::CommandError(error.unwrap()));
179 }
180 Ok(())
181 }
182
183 pub fn loop_or_on_eistr_err<F: FnMut(&mut AtsamdMci) -> bool>(
184 &mut self,
185 mut f: F,
186 ) -> Result<(), MciError> {
187 loop {
188 self.eistr_err()?;
189 if f(self) {
190 break;
191 }
192 }
193 Ok(())
194 }
195}
196
197fn command_error_from_eistr(timeout: bool, crc: bool, end: bool) -> Option<CommandOrDataError> {
198 if timeout {
199 Some(CommandOrDataError::Timeout)
200 } else if crc {
201 Some(CommandOrDataError::Crc)
202 } else if end {
203 Some(CommandOrDataError::EndBit)
204 } else {
205 None
206 }
207}
208
209fn error_from_eistr(
210 cmd_timeout: bool,
211 cmd_crc: bool,
212 cmd_endbit: bool,
213 cmd_index: bool,
214 dat_timeout: bool,
215 dat_crc: bool,
216 dat_endbit: bool,
217 adma: bool,
218 expect_valid_crc: bool,
219) -> Option<MciError> {
220 if cmd_timeout {
221 Some(MciError::CommandError(CommandOrDataError::Timeout))
222 } else if cmd_endbit {
223 Some(MciError::CommandError(CommandOrDataError::EndBit))
224 } else if cmd_index {
225 Some(MciError::CommandError(CommandOrDataError::Index))
226 } else if dat_timeout {
227 Some(MciError::DataError(CommandOrDataError::Timeout))
228 } else if dat_endbit {
229 Some(MciError::DataError(CommandOrDataError::EndBit))
230 } else if adma {
231 Some(MciError::Adma)
232 } else if expect_valid_crc && (cmd_crc || dat_crc) {
233 Some(if cmd_crc {
234 MciError::CommandError(CommandOrDataError::Crc)
235 } else {
236 MciError::DataError(CommandOrDataError::Crc)
237 })
238 } else {
239 None
240 }
241}
242
243impl Mci for AtsamdMci {
244 fn init(&mut self) -> Result<(), MciError> {
245 self.sdhc.srr.modify(|_, w| w.swrstall().set_bit());
246 loop {
247 if self.sdhc.srr.read().swrstall().bit_is_clear() {
248 break;
249 }
250 }
251
252 self.sdhc.tcr.write(|w| unsafe { w.bits(0xe) });
254
255 self.sdhc.pcr.write(|w| w.sdbpwr().on().sdbvsel()._3v3());
257
258 self.sdhc.nister().write(|w| unsafe { w.bits(0x01FF) });
259 self.sdhc.eister().write(|w| unsafe { w.bits(0x03FF) });
260
261 Ok(())
262 }
263
264 fn send_command(&mut self, cmd: u32, arg: u32) -> Result<(), MciError> {
265 if self.sdhc.psr.read().cmdinhc().bit_is_set() {
266 return Err(MciError::CommandInhibited);
267 }
268
269 self.sdhc.tmr.modify(|_, w| w.dmaen().clear_bit());
270 self.sdhc.bcr.modify(|_, w| unsafe { w.bits(0) });
271 self.send_command_execute(0, cmd, arg)
272 }
273
274 fn deinit(&mut self) -> Result<(), MciError> {
275 Ok(())
277 }
278
279 fn select_device(
280 &mut self,
281 _slot: u8,
282 clock: u32,
283 bus_width: &BusWidth,
284 high_speed: bool,
285 ) -> Result<(), MciError> {
286 self.sdhc.hc1r().modify(|_, w| {
287 if high_speed {
288 w.hsen().set_bit()
289 } else {
290 w.hsen().clear_bit()
291 }
292 });
293
294 if self.sdhc.hc2r().read().pvalen().bit_is_clear() {
295 self.set_speed(clock, 0);
296 }
297
298 match bus_width {
299 BusWidth::_1BIT => self.sdhc.hc1r().modify(|_, w| w.dw().clear_bit()),
300 BusWidth::_4BIT => self.sdhc.hc1r().modify(|_, w| w.dw().set_bit()),
301 _ => return Err(MciError::Impl(ImplError::InvalidConfiguration)),
302 }
303 Ok(())
304 }
305
306 fn deselect_device(&mut self, _slot: u8) -> Result<(), MciError> {
307 Ok(())
309 }
310
311 fn get_bus_width(&mut self, slot: u8) -> Result<BusWidth, MciError> {
312 match slot {
313 0 => Ok(BusWidth::_4BIT),
314 _ => Err(MciError::Impl(ImplError::InvalidConfiguration)),
315 }
316 }
317
318 fn is_high_speed_capable(&mut self) -> Result<bool, MciError> {
319 Ok(self.sdhc.ca0r.read().hssup().bit_is_set())
320 }
321
322 fn send_clock(&mut self) -> Result<(), MciError> {
325 for _m in 0..5000u32 {
326 }
328 Ok(())
329 }
330
331 fn get_response(&mut self) -> Result<u32, MciError> {
332 Ok(self.sdhc.rr[0].read().cmdresp().bits())
333 }
334
335 fn get_response128(&mut self) -> Result<[u32; 4], MciError> {
336 Ok([
337 self.sdhc.rr[0].read().cmdresp().bits(),
338 self.sdhc.rr[1].read().cmdresp().bits(),
339 self.sdhc.rr[2].read().cmdresp().bits(),
340 self.sdhc.rr[3].read().cmdresp().bits(),
341 ])
342 }
343
344 fn adtc_start(
345 &mut self,
346 command: u32,
347 argument: u32,
348 block_size: u16,
349 block_amount: u16,
350 _access_in_blocks: bool,
351 ) -> Result<(), MciError> {
352 let psr = self.sdhc.psr.read();
353 if psr.cmdinhc().bit_is_set() || psr.cmdinhd().bit_is_set() {
355 return Err(MciError::CommandInhibited);
356 }
357
358 let command: MciCommand = command.into();
359 if !command.sdio_multi_byte_transfer()
360 && !command.sdio_block_mode_transfer()
361 && !command.single_block_data_transfer()
362 && !command.multi_block_data_transfer()
363 {
364 return Err(MciError::Impl(ImplError::InvalidConfiguration));
365 }
366
367 self.sdhc.tmr.write(|w| {
368 if command.data_write_command() {
369 w.dtdsel().write();
370 } else {
371 w.dtdsel().read();
372 }
373 if command.sdio_multi_byte_transfer() {
374 w.msbsel().single();
375 } else if command.sdio_block_mode_transfer() {
376 w.bcen().enable().msbsel().multiple();
377 } else if command.single_block_data_transfer() {
378 w.msbsel().single();
379 } else if command.multi_block_data_transfer() {
380 w.bcen().enable().msbsel().multiple();
381 }
382 w
383 });
384
385 self.sdhc
386 .bsr
387 .write(|w| unsafe { w.blocksize().bits(block_size) }.boundary()._4k());
388 self.sdhc
389 .bcr
390 .write(|w| unsafe { w.bcnt().bits(block_amount) });
391
392 self.block_amount = block_amount;
393 self.block_size = block_size;
394 self.trans_pos = 0;
395
396 self.send_command_execute(1 << 5, command.val, argument)
397 }
398
399 fn adtc_stop(&self, _command: u32, _argument: u32) -> Result<(), MciError> {
400 Ok(())
402 }
403
404 fn read_word(&mut self) -> Result<(u32, u8), MciError> {
405 let nbytes: u8 =
406 if ((self.block_size as u64) * (self.block_amount as u64)) - self.trans_pos > 4 {
407 (self.block_size % 4) as u8
408 } else {
409 4
410 };
411
412 if self.trans_pos % (self.block_size as u64) == 0 {
413 self.loop_or_on_eistr_err(|f| f.sdhc.nistr().read().brdrdy().bit_is_set())?;
414 }
415
416 let val = self.sdhc.bdpr.read().bits()
418 & match nbytes {
419 3 => 0xFF_FFFF,
420 2 => 0xFFFF,
421 1 => 0xFF,
422 _ => 0xFFFF_FFFF,
423 };
424
425 self.trans_pos += nbytes as u64;
426
427 if (self.block_size as u64) * (self.block_amount as u64) > self.trans_pos {
428 return Ok((val, nbytes));
429 }
430
431 self.loop_or_on_eistr_err(|f| f.sdhc.nistr().read().trfc().bit_is_set())?;
433 self.sdhc.nistr().modify(|_, w| w.trfc().yes());
434 Ok((val, nbytes))
435 }
436
437 fn write_word(&mut self, val: u32) -> Result<bool, MciError> {
438 let nbytes = 4u64; if self.trans_pos % (self.block_size as u64) == 0 {
440 self.loop_or_on_eistr_err(|f| f.sdhc.nistr().read().bwrrdy().bit_is_set())?;
441 }
442
443 self.sdhc.bdpr.write(|w| unsafe { w.bits(val) });
445 self.trans_pos += nbytes;
446
447 if (self.block_size as u64) * (self.block_amount as u64) > self.trans_pos {
448 return Ok(true);
449 }
450
451 self.loop_or_on_eistr_err(|f| f.sdhc.nistr().read().trfc().bit_is_set())?;
453 self.sdhc.nistr().modify(|_, w| w.trfc().yes());
454 Ok(true)
455 }
456
457 fn read_blocks(
458 &mut self,
459 destination: &mut [u8],
460 number_of_blocks: u16,
461 ) -> Result<bool, MciError> {
462 let mut data = (number_of_blocks as u64) * (self.block_size as u64);
463 let len = data as usize;
464 let mut index = 0usize;
465
466 while data > 0 {
467 let (val, nbytes) = self.read_word()?;
468 for m in 0..nbytes {
469 let mm = m as usize;
470 if mm + index >= len {
471 break;
472 }
473 destination[index + mm] = val.get_bits((mm * 8)..((mm + 1) * 8)) as u8;
474 }
475 let nbytes = if (nbytes as u64) > data {
476 (self.block_size % (nbytes as u16)) as u8
477 } else {
478 nbytes
479 };
480 index += nbytes as usize;
481 data -= nbytes as u64;
482 }
483 Ok(true)
484 }
485
486 fn write_blocks(&mut self, write_data: &[u8], number_of_blocks: u16) -> Result<bool, MciError> {
487 let mut data = (number_of_blocks as u64) * (self.block_size as u64);
488 let len = data as usize;
489 let mut index = 0usize;
490
491 while data > 0 {
492 let mut nbytes = 0u8;
493 let mut val = 0u32;
494 for m in 0..4 {
495 let mm = m as usize;
496 if mm + index >= len {
497 break;
498 }
499 val <<= 8;
500 nbytes += 1;
501 val |= write_data[index + mm] as u32;
502 }
503 self.write_word(val)?;
504 data -= nbytes as u64;
505 index += nbytes as usize;
506 }
507 Ok(true)
508 }
509
510 fn wait_until_read_finished(&self) -> Result<(), MciError> {
511 Ok(())
513 }
514
515 fn wait_until_write_finished(&self) -> Result<(), MciError> {
516 Ok(())
518 }
519}