embedded_sdmmc/sdcard/proto.rs
1//! Constants from the SD Specifications
2//!
3//! Based on SdFat, under the following terms:
4//!
5//! > Copyright (c) 2011-2018 Bill Greiman
6//! > This file is part of the SdFat library for SD memory cards.
7//! >
8//! > MIT License
9//! >
10//! > Permission is hereby granted, free of charge, to any person obtaining a
11//! > copy of this software and associated documentation files (the "Software"),
12//! > to deal in the Software without restriction, including without limitation
13//! > the rights to use, copy, modify, merge, publish, distribute, sublicense,
14//! > and/or sell copies of the Software, and to permit persons to whom the
15//! > Software is furnished to do so, subject to the following conditions:
16//! >
17//! > The above copyright notice and this permission notice shall be included
18//! > in all copies or substantial portions of the Software.
19//! >
20//! > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21//! > OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22//! > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23//! > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24//! > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25//! > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26//! > DEALINGS IN THE SOFTWARE.
27
28//==============================================================================
29
30// Possible errors the SD card can return
31
32/// Card indicates last operation was a success
33pub const ERROR_OK: u8 = 0x00;
34
35//==============================================================================
36
37// SD Card Commands
38
39/// GO_IDLE_STATE - init card in spi mode if CS low
40pub const CMD0: u8 = 0x00;
41/// SEND_IF_COND - verify SD Memory Card interface operating condition.*/
42pub const CMD8: u8 = 0x08;
43/// SEND_CSD - read the Card Specific Data (CSD register)
44pub const CMD9: u8 = 0x09;
45/// STOP_TRANSMISSION - end multiple block read sequence
46pub const CMD12: u8 = 0x0C;
47/// SEND_STATUS - read the card status register
48pub const CMD13: u8 = 0x0D;
49/// READ_SINGLE_BLOCK - read a single data block from the card
50pub const CMD17: u8 = 0x11;
51/// READ_MULTIPLE_BLOCK - read a multiple data blocks from the card
52pub const CMD18: u8 = 0x12;
53/// WRITE_BLOCK - write a single data block to the card
54pub const CMD24: u8 = 0x18;
55/// WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION
56pub const CMD25: u8 = 0x19;
57/// APP_CMD - escape for application specific command
58pub const CMD55: u8 = 0x37;
59/// READ_OCR - read the OCR register of a card
60pub const CMD58: u8 = 0x3A;
61/// CRC_ON_OFF - enable or disable CRC checking
62pub const CMD59: u8 = 0x3B;
63/// Pre-erased before writing
64///
65/// > It is recommended using this command preceding CMD25, some of the cards will be faster for Multiple
66/// > Write Blocks operation. Note that the host should send ACMD23 just before WRITE command if the host
67/// > wants to use the pre-erased feature
68pub const ACMD23: u8 = 0x17;
69/// SD_SEND_OP_COMD - Sends host capacity support information and activates
70/// the card's initialization process
71pub const ACMD41: u8 = 0x29;
72
73//==============================================================================
74
75/// status for card in the ready state
76pub const R1_READY_STATE: u8 = 0x00;
77
78/// status for card in the idle state
79pub const R1_IDLE_STATE: u8 = 0x01;
80
81/// status bit for illegal command
82pub const R1_ILLEGAL_COMMAND: u8 = 0x04;
83
84/// start data token for read or write single block*/
85pub const DATA_START_BLOCK: u8 = 0xFE;
86
87/// stop token for write multiple blocks*/
88pub const STOP_TRAN_TOKEN: u8 = 0xFD;
89
90/// start data token for write multiple blocks*/
91pub const WRITE_MULTIPLE_TOKEN: u8 = 0xFC;
92
93/// mask for data response tokens after a write block operation
94pub const DATA_RES_MASK: u8 = 0x1F;
95
96/// write data accepted token
97pub const DATA_RES_ACCEPTED: u8 = 0x05;
98
99/// Card Specific Data, version 1
100#[derive(Default, Debug)]
101#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
102pub struct CsdV1 {
103 /// The 16-bytes of data in this Card Specific Data block
104 pub data: [u8; 16],
105}
106
107/// Card Specific Data, version 2
108#[derive(Default, Debug)]
109#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
110pub struct CsdV2 {
111 /// The 16-bytes of data in this Card Specific Data block
112 pub data: [u8; 16],
113}
114
115/// Card Specific Data
116#[derive(Debug)]
117#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
118pub enum Csd {
119 /// A version 1 CSD
120 V1(CsdV1),
121 /// A version 2 CSD
122 V2(CsdV2),
123}
124
125impl CsdV1 {
126 /// Create a new, empty, CSD
127 pub fn new() -> CsdV1 {
128 CsdV1::default()
129 }
130
131 define_field!(csd_ver, u8, 0, 6, 2);
132 define_field!(data_read_access_time1, u8, 1, 0, 8);
133 define_field!(data_read_access_time2, u8, 2, 0, 8);
134 define_field!(max_data_transfer_rate, u8, 3, 0, 8);
135 define_field!(card_command_classes, u16, [(4, 0, 8), (5, 4, 4)]);
136 define_field!(read_block_length, u8, 5, 0, 4);
137 define_field!(read_partial_blocks, bool, 6, 7);
138 define_field!(write_block_misalignment, bool, 6, 6);
139 define_field!(read_block_misalignment, bool, 6, 5);
140 define_field!(dsr_implemented, bool, 6, 4);
141 define_field!(device_size, u32, [(6, 0, 2), (7, 0, 8), (8, 6, 2)]);
142 define_field!(max_read_current_vdd_max, u8, 8, 0, 3);
143 define_field!(max_read_current_vdd_min, u8, 8, 3, 3);
144 define_field!(max_write_current_vdd_max, u8, 9, 2, 3);
145 define_field!(max_write_current_vdd_min, u8, 9, 5, 3);
146 define_field!(device_size_multiplier, u8, [(9, 0, 2), (10, 7, 1)]);
147 define_field!(erase_single_block_enabled, bool, 10, 6);
148 define_field!(erase_sector_size, u8, [(10, 0, 6), (11, 7, 1)]);
149 define_field!(write_protect_group_size, u8, 11, 0, 7);
150 define_field!(write_protect_group_enable, bool, 12, 7);
151 define_field!(write_speed_factor, u8, 12, 2, 3);
152 define_field!(max_write_data_length, u8, [(12, 0, 2), (13, 6, 2)]);
153 define_field!(write_partial_blocks, bool, 13, 5);
154 define_field!(file_format, u8, 14, 2, 2);
155 define_field!(temporary_write_protection, bool, 14, 4);
156 define_field!(permanent_write_protection, bool, 14, 5);
157 define_field!(copy_flag_set, bool, 14, 6);
158 define_field!(file_format_group_set, bool, 14, 7);
159 define_field!(crc, u8, 15, 0, 8);
160
161 /// Returns the card capacity in bytes
162 pub fn card_capacity_bytes(&self) -> u64 {
163 let multiplier = self.device_size_multiplier() + self.read_block_length() + 2;
164 (u64::from(self.device_size()) + 1) << multiplier
165 }
166
167 /// Returns the card capacity in 512-byte blocks
168 pub fn card_capacity_blocks(&self) -> u32 {
169 let multiplier = self.device_size_multiplier() + self.read_block_length() - 7;
170 (self.device_size() + 1) << multiplier
171 }
172}
173
174impl CsdV2 {
175 /// Create a new, empty, CSD
176 pub fn new() -> CsdV2 {
177 CsdV2::default()
178 }
179
180 define_field!(csd_ver, u8, 0, 6, 2);
181 define_field!(data_read_access_time1, u8, 1, 0, 8);
182 define_field!(data_read_access_time2, u8, 2, 0, 8);
183 define_field!(max_data_transfer_rate, u8, 3, 0, 8);
184 define_field!(card_command_classes, u16, [(4, 0, 8), (5, 4, 4)]);
185 define_field!(read_block_length, u8, 5, 0, 4);
186 define_field!(read_partial_blocks, bool, 6, 7);
187 define_field!(write_block_misalignment, bool, 6, 6);
188 define_field!(read_block_misalignment, bool, 6, 5);
189 define_field!(dsr_implemented, bool, 6, 4);
190 define_field!(device_size, u32, [(7, 0, 6), (8, 0, 8), (9, 0, 8)]);
191 define_field!(erase_single_block_enabled, bool, 10, 6);
192 define_field!(erase_sector_size, u8, [(10, 0, 6), (11, 7, 1)]);
193 define_field!(write_protect_group_size, u8, 11, 0, 7);
194 define_field!(write_protect_group_enable, bool, 12, 7);
195 define_field!(write_speed_factor, u8, 12, 2, 3);
196 define_field!(max_write_data_length, u8, [(12, 0, 2), (13, 6, 2)]);
197 define_field!(write_partial_blocks, bool, 13, 5);
198 define_field!(file_format, u8, 14, 2, 2);
199 define_field!(temporary_write_protection, bool, 14, 4);
200 define_field!(permanent_write_protection, bool, 14, 5);
201 define_field!(copy_flag_set, bool, 14, 6);
202 define_field!(file_format_group_set, bool, 14, 7);
203 define_field!(crc, u8, 15, 0, 8);
204
205 /// Returns the card capacity in bytes
206 pub fn card_capacity_bytes(&self) -> u64 {
207 (u64::from(self.device_size()) + 1) * 512 * 1024
208 }
209
210 /// Returns the card capacity in 512-byte blocks
211 pub fn card_capacity_blocks(&self) -> u32 {
212 (self.device_size() + 1) * 1024
213 }
214}
215
216/// Perform the 7-bit CRC used on the SD card
217pub fn crc7(data: &[u8]) -> u8 {
218 let mut crc = 0u8;
219 for mut d in data.iter().cloned() {
220 for _bit in 0..8 {
221 crc <<= 1;
222 if ((d & 0x80) ^ (crc & 0x80)) != 0 {
223 crc ^= 0x09;
224 }
225 d <<= 1;
226 }
227 }
228 (crc << 1) | 1
229}
230
231/// Perform the X25 CRC calculation, as used for data blocks.
232pub fn crc16(data: &[u8]) -> u16 {
233 let mut crc = 0u16;
234 for &byte in data {
235 crc = ((crc >> 8) & 0xFF) | (crc << 8);
236 crc ^= u16::from(byte);
237 crc ^= (crc & 0xFF) >> 4;
238 crc ^= crc << 12;
239 crc ^= (crc & 0xFF) << 5;
240 }
241 crc
242}
243
244// ****************************************************************************
245//
246// Unit Tests
247//
248// ****************************************************************************
249
250#[cfg(test)]
251mod test {
252 use super::*;
253
254 #[test]
255 fn test_crc7() {
256 const DATA: [u8; 15] = hex!("00 26 00 32 5F 59 83 C8 AD DB CF FF D2 40 40");
257 assert_eq!(crc7(&DATA), 0xA5);
258 }
259
260 #[test]
261 fn test_crc16() {
262 // An actual CSD read from an SD card
263 const DATA: [u8; 16] = hex!("00 26 00 32 5F 5A 83 AE FE FB CF FF 92 80 40 DF");
264 assert_eq!(crc16(&DATA), 0x9fc5);
265 }
266
267 #[test]
268 fn test_csdv1b() {
269 const EXAMPLE: CsdV1 = CsdV1 {
270 data: hex!("00 26 00 32 5F 59 83 C8 AD DB CF FF D2 40 40 A5"),
271 };
272
273 // CSD Structure: describes version of CSD structure
274 // 0b00 [Interpreted: Version 1.0]
275 assert_eq!(EXAMPLE.csd_ver(), 0x00);
276
277 // Data Read Access Time 1: defines Asynchronous part of the read
278 // access time 0x26 [Interpreted: 1.5 x 1ms]
279 assert_eq!(EXAMPLE.data_read_access_time1(), 0x26);
280
281 // Data Read Access Time 2: worst case clock dependent factor for data
282 // access time 0x00 [Decimal: 0 x 100 Clocks]
283 assert_eq!(EXAMPLE.data_read_access_time2(), 0x00);
284
285 // Max Data Transfer Rate: sometimes stated as Mhz
286 // 0x32 [Interpreted: 2.5 x 10Mbit/s]
287 assert_eq!(EXAMPLE.max_data_transfer_rate(), 0x32);
288
289 // Card Command Classes: 0x5f5 [Interpreted: Class 0: Yes. Class 1:
290 // No. Class 2: Yes. Class 3: No. Class 4: Yes. Class 5: Yes. Class 6:
291 // Yes. Class 7: Yes. Class 8: Yes. Class 9: No. Class 10: Yes. Class
292 // 11: No. ]
293 assert_eq!(EXAMPLE.card_command_classes(), 0x5f5);
294
295 // Max Read Data Block Length:
296 // 0x9 [Interpreted: 512 Bytes]
297 assert_eq!(EXAMPLE.read_block_length(), 0x09);
298
299 // Partial Blocks for Read Allowed:
300 // 0b1 [Interpreted: Yes]
301 assert!(EXAMPLE.read_partial_blocks());
302
303 // Write Block Misalignment:
304 // 0b0 [Interpreted: No]
305 assert!(!EXAMPLE.write_block_misalignment());
306
307 // Read Block Misalignment:
308 // 0b0 [Interpreted: No]
309 assert!(!EXAMPLE.read_block_misalignment());
310
311 // DSR Implemented: indicates configurable driver stage integrated on
312 // card 0b0 [Interpreted: No]
313 assert!(!EXAMPLE.dsr_implemented());
314
315 // Device Size: to calculate the card capacity excl. security area
316 // ((device size + 1)*device size multiplier*max read data block
317 // length) bytes 0xf22 [Decimal: 3874]
318 assert_eq!(EXAMPLE.device_size(), 3874);
319
320 // Max Read Current @ VDD Min:
321 // 0x5 [Interpreted: 35mA]
322 assert_eq!(EXAMPLE.max_read_current_vdd_min(), 5);
323
324 // Max Read Current @ VDD Max:
325 // 0x5 [Interpreted: 80mA]
326 assert_eq!(EXAMPLE.max_read_current_vdd_max(), 5);
327
328 // Max Write Current @ VDD Min:
329 // 0x6 [Interpreted: 60mA]
330 assert_eq!(EXAMPLE.max_write_current_vdd_min(), 6);
331
332 // Max Write Current @ VDD Max::
333 // 0x6 [Interpreted: 200mA]
334 assert_eq!(EXAMPLE.max_write_current_vdd_max(), 6);
335
336 // Device Size Multiplier:
337 // 0x7 [Interpreted: x512]
338 assert_eq!(EXAMPLE.device_size_multiplier(), 7);
339
340 // Erase Single Block Enabled:
341 // 0x1 [Interpreted: Yes]
342 assert!(EXAMPLE.erase_single_block_enabled());
343
344 // Erase Sector Size: size of erasable sector in write blocks
345 // 0x1f [Interpreted: 32 blocks]
346 assert_eq!(EXAMPLE.erase_sector_size(), 0x1F);
347
348 // Write Protect Group Size:
349 // 0x7f [Interpreted: 128 sectors]
350 assert_eq!(EXAMPLE.write_protect_group_size(), 0x7f);
351
352 // Write Protect Group Enable:
353 // 0x1 [Interpreted: Yes]
354 assert!(EXAMPLE.write_protect_group_enable());
355
356 // Write Speed Factor: block program time as multiple of read access time
357 // 0x4 [Interpreted: x16]
358 assert_eq!(EXAMPLE.write_speed_factor(), 0x4);
359
360 // Max Write Data Block Length:
361 // 0x9 [Interpreted: 512 Bytes]
362 assert_eq!(EXAMPLE.max_write_data_length(), 0x9);
363
364 // Partial Blocks for Write Allowed:
365 // 0x0 [Interpreted: No]
366 assert!(!EXAMPLE.write_partial_blocks());
367
368 // File Format Group:
369 // 0b0 [Interpreted: is either Hard Disk with Partition Table/DOS FAT without Partition Table/Universal File Format/Other/Unknown]
370 assert!(!EXAMPLE.file_format_group_set());
371
372 // Copy Flag:
373 // 0b1 [Interpreted: Non-Original]
374 assert!(EXAMPLE.copy_flag_set());
375
376 // Permanent Write Protection:
377 // 0b0 [Interpreted: No]
378 assert!(!EXAMPLE.permanent_write_protection());
379
380 // Temporary Write Protection:
381 // 0b0 [Interpreted: No]
382 assert!(!EXAMPLE.temporary_write_protection());
383
384 // File Format:
385 // 0x0 [Interpreted: Hard Disk with Partition Table]
386 assert_eq!(EXAMPLE.file_format(), 0x00);
387
388 // CRC7 Checksum + always 1 in LSB:
389 // 0xa5
390 assert_eq!(EXAMPLE.crc(), 0xa5);
391
392 assert_eq!(EXAMPLE.card_capacity_bytes(), 1_015_808_000);
393 assert_eq!(EXAMPLE.card_capacity_blocks(), 1_984_000);
394 }
395
396 #[test]
397 fn test_csdv1() {
398 const EXAMPLE: CsdV1 = CsdV1 {
399 data: hex!("00 7F 00 32 5B 5A 83 AF 7F FF CF 80 16 80 00 6F"),
400 };
401 // CSD Structure: describes version of CSD structure
402 // 0b00 [Interpreted: Version 1.0]
403 assert_eq!(EXAMPLE.csd_ver(), 0x00);
404
405 // Data Read Access Time 1: defines Asynchronous part of the read access time
406 // 0x7f [Interpreted: 8.0 x 10ms]
407 assert_eq!(EXAMPLE.data_read_access_time1(), 0x7F);
408
409 // Data Read Access Time 2: worst case clock dependent factor for data access time
410 // 0x00 [Decimal: 0 x 100 Clocks]
411 assert_eq!(EXAMPLE.data_read_access_time2(), 0x00);
412
413 // Max Data Transfer Rate: sometimes stated as Mhz
414 // 0x32 [Interpreted: 2.5 x 10Mbit/s]
415 assert_eq!(EXAMPLE.max_data_transfer_rate(), 0x32);
416
417 // Card Command Classes:
418 // 0x5b5 [Interpreted: Class 0: Yes. Class 1: No. Class 2: Yes. Class 3: No. Class 4: Yes. Class 5: Yes. Class 6: No. Class 7: Yes. Class 8: Yes. Class 9: No. Class 10: Yes. Class 11: No. ]
419 assert_eq!(EXAMPLE.card_command_classes(), 0x5b5);
420
421 // Max Read Data Block Length:
422 // 0xa [Interpreted: 1024 Bytes]
423 assert_eq!(EXAMPLE.read_block_length(), 0x0a);
424
425 // Partial Blocks for Read Allowed:
426 // 0b1 [Interpreted: Yes]
427 assert!(EXAMPLE.read_partial_blocks());
428
429 // Write Block Misalignment:
430 // 0b0 [Interpreted: No]
431 assert!(!EXAMPLE.write_block_misalignment());
432
433 // Read Block Misalignment:
434 // 0b0 [Interpreted: No]
435 assert!(!EXAMPLE.read_block_misalignment());
436
437 // DSR Implemented: indicates configurable driver stage integrated on card
438 // 0b0 [Interpreted: No]
439 assert!(!EXAMPLE.dsr_implemented());
440
441 // Device Size: to calculate the card capacity excl. security area
442 // ((device size + 1)*device size multiplier*max read data block
443 // length) bytes 0xebd [Decimal: 3773]
444 assert_eq!(EXAMPLE.device_size(), 3773);
445
446 // Max Read Current @ VDD Min:
447 // 0x7 [Interpreted: 100mA]
448 assert_eq!(EXAMPLE.max_read_current_vdd_min(), 7);
449
450 // Max Read Current @ VDD Max:
451 // 0x7 [Interpreted: 200mA]
452 assert_eq!(EXAMPLE.max_read_current_vdd_max(), 7);
453
454 // Max Write Current @ VDD Min:
455 // 0x7 [Interpreted: 100mA]
456 assert_eq!(EXAMPLE.max_write_current_vdd_min(), 7);
457
458 // Max Write Current @ VDD Max::
459 // 0x7 [Interpreted: 200mA]
460 assert_eq!(EXAMPLE.max_write_current_vdd_max(), 7);
461
462 // Device Size Multiplier:
463 // 0x7 [Interpreted: x512]
464 assert_eq!(EXAMPLE.device_size_multiplier(), 7);
465
466 // Erase Single Block Enabled:
467 // 0x1 [Interpreted: Yes]
468 assert!(EXAMPLE.erase_single_block_enabled());
469
470 // Erase Sector Size: size of erasable sector in write blocks
471 // 0x1f [Interpreted: 32 blocks]
472 assert_eq!(EXAMPLE.erase_sector_size(), 0x1F);
473
474 // Write Protect Group Size:
475 // 0x00 [Interpreted: 1 sectors]
476 assert_eq!(EXAMPLE.write_protect_group_size(), 0x00);
477
478 // Write Protect Group Enable:
479 // 0x0 [Interpreted: No]
480 assert!(!EXAMPLE.write_protect_group_enable());
481
482 // Write Speed Factor: block program time as multiple of read access time
483 // 0x5 [Interpreted: x32]
484 assert_eq!(EXAMPLE.write_speed_factor(), 0x5);
485
486 // Max Write Data Block Length:
487 // 0xa [Interpreted: 1024 Bytes]
488 assert_eq!(EXAMPLE.max_write_data_length(), 0xa);
489
490 // Partial Blocks for Write Allowed:
491 // 0x0 [Interpreted: No]
492 assert!(!EXAMPLE.write_partial_blocks());
493
494 // File Format Group:
495 // 0b0 [Interpreted: is either Hard Disk with Partition Table/DOS FAT without Partition Table/Universal File Format/Other/Unknown]
496 assert!(!EXAMPLE.file_format_group_set());
497
498 // Copy Flag:
499 // 0b0 [Interpreted: Original]
500 assert!(!EXAMPLE.copy_flag_set());
501
502 // Permanent Write Protection:
503 // 0b0 [Interpreted: No]
504 assert!(!EXAMPLE.permanent_write_protection());
505
506 // Temporary Write Protection:
507 // 0b0 [Interpreted: No]
508 assert!(!EXAMPLE.temporary_write_protection());
509
510 // File Format:
511 // 0x0 [Interpreted: Hard Disk with Partition Table]
512 assert_eq!(EXAMPLE.file_format(), 0x00);
513
514 // CRC7 Checksum + always 1 in LSB:
515 // 0x6f
516 assert_eq!(EXAMPLE.crc(), 0x6F);
517
518 assert_eq!(EXAMPLE.card_capacity_bytes(), 1_978_662_912);
519 assert_eq!(EXAMPLE.card_capacity_blocks(), 3_864_576);
520 }
521
522 #[test]
523 fn test_csdv2() {
524 const EXAMPLE: CsdV2 = CsdV2 {
525 data: hex!("40 0E 00 32 5B 59 00 00 1D 69 7F 80 0A 40 00 8B"),
526 };
527 // CSD Structure: describes version of CSD structure
528 // 0b01 [Interpreted: Version 2.0 SDHC]
529 assert_eq!(EXAMPLE.csd_ver(), 0x01);
530
531 // Data Read Access Time 1: defines Asynchronous part of the read access time
532 // 0x0e [Interpreted: 1.0 x 1ms]
533 assert_eq!(EXAMPLE.data_read_access_time1(), 0x0E);
534
535 // Data Read Access Time 2: worst case clock dependent factor for data access time
536 // 0x00 [Decimal: 0 x 100 Clocks]
537 assert_eq!(EXAMPLE.data_read_access_time2(), 0x00);
538
539 // Max Data Transfer Rate: sometimes stated as Mhz
540 // 0x32 [Interpreted: 2.5 x 10Mbit/s]
541 assert_eq!(EXAMPLE.max_data_transfer_rate(), 0x32);
542
543 // Card Command Classes:
544 // 0x5b5 [Interpreted: Class 0: Yes. Class 1: No. Class 2: Yes. Class 3: No. Class 4: Yes. Class 5: Yes. Class 6: No. Class 7: Yes. Class 8: Yes. Class 9: No. Class 10: Yes. Class 11: No. ]
545 assert_eq!(EXAMPLE.card_command_classes(), 0x5b5);
546
547 // Max Read Data Block Length:
548 // 0x9 [Interpreted: 512 Bytes]
549 assert_eq!(EXAMPLE.read_block_length(), 0x09);
550
551 // Partial Blocks for Read Allowed:
552 // 0b0 [Interpreted: Yes]
553 assert!(!EXAMPLE.read_partial_blocks());
554
555 // Write Block Misalignment:
556 // 0b0 [Interpreted: No]
557 assert!(!EXAMPLE.write_block_misalignment());
558
559 // Read Block Misalignment:
560 // 0b0 [Interpreted: No]
561 assert!(!EXAMPLE.read_block_misalignment());
562
563 // DSR Implemented: indicates configurable driver stage integrated on card
564 // 0b0 [Interpreted: No]
565 assert!(!EXAMPLE.dsr_implemented());
566
567 // Device Size: to calculate the card capacity excl. security area
568 // ((device size + 1)* 512kbytes
569 // 0x001d69 [Decimal: 7529]
570 assert_eq!(EXAMPLE.device_size(), 7529);
571
572 // Erase Single Block Enabled:
573 // 0x1 [Interpreted: Yes]
574 assert!(EXAMPLE.erase_single_block_enabled());
575
576 // Erase Sector Size: size of erasable sector in write blocks
577 // 0x7f [Interpreted: 128 blocks]
578 assert_eq!(EXAMPLE.erase_sector_size(), 0x7F);
579
580 // Write Protect Group Size:
581 // 0x00 [Interpreted: 1 sectors]
582 assert_eq!(EXAMPLE.write_protect_group_size(), 0x00);
583
584 // Write Protect Group Enable:
585 // 0x0 [Interpreted: No]
586 assert!(!EXAMPLE.write_protect_group_enable());
587
588 // Write Speed Factor: block program time as multiple of read access time
589 // 0x2 [Interpreted: x4]
590 assert_eq!(EXAMPLE.write_speed_factor(), 0x2);
591
592 // Max Write Data Block Length:
593 // 0x9 [Interpreted: 512 Bytes]
594 assert_eq!(EXAMPLE.max_write_data_length(), 0x9);
595
596 // Partial Blocks for Write Allowed:
597 // 0x0 [Interpreted: No]
598 assert!(!EXAMPLE.write_partial_blocks());
599
600 // File Format Group:
601 // 0b0 [Interpreted: is either Hard Disk with Partition Table/DOS FAT without Partition Table/Universal File Format/Other/Unknown]
602 assert!(!EXAMPLE.file_format_group_set());
603
604 // Copy Flag:
605 // 0b0 [Interpreted: Original]
606 assert!(!EXAMPLE.copy_flag_set());
607
608 // Permanent Write Protection:
609 // 0b0 [Interpreted: No]
610 assert!(!EXAMPLE.permanent_write_protection());
611
612 // Temporary Write Protection:
613 // 0b0 [Interpreted: No]
614 assert!(!EXAMPLE.temporary_write_protection());
615
616 // File Format:
617 // 0x0 [Interpreted: Hard Disk with Partition Table]
618 assert_eq!(EXAMPLE.file_format(), 0x00);
619
620 // CRC7 Checksum + always 1 in LSB:
621 // 0x8b
622 assert_eq!(EXAMPLE.crc(), 0x8b);
623
624 assert_eq!(EXAMPLE.card_capacity_bytes(), 3_947_888_640);
625 assert_eq!(EXAMPLE.card_capacity_blocks(), 7_710_720);
626 }
627
628 #[test]
629 fn test_csdv2b() {
630 const EXAMPLE: CsdV2 = CsdV2 {
631 data: hex!("40 0E 00 32 5B 59 00 00 3A 91 7F 80 0A 40 00 05"),
632 };
633 // CSD Structure: describes version of CSD structure
634 // 0b01 [Interpreted: Version 2.0 SDHC]
635 assert_eq!(EXAMPLE.csd_ver(), 0x01);
636
637 // Data Read Access Time 1: defines Asynchronous part of the read access time
638 // 0x0e [Interpreted: 1.0 x 1ms]
639 assert_eq!(EXAMPLE.data_read_access_time1(), 0x0E);
640
641 // Data Read Access Time 2: worst case clock dependent factor for data access time
642 // 0x00 [Decimal: 0 x 100 Clocks]
643 assert_eq!(EXAMPLE.data_read_access_time2(), 0x00);
644
645 // Max Data Transfer Rate: sometimes stated as Mhz
646 // 0x32 [Interpreted: 2.5 x 10Mbit/s]
647 assert_eq!(EXAMPLE.max_data_transfer_rate(), 0x32);
648
649 // Card Command Classes:
650 // 0x5b5 [Interpreted: Class 0: Yes. Class 1: No. Class 2: Yes. Class 3: No. Class 4: Yes. Class 5: Yes. Class 6: No. Class 7: Yes. Class 8: Yes. Class 9: No. Class 10: Yes. Class 11: No. ]
651 assert_eq!(EXAMPLE.card_command_classes(), 0x5b5);
652
653 // Max Read Data Block Length:
654 // 0x9 [Interpreted: 512 Bytes]
655 assert_eq!(EXAMPLE.read_block_length(), 0x09);
656
657 // Partial Blocks for Read Allowed:
658 // 0b0 [Interpreted: Yes]
659 assert!(!EXAMPLE.read_partial_blocks());
660
661 // Write Block Misalignment:
662 // 0b0 [Interpreted: No]
663 assert!(!EXAMPLE.write_block_misalignment());
664
665 // Read Block Misalignment:
666 // 0b0 [Interpreted: No]
667 assert!(!EXAMPLE.read_block_misalignment());
668
669 // DSR Implemented: indicates configurable driver stage integrated on card
670 // 0b0 [Interpreted: No]
671 assert!(!EXAMPLE.dsr_implemented());
672
673 // Device Size: to calculate the card capacity excl. security area
674 // ((device size + 1)* 512kbytes
675 // 0x003a91 [Decimal: 7529]
676 assert_eq!(EXAMPLE.device_size(), 14993);
677
678 // Erase Single Block Enabled:
679 // 0x1 [Interpreted: Yes]
680 assert!(EXAMPLE.erase_single_block_enabled());
681
682 // Erase Sector Size: size of erasable sector in write blocks
683 // 0x7f [Interpreted: 128 blocks]
684 assert_eq!(EXAMPLE.erase_sector_size(), 0x7F);
685
686 // Write Protect Group Size:
687 // 0x00 [Interpreted: 1 sectors]
688 assert_eq!(EXAMPLE.write_protect_group_size(), 0x00);
689
690 // Write Protect Group Enable:
691 // 0x0 [Interpreted: No]
692 assert!(!EXAMPLE.write_protect_group_enable());
693
694 // Write Speed Factor: block program time as multiple of read access time
695 // 0x2 [Interpreted: x4]
696 assert_eq!(EXAMPLE.write_speed_factor(), 0x2);
697
698 // Max Write Data Block Length:
699 // 0x9 [Interpreted: 512 Bytes]
700 assert_eq!(EXAMPLE.max_write_data_length(), 0x9);
701
702 // Partial Blocks for Write Allowed:
703 // 0x0 [Interpreted: No]
704 assert!(!EXAMPLE.write_partial_blocks());
705
706 // File Format Group:
707 // 0b0 [Interpreted: is either Hard Disk with Partition Table/DOS FAT without Partition Table/Universal File Format/Other/Unknown]
708 assert!(!EXAMPLE.file_format_group_set());
709
710 // Copy Flag:
711 // 0b0 [Interpreted: Original]
712 assert!(!EXAMPLE.copy_flag_set());
713
714 // Permanent Write Protection:
715 // 0b0 [Interpreted: No]
716 assert!(!EXAMPLE.permanent_write_protection());
717
718 // Temporary Write Protection:
719 // 0b0 [Interpreted: No]
720 assert!(!EXAMPLE.temporary_write_protection());
721
722 // File Format:
723 // 0x0 [Interpreted: Hard Disk with Partition Table]
724 assert_eq!(EXAMPLE.file_format(), 0x00);
725
726 // CRC7 Checksum + always 1 in LSB:
727 // 0x05
728 assert_eq!(EXAMPLE.crc(), 0x05);
729
730 assert_eq!(EXAMPLE.card_capacity_bytes(), 7_861_174_272);
731 assert_eq!(EXAMPLE.card_capacity_blocks(), 15_353_856);
732 }
733}
734
735// ****************************************************************************
736//
737// End Of File
738//
739// ****************************************************************************