Skip to main content

rp_sdio/
sdio.rs

1//! Used to interface with SD cards using SDIO
2//!
3
4use crate::errors::SdioError;
5use crate::registers::{SdCic, SdCid, SdCsd, SdOcr};
6use core::{cmp, mem};
7use bytemuck::{bytes_of_mut, bytes_of};
8use cortex_m::singleton;
9use embedded_io::blocking::{Read, Seek, Write};
10use embedded_io::{Io, SeekFrom};
11use hal::dma::single_buffer;
12use hal::dma::single_buffer::Transfer;
13use hal::dma::SingleChannel as SingleChannelDma;
14use hal::pio::{
15    InstalledProgram, MovStatusConfig, PIOBuilder, PIOExt, PinDir, Running, Rx, ShiftDirection,
16    StateMachine, Tx, UninitStateMachine, PIO, SM0, SM1,
17};
18use hal::Timer;
19use pio::{Instruction, InstructionOperands, OutDestination, SetDestination};
20use pio_proc::pio_file;
21use rp2040_hal as hal;
22
23/// Timeout for SD commands, in milliseconds
24pub const SD_CMD_TIMEOUT_MS: u64 = 1_000;
25
26/// Startup time for sd card, in milliseconds
27pub const SD_STARTUP_MS: u64 = 2;
28
29/// OCR voltage range, set to 3.2-3.4
30pub const SD_OCR_VOLT_RANGE: u32 = 0b0011_0000__0000_0000_0000_0000;
31
32/// Block length for SD operations
33pub const SD_BLOCK_LEN: usize = 512;
34
35/// Size of the quaduple-crc at the end of a block
36pub const SD_BLOCK_CRC_LEN: usize = 8;
37
38/// Size of the end signal at the end of tx transmissions
39
40pub const SD_BLOCK_END_LEN: usize = 4;
41
42/// Size of all tx/rx transfers
43
44pub const SD_BLOCK_LEN_TOTAL: usize = SD_BLOCK_LEN + SD_BLOCK_CRC_LEN + SD_BLOCK_END_LEN;
45
46/// Multiplier for nibbles
47
48pub const SD_NIBBLE_MULT: usize = 2;
49
50/// Divider for words
51
52pub const SD_WORD_DIV: usize = 4;
53
54/// Index of the crc in the working block
55
56pub const SD_CRC_IDX_MSB: usize = SD_BLOCK_LEN / SD_WORD_DIV;
57pub const SD_CRC_IDX_LSB: usize = SD_CRC_IDX_MSB + 1;
58pub const SD_TEND_IDX: usize = SD_CRC_IDX_LSB + 1;
59
60/// Clock speed divider for initialization transfers
61pub const SD_CLK_DIV_INIT: u16 = 25;
62
63/// Retry count
64pub const SD_RETRIES: usize = 3;
65
66/// CRC7 Table used for calculating all 7-bit sd-card crcs
67pub static CRC7_TABLE: [u8; 256] = [
68    0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee,
69    0x32, 0x20, 0x16, 0x04, 0x7a, 0x68, 0x5e, 0x4c, 0xa2, 0xb0, 0x86, 0x94, 0xea, 0xf8, 0xce, 0xdc,
70    0x64, 0x76, 0x40, 0x52, 0x2c, 0x3e, 0x08, 0x1a, 0xf4, 0xe6, 0xd0, 0xc2, 0xbc, 0xae, 0x98, 0x8a,
71    0x56, 0x44, 0x72, 0x60, 0x1e, 0x0c, 0x3a, 0x28, 0xc6, 0xd4, 0xe2, 0xf0, 0x8e, 0x9c, 0xaa, 0xb8,
72    0xc8, 0xda, 0xec, 0xfe, 0x80, 0x92, 0xa4, 0xb6, 0x58, 0x4a, 0x7c, 0x6e, 0x10, 0x02, 0x34, 0x26,
73    0xfa, 0xe8, 0xde, 0xcc, 0xb2, 0xa0, 0x96, 0x84, 0x6a, 0x78, 0x4e, 0x5c, 0x22, 0x30, 0x06, 0x14,
74    0xac, 0xbe, 0x88, 0x9a, 0xe4, 0xf6, 0xc0, 0xd2, 0x3c, 0x2e, 0x18, 0x0a, 0x74, 0x66, 0x50, 0x42,
75    0x9e, 0x8c, 0xba, 0xa8, 0xd6, 0xc4, 0xf2, 0xe0, 0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62, 0x70,
76    0x82, 0x90, 0xa6, 0xb4, 0xca, 0xd8, 0xee, 0xfc, 0x12, 0x00, 0x36, 0x24, 0x5a, 0x48, 0x7e, 0x6c,
77    0xb0, 0xa2, 0x94, 0x86, 0xf8, 0xea, 0xdc, 0xce, 0x20, 0x32, 0x04, 0x16, 0x68, 0x7a, 0x4c, 0x5e,
78    0xe6, 0xf4, 0xc2, 0xd0, 0xae, 0xbc, 0x8a, 0x98, 0x76, 0x64, 0x52, 0x40, 0x3e, 0x2c, 0x1a, 0x08,
79    0xd4, 0xc6, 0xf0, 0xe2, 0x9c, 0x8e, 0xb8, 0xaa, 0x44, 0x56, 0x60, 0x72, 0x0c, 0x1e, 0x28, 0x3a,
80    0x4a, 0x58, 0x6e, 0x7c, 0x02, 0x10, 0x26, 0x34, 0xda, 0xc8, 0xfe, 0xec, 0x92, 0x80, 0xb6, 0xa4,
81    0x78, 0x6a, 0x5c, 0x4e, 0x30, 0x22, 0x14, 0x06, 0xe8, 0xfa, 0xcc, 0xde, 0xa0, 0xb2, 0x84, 0x96,
82    0x2e, 0x3c, 0x0a, 0x18, 0x66, 0x74, 0x42, 0x50, 0xbe, 0xac, 0x9a, 0x88, 0xf6, 0xe4, 0xd2, 0xc0,
83    0x1c, 0x0e, 0x38, 0x2a, 0x54, 0x46, 0x70, 0x62, 0x8c, 0x9e, 0xa8, 0xba, 0xc4, 0xd6, 0xe0, 0xf2,
84];
85
86/// Simple function that calculates a crc7 from words.
87/// skip specifies how many bytes to skip before the data begins, len specifies
88/// the length of the data in bytes.
89pub fn calculate_crc7_from_words(words: &[u32], skip: usize, len: usize) -> u8 {
90    let mut crc: u8 = 0;
91
92    let start_word = skip / 4; // Words are 32 bits long
93    let start_shift = 24 - ((skip % 4) * 8);
94
95    let mut word = start_word;
96    let mut shift = start_shift;
97
98    for _ in 0..len {
99        // Calculate crc
100        let byte = ((words[word] >> shift) & 0xFF) as u8;
101        let index = byte ^ crc;
102        crc = CRC7_TABLE[index as usize];
103
104        // Advance the shift and/or the word
105
106        if shift == 0 {
107            shift = 24;
108            word += 1;
109        } else {
110            shift -= 8;
111        }
112    }
113
114    crc
115}
116
117// This crc algorithm is based on the CRC16 generator/checker specified in the
118// Part 1 Physical Layer Simplified Specification
119// !INLINING REDUCES PERFORMANCE!
120pub fn crc16_4bit(data: &[u32]) -> u64 {
121    let mut crc = 0;
122    // Simulate a hardware crc calculator
123    for word in data {
124        // Convert the data from 4 bytes into 1 word, and assign it to "data in"
125        // "data_in" basically represents the input signal to our virtual hardware
126        // crc calculator
127        let data_in = word.swap_bytes();
128
129        // Discard the data that is "getting written out" and use it to xor
130        // with the data "coming in"
131        let mut data_out: u32 = (crc >> 32) as u32;
132        crc <<= 32;
133
134        // "data_out" is only affected by the last XOR in the diagram, which
135        // is the last 4 bits of each data line(last 16 of all 4). pre-xor
136        // the data_out and data in where it matters
137        data_out ^= (data_out ^ data_in) >> 16;
138
139        // xor the data in and the data out, like in the diagram
140        let xorred: u64 = (data_out ^ data_in) as u64;
141
142        // then apply it to the different XORs in the diagram(position 0, 5, and 12)
143        crc ^= xorred;
144        crc ^= xorred << (5 * 4);
145        crc ^= xorred << (12 * 4);
146    }
147
148    crc
149}
150
151const FLAG_ACMD: u16 = 0x40;
152const FLAG_R0: u16 = 0x00;
153const FLAG_R1: u16 = 0x80;
154const FLAG_R1B: u16 = 0x100;
155const FLAG_R2: u16 = 0x180;
156const FLAG_R3: u16 = 0x200;
157const FLAG_R6: u16 = 0x280;
158const FLAG_R7: u16 = 0x300;
159const FLAGS_R: u16 = 0x380;
160
161#[derive(PartialEq, Clone, Copy)]
162#[repr(u16)]
163/// Possible commands to give to the SD card
164/// **May be macro'd out in future versions**
165pub enum SdCmd {
166    /// CMD0: GO_IDLE_STATE, R0
167    GoIdleState = FLAG_R0 | 0,
168    /// CMD2: ALL_SEND_CID, requests all SD cards send their CIDs. R2.
169    AllSendCid = FLAG_R2 | 2,
170    /// CMD3: SEND_RELATIVE_ADDR, asks the card to send it's RCA. R6.
171    SendRelativeAddr = FLAG_R6 | 3,
172    // /// !TODO! CMD6: SWITCH_FUNC, R1
173    /// CMD7: SELECT_DESELECT_CARD, selects the card if the RCA is that of
174    /// the card, deselects it otherwise. Supply the RCA. R1b.
175    SelectDeselectCard(u16) = FLAG_R1B | 7,
176    /// CMD8: SEND_IF_COND, asks if the sd card supports the current voltage along if
177    /// it supports pcie. Supply the check pattern to be verified. R7.
178    SendIfCond(u8) = FLAG_R7 | 8,
179    /// CMD9: SEND_CSD, asks the card to send it's csd. Supply the RCA
180    /// of the card. R2.
181    SendCsd(u16) = FLAG_R2 | 9,
182    // /// !TODO! CMD10: SEND_CID, R1.
183    // /// !TODO! CMD12: STOP_TRANSMISSION, R1b.
184    // /// !TODO! CMD13: SEND_STATUS, R2.
185    /// CMD16: SET_BLOCKLEN, sets the block length to be used in all reads
186    /// and writes. Supply the block length as a u32. R1.
187    SetBlockLen(u32) = FLAG_R1 | 16,
188    /// CMD17: READ_SINGLE_BLOCK, start a single block read from the
189    /// SD card. Supply the data address with this command. R1.
190    ReadSingleBlock(u32) = FLAG_R1 | 17,
191    // /// !TODO! CMD18: READ_MULTIPLE_BLOCK, R1.
192    /// CMD24: WRITE_BLOCK, start a single block write to the SD card. Supply
193    /// the data address with this command. R1.
194    WriteBlock(u32) = FLAG_R1 | 24,
195    // /// !TODO! CMD25: WRITE_MULTIPLE_BLOCK, R1.
196    // /// !TODO! CMD27: PROGRAM_CSD, R1.
197    // /// !TODO! CMD32: ERASE_WR_BLK_START, R1.
198    // /// !TODO! CMD33: ERASE_WR_BLK_END, R1.
199    // /// !TODO! CMD38: ERASE, R1b.
200    /// CMD55: APP_CMD, R1. **DO NOT USE.** APP_CMD is automatically sent before any ACMD.
201    /// Supply the RCA with this command
202    AppCmd(u16) = FLAG_R1 | 55,
203    // /// !TODO! CMD56: GEN_CMD
204    /// ACMD6: SET_BUS_WIDTH, sets the bus width to 4-bit if the supplied boolean
205    /// is true, 1-bit if false. R1
206    SetBusWidth(bool) = FLAG_R1 | FLAG_ACMD | 6,
207    // /// !TODO! ACMD13: SD_STATUS
208    // /// !TODO! ACMD22: SEND_NUM_WR_BLOCKS
209    // /// !TODO! ACMD23: SET_WR_BLK_ERASE_COUNT
210    /// ACMD41: SD_APP_OP_COND, Sends host capacity support info and asks the card to send the OCR
211    /// Supply HCS, XPC, S18R, and Voltage Window. R3
212    SdAppOpCond(bool, bool, bool, u32) = FLAG_R3 | FLAG_ACMD | 41,
213    // /// !TODO! ACMD42: SET_CLR_CARD_DETECT
214    // /// !TODO! ACMD51: SEND_SCR
215}
216
217impl Into<u16> for SdCmd {
218    fn into(self) -> u16 {
219        // SAFETY: the enum is `#[repr(u16)]`
220        unsafe { (&self as *const Self).cast::<u16>().read() }
221    }
222}
223
224impl SdCmd {
225    #[inline]
226    /// Get the index of a command
227    pub fn get_cmd_index(&self) -> u32 {
228        let val: u16 = (*self).into();
229
230        // The first 6 bits is the command index
231        (val & 0x3f) as u32
232    }
233
234    /// Get the response type of a command
235    pub fn get_cmd_response(&self) -> SdCmdResponseType {
236        let val: u16 = (*self).into();
237
238        match val & FLAGS_R {
239            FLAG_R1 => SdCmdResponseType::R1,
240            FLAG_R1B => SdCmdResponseType::R1b,
241            FLAG_R2 => SdCmdResponseType::R2,
242            FLAG_R3 => SdCmdResponseType::R3,
243            FLAG_R6 => SdCmdResponseType::R6,
244            FLAG_R7 => SdCmdResponseType::R7,
245            _ => SdCmdResponseType::R0,
246        }
247    }
248
249    #[inline]
250    /// Returns true if a command is an app command
251    pub fn is_acmd(&self) -> bool {
252        let val: u16 = (*self).into();
253
254        (val & FLAG_ACMD) != 0
255    }
256
257    /// Format command as 2 words. For use with send_command
258    pub fn format(&self) -> [u32; 2] {
259        // Bits 63-56 are the length of the command in bits, -1
260        // Always 47, but specified because PIO asm can't autonomously set it's
261        // internal registers to anything above 31
262        //
263        // Bits 55-54 will always be 0b01, as it specifies the starting bit(0) and the command
264        // direction(host->card)
265        //
266        // Bit 8 is always 1(end bit)
267        let mut data: [u32; 2] = [
268            0b0010_1111_0100_0000__0000_0000_0000_0000,
269            0b0000_0000_0000_0000__0000_0001_0000_0000,
270        ];
271
272        // Bits 53-48 is the command index
273        data[0] |= self.get_cmd_index() << 16;
274
275        // Bits 47-16 is the argument
276        // Sort this match case by most commonly used first
277        // May macro out this entire code block
278        match self {
279            Self::SetBlockLen(unsigned32)
280            | Self::ReadSingleBlock(unsigned32)
281            | Self::WriteBlock(unsigned32) => {
282                data[0] |= (unsigned32 >> 16) & 0xFFFF;
283                data[1] |= (unsigned32 << 16) & 0xFFFF_0000;
284            }
285            // And some commands don't have an argument
286            Self::GoIdleState | Self::AllSendCid | Self::SendRelativeAddr => {}
287            Self::SelectDeselectCard(rca) | Self::SendCsd(rca) | Self::AppCmd(rca) => {
288                // Bits 47-32 are the RCA, 31-16 are stuff bits
289                data[0] |= *rca as u32;
290            }
291            Self::SetBusWidth(fourbit) => {
292                data[1] |= match fourbit {
293                    true => 0b10 << 16,
294                    false => 0,
295                }
296            }
297            Self::SendIfCond(test_pattern) => {
298                // Bits 47-28 are reserved
299                // 27-24 is the supply voltage, however always 0b0001 (2.7-3.6v)
300                // both because that is the rp2040 voltage and because no other
301                // ranges are specified
302                data[1] |= 0b0001 << 24;
303                // 23-16 is the check pattern
304                data[1] |= (*test_pattern as u32) << 16;
305            }
306            Self::SdAppOpCond(hcs, xpc, s18r, voltage_window) => {
307                // Bit 47 is reserved
308                // Bit 46 is the HCS
309                if *hcs {
310                    data[0] |= 1 << 14;
311                }
312                // Bit 45 is reserved
313                // Bit 44 is XPC
314                if *xpc {
315                    data[0] |= 1 << 12;
316                }
317                // Bits 43-41 are reserved
318                // Bit 40 is S18R
319                if *s18r {
320                    data[0] |= 1 << 8;
321                }
322
323                // Bits 39-16 is the Voltage Window
324                data[0] |= (voltage_window >> 16) & 0xFF;
325                data[1] |= (voltage_window << 16) & 0xFFFF_0000;
326            }
327        }
328
329        // Bits 15-9 is the crc7 of the command, processed in big endian
330        let crc = calculate_crc7_from_words(&data, 1, 5);
331        data[1] |= (crc as u32) << 8;
332
333        // Bits 7-0 is the length of the response to the command - 1
334        let response_len = self.get_cmd_response().get_response_len() as u32;
335
336        if response_len > 0 {
337            data[1] |= response_len - 1;
338        }
339
340        data
341    }
342}
343
344/// Possible response types for SD commands
345#[derive(PartialEq)]
346pub enum SdCmdResponseType {
347    /// R0, no response
348    R0,
349    /// R1, normal response
350    R1,
351    /// R1b, normal response with busyx_dm
352    R1b,
353    /// R2, CID/CSD register
354    R2,
355    /// R3, OCR register
356    R3,
357    /// R6, Published RCA response
358    R6,
359    /// R7, Card interface condition
360    R7,
361}
362
363impl SdCmdResponseType {
364    /// Get the length of the response in bits
365    pub fn get_response_len(&self) -> u8 {
366        match self {
367            SdCmdResponseType::R0 => 0,
368            SdCmdResponseType::R1
369            | SdCmdResponseType::R1b
370            | SdCmdResponseType::R3
371            | SdCmdResponseType::R6
372            | SdCmdResponseType::R7 => 48,
373            SdCmdResponseType::R2 => 136,
374        }
375    }
376}
377
378/// Same as SdCmdResponseType, just for returning the actual values
379pub enum SdCmdResponse {
380    /// R0, returns nothing
381    R0,
382    /// R1, returns the card status
383    R1(SdCardStatus),
384    /// R1b, identical to R1
385    R1b(SdCardStatus),
386    /// R2, returns cid or csd
387    R2([u32; 4]),
388    /// R3, returns OCR register
389    R3(SdOcr),
390    /// R6, returns RCA
391    R6(u16),
392    /// R7, returns CIC
393    R7(SdCic),
394}
395
396/// Status of the sd card
397pub struct SdCardStatus {
398    pub card_status: u32,
399}
400
401impl SdCardStatus {
402    /// Gets the current state of the card
403    pub fn get_current_state(&self) -> SdCurrentState {
404        let current_state = (self.card_status >> 9) & 0xF;
405
406        SdCurrentState::from_int(current_state as u8)
407    }
408
409    pub fn get_worst_error(&self) -> Result<(), SdioError> {
410        // First see if there is an error
411        if (self.card_status & 0b1111_1101_1111_1001__1000_0000_0000_1000) == 0 {
412            return Ok(());
413        }
414
415        // Proceed with the if statements...
416        // !TODO! make less ugly
417        if self.cc_error() {
418            return Err(SdioError::CcError {});
419        }
420
421        if self.com_crc_error() {
422            return Err(SdioError::BadTxCrc7 {});
423        }
424
425        if self.illegal_command() {
426            return Err(SdioError::IllegalCommand {});
427        }
428
429        if self.card_ecc_failed() {
430            return Err(SdioError::CardEccFailed {});
431        }
432
433        if self.out_of_range() {
434            return Err(SdioError::OutOfRange {});
435        }
436
437        if self.address_error() {
438            return Err(SdioError::AddressError {});
439        }
440
441        if self.block_len_error() {
442            return Err(SdioError::BlockLenError {});
443        }
444
445        if self.erase_seq_error() {
446            return Err(SdioError::EraseSeqError {});
447        }
448
449        if self.erase_param() {
450            return Err(SdioError::EraseParamError {});
451        }
452
453        if self.wp_violation() {
454            return Err(SdioError::WpViolation {});
455        }
456
457        if self.lock_unlocked_failed() {
458            return Err(SdioError::LockUnlockFailed {});
459        }
460
461        if self.wp_erase_skip() {
462            return Err(SdioError::WpEraseSkip {});
463        }
464
465        if self.ake_seq_error() {
466            return Err(SdioError::AkeSeqError {});
467        }
468
469        Err(SdioError::CmdUnknownErr {})
470    }
471
472    #[inline]
473    /// Returns true if the OUT_OF_RANGE bit is set
474    pub fn out_of_range(&self) -> bool {
475        (self.card_status & (1 << 31)) > 0
476    }
477    #[inline]
478    /// Returns true if the ADDRESS_ERROR bit is set
479    pub fn address_error(&self) -> bool {
480        (self.card_status & (1 << 30)) > 0
481    }
482    #[inline]
483    /// Returns true if the BLOCK_LEN_ERROR bit is set
484    pub fn block_len_error(&self) -> bool {
485        (self.card_status & (1 << 29)) > 0
486    }
487    #[inline]
488    /// Returns true if the ERASE_SEQ_ERROR bit is set
489    pub fn erase_seq_error(&self) -> bool {
490        (self.card_status & (1 << 28)) > 0
491    }
492    #[inline]
493    /// Returns true if the ERASE_PARAM bit is set
494    pub fn erase_param(&self) -> bool {
495        (self.card_status & (1 << 27)) > 0
496    }
497    #[inline]
498    /// Returns true if the WP_VIOLATION bit is set
499    pub fn wp_violation(&self) -> bool {
500        (self.card_status & (1 << 26)) > 0
501    }
502    #[inline]
503    /// Returns true if the CARD_IS_LOCKED bit is set
504    pub fn card_is_locked(&self) -> bool {
505        (self.card_status & (1 << 25)) > 0
506    }
507    #[inline]
508    /// Returns true if the LOCK_UNLOCK_FAILED bit is set
509    pub fn lock_unlocked_failed(&self) -> bool {
510        (self.card_status & (1 << 24)) > 0
511    }
512    #[inline]
513    /// Returns true if the COM_CRC_ERROR bit is set
514    pub fn com_crc_error(&self) -> bool {
515        (self.card_status & (1 << 23)) > 0
516    }
517    #[inline]
518    /// Returns true if the ILLEGAL_COMMAND bit is set
519    pub fn illegal_command(&self) -> bool {
520        (self.card_status & (1 << 22)) > 0
521    }
522    #[inline]
523    /// Returns true if the CARD_ECC_FAILED bit is set
524    pub fn card_ecc_failed(&self) -> bool {
525        (self.card_status & (1 << 21)) > 0
526    }
527    #[inline]
528    /// Returns true if the CC_ERROR bit is set
529    pub fn cc_error(&self) -> bool {
530        (self.card_status & (1 << 20)) > 0
531    }
532    #[inline]
533    /// Returns true if the ERROR bit is set
534    pub fn error(&self) -> bool {
535        (self.card_status & (1 << 19)) > 0
536    }
537    #[inline]
538    /// Returns true if the CSD_OVERWRITE bit is set
539    pub fn csd_overwrite(&self) -> bool {
540        (self.card_status & (1 << 16)) > 0
541    }
542    #[inline]
543    /// Returns true if the WP_ERASE_SKIP bit is set
544    pub fn wp_erase_skip(&self) -> bool {
545        (self.card_status & (1 << 15)) > 0
546    }
547    #[inline]
548    /// Returns true if the CARD_ECC_DISABLED bit is set
549    pub fn card_ecc_disabled(&self) -> bool {
550        (self.card_status & (1 << 14)) > 0
551    }
552    #[inline]
553    /// Returns true if the ERASE_RESET bit is set
554    pub fn erase_reset(&self) -> bool {
555        (self.card_status & (1 << 13)) > 0
556    }
557    #[inline]
558    /// Returns true if the READY_FOR_DATA bit is set
559    pub fn ready_for_data(&self) -> bool {
560        (self.card_status & (1 << 8)) > 0
561    }
562    #[inline]
563    /// Returns true if the FX_EVENT bit is set
564    pub fn fx_event(&self) -> bool {
565        (self.card_status & (1 << 6)) > 0
566    }
567    #[inline]
568    /// Returns true if the APP_CMD bit is set
569    pub fn app_cmd(&self) -> bool {
570        (self.card_status & (1 << 5)) > 0
571    }
572    #[inline]
573    /// Returns true if the AKE_SEQ_ERROR bit is set
574    pub fn ake_seq_error(&self) -> bool {
575        (self.card_status & (1 << 3)) > 0
576    }
577}
578
579pub enum SdCurrentState {
580    Idle,
581    Ready,
582    Ident,
583    Stby,
584    Tran,
585    Data,
586    Rcv,
587    Prg,
588    Dis,
589    Reserved,
590}
591
592impl SdCurrentState {
593    /// Grabs the sd state from a nibble
594    pub fn from_int(nibble: u8) -> Self {
595        match nibble {
596            0 => Self::Idle,
597            1 => Self::Ready,
598            2 => Self::Ident,
599            3 => Self::Stby,
600            4 => Self::Tran,
601            5 => Self::Data,
602            6 => Self::Rcv,
603            7 => Self::Prg,
604            8 => Self::Dis,
605            _ => Self::Reserved,
606        }
607    }
608}
609
610/// SDIO 4bit interface struct
611pub struct Sdio4bit<'a, DmaCh: SingleChannelDma, P: PIOExt> {
612    /// DMA used to read/write data from the SD card
613    dma: Option<DmaCh>,
614    /// Reference to the processor's timer
615    timer: &'a Timer,
616    /// The command state machine, controls SD_CLK and SD_CMD
617    sm_cmd: StateMachine<(P, SM0), Running>,
618    sm_cmd_rx: Rx<(P, SM0)>,
619    sm_cmd_tx: Tx<(P, SM0)>,
620    /// The data state machine, controls SD_DAT0-SD_DAT3
621    /// Is an option since it can be used up during a tx or an rx
622    sm_dat: Option<UninitStateMachine<(P, SM1)>>,
623    /// The base pin for the data lines, aka DAT0
624    sd_dat_base_id: u8,
625    /// The data recieve program
626    program_data_rx: Option<InstalledProgram<P>>,
627    /// The data transmit program
628    /// Is an option since it can be used up during a tx
629    program_data_tx: Option<InstalledProgram<P>>,
630
631    /// The CID register for the card
632    cid: SdCid,
633    /// The RCA register for the card
634    rca: u16,
635    /// The CSD register for the card
636    csd: SdCsd,
637
638    /// The current working block for the SD card
639    working_block: Option<&'static mut [u32; SD_BLOCK_LEN_TOTAL / SD_WORD_DIV]>,
640    /// The address of the current working block
641    working_block_num: u32,
642    /// Set true if we dirty
643    dirty: bool,
644
645    /// The current read/write position
646    position: u64,
647    /// The size of the sd card in blocks
648    size: u32,
649
650    /// Temporary home for Rx and Tx not used by DMAs
651    sm_dat_rx: Option<Rx<(P, SM1)>>,
652    sm_dat_tx: Option<Tx<(P, SM1)>>,
653
654    /// Home for DMA during TX
655    tx_dma_in_use:
656        Option<Transfer<DmaCh, &'static mut [u32; SD_BLOCK_LEN_TOTAL / SD_WORD_DIV], Tx<(P, SM1)>>>,
657    /// Home for DMA during RX
658    rx_dma_in_use:
659        Option<Transfer<DmaCh, Rx<(P, SM1)>, &'static mut [u32; SD_BLOCK_LEN_TOTAL / SD_WORD_DIV]>>,
660    /// Home for the cmd state machine during TX and RX
661    sm_in_use: Option<StateMachine<(P, SM1), Running>>,
662
663    /// Clock divider after initialization
664    sd_full_clk_div: u16,
665}
666
667impl<'a, DmaCh: SingleChannelDma, P: PIOExt> Sdio4bit<'a, DmaCh, P> {
668    /// Create a new SDIO interface
669    pub fn new(
670        pio: &mut PIO<P>,
671        dma: DmaCh,
672        timer: &'a Timer,
673        sm0: UninitStateMachine<(P, SM0)>,
674        sm1: UninitStateMachine<(P, SM1)>,
675        sd_clk_id: u8,
676        sd_cmd_id: u8,
677        sd_dat_base_id: u8,
678        sd_full_clk_div: u16,
679    ) -> Self {
680        // Initialilze the raw program variables from the rp2040_sdio.pio file
681        let program_cmd_clk =
682            pio_file!("src/rp2040_sdio.pio", select_program("sdio_cmd_clk")).program;
683        let program_data_rx =
684            pio_file!("src/rp2040_sdio.pio", select_program("sdio_data_rx")).program;
685        let program_data_tx =
686            pio_file!("src/rp2040_sdio.pio", select_program("sdio_data_tx")).program;
687
688        // Install them to the pio
689        let program_cmd_clk = pio.install(&program_cmd_clk).unwrap();
690        let program_data_rx = pio.install(&program_data_rx).unwrap();
691        let program_data_tx = pio.install(&program_data_tx).unwrap();
692
693        let (mut sm_cmd, sm_cmd_rx, sm_cmd_tx) = PIOBuilder::from_program(program_cmd_clk)
694            .set_mov_status_config(MovStatusConfig::Tx(2))
695            .set_pins(sd_cmd_id, 1)
696            .out_pins(sd_cmd_id, 1)
697            .in_pin_base(sd_cmd_id)
698            .jmp_pin(sd_cmd_id)
699            .side_set_pin_base(sd_clk_id)
700            .out_shift_direction(ShiftDirection::Left)
701            .in_shift_direction(ShiftDirection::Left)
702            // Set the initial clock speed to ~1mhz for initialization
703            .clock_divisor_fixed_point(SD_CLK_DIV_INIT, 0)
704            .autopush(true)
705            .autopull(true)
706            .build(sm0);
707
708        let working_block = singleton!(: [u32; SD_BLOCK_LEN_TOTAL / SD_WORD_DIV] = [0xAF; SD_BLOCK_LEN_TOTAL / SD_WORD_DIV]).unwrap();
709
710        sm_cmd.set_pindirs([(sd_clk_id, PinDir::Output), (sd_cmd_id, PinDir::Output)]);
711        // Start the state machine
712        let sm_cmd = sm_cmd.start();
713
714        let sm_dat = sm1;
715
716        Self {
717            dma: Some(dma),
718            timer,
719            sm_cmd,
720            sm_cmd_rx,
721            sm_cmd_tx,
722            sm_dat: Some(sm_dat),
723            sd_dat_base_id,
724            program_data_rx: Some(program_data_rx),
725            program_data_tx: Some(program_data_tx),
726            cid: SdCid::new([0; 4]),
727            // RCA must initially be 0 for the first CMD55 to work properly
728            rca: 0,
729            csd: SdCsd::new([0; 4]),
730
731            working_block: Some(working_block),
732            working_block_num: 0,
733            dirty: false,
734
735            position: 0,
736            size: 0,
737            // All start as none
738            sm_dat_rx: None,
739            sm_dat_tx: None,
740            tx_dma_in_use: None,
741            rx_dma_in_use: None,
742            sm_in_use: None,
743            sd_full_clk_div,
744        }
745    }
746
747    /// Send a command to the SD card
748    pub fn send_command(&mut self, command: SdCmd) -> Result<SdCmdResponse, SdioError> {
749        // If the command is an app command, first send the AppCmd command
750        if command.is_acmd() {
751            self.send_command(SdCmd::AppCmd(self.rca))?;
752        }
753
754        // Get the data for the command
755        let command_data = command.format();
756
757        // Push both words into tx
758        self.sm_cmd_tx.write(command_data[0]);
759        self.sm_cmd_tx.write(command_data[1]);
760
761        let response_type = command.get_cmd_response();
762
763        // Create a buffer and make the actually accessable portion equal to
764        // the response size. Max size is R2, which is 136 bits/17 bytes/4.25 wqrds
765        let mut resp_buf: [u32; 5] = [0; 5];
766
767        // Calculate the length of the response, and add 1 since all response lengths are not
768        // divisable by 32 bits
769        let resp_len_bits = response_type.get_response_len();
770        let resp_len: usize = ((resp_len_bits / 32) + 1) as usize;
771
772        for i in 0..resp_len {
773            let start_time = self.timer.get_counter();
774            while self.sm_cmd_rx.is_empty() {
775                let current_time = self.timer.get_counter();
776
777                let time_delta = current_time
778                    .checked_duration_since(start_time)
779                    .unwrap()
780                    .to_millis();
781
782                if time_delta > SD_CMD_TIMEOUT_MS {
783                    return Err(SdioError::CmdTimeout {
784                        cmd: command.get_cmd_index() as u8,
785                        time_ms: time_delta,
786                    });
787                }
788            }
789
790            resp_buf[i] = self.sm_cmd_rx.read().unwrap();
791        }
792
793        // shift the last word so the same crc calculation can be used for in
794        // and out data
795        resp_buf[resp_len - 1] = resp_buf[resp_len - 1] << (32 - (resp_len_bits % 32));
796
797        // Return here if no response, otherwise get the response
798        if response_type == SdCmdResponseType::R0 {
799            return Ok(SdCmdResponse::R0);
800        }
801
802        // Verifty the command index and crc (if it has one)
803        if response_type != SdCmdResponseType::R2 && response_type != SdCmdResponseType::R3 {
804            // All commands with a CRC are 48 bits, with the last 8 bits being the CRC7 + stop bit
805
806            // Calculate the CRC up to the CRC
807            let good_crc = calculate_crc7_from_words(&resp_buf, 0, 5);
808
809            let crc = ((resp_buf[1] >> 16) & 0xFE) as u8;
810
811            if good_crc != crc {
812                return Err(SdioError::BadRxCrc7 {
813                    good_crc,
814                    bad_crc: crc,
815                });
816            }
817
818            let good_command_index = command.get_cmd_index();
819
820            let command_index = (resp_buf[0] >> 24) & 0x3F;
821
822            if good_command_index != command_index {
823                return Err(SdioError::WrongCmd {
824                    good_cmd: good_command_index as u8,
825                    bad_cmd: command_index as u8,
826                });
827            }
828        }
829
830        // Construct the response
831        match response_type {
832            SdCmdResponseType::R1 => {
833                let card_status = SdCardStatus {
834                    card_status: ((resp_buf[0] & 0x00FF_FFFF) << 8)
835                        | ((resp_buf[1] & 0xFF00_0000) >> 24),
836                };
837
838                // Make sure we didn't get any errors
839                card_status.get_worst_error()?;
840
841                Ok(SdCmdResponse::R1(card_status))
842            }
843            SdCmdResponseType::R1b => {
844                let card_status = SdCardStatus {
845                    card_status: ((resp_buf[0] & 0x00FF_FFFF) << 8)
846                        | ((resp_buf[1] & 0xFF00_0000) >> 24),
847                };
848
849                card_status.get_worst_error()?;
850
851                Ok(SdCmdResponse::R1b(card_status))
852            }
853            SdCmdResponseType::R2 => {
854                let mut words: [u32; 4] = [0; 4];
855
856                // Shift all the data left 8 bits to remove the first 8 bits of
857                // the response
858                words[0] = ((resp_buf[0] & 0x00FF_FFFF) << 8) | ((resp_buf[1] & 0xFF00_0000) >> 24);
859                words[1] = ((resp_buf[1] & 0x00FF_FFFF) << 8) | ((resp_buf[2] & 0xFF00_0000) >> 24);
860                words[2] = ((resp_buf[2] & 0x00FF_FFFF) << 8) | ((resp_buf[3] & 0xFF00_0000) >> 24);
861                words[3] = ((resp_buf[3] & 0x00FF_FFFF) << 8) | ((resp_buf[4] & 0xFF00_0000) >> 24);
862
863                Ok(SdCmdResponse::R2(words))
864            }
865            SdCmdResponseType::R3 => {
866                let ocr = ((resp_buf[0] & 0x00FF_FFFF) << 8) | ((resp_buf[1] & 0xFF00_0000) >> 24);
867
868                Ok(SdCmdResponse::R3(SdOcr { ocr }))
869            }
870            SdCmdResponseType::R6 => {
871                let rca: u16 = ((resp_buf[0] & 0x00FF_FF00) >> 8) as u16;
872
873                // You also get some status bits with this command, but I doubt
874                // there is a single scenario where it is useful to read them.
875                //
876                // Feel free to correct me though.
877                Ok(SdCmdResponse::R6(rca))
878            }
879            SdCmdResponseType::R7 => {
880                let good_check_pattern = match command {
881                    SdCmd::SendIfCond(check_pattern) => check_pattern,
882                    _ => panic!("Command repsonds with R7, not SendIfCond!"),
883                };
884                // Bit 21 is the 1.2v support bit, 20 is the pcie support
885                //                                   4444 4444 3333 3333  3322 2222 2222 1111
886                //                                   7654 3210 9876 5432  1098 7654 3210 9876
887                let supports_1p2v = (resp_buf[0] & 0x0000_0000_0000_0000__0000_0000_0010_0000) > 0;
888                let supports_pcie = (resp_buf[0] & 0x0000_0000_0000_0000__0000_0000_0001_0000) > 0;
889
890                // Verify the correct voltage is in use
891                let voltage = (resp_buf[0] & 0x0000_0000_0000_0000__0000_0000_0000_1111) as u8;
892
893                if voltage != 0b0001 {
894                    return Err(SdioError::BadVoltage { bad_volt: voltage });
895                }
896
897                // Verify the check pattern
898                let check_pattern = ((resp_buf[1] >> 24) & 0xFF) as u8;
899
900                if check_pattern != good_check_pattern {
901                    return Err(SdioError::BadCheck {
902                        good_check: good_check_pattern,
903                        bad_check: check_pattern,
904                    });
905                }
906
907                Ok(SdCmdResponse::R7(SdCic {
908                    supports_1p2v,
909                    supports_pcie,
910                }))
911            }
912            SdCmdResponseType::R0 => {
913                panic!("Reached R0 somehow!");
914            } // Shouldn't happen
915        }
916    }
917
918    /// Write the block to the SD card
919    pub fn start_block_tx(&mut self) -> Result<(), SdioError> {
920        // If this value is None, there is already a transfer occuring
921        let sm_dat = match mem::take(&mut self.sm_dat) {
922            Some(sm) => sm,
923
924            None => {
925                return Err(SdioError::InTxRx {});
926            }
927        };
928
929        // If these values are None, there is already a transfer occuring but
930        // for some reason the sm_dat didn't get used up. Something that
931        // shouldn't happen, and an unwrap is appropriate here I think.
932        let dma = mem::take(&mut self.dma).unwrap();
933        let program = mem::take(&mut self.program_data_tx).unwrap();
934        let working_block = mem::take(&mut self.working_block).unwrap();
935
936        // Calculate the crc of the block and place it at the end of the block
937        let crc = crc16_4bit(&working_block[..SD_BLOCK_LEN / SD_WORD_DIV]);
938
939        working_block[SD_CRC_IDX_LSB] = ((crc & 0xFFFF_FFFF) as u32).swap_bytes();
940        working_block[SD_CRC_IDX_MSB] = (((crc >> 32) & 0xFFFF_FFFF) as u32).swap_bytes();
941
942        // Place the transimssion end signal at the end of the block
943        working_block[SD_TEND_IDX] = 0xFFFF_FFFF;
944
945        // Now initialize the state machine with the TX program
946        let (mut sm_dat, sm_dat_rx, mut sm_dat_tx) = PIOBuilder::from_program(program)
947            .in_pin_base(self.sd_dat_base_id)
948            .set_pins(self.sd_dat_base_id, 4)
949            .out_pins(self.sd_dat_base_id, 4)
950            .in_shift_direction(ShiftDirection::Left)
951            .out_shift_direction(ShiftDirection::Left)
952            .autopush(false)
953            .autopull(true)
954            .clock_divisor_fixed_point(self.sd_full_clk_div, 0)
955            .build(sm_dat);
956
957        // Manually store the nibble count and response bit count to X an Y
958        sm_dat_tx.write((SD_BLOCK_LEN_TOTAL * SD_NIBBLE_MULT) as u32);
959        sm_dat.exec_instruction(Instruction {
960            operands: InstructionOperands::OUT {
961                destination: OutDestination::X,
962                bit_count: 32,
963            },
964            delay: 0,
965            side_set: None,
966        });
967
968        sm_dat_tx.write(31);
969        sm_dat.exec_instruction(Instruction {
970            operands: InstructionOperands::OUT {
971                destination: OutDestination::Y,
972                bit_count: 32,
973            },
974            delay: 0,
975            side_set: None,
976        });
977
978        // Initialize the pins and output to high
979        sm_dat.exec_instruction(Instruction {
980            operands: InstructionOperands::SET {
981                destination: SetDestination::PINS,
982                data: 0xF,
983            },
984            delay: 0,
985            side_set: None,
986        });
987
988        sm_dat.exec_instruction(Instruction {
989            operands: InstructionOperands::SET {
990                destination: SetDestination::PINDIRS,
991                data: 0xF,
992            },
993            delay: 0,
994            side_set: None,
995        });
996
997        // prep the state machine with the start token
998        sm_dat_tx.write(0b1111_1111_1111_1111__1111_1111_1111_0000);
999
1000        // Initialize the DMA transfer
1001        let mut tx_transfer = single_buffer::Config::new(dma, working_block, sm_dat_tx);
1002        tx_transfer.bswap(true);
1003
1004        // Send the write block command
1005        self.send_command(SdCmd::WriteBlock(self.working_block_num))?;
1006
1007        // Start the state machine and DMA
1008        let tx_transfer = tx_transfer.start();
1009        let sm_dat = sm_dat.start();
1010
1011        // Store everything needed in the future
1012        self.tx_dma_in_use = Some(tx_transfer);
1013        self.sm_in_use = Some(sm_dat);
1014        self.sm_dat_rx = Some(sm_dat_rx);
1015
1016        Ok(())
1017    }
1018
1019    /// Check the checks the response of the SD card to make sure there
1020    /// haven't been any errors in writing. Will throw an error if one
1021    /// is detected.
1022    pub fn check_write_response(mut response: u32) -> Result<(), SdioError> {
1023        if (!response & 0xFFFF_0000) == 0 {
1024            response <<= 16;
1025        }
1026
1027        if (!response & 0xFF00_0000) == 0 {
1028            response <<= 8;
1029        }
1030
1031        if (!response & 0xF000_0000) == 0 {
1032            response <<= 4;
1033        }
1034
1035        if (!response & 0xC000_0000) == 0 {
1036            response <<= 2;
1037        }
1038
1039        if (!response & 0x8000_0000) == 0 {
1040            response <<= 1;
1041        }
1042
1043        response = response >> 28 & 7;
1044
1045        match response {
1046            2 => Ok(()),
1047            5 => Err(SdioError::BadTxCrc16 {}),
1048            6 => Err(SdioError::WriteFail {}),
1049            _ => Err(SdioError::WriteUnknown { response }),
1050        }
1051    }
1052
1053    #[inline]
1054    /// Returns true if you need to poll the tx
1055    pub fn is_tx(&self) -> bool {
1056        match &self.tx_dma_in_use {
1057            Some(_) => true,
1058            None => false,
1059        }
1060    }
1061
1062    /// Poll the current transfer, return true if still transferring
1063    pub fn poll_tx(&mut self) -> Result<bool, SdioError> {
1064        // Return false if we don't need to poll tx, true if the DMA is still transferring
1065        let ready = match &self.tx_dma_in_use {
1066            Some(tx_dma) => tx_dma.is_done(),
1067            None => return Ok(false),
1068        };
1069
1070        if !ready {
1071            return Ok(true);
1072        }
1073
1074        // Wait until there is something in the fifo
1075        let start_time = self.timer.get_counter();
1076        let mut time_delta = 0;
1077        while self.sm_dat_rx.as_ref().unwrap().is_empty() {
1078            let current_time = self.timer.get_counter();
1079
1080            time_delta = current_time
1081                .checked_duration_since(start_time)
1082                .unwrap()
1083                .to_millis();
1084
1085            if time_delta > SD_CMD_TIMEOUT_MS {
1086                break;
1087            }
1088        }
1089
1090        // The RX should be there. If not, we'll throw the timeout error after
1091        // we clean up
1092        let response = self.sm_dat_rx.as_mut().unwrap().read();
1093
1094        // Put away everything we used
1095        // Deconstruct the DMA
1096        let (dma, working_block, sm_dat_tx) = mem::take(&mut self.tx_dma_in_use).unwrap().wait();
1097
1098        // Deconstruct the state machine
1099        let sm_dat_rx = mem::take(&mut self.sm_dat_rx).unwrap();
1100        let (sm_dat, program_data_tx) = mem::take(&mut self.sm_in_use)
1101            .unwrap()
1102            .uninit(sm_dat_rx, sm_dat_tx);
1103
1104        // Replace the appropriate borrowed variables
1105        self.program_data_tx = Some(program_data_tx);
1106        self.dma = Some(dma);
1107        self.working_block = Some(working_block);
1108        self.sm_dat = Some(sm_dat);
1109        
1110        let response = match response {
1111            Some(response) => response,
1112            None => {
1113                return Err(SdioError::WriteTimeout {
1114                    time_ms: time_delta,
1115                });
1116            }
1117        };
1118
1119        // Check the status of the response and throw errors if appropriate
1120        Self::check_write_response(response)?;
1121
1122        // Return false since we are no longer transferring!
1123        Ok(false)
1124    }
1125
1126    #[inline]
1127    /// Wait for the data transfer to finish
1128    pub fn wait_tx(&mut self) -> Result<(), SdioError> {
1129        while self.poll_tx()? {}
1130
1131        Ok(())
1132    }
1133
1134    #[inline]
1135    /// Start reading data from the SD card into the working block
1136    pub fn start_block_rx(&mut self) -> Result<(), SdioError> {
1137        // If this value is None, there is already a transfer occuring
1138        let sm_dat = match mem::take(&mut self.sm_dat) {
1139            Some(sm) => sm,
1140
1141            None => {
1142                return Err(SdioError::InTxRx {});
1143            }
1144        };
1145
1146        // If these values are None, there is already a transfer occuring but
1147        // for some reason the sm_dat didn't get used up. Something that
1148        // shouldn't happen, and an unwrap is appropriate here I think.
1149        let dma = mem::take(&mut self.dma).unwrap();
1150        let program = mem::take(&mut self.program_data_rx).unwrap();
1151        let working_block = mem::take(&mut self.working_block).unwrap();
1152
1153        // Now initialize the state machine with the RX program
1154        let (mut sm_dat, sm_dat_rx, mut sm_dat_tx) = PIOBuilder::from_program(program)
1155            .in_pin_base(self.sd_dat_base_id)
1156            .set_pins(self.sd_dat_base_id, 4)
1157            .out_pins(self.sd_dat_base_id, 4)
1158            .in_shift_direction(ShiftDirection::Left)
1159            .autopush(true)
1160            .autopull(true)
1161            .clock_divisor_fixed_point(self.sd_full_clk_div, 0)
1162            .build(sm_dat);
1163
1164        // Manually store the nibble count to X
1165        sm_dat_tx.write((SD_BLOCK_LEN_TOTAL * SD_NIBBLE_MULT) as u32);
1166        sm_dat.exec_instruction(Instruction {
1167            operands: InstructionOperands::OUT {
1168                destination: OutDestination::X,
1169                bit_count: 32,
1170            },
1171            delay: 0,
1172            side_set: None,
1173        });
1174
1175        // Initialize the pins and output to high (not setting the pins to high
1176        // can cause errors in testing...)
1177        sm_dat.exec_instruction(Instruction {
1178            operands: InstructionOperands::SET {
1179                destination: SetDestination::PINS,
1180                data: 0xF,
1181            },
1182            delay: 0,
1183            side_set: None,
1184        });
1185
1186        sm_dat.exec_instruction(Instruction {
1187            operands: InstructionOperands::SET {
1188                destination: SetDestination::PINDIRS,
1189                data: 0xF,
1190            },
1191            delay: 0,
1192            side_set: None,
1193        });
1194
1195        // Initialize the pins to input
1196        sm_dat.exec_instruction(Instruction {
1197            operands: InstructionOperands::SET {
1198                destination: SetDestination::PINDIRS,
1199                data: 0x0,
1200            },
1201            delay: 0,
1202            side_set: None,
1203        });
1204
1205        // Initialize the DMA transfer
1206        let mut rx_transfer = single_buffer::Config::new(dma, sm_dat_rx, working_block);
1207        rx_transfer.bswap(true);
1208
1209        // Start the state machine and DMA
1210        let rx_transfer = rx_transfer.start();
1211        let sm_dat = sm_dat.start();
1212
1213        // Send the read block command
1214        self.send_command(SdCmd::ReadSingleBlock(self.working_block_num))?;
1215
1216        // Store everything needed in the future
1217        self.rx_dma_in_use = Some(rx_transfer);
1218        self.sm_in_use = Some(sm_dat);
1219        self.sm_dat_tx = Some(sm_dat_tx);
1220
1221        Ok(())
1222    }
1223
1224    #[inline]
1225    /// Return true if you need to poll rx
1226    pub fn is_rx(&self) -> bool {
1227        match &self.rx_dma_in_use {
1228            Some(_) => true,
1229            None => false,
1230        }
1231    }
1232
1233    /// Poll the current transfer, return true if still transferring
1234    pub fn poll_rx(&mut self) -> Result<bool, SdioError> {
1235        // Return false if we don't need to poll rx, true if the DMA is still transferring
1236        let ready = match &self.rx_dma_in_use {
1237            Some(rx_dma) => rx_dma.is_done(),
1238            None => return Ok(false),
1239        };
1240
1241        if !ready {
1242            return Ok(true);
1243        }
1244
1245        // Put away everything we used
1246        // Deconstruct the DMA
1247        let (dma, sm_dat_rx, working_block) = mem::take(&mut self.rx_dma_in_use).unwrap().wait();
1248
1249        // Deconstruct the state machine
1250        let sm_dat_tx = mem::take(&mut self.sm_dat_tx).unwrap();
1251        let (sm_dat, program_data_rx) = mem::take(&mut self.sm_in_use)
1252            .unwrap()
1253            .uninit(sm_dat_rx, sm_dat_tx);
1254
1255        // Save the CRC for later
1256
1257        let crc: u64 =
1258            (working_block[SD_CRC_IDX_LSB].swap_bytes() as u64) | ((working_block[SD_CRC_IDX_MSB].swap_bytes() as u64) << 32);
1259        let good_crc = crc16_4bit(&working_block[..SD_BLOCK_LEN / SD_WORD_DIV]);
1260
1261        // Replace the appropriate borrowed variables
1262        self.program_data_rx = Some(program_data_rx);
1263        self.dma = Some(dma);
1264        self.working_block = Some(working_block);
1265        self.sm_dat = Some(sm_dat);
1266
1267
1268        // Check the crc and if it's bad, error out!
1269
1270        if crc != good_crc {
1271            return Err(SdioError::BadRxCrc16 {
1272                good_crc,
1273                bad_crc: crc,
1274            });
1275        }
1276
1277        // Return false since we are no longer transferring!
1278        Ok(false)
1279    }
1280
1281    #[inline]
1282    /// Wait until we're done recieving data
1283    pub fn wait_rx(&mut self) -> Result<(), SdioError> {
1284        while self.poll_rx()? {}
1285
1286        Ok(())
1287    }
1288
1289    /// Returns true if you need to poll rx or tx
1290    pub fn is_rx_tx(&self) -> bool {
1291        self.is_rx() | self.is_tx()
1292    }
1293
1294    /// Polls both RX and TX, when we don't know which one needs to be polled
1295    pub fn poll_rx_tx(&mut self) -> Result<bool, SdioError> {
1296        // If the tx dma or rx dma is Some, call the appropriate poll function
1297        if let Some(_) = self.tx_dma_in_use {
1298            return self.poll_tx();
1299        }
1300
1301        if let Some(_) = self.rx_dma_in_use {
1302            return self.poll_rx();
1303        }
1304
1305        // Otherwise, neither are in use
1306        Ok(false)
1307    }
1308
1309    /// Waits until the card is neither recieving nor transferring data
1310    pub fn wait_rx_tx(&mut self) -> Result<(), SdioError> {
1311        while self.poll_rx_tx()? {}
1312
1313        Ok(())
1314    }
1315
1316    /// Initialize the SD card
1317    pub fn init(&mut self) -> Result<(), SdioError> {
1318        // Wait 1ms to ensure that the card is properly initialized
1319        let start_time = self.timer.get_counter();
1320        let mut current_time = start_time;
1321        while current_time
1322            .checked_duration_since(start_time)
1323            .unwrap()
1324            .to_millis()
1325            < SD_STARTUP_MS
1326        {
1327            current_time = self.timer.get_counter();
1328        }
1329
1330        // Send CMD0
1331        self.send_command(SdCmd::GoIdleState)?;
1332
1333        // Send CMD8
1334        // !TODO! less runtime checks
1335        let cic = match self.send_command(SdCmd::SendIfCond(0xAA))? {
1336            SdCmdResponse::R7(cic) => cic,
1337            _ => {
1338                panic!("Incorrect response type!");
1339            }
1340        };
1341
1342        // Send ACMD41 until the card is no longer busy, and once ready verify
1343        // the voltage window is valid
1344        let acmd41 = SdCmd::SdAppOpCond(true, true, false, SD_OCR_VOLT_RANGE);
1345
1346        let mut is_busy = true;
1347        let mut ocr = SdOcr { ocr: 0 };
1348
1349        while is_busy {
1350            ocr = match self.send_command(acmd41)? {
1351                SdCmdResponse::R3(ocr) => ocr,
1352                _ => {
1353                    panic!("Incorrect response type!");
1354                }
1355            };
1356
1357            is_busy = ocr.is_busy();
1358        }
1359
1360        let voltage_range = ocr.get_voltage_window();
1361        if (voltage_range & SD_OCR_VOLT_RANGE) != SD_OCR_VOLT_RANGE {
1362            return Err(SdioError::BadVoltRange {
1363                range: voltage_range,
1364            });
1365        }
1366
1367        // Get the CID
1368        let cid = match self.send_command(SdCmd::AllSendCid)? {
1369            SdCmdResponse::R2(cid) => cid,
1370            _ => panic!("Incorrect response type!"),
1371        };
1372
1373        self.cid = SdCid::new(cid);
1374
1375        // Get the RCA
1376        let rca = match self.send_command(SdCmd::SendRelativeAddr)? {
1377            SdCmdResponse::R6(rca) => rca,
1378            _ => {
1379                panic!("Incorrect response type!");
1380            }
1381        };
1382
1383        self.rca = rca;
1384
1385        // Get the CSD
1386        let csd = match self.send_command(SdCmd::SendCsd(rca))? {
1387            SdCmdResponse::R2(csd) => csd,
1388            _ => {
1389                panic!("Incorrect response type!");
1390            }
1391        };
1392
1393        self.csd = SdCsd::new(csd);
1394
1395        // Select the card
1396        self.send_command(SdCmd::SelectDeselectCard(rca))?;
1397
1398        // Set the bus width to 4 bits(true means 4 bits)
1399        self.send_command(SdCmd::SetBusWidth(true))?;
1400
1401        // Set the block lenth
1402        self.send_command(SdCmd::SetBlockLen(SD_BLOCK_LEN as u32))?;
1403
1404        // Speed up the clock to 25mhz
1405        self.sm_cmd
1406            .clock_divisor_fixed_point(self.sd_full_clk_div, 0);
1407
1408        // Read the first block
1409        self.start_block_rx()?;
1410        self.wait_rx()?;
1411        Ok(())
1412    }
1413}
1414
1415impl<'a, DmaCh: SingleChannelDma, P: PIOExt> Io for Sdio4bit<'a, DmaCh, P> {
1416    type Error = SdioError;
1417}
1418
1419impl<'a, DmaCh: SingleChannelDma, P: PIOExt> Read for Sdio4bit<'a, DmaCh, P> {
1420    fn read(&mut self, buffer: &mut [u8]) -> Result<usize, SdioError> {
1421        // Wait until we are doing nothing
1422        self.wait_rx_tx()?;
1423
1424        // If the position isn't in the current working block, flush,
1425        // then load the correct working block
1426        let current_block_num = (self.position / (SD_BLOCK_LEN as u64)) as u32;
1427
1428        if current_block_num != self.working_block_num {
1429            self.flush()?;
1430            self.wait_tx()?;
1431
1432            self.working_block_num = current_block_num;
1433            self.start_block_rx()?;
1434            self.wait_rx()?;
1435        }
1436
1437        let working_block = & **self.working_block.as_ref().unwrap();
1438        let working_block_bytes = bytes_of(working_block); 
1439
1440        let block_index: usize = (self.position % (SD_BLOCK_LEN as u64)) as usize;
1441
1442        let bytes_transfered = cmp::min(SD_BLOCK_LEN - block_index, buffer.len());
1443
1444        buffer[..bytes_transfered].copy_from_slice(&working_block_bytes[block_index..block_index + bytes_transfered]);
1445
1446        self.position += bytes_transfered as u64;
1447        
1448        Ok(bytes_transfered)
1449    }
1450}
1451
1452impl<'a, DmaCh: SingleChannelDma, P: PIOExt> Write for Sdio4bit<'a, DmaCh, P> {
1453    /// Write bytes to the sd card. The PIO requires bytes to be converted to
1454    /// little endian words, so there is a lot of conversion that needs to take
1455    /// place...
1456    /// Will return when the end of the block is encountered so be mindful...
1457    fn write(&mut self, buffer: &[u8]) -> Result<usize, SdioError> {
1458        // Wait until we are doing nothing
1459        self.wait_rx_tx()?;
1460
1461        // If the position isn't in the current working block, flush,
1462        // then load the correct working block
1463        let current_block_num = (self.position / (SD_BLOCK_LEN as u64)) as u32;
1464
1465        if current_block_num != self.working_block_num {
1466            self.flush()?;
1467            self.wait_tx()?;
1468
1469            self.working_block_num = current_block_num;
1470            self.start_block_rx()?;
1471            self.wait_rx()?;
1472        }
1473
1474        // Set "dirty" to true since we are writing to the data!
1475        self.dirty = true;
1476
1477        let working_block = &mut **self.working_block.as_mut().unwrap();
1478        let working_block_bytes = bytes_of_mut(working_block);
1479
1480        let block_index: usize = (self.position % (SD_BLOCK_LEN as u64)) as usize;
1481
1482        let bytes_transfered = cmp::min(SD_BLOCK_LEN - block_index, buffer.len());
1483
1484        working_block_bytes[block_index..block_index + bytes_transfered].copy_from_slice(&buffer[..bytes_transfered]);
1485
1486        self.position += bytes_transfered as u64;
1487
1488        Ok(bytes_transfered)
1489
1490    }
1491
1492    fn flush(&mut self) -> Result<(), SdioError> {
1493        // If we don't need to flush, don't flush!
1494        if !self.dirty {
1495            return Ok(());
1496        }
1497
1498        // Set "dirty" to false since we are currently flushing...
1499        self.dirty = false;
1500
1501        // If already in tx, we don't need to flush
1502        if self.is_tx() {
1503            return Ok(());
1504        }
1505
1506        // Otherwise wait to make sure there are no recieves
1507        self.wait_rx()?;
1508
1509        self.start_block_tx()?;
1510
1511        Ok(())
1512    }
1513}
1514
1515impl<'a, DmaCh: SingleChannelDma, P: PIOExt> Seek for Sdio4bit<'a, DmaCh, P> {
1516    fn seek(&mut self, position: SeekFrom) -> Result<u64, SdioError> {
1517        Ok(match position {
1518            SeekFrom::Start(position) => {
1519                self.position = position;
1520                self.position
1521            }
1522            SeekFrom::End(position) => {
1523                todo!()
1524            }
1525            SeekFrom::Current(delta) => {
1526                self.position = ((self.position as i64) + delta) as u64;
1527                self.position
1528            }
1529        })
1530    }
1531}