Hanna
Sourcecode Batteriemanagementsystem
sd_raw.c
gehe zur Dokumentation dieser Datei
1 
20 /*
21  * Copyright (c) 2006-2011 by Roland Riegel <feedback@roland-riegel.de>
22  *
23  * This file is free software; you can redistribute it and/or modify
24  * it under the terms of either the GNU General Public License version 2
25  * or the GNU Lesser General Public License version 2.1, both as
26  * published by the Free Software Foundation.
27  */
28 
29 #include <string.h>
30 #include <stdio.h>
31 #include <avr/io.h>
32 #include "sd_raw.h"
33 #include "port_driver.h"
34 
40 /* commands available in SPI mode */
41 
42 /* CMD0: response R1 */
43 #define CMD_GO_IDLE_STATE 0x00
44 /* CMD1: response R1 */
45 #define CMD_SEND_OP_COND 0x01
46 /* CMD8: response R7 */
47 #define CMD_SEND_IF_COND 0x08
48 /* CMD9: response R1 */
49 #define CMD_SEND_CSD 0x09
50 /* CMD10: response R1 */
51 #define CMD_SEND_CID 0x0a
52 /* CMD12: response R1 */
53 #define CMD_STOP_TRANSMISSION 0x0c
54 /* CMD13: response R2 */
55 #define CMD_SEND_STATUS 0x0d
56 /* CMD16: arg0[31:0]: block length, response R1 */
57 #define CMD_SET_BLOCKLEN 0x10
58 /* CMD17: arg0[31:0]: data address, response R1 */
59 #define CMD_READ_SINGLE_BLOCK 0x11
60 /* CMD18: arg0[31:0]: data address, response R1 */
61 #define CMD_READ_MULTIPLE_BLOCK 0x12
62 /* CMD24: arg0[31:0]: data address, response R1 */
63 #define CMD_WRITE_SINGLE_BLOCK 0x18
64 /* CMD25: arg0[31:0]: data address, response R1 */
65 #define CMD_WRITE_MULTIPLE_BLOCK 0x19
66 /* CMD27: response R1 */
67 #define CMD_PROGRAM_CSD 0x1b
68 /* CMD28: arg0[31:0]: data address, response R1b */
69 #define CMD_SET_WRITE_PROT 0x1c
70 /* CMD29: arg0[31:0]: data address, response R1b */
71 #define CMD_CLR_WRITE_PROT 0x1d
72 /* CMD30: arg0[31:0]: write protect data address, response R1 */
73 #define CMD_SEND_WRITE_PROT 0x1e
74 /* CMD32: arg0[31:0]: data address, response R1 */
75 #define CMD_TAG_SECTOR_START 0x20
76 /* CMD33: arg0[31:0]: data address, response R1 */
77 #define CMD_TAG_SECTOR_END 0x21
78 /* CMD34: arg0[31:0]: data address, response R1 */
79 #define CMD_UNTAG_SECTOR 0x22
80 /* CMD35: arg0[31:0]: data address, response R1 */
81 #define CMD_TAG_ERASE_GROUP_START 0x23
82 /* CMD36: arg0[31:0]: data address, response R1 */
83 #define CMD_TAG_ERASE_GROUP_END 0x24
84 /* CMD37: arg0[31:0]: data address, response R1 */
85 #define CMD_UNTAG_ERASE_GROUP 0x25
86 /* CMD38: arg0[31:0]: stuff bits, response R1b */
87 #define CMD_ERASE 0x26
88 /* ACMD41: arg0[31:0]: OCR contents, response R1 */
89 #define CMD_SD_SEND_OP_COND 0x29
90 /* CMD42: arg0[31:0]: stuff bits, response R1b */
91 #define CMD_LOCK_UNLOCK 0x2a
92 /* CMD55: arg0[31:0]: stuff bits, response R1 */
93 #define CMD_APP 0x37
94 /* CMD58: arg0[31:0]: stuff bits, response R3 */
95 #define CMD_READ_OCR 0x3a
96 /* CMD59: arg0[31:1]: stuff bits, arg0[0:0]: crc option, response R1 */
97 #define CMD_CRC_ON_OFF 0x3b
98 
99 /* command responses */
100 /* R1: size 1 byte */
101 #define R1_IDLE_STATE 0
102 #define R1_ERASE_RESET 1
103 #define R1_ILL_COMMAND 2
104 #define R1_COM_CRC_ERR 3
105 #define R1_ERASE_SEQ_ERR 4
106 #define R1_ADDR_ERR 5
107 #define R1_PARAM_ERR 6
108 /* R1b: equals R1, additional busy bytes */
109 /* R2: size 2 bytes */
110 #define R2_CARD_LOCKED 0
111 #define R2_WP_ERASE_SKIP 1
112 #define R2_ERR 2
113 #define R2_CARD_ERR 3
114 #define R2_CARD_ECC_FAIL 4
115 #define R2_WP_VIOLATION 5
116 #define R2_INVAL_ERASE 6
117 #define R2_OUT_OF_RANGE 7
118 #define R2_CSD_OVERWRITE 7
119 #define R2_IDLE_STATE (R1_IDLE_STATE + 8)
120 #define R2_ERASE_RESET (R1_ERASE_RESET + 8)
121 #define R2_ILL_COMMAND (R1_ILL_COMMAND + 8)
122 #define R2_COM_CRC_ERR (R1_COM_CRC_ERR + 8)
123 #define R2_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 8)
124 #define R2_ADDR_ERR (R1_ADDR_ERR + 8)
125 #define R2_PARAM_ERR (R1_PARAM_ERR + 8)
126 /* R3: size 5 bytes */
127 #define R3_OCR_MASK (0xffffffffUL)
128 #define R3_IDLE_STATE (R1_IDLE_STATE + 32)
129 #define R3_ERASE_RESET (R1_ERASE_RESET + 32)
130 #define R3_ILL_COMMAND (R1_ILL_COMMAND + 32)
131 #define R3_COM_CRC_ERR (R1_COM_CRC_ERR + 32)
132 #define R3_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 32)
133 #define R3_ADDR_ERR (R1_ADDR_ERR + 32)
134 #define R3_PARAM_ERR (R1_PARAM_ERR + 32)
135 /* Data Response: size 1 byte */
136 #define DR_STATUS_MASK 0x0e
137 #define DR_STATUS_ACCEPTED 0x05
138 #define DR_STATUS_CRC_ERR 0x0a
139 #define DR_STATUS_WRITE_ERR 0x0c
140 
141 /* status bits for card types */
142 #define SD_RAW_SPEC_1 0
143 #define SD_RAW_SPEC_2 1
144 #define SD_RAW_SPEC_SDHC 2
145 
146 #if !SD_RAW_SAVE_RAM
147 /* static data buffer for acceleration */
148 static uint8_t raw_block[512];
149 /* offset where the data within raw_block lies on the card */
150 static offset_t raw_block_address;
151 #if SD_RAW_WRITE_BUFFERING
152 /* flag to remember if raw_block was written to the card */
153 static uint8_t raw_block_written;
154 #endif
155 #endif
156 
157 /* card type state */
158 static uint8_t sd_raw_card_type;
159 
160 /* private helper functions */
161 static void sd_raw_send_byte ( uint8_t b );
162 static uint8_t sd_raw_rec_byte ();
163 static uint8_t sd_raw_send_command ( uint8_t command, uint32_t arg );
164 
171 uint8_t sd_raw_init ()
172 {
173  /* enable inputs for reading card status */
174 // configure_pin_available();configure_pin_locked();
175  /*
176  Wird in board_init bearbeitet - enable outputs for MOSI, SCK, SS, input for MISO
177  configure_pin_mosi();
178  configure_pin_sck();
179  configure_pin_ss();
180  configure_pin_miso();
181  */
182 
183  PORTB.PIN2CTRL = PORT_OPC_WIREDANDPULL_gc;
184 
185  PORTE.DIRSET = PIN4_bm; // !SS PIN wird nicht benutzt => entweder als Input mit Eingang high oder als Output konfigurieren, sonst wechselt SPI in Slave Mode !
186 
187  unselect_card();
188 
189 /*
190  * Initialise SPI with lowest frequency; max. 400 kHz during identification mode of card
191  * Clock Double off + CLK 11 => ClkPER/128 => 32 MHz / 128 = 250 kHz SPI frequency
192  */
193 
194  SD_READER_SPI.CTRL = 0x53; // 0b01010011; Clock Double off, SPI Enable, Data Order MSB first, Master Select, Transfer Mode 00, Prescaler ClkPER/128
195 
196  /* Initialisation procedure */
197  sd_raw_card_type = 0;
198 
199 // if(!sd_raw_available())
200 // return 0;
201 
202  select_card();
203  /* card needs 74 cycles minimum to start up */
204  for ( uint8_t i = 0; i < 10; ++i )
205  {
206  /* wait 8 clock cycles */
207  sd_raw_rec_byte ();
208  }
209 
210  /* address card */
211  select_card();
212 
213  /* reset card */
214  uint8_t response;
215  for ( uint16_t i = 0;; ++i )
216  {
217 
218  response = sd_raw_send_command ( CMD_GO_IDLE_STATE, 0 );
219  if ( response == (1 << R1_IDLE_STATE) ) break;
220 
221  if ( i == 0x1ff )
222  {
223  unselect_card();
224  return 0;
225  }
226  }
227 
228 #if SD_RAW_SDHC
229  /* check for version of SD card specification */
230  response = sd_raw_send_command ( CMD_SEND_IF_COND, 0x100 /* 2.7V - 3.6V */| 0xaa /* test pattern */);
231  if ( (response & (1 << R1_ILL_COMMAND)) == 0 )
232  {
233  sd_raw_rec_byte ();
234  sd_raw_rec_byte ();
235  if ( (sd_raw_rec_byte () & 0x01) == 0 ) return 0; /* card operation voltage range doesn't match */
236  if ( sd_raw_rec_byte () != 0xaa ) return 0; /* wrong test pattern */
237 
238  /* card conforms to SD 2 card specification */
239  sd_raw_card_type |= (1 << SD_RAW_SPEC_2);
240  }
241  else
242 #endif
243  {
244  /* determine SD/MMC card type */
245  sd_raw_send_command ( CMD_APP, 0 );
246  response = sd_raw_send_command ( CMD_SD_SEND_OP_COND, 0 );
247  if ( (response & (1 << R1_ILL_COMMAND)) == 0 )
248  {
249  /* card conforms to SD 1 card specification */
250  sd_raw_card_type |= (1 << SD_RAW_SPEC_1);
251  }
252  else
253  {
254  /* MMC card */
255  }
256  }
257 
258  /* wait for card to get ready */
259  for ( uint16_t i = 0;; ++i )
260  {
261  if ( sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2)) )
262  {
263  uint32_t arg = 0;
264 #if SD_RAW_SDHC
265  if ( sd_raw_card_type & (1 << SD_RAW_SPEC_2) ) arg = 0x40000000;
266 #endif
267  sd_raw_send_command ( CMD_APP, 0 );
268  response = sd_raw_send_command ( CMD_SD_SEND_OP_COND, arg );
269  }
270  else
271  {
272  response = sd_raw_send_command ( CMD_SEND_OP_COND, 0 );
273  }
274 
275  if ( (response & (1 << R1_IDLE_STATE)) == 0 ) break;
276 
277  if ( i == 0x7fff )
278  {
279  unselect_card();
280  return 0;
281  }
282  }
283 
284 #if SD_RAW_SDHC
285  if ( sd_raw_card_type & (1 << SD_RAW_SPEC_2) )
286  {
287  if ( sd_raw_send_command ( CMD_READ_OCR, 0 ) )
288  {
289  unselect_card();
290  return 0;
291  }
292 
293  if ( sd_raw_rec_byte () & 0x40 ) sd_raw_card_type |= (1 << SD_RAW_SPEC_SDHC);
294 
295  sd_raw_rec_byte ();
296  sd_raw_rec_byte ();
297  sd_raw_rec_byte ();
298  }
299 #endif
300 
301  /* set block size to 512 bytes */
302  if ( sd_raw_send_command ( CMD_SET_BLOCKLEN, 512 ) )
303  {
304  unselect_card();
305  return 0;
306  }
307 
308  /* deaddress card */
309  unselect_card();
310 
311  /* switch to highest SPI frequency possible, Clock Double + CLK 00 => ClkPER/2 => 32 MHz / 2 = 16 MHz SPI frequency*/
312  SD_READER_SPI.CTRL = 0b11010000; // 0b11010000; Clock Double, SPI Enable, Data Order MSB first, Master Select, Transfer Mode 00, Prescaler ClkPER/2
313 
314 #if !SD_RAW_SAVE_RAM
315  /* the first block is likely to be accessed first, so precache it here */
316  raw_block_address = (offset_t) -1;
317 #if SD_RAW_WRITE_BUFFERING
318  raw_block_written = 1;
319 #endif
320  if ( !sd_raw_read ( 0, raw_block, sizeof(raw_block) ) ) return 0;
321 #endif
322 
323  return 1;
324 }
325 
333 {
334  return get_pin_available() == 0x00;
335 }
336 
343 uint8_t sd_raw_locked ()
344 {
345  return get_pin_locked() == 0x00;
346 }
347 
355 void sd_raw_send_byte ( uint8_t b )
356 {
357 #if XMEGA
358  SD_READER_SPI.DATA = b;
359  /* wait for byte to be shifted out */
360  while ( !(SD_READER_SPI.STATUS & 0x80) )
361  ;
363 #else
364  SPDR = b;
365  /* wait for byte to be shifted out */
366  while(!(SPSR & (1 << SPIF)));
367  SPSR &= ~(1 << SPIF);
368 #endif
369 }
370 
378 uint8_t sd_raw_rec_byte ()
379 {
380 #if XMEGA
381  /* send dummy data for receiving some */
382 
383  SD_READER_SPI.DATA = 0xFF;
384 
385  while ( !(SD_READER_SPI.STATUS & 0x80) )
386  ;
387 
388  return SD_READER_SPI.DATA;
389 #else
390  /* send dummy data for receiving some */
391  SPDR = 0xff;
392  while(!(SPSR & (1 << SPIF)));
393  SPSR &= ~(1 << SPIF);
394 
395  return SPDR;
396 #endif
397 }
398 
407 uint8_t sd_raw_send_command ( uint8_t command, uint32_t arg )
408 {
409  uint8_t response;
410 
411  /* wait some clock cycles */
412  sd_raw_rec_byte ();
413 
414  /* send command via SPI */
415  sd_raw_send_byte ( 0x40 | command );
416  sd_raw_send_byte ( (arg >> 24) & 0xff );
417  sd_raw_send_byte ( (arg >> 16) & 0xff );
418  sd_raw_send_byte ( (arg >> 8) & 0xff );
419  sd_raw_send_byte ( (arg >> 0) & 0xff );
420  switch (command)
421  {
422  case CMD_GO_IDLE_STATE:
423  sd_raw_send_byte ( 0x95 );
424  break;
425  case CMD_SEND_IF_COND:
426  sd_raw_send_byte ( 0x87 );
427  break;
428  default:
429  sd_raw_send_byte ( 0xff );
430  break;
431  }
432 
433  /* receive response */
434  for ( uint8_t i = 0; i < 10; ++i )
435  {
436  response = sd_raw_rec_byte ();
437  if ( response != 0xff ) break;
438  }
439 
440  return response;
441 }
442 
453 uint8_t sd_raw_read ( offset_t offset, uint8_t* buffer, uintptr_t length )
454 {
455  offset_t block_address;
456  uint16_t block_offset;
457  uint16_t read_length;
458  while ( length > 0 )
459  {
460  /* determine byte count to read at once */
461  block_offset = offset & 0x01ff;
462  block_address = offset - block_offset;
463  read_length = 512 - block_offset; /* read up to block border */
464  if ( read_length > length ) read_length = length;
465 
466 #if !SD_RAW_SAVE_RAM
467  /* check if the requested data is cached */
468  if ( block_address != raw_block_address )
469 #endif
470  {
471 #if SD_RAW_WRITE_BUFFERING
472  if ( !sd_raw_sync () ) return 0;
473 #endif
474 
475  /* address card */
476  select_card();
477 
478  /* send single block request */
479 #if SD_RAW_SDHC
480  if ( sd_raw_send_command ( CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address) ) )
481 #else
482  if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address))
483 #endif
484  {
485  unselect_card();
486  return 0;
487  }
488 
489  /* wait for data block (start byte 0xfe) */
490  while ( sd_raw_rec_byte () != 0xfe )
491  ;
492 
493 #if SD_RAW_SAVE_RAM
494  /* read byte block */
495  uint16_t read_to = block_offset + read_length;
496  for(uint16_t i = 0; i < 512; ++i)
497  {
498  uint8_t b = sd_raw_rec_byte();
499  if(i >= block_offset && i < read_to)
500  *buffer++ = b;
501  }
502 #else
503  /* read byte block */
504  uint8_t* cache = raw_block;
505  for ( uint16_t i = 0; i < 512; ++i )
506  *cache++ = sd_raw_rec_byte ();
507  raw_block_address = block_address;
508 
509  memcpy ( buffer, raw_block + block_offset, read_length );
510  buffer += read_length;
511 #endif
512 
513  /* read crc16 */
514  sd_raw_rec_byte ();
515  sd_raw_rec_byte ();
516 
517  /* deaddress card */
518  unselect_card();
519 
520  /* let card some time to finish */
521  sd_raw_rec_byte ();
522  }
523 #if !SD_RAW_SAVE_RAM
524  else
525  {
526  /* use cached data */
527  memcpy ( buffer, raw_block + block_offset, read_length );
528  buffer += read_length;
529  }
530 #endif
531 
532  length -= read_length;
533  offset += read_length;
534  }
535 
536  return 1;
537 }
538 
563 uint8_t sd_raw_read_interval ( offset_t offset, uint8_t* buffer, uintptr_t interval, uintptr_t length, sd_raw_read_interval_handler_t callback, void* p )
564 {
565  if ( !buffer || interval == 0 || length < interval || !callback ) return 0;
566 
567 #if !SD_RAW_SAVE_RAM
568  while ( length >= interval )
569  {
570  /* as reading is now buffered, we directly
571  * hand over the request to sd_raw_read()
572  */
573  if ( !sd_raw_read ( offset, buffer, interval ) ) return 0;
574  if ( !callback ( buffer, offset, p ) ) break;
575  offset += interval;
576  length -= interval;
577  }
578 
579  return 1;
580 #else
581  /* address card */
582  select_card();
583 
584  uint16_t block_offset;
585  uint16_t read_length;
586  uint8_t* buffer_cur;
587  uint8_t finished = 0;
588  do
589  {
590  /* determine byte count to read at once */
591  block_offset = offset & 0x01ff;
592  read_length = 512 - block_offset;
593 
594  /* send single block request */
595 #if SD_RAW_SDHC
596  if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? offset / 512 : offset - block_offset)))
597 #else
598  if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, offset - block_offset))
599 #endif
600  {
601  unselect_card();
602  return 0;
603  }
604 
605  /* wait for data block (start byte 0xfe) */
606  while(sd_raw_rec_byte() != 0xfe);
607 
608  /* read up to the data of interest */
609  for(uint16_t i = 0; i < block_offset; ++i)
610  sd_raw_rec_byte();
611 
612  /* read interval bytes of data and execute the callback */
613  do
614  {
615  if(read_length < interval || length < interval)
616  break;
617 
618  buffer_cur = buffer;
619  for(uint16_t i = 0; i < interval; ++i)
620  *buffer_cur++ = sd_raw_rec_byte();
621 
622  if(!callback(buffer, offset + (512 - read_length), p))
623  {
624  finished = 1;
625  break;
626  }
627 
628  read_length -= interval;
629  length -= interval;
630 
631  }while(read_length > 0 && length > 0);
632 
633  /* read rest of data block */
634  while(read_length-- > 0)
635  sd_raw_rec_byte();
636 
637  /* read crc16 */
638  sd_raw_rec_byte();
639  sd_raw_rec_byte();
640 
641  if(length < interval)
642  break;
643 
644  offset = offset - block_offset + 512;
645 
646  }while(!finished);
647 
648  /* deaddress card */
649  unselect_card();
650 
651  /* let card some time to finish */
652  sd_raw_rec_byte();
653 
654  return 1;
655 #endif
656 }
657 
658 #if DOXYGEN || SD_RAW_WRITE_SUPPORT
659 
673 uint8_t sd_raw_write ( offset_t offset, const uint8_t* buffer, uintptr_t length )
674 {
675  if ( sd_raw_locked () ) return 0;
676 
677  offset_t block_address;
678  uint16_t block_offset;
679  uint16_t write_length;
680  while ( length > 0 )
681  {
682  /* determine byte count to write at once */
683  block_offset = offset & 0x01ff;
684  block_address = offset - block_offset;
685  write_length = 512 - block_offset; /* write up to block border */
686  if ( write_length > length ) write_length = length;
687 
688  /* Merge the data to write with the content of the block.
689  * Use the cached block if available.
690  */
691  if ( block_address != raw_block_address )
692  {
693 #if SD_RAW_WRITE_BUFFERING
694  if ( !sd_raw_sync () ) return 0;
695 #endif
696 
697  if ( block_offset || write_length < 512 )
698  {
699  if ( !sd_raw_read ( block_address, raw_block, sizeof(raw_block) ) ) return 0;
700  }
701  raw_block_address = block_address;
702  }
703 
704  if ( buffer != raw_block )
705  {
706  memcpy ( raw_block + block_offset, buffer, write_length );
707 
708 #if SD_RAW_WRITE_BUFFERING
709  raw_block_written = 0;
710 
711  if ( length == write_length ) return 1;
712 #endif
713  }
714 
715  /* address card */
716  select_card();
717 
718  /* send single block request */
719 #if SD_RAW_SDHC
720  if ( sd_raw_send_command ( CMD_WRITE_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address) ) )
721 #else
722  if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, block_address))
723 #endif
724  {
725  unselect_card();
726  return 0;
727  }
728 
729  /* send start byte */
730  sd_raw_send_byte ( 0xfe );
731 
732  /* write byte block */
733  uint8_t* cache = raw_block;
734  for ( uint16_t i = 0; i < 512; ++i )
735  sd_raw_send_byte ( *cache++ );
736 
737  /* write dummy crc16 */
738  sd_raw_send_byte ( 0xff );
739  sd_raw_send_byte ( 0xff );
740 
741  /* wait while card is busy */
742  while ( sd_raw_rec_byte () != 0xff )
743  ;
744  sd_raw_rec_byte ();
745 
746  /* deaddress card */
747  unselect_card();
748 
749  buffer += write_length;
750  offset += write_length;
751  length -= write_length;
752 
753 #if SD_RAW_WRITE_BUFFERING
754  raw_block_written = 1;
755 #endif
756  }
757 
758  return 1;
759 }
760 #endif
761 
762 #if DOXYGEN || SD_RAW_WRITE_SUPPORT
763 
781 uint8_t sd_raw_write_interval ( offset_t offset, uint8_t* buffer, uintptr_t length, sd_raw_write_interval_handler_t callback, void* p )
782 {
783 #if SD_RAW_SAVE_RAM
784 #error "SD_RAW_WRITE_SUPPORT is not supported together with SD_RAW_SAVE_RAM"
785 #endif
786 
787  if ( !buffer || !callback ) return 0;
788 
789  uint8_t endless = (length == 0);
790  while ( endless || length > 0 )
791  {
792  uint16_t bytes_to_write = callback ( buffer, offset, p );
793  if ( !bytes_to_write ) break;
794  if ( !endless && bytes_to_write > length ) return 0;
795 
796  /* as writing is always buffered, we directly
797  * hand over the request to sd_raw_write()
798  */
799  if ( !sd_raw_write ( offset, buffer, bytes_to_write ) ) return 0;
800 
801  offset += bytes_to_write;
802  length -= bytes_to_write;
803  }
804 
805  return 1;
806 }
807 #endif
808 
809 #if DOXYGEN || SD_RAW_WRITE_SUPPORT
810 
822 uint8_t sd_raw_sync ()
823 {
824 #if SD_RAW_WRITE_BUFFERING
825  if ( raw_block_written ) return 1;
826  if ( !sd_raw_write ( raw_block_address, raw_block, sizeof(raw_block) ) ) return 0;
827  raw_block_written = 1;
828 #endif
829  return 1;
830 }
831 #endif
832 
848 uint8_t sd_raw_get_info ( struct sd_raw_info* info )
849 {
850  if ( !info || !sd_raw_available () ) return 0;
851 
852  memset ( info, 0, sizeof(*info) );
853 
854  select_card();
855 
856  /* read cid register */
857  if ( sd_raw_send_command ( CMD_SEND_CID, 0 ) )
858  {
859  unselect_card();
860  return 0;
861  }
862  while ( sd_raw_rec_byte () != 0xfe )
863  ;
864  for ( uint8_t i = 0; i < 18; ++i )
865  {
866  uint8_t b = sd_raw_rec_byte ();
867 
868  switch (i)
869  {
870  case 0:
871  info->manufacturer = b;
872  break;
873  case 1:
874  case 2:
875  info->oem[i - 1] = b;
876  break;
877  case 3:
878  case 4:
879  case 5:
880  case 6:
881  case 7:
882  info->product[i - 3] = b;
883  break;
884  case 8:
885  info->revision = b;
886  break;
887  case 9:
888  case 10:
889  case 11:
890  case 12:
891  info->serial |= (uint32_t) b << ((12 - i) * 8);
892  break;
893  case 13:
894  info->manufacturing_year = b << 4;
895  break;
896  case 14:
897  info->manufacturing_year |= b >> 4;
898  info->manufacturing_month = b & 0x0f;
899  break;
900  }
901  }
902 
903  /* read csd register */
904  uint8_t csd_read_bl_len = 0;
905  uint8_t csd_c_size_mult = 0;
906 #if SD_RAW_SDHC
907  uint16_t csd_c_size = 0;
908 #else
909  uint32_t csd_c_size = 0;
910 #endif
911  if ( sd_raw_send_command ( CMD_SEND_CSD, 0 ) )
912  {
913  unselect_card();
914  return 0;
915  }
916  while ( sd_raw_rec_byte () != 0xfe )
917  ;
918  for ( uint8_t i = 0; i < 18; ++i )
919  {
920  uint8_t b = sd_raw_rec_byte ();
921 
922  if ( i == 14 )
923  {
924  if ( b & 0x40 ) info->flag_copy = 1;
925  if ( b & 0x20 ) info->flag_write_protect = 1;
926  if ( b & 0x10 ) info->flag_write_protect_temp = 1;
927  info->format = (b & 0x0c) >> 2;
928  }
929  else
930  {
931 #if SD_RAW_SDHC
932  if ( sd_raw_card_type & (1 << SD_RAW_SPEC_2) )
933  {
934  switch (i)
935  {
936  case 7:
937  b &= 0x3f;
938  break;
939  case 8:
940  case 9:
941  csd_c_size <<= 8;
942  csd_c_size |= b;
943  break;
944  }
945  if ( i == 9 )
946  {
947  ++csd_c_size;
948  info->capacity = (offset_t) csd_c_size * 512 * 1024;
949  }
950  }
951  else
952 #endif
953  {
954  switch (i)
955  {
956  case 5:
957  csd_read_bl_len = b & 0x0f;
958  break;
959  case 6:
960  csd_c_size = b & 0x03;
961  csd_c_size <<= 8;
962  break;
963  case 7:
964  csd_c_size |= b;
965  csd_c_size <<= 2;
966  break;
967  case 8:
968  csd_c_size |= b >> 6;
969  ++csd_c_size;
970  break;
971  case 9:
972  csd_c_size_mult = b & 0x03;
973  csd_c_size_mult <<= 1;
974  break;
975  case 10:
976  csd_c_size_mult |= b >> 7;
977 
978  info->capacity = (uint32_t) csd_c_size << (csd_c_size_mult + csd_read_bl_len + 2);
979 
980  break;
981  }
982  }
983  }
984  }
985 
986  unselect_card();
987 
988  return 1;
989 }
990 
uint8_t format
Definition: sd_raw.h:124
uint8_t sd_raw_read_interval(offset_t offset, uint8_t *buffer, uintptr_t interval, uintptr_t length, sd_raw_read_interval_handler_t callback, void *p)
Definition: sd_raw.c:563
uint8_t sd_raw_locked()
Definition: sd_raw.c:343
uint8_t sd_raw_get_info(struct sd_raw_info *info)
Definition: sd_raw.c:848
uint8_t manufacturing_month
Definition: sd_raw.h:92
uint8_t sd_raw_init()
Definition: sd_raw.c:171
static uint8_t sd_raw_rec_byte()
Definition: sd_raw.c:378
uint8_t manufacturer
Definition: sd_raw.h:64
uint8_t flag_copy
Definition: sd_raw.h:102
uint8_t manufacturing_year
Definition: sd_raw.h:88
uint32_t serial
Definition: sd_raw.h:82
XMEGA I/O Port driver header file.
offset_t capacity
Definition: sd_raw.h:96
SD-Card Reader Bibliothek von Roland Riegel. MMC/SD/SDHC raw access header (license: GPLv2 or LGPLv2...
uint8_t sd_raw_read(offset_t offset, uint8_t *buffer, uintptr_t length)
Definition: sd_raw.c:453
uint8_t sd_raw_sync()
Definition: sd_raw.c:822
uint8_t oem[3]
Definition: sd_raw.h:68
uint8_t flag_write_protect
Definition: sd_raw.h:109
static uint8_t sd_raw_send_command(uint8_t command, uint32_t arg)
Definition: sd_raw.c:407
uint8_t product[6]
Definition: sd_raw.h:72
uint8_t revision
Definition: sd_raw.h:78
uint8_t sd_raw_write_interval(offset_t offset, uint8_t *buffer, uintptr_t length, sd_raw_write_interval_handler_t callback, void *p)
Definition: sd_raw.c:781
uint8_t flag_write_protect_temp
Definition: sd_raw.h:116
uint8_t sd_raw_available()
Definition: sd_raw.c:332
uint8_t sd_raw_write(offset_t offset, const uint8_t *buffer, uintptr_t length)
Definition: sd_raw.c:673
static void sd_raw_send_byte(uint8_t b)
Definition: sd_raw.c:355