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, 0) {
215 Err(CardError::Timeout) if e == 0 => return Err(CardError::Timeout),
216 Err(CardError::Timeout) => {
217 for _ in 0..0xFF {
218 self.spi.write_single(0xFFu8);
219 }
220 e = e.saturating_sub(1);
222 c.reset(); },
224 Err(e) => return Err(e),
225 Ok(0x0 | 0x3F) if o == 0 => break,
235 Ok(0x0 | 0x3F) => o = o.saturating_sub(1),
236 Ok(0x1) => break,
237 Ok(_) => (),
238 }
239 c.wait()?;
240 }
241 if self.crc && self.cmd(CMD59, 0x1)? != 0x1 {
242 return Err(CardError::InvalidOptions);
243 }
244 c.reset();
245 let a = loop {
246 if self.cmd(CMD8, 0x1AA)? == 0x5 {
247 self.ver = CardType::SD1;
248 break 0;
249 }
250 let mut b = [0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8];
251 self.spi.transfer_in_place(&mut b);
252 if b[3] == 0xAA {
253 self.ver = CardType::SD2;
254 break 0x40000000;
255 }
256 c.wait()?;
257 };
258 c.reset();
259 while self.cmd_app(CMDA41, a)? != 0 {
260 c.wait()?;
261 }
262 if !matches!(self.ver, CardType::SD2) {
263 return Ok(());
264 }
265 if self.cmd(CMD58, 0)? != 0 {
266 return Err(CardError::InvalidResponse);
267 }
268 let mut b = [0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8];
269 self.spi.transfer_in_place(&mut b);
270 if (b[0] & 0xC0) == 0xC0 {
271 self.ver = CardType::SDHC;
272 }
273 let _ = self.read_byte();
274 Ok(())
275 }
276 #[inline]
277 fn wait_busy(&mut self) -> Result<(), CardError> {
278 let mut c = self.counter();
279 loop {
280 if self.read_byte() == 0xFF {
281 return Ok(());
282 }
283 c.wait()?;
284 }
285 }
286 #[inline(always)]
287 fn index(&self, s: u32) -> Result<u32, CardError> {
288 match self.ver {
289 CardType::None => Err(CardError::InitFailed),
290 CardType::SDHC => Ok(s),
291 CardType::SD1 | CardType::SD2 => Ok(s * 0x200),
292 }
293 }
294 fn read(&mut self, b: &mut [u8]) -> Result<(), CardError> {
295 let mut c = self.counter();
296 loop {
297 match self.read_byte() {
298 0xFF => (),
299 0xFE => break,
300 _ => return Err(CardError::Read),
301 }
302 c.wait()?;
303 }
304 self.spi.read_with(0xFFu8, b);
305 let mut v = [0xFFu8, 0xFFu8];
306 self.spi.transfer_in_place(&mut v);
307 if !self.crc {
308 return Ok(());
309 }
310 let c = u16::from_be_bytes(v);
311 let a = crc_v16(b);
312 if a != c { Err(CardError::InvalidChecksum) } else { Ok(()) }
313 }
314 fn cmd(&mut self, x: u8, arg: u32) -> Result<u8, CardError> {
315 if x != CMD0 && x != CMD12 {
316 self.wait_busy()?;
317 }
318 let mut b = [
319 0x40u8 | x,
320 (arg >> 24) as u8,
321 (arg >> 16) as u8,
322 (arg >> 8) as u8,
323 arg as u8,
324 0,
325 ];
326 b[5] = crc_v7(&b[0..5]);
327 self.spi.write(&b);
328 if x == CMD12 {
329 let _ = self.read_byte();
330 }
331 let mut c = self.counter();
332 loop {
333 let v = self.read_byte();
334 if (v & 0x80) == 0 {
335 return Ok(v);
336 }
337 c.wait()?;
338 }
339 }
340 fn write(&mut self, t: u8, b: &[u8]) -> Result<(), CardError> {
341 self.spi.write_single(t);
342 self.spi.write(b);
343 let c = if self.crc { crc_v16(b).to_be_bytes() } else { [0xFFu8, 0xFFu8] };
344 self.spi.write(&c);
345 if self.read_byte() & 0x1F != 0x5 { Err(CardError::Write) } else { Ok(()) }
346 }
347 #[inline(always)]
348 fn cmd_app(&mut self, x: u8, arg: u32) -> Result<u8, CardError> {
349 self.cmd(CMD55, 0)?;
350 self.cmd(x, arg)
351 }
352 fn _write_block(&mut self, b: &Block, i: u32) -> Result<(), CardError> {
353 self.cmd(CMD24, i)?;
354 self.write(0xFE, &b)?;
355 self.wait_busy()?;
356 if self.cmd(CMD13, 0)? != 0 {
357 return Err(CardError::Write);
358 }
359 if self.read_byte() != 0 {
360 return Err(CardError::Write);
361 }
362 Ok(())
363 }
364 #[inline(always)]
365 fn _read_block(&mut self, b: &mut Block, i: u32) -> Result<(), CardError> {
366 self.cmd(CMD17, i)?;
367 self.read(b)
368 }
369 fn _write_blocks(&mut self, b: &[Block], i: u32) -> Result<(), CardError> {
370 if b.len() == 1 {
371 return self._write_block(&b[0], i);
372 }
373 self.cmd_app(CMDA23, b.len() as u32)?;
374 self.wait_busy()?;
375 self.cmd(CMD25, i)?;
376 for v in b.iter() {
377 self.wait_busy()?;
378 self.write(0xFC, v)?;
379 }
380 self.wait_busy()?;
381 self.spi.write_single(0xFDu8);
382 Ok(())
383 }
384 fn _read_blocks(&mut self, b: &mut [Block], i: u32) -> Result<(), CardError> {
385 if b.len() == 1 {
386 return self._read_block(&mut b[0], i);
387 }
388 self.cmd(CMD18, i)?;
389 for v in b.iter_mut() {
390 self.read(v)?;
391 }
392 self.cmd(CMD12, 0)?;
393 Ok(())
394 }
395}
396impl CardInfo {
397 #[inline(always)]
398 fn new(v2: bool) -> CardInfo {
399 CardInfo { v2, buf: [0u8; 16] }
400 }
401
402 #[inline(always)]
403 pub fn crc(&self) -> u8 {
404 self.buf[0xF] & 0xFF
405 }
406 #[inline]
407 pub fn size(&self) -> u64 {
408 if self.v2 {
409 (self.device_size() as u64 + 1) * 0x200 * 0x400
410 } else {
411 (self.device_size() as u64 + 1) << (self.device_size_multiplier() as u64 * self.block_length() as u64 + 2)
412 }
413 }
414 #[inline]
415 pub fn blocks(&self) -> u32 {
416 if self.v2 {
417 (self.device_size() + 1) * 0x400
418 } else {
419 (self.device_size() + 1) << (self.device_size_multiplier() as u32 * self.block_length() as u32 + 7)
420 }
421 }
422 #[inline(always)]
423 pub fn is_v2(&self) -> bool {
424 self.v2
425 }
426 #[inline(always)]
427 pub fn block_length(&self) -> u8 {
428 self.buf[0x5] & 0xF
429 }
430 #[inline(always)]
431 pub fn device_size(&self) -> u32 {
432 if self.v2 {
433 (((self.buf[0x7] & 0x3F) as u32) << 8) | (((self.buf[0x8] & 0xFF) as u32) << 8) | ((self.buf[0x9] & 0xFF) as u32)
434 } else {
435 (((self.buf[0x6] & 0x3) as u32) << 8) | (((self.buf[0x7] & 0xFF) as u32) << 8) | (((self.buf[0x8] >> 0x6) & 0x3) as u32)
436 }
437 }
438 #[inline(always)]
439 pub fn device_size_multiplier(&self) -> u8 {
440 if self.v2 { ((self.buf[0x9] & 0x3) << 1) | (self.buf[0xA] >> 0x7) } else { 0u8 }
441 }
442}
443
444impl Deref for CardInfo {
445 type Target = [u8];
446
447 #[inline(always)]
448 fn deref(&self) -> &[u8] {
449 &self.buf
450 }
451}
452impl DerefMut for CardInfo {
453 #[inline(always)]
454 fn deref_mut(&mut self) -> &mut [u8] {
455 &mut self.buf
456 }
457}
458
459impl BlockDevice for Card<'_> {
460 #[inline(always)]
461 fn blocks(&mut self) -> Result<u32, DeviceError> {
462 Ok(self.blocks()?)
463 }
464 #[inline(always)]
465 fn write(&mut self, b: &[Block], start: u32) -> Result<(), DeviceError> {
466 Ok(self.write_blocks(b, start)?)
467 }
468 #[inline(always)]
469 fn read(&mut self, b: &mut [Block], start: u32) -> Result<(), DeviceError> {
470 Ok(self.read_blocks(b, start)?)
471 }
472 #[inline(always)]
473 fn write_single(&mut self, b: &Block, start: u32) -> Result<(), DeviceError> {
474 Ok(self.write_block(b, start)?)
475 }
476 #[inline(always)]
477 fn read_single(&mut self, b: &mut Block, start: u32) -> Result<(), DeviceError> {
478 Ok(self.read_block(b, start)?)
479 }
480}
481
482impl From<CardError> for DeviceError {
483 #[inline(always)]
484 fn from(v: CardError) -> DeviceError {
485 match v {
486 CardError::Read => DeviceError::Read,
487 CardError::Write => DeviceError::Write,
488 CardError::Timeout => DeviceError::Timeout,
489 CardError::InvalidChecksum => DeviceError::BadData,
490 CardError::InvalidOptions => DeviceError::InvalidOptions,
491 _ => DeviceError::Hardware(v as u8),
492 }
493 }
494}
495
496#[cfg(feature = "debug")]
497impl Debug for CardError {
498 #[inline]
499 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
500 match self {
501 CardError::Read => f.write_str("Read"),
502 CardError::Write => f.write_str("Write"),
503 CardError::Timeout => f.write_str("Timeout"),
504 CardError::InitFailed => f.write_str("InitFailed"),
505 CardError::InvalidDevice => f.write_str("InvalidDevice"),
506 CardError::InvalidOptions => f.write_str("InvalidOptions"),
507 CardError::InvalidResponse => f.write_str("InvalidResponse"),
508 CardError::InvalidChecksum => f.write_str("InvalidChecksum"),
509 }
510 }
511}
512#[cfg(not(feature = "debug"))]
513impl Debug for CardError {
514 #[inline(always)]
515 fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
516 Ok(())
517 }
518}
519
520fn crc_v7(b: &[u8]) -> u8 {
521 let mut r = 0u8;
522 for i in b {
523 let mut v = *i;
524 for _ in 0..8 {
525 r <<= 1;
526 if ((v & 0x80) ^ (r & 0x80)) != 0 {
527 r ^= 0x9;
528 }
529 v <<= 1;
530 }
531 }
532 (r << 1) | 1
533}
534fn crc_v16(b: &[u8]) -> u16 {
535 let mut r = 0u16;
536 for i in b {
537 r = ((r >> 8) & 0xFF) | (r << 8);
538 r ^= *i as u16;
539 r ^= (r & 0xFF) >> 4;
540 r ^= r << 12;
541 r ^= (r & 0xFF) << 5;
542 }
543 r
544}