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