inky_frame/
sd.rs

1// Permission is hereby granted, free of charge, to any person obtaining a copy
2// of this software and associated documentation files (the "Software"), to deal
3// in the Software without restriction, including without limitation the rights
4// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5// copies of the Software, and to permit persons to whom the Software is
6// furnished to do so, subject to the following conditions:
7//
8// The above copyright notice and this permission notice shall be included in
9// all copies or substantial portions of the Software.
10//
11// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17// SOFTWARE.
18//
19
20#![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            // 0xF9F9F9F9 - Switch to SDR12 mode. Forces fast-boot on all cards
215            // so they startup properly.
216            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                    // NOTE(sf): Timeout 64 times before giving up.
223                    e = e.saturating_sub(1);
224                    c.reset(); // Reset Counter
225                },
226                Err(e) => return Err(e),
227                // NOTE(sf): Some SDCards do not respond with 'R1_IDLE_STATE' (1)
228                //           when asked to go to IDLE. Instead, they respond with
229                //           'R1_READY_STATE' (0) or 'UNKNOWN' (63) which I don't
230                //           know what it means. But! If we keep going from here
231                //           the SDCard works perfectly!! Fucking cheap shit..
232                //
233                //           Anyway, we don't break immediately on this, we let
234                //           it cycle for 255 times before, just to be 1000% sure
235                //           that it's one of those weird cards first.
236                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}