1#![no_implicit_prelude]
21
22extern crate core;
23extern crate rpsp;
24
25use core::clone::Clone;
26use core::convert::{From, Into};
27use core::fmt::{self, Debug, Formatter};
28use core::matches;
29use core::ops::{Deref, DerefMut};
30use core::ptr::NonNull;
31use core::result::Result::{self, Err, Ok};
32
33use rpsp::Board;
34use rpsp::clock::Timer;
35use rpsp::pin::gpio::Output;
36use rpsp::pin::{Pin, PinID};
37use rpsp::spi::{Spi, SpiBus, SpiIO};
38
39use crate::fs::{Block, BlockDevice, DeviceError};
40
41const CMD0: u8 = 0x00u8;
42const CMD8: u8 = 0x08u8;
43const CMD9: u8 = 0x09u8;
44const CMD12: u8 = 0x0Cu8;
45const CMD13: u8 = 0x0Du8;
46const CMD17: u8 = 0x11u8;
47const CMD18: u8 = 0x12u8;
48const CMD24: u8 = 0x18u8;
49const CMD25: u8 = 0x19u8;
50const CMD55: u8 = 0x37u8;
51const CMD58: u8 = 0x3Au8;
52const CMD59: u8 = 0x3Bu8;
53const CMDA23: u8 = 0x17u8;
54const CMDA41: u8 = 0x29u8;
55
56pub enum CardType {
57 None,
58 SD1,
59 SD2,
60 SDHC,
61}
62#[repr(u8)]
63pub enum CardError {
64 Read = 0x1,
65 Write = 0x2,
66 Timeout = 0x0,
67 InitFailed = 0xA,
68 InvalidDevice = 0xB,
69 InvalidOptions = 0xC,
70 InvalidResponse = 0xD,
71 InvalidChecksum = 0xE,
72}
73
74pub struct CardInfo {
75 v2: bool,
76 buf: [u8; 16],
77}
78pub struct Card<'a> {
79 cs: Pin<Output>,
80 spi: SpiBus<'a>,
81 timer: Timer,
82 ver: CardType,
83 crc: bool,
84 attempts: u16,
85}
86
87struct Counter {
88 t: NonNull<Timer>,
89 cur: u16,
90 hit: u16,
91}
92
93impl Counter {
94 #[inline(always)]
95 fn reset(&mut self) {
96 self.cur = 0;
97 }
98 #[inline]
99 fn wait(&mut self) -> Result<(), CardError> {
100 if self.cur >= self.hit {
101 return Err(CardError::Timeout);
102 }
103 unsafe { (&*self.t.as_ptr()).sleep_us(10) };
104 self.cur += 1;
105 Ok(())
106 }
107}
108impl Card<'_> {
109 #[inline(always)]
110 pub fn new<'a>(p: &Board, cs: PinID, spi: impl Into<SpiBus<'a>>) -> Card<'a> {
111 Card::new_crc(p, cs, spi, true)
112 }
113 #[inline]
114 pub fn new_crc<'a>(p: &Board, cs: PinID, spi: impl Into<SpiBus<'a>>, crc: bool) -> Card<'a> {
115 Card {
116 crc,
117 cs: p.pin(cs).output_high(),
118 spi: spi.into(),
119 ver: CardType::None,
120 timer: p.timer().clone(),
121 attempts: 0xFFFu16,
122 }
123 }
124
125 #[inline(always)]
126 pub fn bus(&self) -> &Spi {
127 &self.spi
128 }
129 #[inline(always)]
130 pub fn blocks(&mut self) -> Result<u32, CardError> {
131 Ok(self.info()?.blocks())
132 }
133 pub fn info(&mut self) -> Result<CardInfo, CardError> {
134 if matches!(self.ver, CardType::None) {
135 self.init()?;
136 }
137 let mut i = match self.ver {
138 CardType::None => return Err(CardError::InitFailed),
139 CardType::SD2 | CardType::SDHC => CardInfo::new(true),
140 CardType::SD1 => CardInfo::new(false),
141 };
142 self.cs.low();
143 let r = match self.cmd(CMD9, 0) {
144 Ok(v) if v == 0 => self.read(&mut i.buf),
145 Ok(_) => Err(CardError::InvalidResponse),
146 Err(e) => Err(e),
147 };
148 self.cs.high();
149 r.map(|_| i)
150 }
151 #[inline]
152 pub fn write_block(&mut self, b: &Block, start: u32) -> Result<(), CardError> {
153 if matches!(self.ver, CardType::None) {
154 self.init()?;
155 }
156 self.cs.low();
157 let r = self._write_block(b, self.index(start)?);
158 self.cs.high();
159 r
160 }
161 #[inline]
162 pub fn read_block(&mut self, b: &mut Block, start: u32) -> Result<(), CardError> {
163 if matches!(self.ver, CardType::None) {
164 self.init()?;
165 }
166 self.cs.low();
167 let r = self._read_block(b, self.index(start)?);
168 self.cs.high();
169 r
170 }
171 #[inline]
172 pub fn write_blocks(&mut self, b: &[Block], start: u32) -> Result<(), CardError> {
173 if matches!(self.ver, CardType::None) {
174 self.init()?;
175 }
176 self.cs.low();
177 let r = self._write_blocks(b, self.index(start)?);
178 self.cs.high();
179 r
180 }
181 #[inline]
182 pub fn read_blocks(&mut self, b: &mut [Block], start: u32) -> Result<(), CardError> {
183 if matches!(self.ver, CardType::None) {
184 self.init()?;
185 }
186 self.cs.low();
187 let r = self._read_blocks(b, self.index(start)?);
188 self.cs.high();
189 r
190 }
191
192 #[inline(always)]
193 fn read_byte(&mut self) -> u8 {
194 self.spi.transfer_single(0xFFu8)
195 }
196 #[inline(always)]
197 fn counter(&mut self) -> Counter {
198 Counter {
199 t: unsafe { NonNull::new_unchecked(&mut self.timer) },
200 cur: 0,
201 hit: self.attempts,
202 }
203 }
204 #[inline]
205 fn init(&mut self) -> Result<(), CardError> {
206 self.cs.low();
207 let r = self._init();
208 self.cs.high();
209 r
210 }
211 fn _init(&mut self) -> Result<(), CardError> {
212 let (mut c, mut e, mut o) = (self.counter(), 0x40u8, 0xFFu8);
213 loop {
214 match self.cmd(CMD0, 0xF9F9F9F9) {
217 Err(CardError::Timeout) if e == 0 => return Err(CardError::Timeout),
218 Err(CardError::Timeout) => {
219 for _ in 0..0xFF {
220 self.spi.write_single(0xFFu8);
221 }
222 e = e.saturating_sub(1);
224 c.reset(); },
226 Err(e) => return Err(e),
227 Ok(0x0 | 0x3F) if o == 0 => break,
237 Ok(0x0 | 0x3F) => o = o.saturating_sub(1),
238 Ok(0x1) => break,
239 Ok(_) => (),
240 }
241 c.wait()?;
242 }
243 c.reset();
244 if self.crc && self.cmd(CMD59, 0x1)? != 0x1 {
245 return Err(CardError::InvalidOptions);
246 }
247 let a = loop {
248 if self.cmd(CMD8, 0x1AA)? == 0x5 {
249 self.ver = CardType::SD1;
250 break 0;
251 }
252 let mut b = [0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8];
253 self.spi.transfer_in_place(&mut b);
254 if b[3] == 0xAA {
255 self.ver = CardType::SD2;
256 break 0x40000000;
257 }
258 c.wait()?;
259 };
260 c.reset();
261 while self.cmd_app(CMDA41, a)? != 0 {
262 c.wait()?;
263 }
264 if !matches!(self.ver, CardType::SD2) {
265 return Ok(());
266 }
267 if self.cmd(CMD58, 0)? != 0 {
268 return Err(CardError::InvalidResponse);
269 }
270 let mut b = [0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8];
271 self.spi.transfer_in_place(&mut b);
272 if (b[0] & 0xC0) == 0xC0 {
273 self.ver = CardType::SDHC;
274 }
275 let _ = self.read_byte();
276 Ok(())
277 }
278 #[inline]
279 fn wait_busy(&mut self) -> Result<(), CardError> {
280 let mut c = self.counter();
281 loop {
282 if self.read_byte() == 0xFF {
283 return Ok(());
284 }
285 c.wait()?;
286 }
287 }
288 #[inline(always)]
289 fn index(&self, s: u32) -> Result<u32, CardError> {
290 match self.ver {
291 CardType::None => Err(CardError::InitFailed),
292 CardType::SDHC => Ok(s),
293 CardType::SD1 | CardType::SD2 => Ok(s * 0x200),
294 }
295 }
296 fn read(&mut self, b: &mut [u8]) -> Result<(), CardError> {
297 let mut c = self.counter();
298 loop {
299 match self.read_byte() {
300 0xFF => (),
301 0xFE => break,
302 _ => return Err(CardError::Read),
303 }
304 c.wait()?;
305 }
306 self.spi.read_with(0xFFu8, b);
307 let mut v = [0xFFu8, 0xFFu8];
308 self.spi.transfer_in_place(&mut v);
309 if !self.crc {
310 return Ok(());
311 }
312 let c = u16::from_be_bytes(v);
313 let a = crc_v16(b);
314 if a != c { Err(CardError::InvalidChecksum) } else { Ok(()) }
315 }
316 fn cmd(&mut self, x: u8, arg: u32) -> Result<u8, CardError> {
317 if x != CMD0 && x != CMD12 {
318 self.wait_busy()?;
319 }
320 let mut b = [
321 0x40u8 | x,
322 (arg >> 24) as u8,
323 (arg >> 16) as u8,
324 (arg >> 8) as u8,
325 arg as u8,
326 0,
327 ];
328 b[5] = crc_v7(&b[0..5]);
329 self.spi.write(&b);
330 if x == CMD12 {
331 let _ = self.read_byte();
332 }
333 let mut c = self.counter();
334 loop {
335 let v = self.read_byte();
336 if (v & 0x80) == 0 {
337 return Ok(v);
338 }
339 c.wait()?;
340 }
341 }
342 fn write(&mut self, t: u8, b: &[u8]) -> Result<(), CardError> {
343 self.spi.write_single(t);
344 self.spi.write(b);
345 let c = if self.crc { crc_v16(b).to_be_bytes() } else { [0xFFu8, 0xFFu8] };
346 self.spi.write(&c);
347 if self.read_byte() & 0x1F != 0x5 { Err(CardError::Write) } else { Ok(()) }
348 }
349 #[inline(always)]
350 fn cmd_app(&mut self, x: u8, arg: u32) -> Result<u8, CardError> {
351 self.cmd(CMD55, 0)?;
352 self.cmd(x, arg)
353 }
354 fn _write_block(&mut self, b: &Block, i: u32) -> Result<(), CardError> {
355 self.cmd(CMD24, i)?;
356 self.write(0xFE, &b)?;
357 self.wait_busy()?;
358 if self.cmd(CMD13, 0)? != 0 {
359 return Err(CardError::Write);
360 }
361 if self.read_byte() != 0 {
362 return Err(CardError::Write);
363 }
364 Ok(())
365 }
366 #[inline(always)]
367 fn _read_block(&mut self, b: &mut Block, i: u32) -> Result<(), CardError> {
368 self.cmd(CMD17, i)?;
369 self.read(b)
370 }
371 fn _write_blocks(&mut self, b: &[Block], i: u32) -> Result<(), CardError> {
372 if b.len() == 1 {
373 return self._write_block(&b[0], i);
374 }
375 self.cmd_app(CMDA23, b.len() as u32)?;
376 self.wait_busy()?;
377 self.cmd(CMD25, i)?;
378 for v in b.iter() {
379 self.wait_busy()?;
380 self.write(0xFC, v)?;
381 }
382 self.wait_busy()?;
383 self.spi.write_single(0xFDu8);
384 Ok(())
385 }
386 fn _read_blocks(&mut self, b: &mut [Block], i: u32) -> Result<(), CardError> {
387 if b.len() == 1 {
388 return self._read_block(&mut b[0], i);
389 }
390 self.cmd(CMD18, i)?;
391 for v in b.iter_mut() {
392 self.read(v)?;
393 }
394 self.cmd(CMD12, 0)?;
395 Ok(())
396 }
397}
398impl CardInfo {
399 #[inline(always)]
400 fn new(v2: bool) -> CardInfo {
401 CardInfo { v2, buf: [0u8; 16] }
402 }
403
404 #[inline(always)]
405 pub fn crc(&self) -> u8 {
406 self.buf[0xF] & 0xFF
407 }
408 #[inline]
409 pub fn size(&self) -> u64 {
410 if self.v2 {
411 (self.device_size() as u64 + 1) * 0x200 * 0x400
412 } else {
413 (self.device_size() as u64 + 1) << (self.device_size_multiplier() as u64 * self.block_length() as u64 + 2)
414 }
415 }
416 #[inline]
417 pub fn blocks(&self) -> u32 {
418 if self.v2 {
419 (self.device_size() + 1) * 0x400
420 } else {
421 (self.device_size() + 1) << (self.device_size_multiplier() as u32 * self.block_length() as u32 + 7)
422 }
423 }
424 #[inline(always)]
425 pub fn is_v2(&self) -> bool {
426 self.v2
427 }
428 #[inline(always)]
429 pub fn block_length(&self) -> u8 {
430 self.buf[0x5] & 0xF
431 }
432 #[inline(always)]
433 pub fn device_size(&self) -> u32 {
434 if self.v2 {
435 (((self.buf[0x7] & 0x3F) as u32) << 8) | (((self.buf[0x8] & 0xFF) as u32) << 8) | ((self.buf[0x9] & 0xFF) as u32)
436 } else {
437 (((self.buf[0x6] & 0x3) as u32) << 8) | (((self.buf[0x7] & 0xFF) as u32) << 8) | (((self.buf[0x8] >> 0x6) & 0x3) as u32)
438 }
439 }
440 #[inline(always)]
441 pub fn device_size_multiplier(&self) -> u8 {
442 if self.v2 { ((self.buf[0x9] & 0x3) << 1) | (self.buf[0xA] >> 0x7) } else { 0u8 }
443 }
444}
445
446impl Deref for CardInfo {
447 type Target = [u8];
448
449 #[inline(always)]
450 fn deref(&self) -> &[u8] {
451 &self.buf
452 }
453}
454impl DerefMut for CardInfo {
455 #[inline(always)]
456 fn deref_mut(&mut self) -> &mut [u8] {
457 &mut self.buf
458 }
459}
460
461impl BlockDevice for Card<'_> {
462 #[inline(always)]
463 fn blocks(&mut self) -> Result<u32, DeviceError> {
464 Ok(self.blocks()?)
465 }
466 #[inline(always)]
467 fn write(&mut self, b: &[Block], start: u32) -> Result<(), DeviceError> {
468 Ok(self.write_blocks(b, start)?)
469 }
470 #[inline(always)]
471 fn read(&mut self, b: &mut [Block], start: u32) -> Result<(), DeviceError> {
472 Ok(self.read_blocks(b, start)?)
473 }
474 #[inline(always)]
475 fn write_single(&mut self, b: &Block, start: u32) -> Result<(), DeviceError> {
476 Ok(self.write_block(b, start)?)
477 }
478 #[inline(always)]
479 fn read_single(&mut self, b: &mut Block, start: u32) -> Result<(), DeviceError> {
480 Ok(self.read_block(b, start)?)
481 }
482}
483
484impl From<CardError> for DeviceError {
485 #[inline(always)]
486 fn from(v: CardError) -> DeviceError {
487 match v {
488 CardError::Read => DeviceError::Read,
489 CardError::Write => DeviceError::Write,
490 CardError::Timeout => DeviceError::Timeout,
491 CardError::InvalidChecksum => DeviceError::BadData,
492 CardError::InvalidOptions => DeviceError::InvalidOptions,
493 _ => DeviceError::Hardware(v as u8),
494 }
495 }
496}
497
498#[cfg(feature = "debug")]
499impl Debug for CardError {
500 #[inline]
501 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
502 match self {
503 CardError::Read => f.write_str("Read"),
504 CardError::Write => f.write_str("Write"),
505 CardError::Timeout => f.write_str("Timeout"),
506 CardError::InitFailed => f.write_str("InitFailed"),
507 CardError::InvalidDevice => f.write_str("InvalidDevice"),
508 CardError::InvalidOptions => f.write_str("InvalidOptions"),
509 CardError::InvalidResponse => f.write_str("InvalidResponse"),
510 CardError::InvalidChecksum => f.write_str("InvalidChecksum"),
511 }
512 }
513}
514#[cfg(not(feature = "debug"))]
515impl Debug for CardError {
516 #[inline(always)]
517 fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
518 Ok(())
519 }
520}
521
522fn crc_v7(b: &[u8]) -> u8 {
523 let mut r = 0u8;
524 for i in b {
525 let mut v = *i;
526 for _ in 0..8 {
527 r <<= 1;
528 if ((v & 0x80) ^ (r & 0x80)) != 0 {
529 r ^= 0x9;
530 }
531 v <<= 1;
532 }
533 }
534 (r << 1) | 1
535}
536fn crc_v16(b: &[u8]) -> u16 {
537 let mut r = 0u16;
538 for i in b {
539 r = ((r >> 8) & 0xFF) | (r << 8);
540 r ^= *i as u16;
541 r ^= (r & 0xFF) >> 4;
542 r ^= r << 12;
543 r ^= (r & 0xFF) << 5;
544 }
545 r
546}