zoukankan      html  css  js  c++  java
  • stm32 spi sdcard fatfs

       1 http://cba.si/stuff/fatfs_diskio_sdcard_spi.c
       2 
       3 /*
       4  * (c) Domen Puncer, Visionect, d.o.o.
       5  * BSD License
       6  *
       7  * v0.2 add support for SDHC
       8  */
       9 
      10 #include <stdio.h>
      11 #include "stm32f10x_lib.h"
      12 
      13 /*
      14  * Code is split into 3 parts:
      15  * - generic SPI code: adapt for your MCU
      16  * - sd card code, with crc7 and crc16 calculations
      17  *   there's lots of it, but it's simple
      18  * - fatfs interface. If you use anything else, look here for
      19  *   interface to SD card code
      20  */
      21 
      22 struct hwif
      23 {
      24   int initialized;
      25   int sectors;
      26   int erase_sectors;
      27   int capabilities;
      28 } ;
      29 
      30 typedef struct hwif hwif;
      31 
      32 #define CAP_VER2_00    (1<<0)
      33 #define CAP_SDHC    (1<<1)
      34 
      35 enum sd_speed
      36 {
      37   SD_SPEED_INVALID, SD_SPEED_400KHZ, SD_SPEED_25MHZ
      38 } ;
      39 
      40 /*** spi functions ***/
      41 
      42 static void spi_set_speed ( enum sd_speed speed );
      43 
      44 /* SD card is connected to SPI1, PA4-7 */
      45 #define SPI_SD SPI1
      46 
      47 static void spi_init ( void )
      48 {
      49   GPIO_InitTypeDef gpio;
      50 
      51   RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA, ENABLE );
      52   RCC_APB2PeriphClockCmd ( RCC_APB2Periph_SPI1, ENABLE );
      53 
      54   gpio.GPIO_Pin   = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
      55   gpio.GPIO_Speed = GPIO_Speed_50MHz;
      56   gpio.GPIO_Mode  = GPIO_Mode_AF_PP;
      57   GPIO_Init ( GPIOA, & gpio );
      58 
      59   gpio.GPIO_Pin   = GPIO_Pin_4;
      60   gpio.GPIO_Speed = GPIO_Speed_50MHz;
      61   gpio.GPIO_Mode  = GPIO_Mode_Out_PP;
      62   GPIO_Init ( GPIOA, & gpio );
      63 
      64   spi_set_speed ( SD_SPEED_400KHZ );
      65 }
      66 #define spi_cs_low() do { GPIOA->BRR = GPIO_Pin_4; } while (0)
      67 #define spi_cs_high() do { GPIOA->BSRR = GPIO_Pin_4; } while (0)
      68 
      69 static void spi_set_speed ( enum sd_speed speed )
      70 {
      71   SPI_InitTypeDef spi;
      72   int prescaler = SPI_BaudRatePrescaler_128;
      73 
      74   if ( speed == SD_SPEED_400KHZ )
      75   {
      76     prescaler = SPI_BaudRatePrescaler_128;
      77   }
      78   else if ( speed == SD_SPEED_25MHZ )
      79   {
      80     prescaler = SPI_BaudRatePrescaler_2;
      81   }
      82   /* ^ with /2 APB1 this will be 15mhz/234k at 60mhz
      83    * 18/281 at 72. which is ok, 100<x<400khz, and <25mhz */
      84 
      85   SPI_Cmd ( SPI_SD, DISABLE );
      86 
      87   spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
      88   spi.SPI_Mode      = SPI_Mode_Master;
      89   spi.SPI_DataSize  = SPI_DataSize_8b;
      90   spi.SPI_CPOL      = SPI_CPOL_Low;
      91   spi.SPI_CPHA      = SPI_CPHA_1Edge;
      92 
      93   spi.SPI_NSS               = SPI_NSS_Soft;
      94   spi.SPI_BaudRatePrescaler = prescaler;
      95   spi.SPI_FirstBit          = SPI_FirstBit_MSB;
      96   spi.SPI_CRCPolynomial     = 7;
      97   SPI_Init ( SPI_SD, & spi );
      98 
      99   SPI_Cmd ( SPI_SD, ENABLE );
     100 }
     101 
     102 static u8 spi_txrx ( u8 data )
     103 {
     104   /* RXNE always happens after TXE, so if this function is used
     105    * we don't need to check for TXE */
     106   SPI_SD->DR = data;
     107   while ( ( SPI_SD->SR & SPI_I2S_FLAG_RXNE ) == 0 )
     108   { ;
     109   }
     110   return SPI_SD->DR;
     111 }
     112 
     113 /* crc helpers */
     114 static u8 crc7_one ( u8 t, u8 data )
     115 {
     116   int i;
     117   const u8 g = 0x89;
     118 
     119   t ^= data;
     120   for ( i = 0; i < 8; i++ )
     121   {
     122     if ( t & 0x80 )
     123     {
     124       t ^= g;
     125     }
     126     t <<= 1;
     127   }
     128   return t;
     129 }
     130 
     131 u8 crc7 ( const u8 * p, int len )
     132 {
     133   int j;
     134   u8 crc = 0;
     135   for ( j = 0; j < len; j++ )
     136   {
     137     crc = crc7_one ( crc, p[ j ] );
     138   }
     139 
     140   return crc >> 1;
     141 }
     142 
     143 /* http://www.eagleairaust.com.au/code/crc16.htm */
     144 static u16 crc16_ccitt ( u16 crc, u8 ser_data )
     145 {
     146   crc = ( u8 )( crc >> 8 ) | ( crc << 8 );
     147   crc ^= ser_data;
     148   crc ^= ( u8 )( crc & 0xff ) >> 4;
     149   crc ^= ( crc << 8 ) << 4;
     150   crc ^= ( ( crc & 0xff ) << 4 ) << 1;
     151 
     152   return crc;
     153 }
     154 
     155 u16 crc16 ( const u8 * p, int len )
     156 {
     157   int i;
     158   u16 crc = 0;
     159 
     160   for ( i = 0; i < len; i++ )
     161   {
     162     crc = crc16_ccitt ( crc, p[ i ] );
     163   }
     164 
     165   return crc;
     166 }
     167 
     168 /*** sd functions - on top of spi code ***/
     169 
     170 static void sd_cmd ( u8 cmd, u32 arg )
     171 {
     172   u8 crc = 0;
     173   spi_txrx ( 0x40 | cmd );
     174   crc = crc7_one ( crc, 0x40 | cmd );
     175   spi_txrx ( arg >> 24 );
     176   crc = crc7_one ( crc, arg >> 24 );
     177   spi_txrx ( arg >> 16 );
     178   crc = crc7_one ( crc, arg >> 16 );
     179   spi_txrx ( arg >> 8 );
     180   crc = crc7_one ( crc, arg >> 8 );
     181   spi_txrx ( arg );
     182   crc = crc7_one ( crc, arg );
     183   // spi_txrx(0x95);    /* crc7, for cmd0 */
     184   spi_txrx ( crc | 0x1 ); /* crc7, for cmd0 */
     185 }
     186 
     187 static u8 sd_get_r1 ( )
     188 {
     189   int tries = 1000;
     190   u8 r;
     191 
     192   while ( tries-- )
     193   {
     194     r = spi_txrx ( 0xff );
     195     if ( ( r & 0x80 ) == 0 )
     196     {
     197       return r;
     198     }
     199   }
     200   return 0xff;
     201 }
     202 
     203 static u16 sd_get_r2 ( )
     204 {
     205   int tries = 1000;
     206   u16 r;
     207 
     208   while ( tries-- )
     209   {
     210     r = spi_txrx ( 0xff );
     211     if ( ( r & 0x80 ) == 0 )
     212     {
     213       break;
     214     }
     215   }
     216   if ( tries < 0 )
     217   {
     218     return 0xff;
     219   }
     220   r = r << 8 | spi_txrx ( 0xff );
     221 
     222   return r;
     223 }
     224 
     225 /*
     226  * r1, then 32-bit reply... same format as r3
     227  */
     228 static u8 sd_get_r7 ( u32 * r7 )
     229 {
     230   u32 r;
     231   r = sd_get_r1 ( );
     232   if ( r != 0x01 )
     233   {
     234     return r;
     235   }
     236 
     237   r = spi_txrx ( 0xff ) << 24;
     238   r |= spi_txrx ( 0xff ) << 16;
     239   r |= spi_txrx ( 0xff ) << 8;
     240   r |= spi_txrx ( 0xff );
     241 
     242   *r7 = r;
     243   return 0x01;
     244 }
     245 #define sd_get_r3 sd_get_r7
     246 
     247 static const char * r1_strings[ 7 ] =
     248 {
     249   "in idle",
     250   "erase reset",
     251   "illegal command",
     252   "communication crc error",
     253   "erase sequence error",
     254   "address error",
     255   "parameter error"
     256 } ;
     257 
     258 static void print_r1 ( u8 r )
     259 {
     260   int i;
     261   printf ( "R1: %02x\n", r );
     262   for ( i = 0; i < 7; i++ )
     263   {
     264     if ( r & ( 1 << i ) )
     265     {
     266       printf ( "  %s\n", r1_strings[ i ] );
     267     }
     268   }
     269 }
     270 
     271 static const char * r2_strings[ 15 ] =
     272 {
     273   "card is locked",
     274   "wp erase skip | lock/unlock cmd failed",
     275   "error",
     276   "CC error",
     277   "card ecc failed",
     278   "wp violation",
     279   "erase param",
     280   "out of range | csd overwrite",
     281   "in idle state",
     282   "erase reset",
     283   "illegal command",
     284   "com crc error",
     285   "erase sequence error",
     286   "address error",
     287   "parameter error",
     288 } ;
     289 
     290 static void print_r2 ( u16 r )
     291 {
     292   int i;
     293   printf ( "R2: %04x\n", r );
     294   for ( i = 0; i < 15; i++ )
     295   {
     296     if ( r & ( 1 << i ) )
     297     {
     298       printf ( "  %s\n", r2_strings[ i ] );
     299     }
     300   }
     301 }
     302 
     303 /* Nec (=Ncr? which is limited to [0,8]) dummy bytes before lowering CS,
     304  * as described in sandisk doc, 5.4. */
     305 static void sd_nec ( )
     306 {
     307   int i;
     308   for ( i = 0; i < 8; i++ )
     309   {
     310     spi_txrx ( 0xff );
     311   }
     312 }
     313 
     314 static int sd_init ( hwif * hw )
     315 {
     316   int i;
     317   int r;
     318   u32 r7;
     319   u32 r3;
     320   int tries;
     321 
     322   hw->capabilities = 0;
     323 
     324   /* start with 100-400 kHz clock */
     325   spi_set_speed ( SD_SPEED_400KHZ );
     326 
     327   printf ( "cmd0 - reset.. " );
     328   spi_cs_high ( );
     329   /* 74+ clocks with CS high */
     330   for ( i = 0; i < 10; i++ )
     331   {
     332     spi_txrx ( 0xff );
     333   }
     334 
     335   /* reset */
     336   spi_cs_low ( );
     337   sd_cmd ( 0, 0 );
     338   r = sd_get_r1 ( );
     339   sd_nec ( );
     340   spi_cs_high ( );
     341   if ( r == 0xff )
     342   {
     343     goto err_spi;
     344   }
     345   if ( r != 0x01 )
     346   {
     347     printf ( "fail\n" );
     348     print_r1 ( r );
     349     goto err;
     350   }
     351   printf ( "success\n" );
     352 
     353   printf ( "cmd8 - voltage.. " );
     354   /* ask about voltage supply */
     355   spi_cs_low ( );
     356   sd_cmd ( 8, 0x1aa /* VHS = 1 */ );
     357   r = sd_get_r7 ( &r7 );
     358   sd_nec ( );
     359   spi_cs_high ( );
     360   hw->capabilities |= CAP_VER2_00;
     361   if ( r == 0xff )
     362   {
     363     goto err_spi;
     364   }
     365   if ( r == 0x01 )
     366   {
     367     printf ( "success, SD v2.x\n" );
     368   }
     369   else if ( r & 0x4 )
     370   {
     371     hw->capabilities &= ~CAP_VER2_00;
     372     printf ( "not implemented, SD v1.x\n" );
     373   }
     374   else
     375   {
     376     printf ( "fail\n" );
     377     print_r1 ( r );
     378     return -2;
     379   }
     380 
     381   printf ( "cmd58 - ocr.. " );
     382   /* ask about voltage supply */
     383   spi_cs_low ( );
     384   sd_cmd ( 58, 0 );
     385   r = sd_get_r3 ( &r3 );
     386   sd_nec ( );
     387   spi_cs_high ( );
     388   if ( r == 0xff )
     389   {
     390     goto err_spi;
     391   }
     392   if ( r != 0x01 && !( r & 0x4 ) )
     393   { /* allow it to not be implemented - old cards */
     394     printf ( "fail\n" );
     395     print_r1 ( r );
     396     return -2;
     397   }
     398   else
     399   {
     400     int i;
     401     for ( i = 4; i <= 23; i++ )
     402     {
     403       if ( r3 & 1 << i )
     404       {
     405         break;
     406       }
     407     }
     408     printf ( "Vdd voltage window: %i.%i-", ( 12 + i ) / 10, ( 12 + i ) % 10 );
     409     for ( i = 23; i >= 4; i-- )
     410     {
     411       if ( r3 & 1 << i )
     412       {
     413         break;
     414       }
     415     }
     416     /* CCS shouldn't be valid here yet */
     417     printf ( "%i.%iV, CCS:%li, power up status:%li\n", ( 13 + i ) / 10,
     418       ( 13 + i ) % 10, r3 >> 30 & 1, r3 >> 31 );
     419     printf ( "success\n" );
     420   }
     421 
     422   printf ( "acmd41 - hcs.. " );
     423   tries   = 1000;
     424   u32 hcs = 0;
     425   /* say we support SDHC */
     426   if ( hw->capabilities & CAP_VER2_00 )
     427   {
     428     hcs = 1 << 30;
     429   }
     430 
     431   /* needs to be polled until in_idle_state becomes 0 */
     432   do
     433   {
     434     /* send we don't support SDHC */
     435     spi_cs_low ( );
     436     /* next cmd is ACMD */
     437     sd_cmd ( 55, 0 );
     438     r = sd_get_r1 ( );
     439     sd_nec ( );
     440     spi_cs_high ( );
     441     if ( r == 0xff )
     442     {
     443       goto err_spi;
     444     }
     445     /* well... it's probably not idle here, but specs aren't clear */
     446     if ( r & 0xfe )
     447     {
     448       printf ( "fail\n" );
     449       print_r1 ( r );
     450       goto err;
     451     }
     452 
     453     spi_cs_low ( );
     454     sd_cmd ( 41, hcs );
     455     r = sd_get_r1 ( );
     456     sd_nec ( );
     457     spi_cs_high ( );
     458     if ( r == 0xff )
     459     {
     460       goto err_spi;
     461     }
     462     if ( r & 0xfe )
     463     {
     464       printf ( "fail\n" );
     465       print_r1 ( r );
     466       goto err;
     467     }
     468   }
     469   while ( r != 0 && tries-- );
     470   if ( tries == -1 )
     471   {
     472     printf ( "timeouted\n" );
     473     goto err;
     474   }
     475   printf ( "success\n" );
     476 
     477   /* Seems after this card is initialized which means bit 0 of R1
     478    * will be cleared. Not too sure. */
     479 
     480   if ( hw->capabilities & CAP_VER2_00 )
     481   {
     482     printf ( "cmd58 - ocr, 2nd time.. " );
     483     /* ask about voltage supply */
     484     spi_cs_low ( );
     485     sd_cmd ( 58, 0 );
     486     r = sd_get_r3 ( &r3 );
     487     sd_nec ( );
     488     spi_cs_high ( );
     489     if ( r == 0xff )
     490     {
     491       goto err_spi;
     492     }
     493     if ( r & 0xfe )
     494     {
     495       printf ( "fail\n" );
     496       print_r1 ( r );
     497       return -2;
     498     }
     499     else
     500     {
     501       #if 1
     502       int i;
     503       for ( i = 4; i <= 23; i++ )
     504       {
     505         if ( r3 & 1 << i )
     506         {
     507           break;
     508         }
     509       }
     510       printf ( "Vdd voltage window: %i.%i-", ( 12 + i ) / 10, ( 12 + i ) % 10 );
     511       for ( i = 23; i >= 4; i-- )
     512       {
     513         if ( r3 & 1 << i )
     514         {
     515           break;
     516         }
     517       }
     518       /* CCS shouldn't be valid here yet */
     519       printf ( "%i.%iV, CCS:%li, power up status:%li\n", ( 13 + i ) / 10,
     520         ( 13 + i ) % 10, r3 >> 30 & 1, r3 >> 31 );
     521       // XXX power up status should be 1 here, since we're finished initializing, but it's not. WHY?
     522       // that means CCS is invalid, so we'll set CAP_SDHC later
     523       #endif
     524       if ( r3 >> 30 & 1 )
     525       {
     526         hw->capabilities |= CAP_SDHC;
     527       }
     528 
     529       printf ( "success\n" );
     530     }
     531   }
     532 
     533   /* with SDHC block length is fixed to 1024 */
     534   if ( ( hw->capabilities & CAP_SDHC ) == 0 )
     535   {
     536     printf ( "cmd16 - block length.. " );
     537     spi_cs_low ( );
     538     sd_cmd ( 16, 512 );
     539     r = sd_get_r1 ( );
     540     sd_nec ( );
     541     spi_cs_high ( );
     542     if ( r == 0xff )
     543     {
     544       goto err_spi;
     545     }
     546     if ( r & 0xfe )
     547     {
     548       printf ( "fail\n" );
     549       print_r1 ( r );
     550       goto err;
     551     }
     552     printf ( "success\n" );
     553   }
     554 
     555   printf ( "cmd59 - enable crc.. " );
     556   /* crc on */
     557   spi_cs_low ( );
     558   sd_cmd ( 59, 0 );
     559   r = sd_get_r1 ( );
     560   sd_nec ( );
     561   spi_cs_high ( );
     562   if ( r == 0xff )
     563   {
     564     goto err_spi;
     565   }
     566   if ( r & 0xfe )
     567   {
     568     printf ( "fail\n" );
     569     print_r1 ( r );
     570     goto err;
     571   }
     572   printf ( "success\n" );
     573 
     574   /* now we can up the clock to <= 25 MHz */
     575   spi_set_speed ( SD_SPEED_25MHZ );
     576 
     577   return 0;
     578 
     579 err_spi:
     580   printf ( "fail spi\n" );
     581   return -1;
     582 err:
     583   return -2;
     584 }
     585 
     586 static int sd_read_status ( hwif * hw )
     587 {
     588   u16 r2;
     589 
     590   spi_cs_low ( );
     591   sd_cmd ( 13, 0 );
     592   r2 = sd_get_r2 ( );
     593   sd_nec ( );
     594   spi_cs_high ( );
     595   if ( r2 & 0x8000 )
     596   {
     597     return -1;
     598   }
     599   if ( r2 )
     600   {
     601     print_r2 ( r2 );
     602   }
     603 
     604   return 0;
     605 }
     606 
     607 /* 0xfe marks data start, then len bytes of data and crc16 */
     608 static int sd_get_data ( hwif * hw, u8 * buf, int len )
     609 {
     610   int tries = 20000;
     611   u8 r;
     612   u16 _crc16;
     613   u16 calc_crc;
     614   int i;
     615 
     616   while ( tries-- )
     617   {
     618     r = spi_txrx ( 0xff );
     619     if ( r == 0xfe )
     620     {
     621       break;
     622     }
     623   }
     624   if ( tries < 0 )
     625   {
     626     return -1;
     627   }
     628 
     629   for ( i = 0; i < len; i++ )
     630   {
     631     buf[ i ] = spi_txrx ( 0xff );
     632   }
     633 
     634   _crc16 = spi_txrx ( 0xff ) << 8;
     635   _crc16 |= spi_txrx ( 0xff );
     636 
     637   calc_crc = crc16 ( buf, len );
     638   if ( _crc16 != calc_crc )
     639   {
     640     printf ( "%s, crcs differ: %04x vs. %04x, len:%i\n", __func__, _crc16,
     641       calc_crc, len );
     642     return -1;
     643   }
     644 
     645   return 0;
     646 }
     647 
     648 static int sd_put_data ( hwif * hw, const u8 * buf, int len )
     649 {
     650   u8 r;
     651   int tries = 10;
     652   u8 b[ 16 ];
     653   int bi = 0;
     654   u16 crc;
     655 
     656   spi_txrx ( 0xfe ); /* data start */
     657 
     658   while ( len-- )
     659   {
     660     spi_txrx ( * buf++ );
     661   }
     662 
     663   crc = crc16 ( buf, len );
     664   /* crc16 */
     665   spi_txrx ( crc >> 8 );
     666   spi_txrx ( crc );
     667 
     668   /* normally just one dummy read in between... specs don't say how many */
     669   while ( tries-- )
     670   {
     671     b[ bi++ ] = r = spi_txrx ( 0xff );
     672     if ( r != 0xff )
     673     {
     674       break;
     675     }
     676   }
     677   if ( tries < 0 )
     678   {
     679     return -1;
     680   }
     681 
     682   /* poll busy, about 300 reads for 256 MB card */
     683   tries = 100000;
     684   while ( tries-- )
     685   {
     686     if ( spi_txrx( 0xff ) == 0xff )
     687     {
     688       break;
     689     }
     690   }
     691   if ( tries < 0 )
     692   {
     693     return -2;
     694   }
     695 
     696   /* data accepted, WIN */
     697   if ( ( r & 0x1f ) == 0x05 )
     698   {
     699     return 0;
     700   }
     701 
     702   return r;
     703 }
     704 
     705 static int sd_read_csd ( hwif * hw )
     706 {
     707   u8 buf[ 16 ];
     708   int r;
     709   int capacity;
     710 
     711   spi_cs_low ( );
     712   sd_cmd ( 9, 0 );
     713   r = sd_get_r1 ( );
     714   if ( r == 0xff )
     715   {
     716     spi_cs_high ( );
     717     return -1;
     718   }
     719   if ( r & 0xfe )
     720   {
     721     spi_cs_high ( );
     722     printf ( "%s ", __func__ );
     723     print_r1 ( r );
     724     return -2;
     725   }
     726 
     727   r = sd_get_data ( hw, buf, 16 );
     728   sd_nec ( );
     729   spi_cs_high ( );
     730   if ( r == -1 )
     731   {
     732     printf ( "failed to get csd\n" );
     733     return -3;
     734   }
     735 
     736   if ( ( buf[ 0 ] >> 6 ) + 1 == 1 )
     737   {
     738     /* CSD v1 */
     739     printf (
     740       "CSD: CSD v%i taac:%02x, nsac:%i, tran:%02x, classes:%02x%x, read_bl_len:%i, " "read_bl_part:%i, write_blk_misalign:%i, read_blk_misalign:%i, dsr_imp:%i, "
     741       "c_size:%i, vdd_rmin:%i, vdd_rmax:%i, vdd_wmin:%i, vdd_wmax:%i, " "c_size_mult:%i, erase_blk_en:%i, erase_s_size:%i, "
     742       "wp_grp_size:%i, wp_grp_enable:%i, r2w_factor:%i, write_bl_len:%i, write_bl_part:%i, " "filef_gpr:%i, copy:%i, perm_wr_prot:%i, tmp_wr_prot:%i, filef:%i\n"
     743       , ( buf[ 0 ] >> 6 ) + 1, buf[ 1 ], buf[ 2 ], buf[ 3 ], buf[ 4 ],
     744       buf[ 5 ] >> 4, 1 << ( buf[ 5 ] & 0xf ),
     745       /* classes, read_bl_len */ buf[ 6 ] >> 7, ( buf[ 6 ] >> 6 ) & 1,
     746       ( buf[ 6 ] >> 5 ) & 1, ( buf[ 6 ] >> 4 ) & 1,
     747       ( buf[ 6 ] & 0x3 ) << 10 | buf[ 7 ] << 2 | buf[ 8 ] >> 6,
     748       /* c_size */ ( buf[ 8 ] & 0x38 ) >> 3, buf[ 8 ] & 0x07, buf[ 9 ] >> 5,
     749       ( buf[ 9 ] >> 2 ) & 0x7,
     750       1 << ( 2 + ( ( ( buf[ 9 ] & 3 ) << 1 ) | buf[ 10 ] >> 7 ) ),
     751       /* c_size_mult */ ( buf[ 10 ] >> 6 ) & 1,
     752       ( ( buf[ 10 ] & 0x3f ) << 1 | buf[ 11 ] >> 7 ) + 1,
     753       /* erase sector size */ ( buf[ 11 ] & 0x7f ) + 1,
     754       /* write protect group size */ buf[ 12 ] >> 7,
     755       1 << ( ( buf[ 12 ] >> 2 ) & 7 ),
     756       1 << ( ( buf[ 12 ] & 3 ) << 2 | buf[ 13 ] >> 6 ),
     757       /* write_bl_len */ ( buf[ 13 ] >> 5 ) & 1, buf[ 14 ] >> 7,
     758       ( buf[ 14 ] >> 6 ) & 1, ( buf[ 14 ] >> 5 ) & 1, ( buf[ 14 ] >> 4 ) & 1,
     759       ( buf[ 14 ] >> 2 ) & 3 /* file format */ );
     760 
     761     capacity = ( ( ( buf[ 6 ] & 0x3 ) << 10 | buf[ 7 ] << 2 | buf[ 8 ] >> 6 ) +
     762       1 ) << ( 2 + ( ( ( buf[ 9 ] & 3 ) << 1 ) | buf[ 10 ] >> 7 ) ) <<
     763       ( ( buf[ 5 ] & 0xf ) - 9 );
     764     /* ^ = (c_size+1) * 2**(c_size_mult+2) * 2**(read_bl_len-9) */
     765 
     766   }
     767   else
     768   {
     769     /* CSD v2 */
     770     /* this means the card is HC */
     771     hw->capabilities |= CAP_SDHC;
     772 
     773     printf (
     774       "CSD: CSD v%i taac:%02x, nsac:%i, tran:%02x, classes:%02x%x, read_bl_len:%i, " "read_bl_part:%i, write_blk_misalign:%i, read_blk_misalign:%i, dsr_imp:%i, "
     775       "c_size:%i, erase_blk_en:%i, erase_s_size:%i, " "wp_grp_size:%i, wp_grp_enable:%i, r2w_factor:%i, write_bl_len:%i, write_bl_part:%i, "
     776       "filef_gpr:%i, copy:%i, perm_wr_prot:%i, tmp_wr_prot:%i, filef:%i\n",
     777       ( buf[ 0 ] >> 6 ) + 1, buf[ 1 ], buf[ 2 ], buf[ 3 ], buf[ 4 ],
     778       buf[ 5 ] >> 4, 1 << ( buf[ 5 ] & 0xf ),
     779       /* classes, read_bl_len */ buf[ 6 ] >> 7, ( buf[ 6 ] >> 6 ) & 1,
     780       ( buf[ 6 ] >> 5 ) & 1, ( buf[ 6 ] >> 4 ) & 1,
     781       buf[ 7 ] << 16 | buf[ 8 ] << 8 | buf[ 9 ],
     782       /* c_size */ ( buf[ 10 ] >> 6 ) & 1,
     783       ( ( buf[ 10 ] & 0x3f ) << 1 | buf[ 11 ] >> 7 ) + 1,
     784       /* erase sector size */ ( buf[ 11 ] & 0x7f ) + 1,
     785       /* write protect group size */ buf[ 12 ] >> 7,
     786       1 << ( ( buf[ 12 ] >> 2 ) & 7 ),
     787       1 << ( ( buf[ 12 ] & 3 ) << 2 | buf[ 13 ] >> 6 ),
     788       /* write_bl_len */ ( buf[ 13 ] >> 5 ) & 1, buf[ 14 ] >> 7,
     789       ( buf[ 14 ] >> 6 ) & 1, ( buf[ 14 ] >> 5 ) & 1, ( buf[ 14 ] >> 4 ) & 1,
     790       ( buf[ 14 ] >> 2 ) & 3 /* file format */ );
     791 
     792     capacity = buf[ 7 ] << 16 | buf[ 8 ] << 8 | buf[ 9 ]; /* in 512 kB */
     793     capacity *= 1024; /* in 512 B sectors */
     794 
     795   }
     796 
     797   printf ( "capacity = %i kB\n", capacity / 2 );
     798   hw->sectors = capacity;
     799 
     800   /* if erase_blk_en = 0, then only this many sectors can be erased at once
     801    * this is NOT yet tested */
     802   hw->erase_sectors = 1;
     803   if ( ( ( buf[ 10 ] >> 6 ) & 1 ) == 0 )
     804   {
     805     hw->erase_sectors = ( ( buf[ 10 ] & 0x3f ) << 1 | buf[ 11 ] >> 7 ) + 1;
     806   }
     807 
     808   return 0;
     809 }
     810 
     811 static int sd_read_cid ( hwif * hw )
     812 {
     813   u8 buf[ 16 ];
     814   int r;
     815 
     816   spi_cs_low ( );
     817   sd_cmd ( 10, 0 );
     818   r = sd_get_r1 ( );
     819   if ( r == 0xff )
     820   {
     821     spi_cs_high ( );
     822     return -1;
     823   }
     824   if ( r & 0xfe )
     825   {
     826     spi_cs_high ( );
     827     printf ( "%s ", __func__ );
     828     print_r1 ( r );
     829     return -2;
     830   }
     831 
     832   r = sd_get_data ( hw, buf, 16 );
     833   sd_nec ( );
     834   spi_cs_high ( );
     835   if ( r == -1 )
     836   {
     837     printf ( "failed to get cid\n" );
     838     return -3;
     839   }
     840 
     841   printf (
     842     "CID: mid:%x, oid:%c%c, pnm:%c%c%c%c%c, prv:%i.%i, psn:%02x%02x%02x%02x, mdt:%i/%i\n",
     843     buf[ 0 ], buf[ 1 ], buf[ 2 ], /* mid, oid */ buf[ 3 ], buf[ 4 ], buf[ 5 ],
     844     buf[ 6 ], buf[ 7 ], /* pnm */ buf[ 8 ] >> 4, buf[ 8 ] & 0xf,
     845     /* prv */ buf[ 9 ], buf[ 10 ], buf[ 11 ], buf[ 12 ],
     846     /* psn */ 2000 + ( buf[ 13 ] << 4 | buf[ 14 ] >> 4 ),
     847     1 + ( buf[ 14 ] & 0xf ) );
     848 
     849   return 0;
     850 }
     851 
     852 static int sd_readsector ( hwif * hw, u32 address, u8 * buf )
     853 {
     854   int r;
     855 
     856   spi_cs_low ( );
     857   if ( hw->capabilities & CAP_SDHC )
     858   {
     859     sd_cmd ( 17, address );
     860   } /* read single block */
     861   else
     862   {
     863     sd_cmd ( 17, address * 512 );
     864   } /* read single block */
     865 
     866   r = sd_get_r1 ( );
     867   if ( r == 0xff )
     868   {
     869     spi_cs_high ( );
     870     r = -1;
     871     goto fail;
     872   }
     873   if ( r & 0xfe )
     874   {
     875     spi_cs_high ( );
     876     printf ( "%s\n", __func__ );
     877     print_r1 ( r );
     878     r = -2;
     879     goto fail;
     880   }
     881 
     882   r = sd_get_data ( hw, buf, 512 );
     883   sd_nec ( );
     884   spi_cs_high ( );
     885   if ( r == -1 )
     886   {
     887     r = -3;
     888     goto fail;
     889   }
     890 
     891   return 0;
     892 fail:
     893   printf ( "failed to read sector %li, err:%i\n", address, r );
     894   return r;
     895 }
     896 
     897 static int sd_writesector ( hwif * hw, u32 address, const u8 * buf )
     898 {
     899   int r;
     900 
     901   spi_cs_low ( );
     902   if ( hw->capabilities & CAP_SDHC )
     903   {
     904     sd_cmd ( 24, address );
     905   } /* write block */
     906   else
     907   {
     908     sd_cmd ( 24, address * 512 );
     909   } /* write block */
     910 
     911   r = sd_get_r1 ( );
     912   if ( r == 0xff )
     913   {
     914     spi_cs_high ( );
     915     r = -1;
     916     goto fail;
     917   }
     918   if ( r & 0xfe )
     919   {
     920     spi_cs_high ( );
     921     printf ( "%s\n", __func__ );
     922     print_r1 ( r );
     923     r = -2;
     924     goto fail;
     925   }
     926 
     927   spi_txrx ( 0xff ); /* Nwr (>= 1) high bytes */
     928   r = sd_put_data ( hw, buf, 512 );
     929   sd_nec ( );
     930   spi_cs_high ( );
     931   if ( r != 0 )
     932   {
     933     printf ( "sd_put_data returned: %i\n", r );
     934     r = -3;
     935     goto fail;
     936   }
     937 
     938   /* efsl code is weird shit, 0 is error in there?
     939    * not that it's properly handled or anything,
     940    * and the return type is char, fucking efsl */
     941   return 0;
     942 fail:
     943   printf ( "failed to write sector %li, err:%i\n", address, r );
     944   return r;
     945 }
     946 
     947 /*** public API - on top of sd/spi code ***/
     948 
     949 int hwif_init ( hwif * hw )
     950 {
     951   int tries = 10;
     952 
     953   if ( hw->initialized )
     954   {
     955     return 0;
     956   }
     957 
     958   spi_init ( );
     959 
     960   while ( tries-- )
     961   {
     962     if ( sd_init( hw ) == 0 )
     963     {
     964       break;
     965     }
     966   }
     967   if ( tries == -1 )
     968   {
     969     return -1;
     970   }
     971 
     972   /* read status register */
     973   sd_read_status ( hw );
     974 
     975   sd_read_cid ( hw );
     976   if ( sd_read_csd( hw ) != 0 )
     977   {
     978     return -1;
     979   }
     980 
     981   hw->initialized = 1;
     982   return 0;
     983 }
     984 
     985 int sd_read ( hwif * hw, u32 address, u8 * buf )
     986 {
     987   int r;
     988   int tries = 10;
     989 
     990   r = sd_readsector ( hw, address, buf );
     991 
     992   while ( r < 0 && tries-- )
     993   {
     994     if ( sd_init( hw ) != 0 )
     995     {
     996       continue;
     997     }
     998 
     999     /* read status register */
    1000     sd_read_status ( hw );
    1001 
    1002     r = sd_readsector ( hw, address, buf );
    1003   }
    1004   if ( tries == -1 )
    1005   {
    1006     printf ( "%s: couldn't read sector %li\n", __func__, address );
    1007   }
    1008 
    1009   return r;
    1010 }
    1011 
    1012 int sd_write ( hwif * hw, u32 address, const u8 * buf )
    1013 {
    1014   int r;
    1015   int tries = 10;
    1016 
    1017   r = sd_writesector ( hw, address, buf );
    1018 
    1019   while ( r < 0 && tries-- )
    1020   {
    1021     if ( sd_init( hw ) != 0 )
    1022     {
    1023       continue;
    1024     }
    1025 
    1026     /* read status register */
    1027     sd_read_status ( hw );
    1028 
    1029     r = sd_writesector ( hw, address, buf );
    1030   }
    1031   if ( tries == -1 )
    1032   {
    1033     printf ( "%s: couldn't write sector %li\n", __func__, address );
    1034   }
    1035 
    1036   return r;
    1037 }
    1038 
    1039 /*** fatfs code that uses the public API ***/
    1040 
    1041 #include "diskio.h"
    1042 
    1043 hwif hw;
    1044 
    1045 DSTATUS disk_initialize ( BYTE drv )
    1046 {
    1047   if ( hwif_init( &hw ) == 0 )
    1048   {
    1049     return 0;
    1050   }
    1051 
    1052   return STA_NOINIT;
    1053 }
    1054 
    1055 DSTATUS disk_status ( BYTE drv )
    1056 {
    1057   if ( hw.initialized )
    1058   {
    1059     return 0;
    1060   }
    1061 
    1062   return STA_NOINIT;
    1063 }
    1064 
    1065 DRESULT disk_read ( BYTE drv, BYTE * buff, DWORD sector, BYTE count )
    1066 {
    1067   int i;
    1068 
    1069   for ( i = 0; i < count; i++ )
    1070   {
    1071     if ( sd_read( &hw, sector + i, buff + 512 * i ) != 0 )
    1072     {
    1073       return RES_ERROR;
    1074     }
    1075   }
    1076 
    1077   return RES_OK;
    1078 }
    1079 
    1080 #if _READONLY == 0
    1081 
    1082 DRESULT disk_write ( BYTE drv, const BYTE * buff, DWORD sector, BYTE count )
    1083 {
    1084   int i;
    1085 
    1086   for ( i = 0; i < count; i++ )
    1087   {
    1088     if ( sd_write( &hw, sector + i, buff + 512 * i ) != 0 )
    1089     {
    1090       return RES_ERROR;
    1091     }
    1092   }
    1093 
    1094   return RES_OK;
    1095 }
    1096 #endif /* _READONLY */
    1097 
    1098 DRESULT disk_ioctl ( BYTE drv, BYTE ctrl, void * buff )
    1099 {
    1100   switch ( ctrl )
    1101   {
    1102   case CTRL_SYNC:
    1103     return RES_OK;
    1104   case GET_SECTOR_SIZE:
    1105     *( WORD * )buff = 512;
    1106     return RES_OK;
    1107   case GET_SECTOR_COUNT:
    1108     *( DWORD* )buff = hw.sectors;
    1109     return RES_OK;
    1110   case GET_BLOCK_SIZE:
    1111     *( DWORD* )buff = hw.erase_sectors;
    1112     return RES_OK;
    1113   }
    1114   return RES_PARERR;
    1115 }
    1116 
    1117 /*
    1118  * FAT filestamp format:
    1119  * [31:25] - year - 1980
    1120  * [24:21] - month 1..12
    1121  * [20:16] - day 1..31
    1122  * [15:11] - hour 0..23
    1123  * [10:5]  - minute 0..59
    1124  * [4:0]   - second/2 0..29
    1125  * so... midnight 2009 is 0x3a000000
    1126  */
    1127 DWORD get_fattime ( )
    1128 {
    1129   int time = RTC_GetCounter ( );
    1130   int y, m, d;
    1131   epoch_days_to_date ( time / DAY_SECONDS, & y, & m, & d );
    1132   time %= DAY_SECONDS;
    1133   return ( y - 1980 ) << 25 | m << 21 | d << 16 | ( time / 3600 ) << 11 |
    1134     ( time / 60 % 60 ) << 5 | ( time / 2 % 30 );
    1135 }

  • 相关阅读:
    Taurus.MVC 2.2 开源发布:WebAPI 功能增强(请求跨域及Json转换)
    聊聊程序员如何学习英语单词:写了一个记单词的小程序
    ASP.NET Core 折腾笔记二:自己写个完整的Cache缓存类来支持.NET Core
    关于开启.NET在线提升教育培训的通知!
    彻查手机端浏览博客园出现广告一事!
    ASP.NET Aries 入门开发教程9:业务表单的开发
    ASP.NET Aries 入门开发教程8:树型列表及自定义右键菜单
    ASP.NET Aries 入门开发教程7:DataGrid的行操作(主键操作区)
    ASP.NET Aries 入门开发教程6:列表数据表格的格式化处理及行内编辑
    ASP.NET Aries 入门开发教程5:自定义列表页工具栏区
  • 原文地址:https://www.cnblogs.com/shangdawei/p/2616802.html
Copyright © 2011-2022 走看看