查看: 2976|回复: 0

FATFS文件系统-SD卡

[复制链接]

该用户从未签到

发表于 2017-6-9 17:13:38 | 显示全部楼层 |阅读模式
分享到:
这两天调了下SD卡,以前没用过这玩意儿,查了好多资料,现在基本理清了SD卡相关的概念和使用方法,先移植一个FATFS文件系统测试下,可以实现正常的文件读写了。

工程用了点ST32F4的外设文件,正好研究了下GD固件库和ST固件库共存的问题。大体的思路是不要让GD的头文件和ST的头文件出现在同一个c文件中,另外ST的外设编号是从1开始,GD是0开始,使用的时候要错下位。比如用GD的SPI3,要用ST的SPI4来操作。

完成fatfs读写文件主要是改写diskio.c中的硬件接口函数以及SD卡的底层操作函数。


代码清单:
sd_lpc.h
  1. /**************************************************************************//**
  2. * @file     sd.h
  3. * @brief    Header file for sd.c
  4. * @version  1.0
  5. * @date     18. Nov. 2010
  6. *
  7. * @note
  8. * Copyright (C) 2010 NXP Semiconductors(NXP), ChaN.
  9. * All rights reserved.
  10. *
  11. ******************************************************************************/

  12. #ifndef __SD_LPC_H
  13. #define __SD_LPC_H

  14. #include "stdint.h"         

  15. /* type defintion */
  16. typedef unsigned char    SD_BOOL;
  17. #define SD_TRUE     1
  18. #define SD_FALSE    0

  19. #ifndef NULL
  20. #ifdef __cplusplus              // EC++
  21.   #define NULL          0
  22. #else
  23.   #define NULL          ((void *) 0)
  24. #endif
  25. #endif

  26. /* Memory card type definitions */
  27. #define CARDTYPE_UNKNOWN        0
  28. #define CARDTYPE_MMC            1   /* MMC */
  29. #define CARDTYPE_SDV1           2   /* V1.x Standard Capacity SD card */
  30. #define CARDTYPE_SDV2_SC        3   /* V2.0 or later Standard Capacity SD card */
  31. #define CARDTYPE_SDV2_HC        4   /* V2.0 or later High/eXtended Capacity SD card */

  32. /* SD/MMC card configuration */
  33. typedef struct tagCARDCONFIG
  34. {
  35.     uint32_t sectorsize;    /* size (in byte) of each sector, fixed to 512bytes */
  36.     uint32_t sectorcnt;     /* total sector number */  
  37.     uint32_t blocksize;     /* erase block size in unit of sector */     
  38.         uint8_t  ocr[4];                /* OCR */
  39.         uint8_t  cid[16];                /* CID */
  40.         uint8_t  csd[16];                /* CSD */
  41.     uint8_t  status[64];    /* Status */
  42. } CARDCONFIG;

  43. /* Public variables */
  44. extern uint8_t CardType;
  45. extern CARDCONFIG CardConfig;


  46. /* Public functions */
  47. SD_BOOL     FS_SD_Init(void);
  48. SD_BOOL     SD_ReadSector (uint32_t sect, uint8_t *buf, uint32_t cnt);
  49. SD_BOOL     SD_WriteSector (uint32_t sect, const uint8_t *buf, uint32_t cnt);
  50. SD_BOOL     SD_ReadConfiguration (void);
  51. uint8_t     SD_SendCommand (uint8_t cmd, uint32_t arg, uint8_t *buf, uint32_t len);
  52. uint8_t     SD_SendACommand (uint8_t cmd, uint32_t arg, uint8_t *buf, uint32_t len);
  53. SD_BOOL     SD_RecvDataBlock (uint8_t *buf, uint32_t len);
  54. SD_BOOL     SD_SendDataBlock (const uint8_t *buf, uint8_t tkn, uint32_t len) ;
  55. SD_BOOL     SD_WaitForReady (void);

  56. #endif // __SD_LPC_H

  57. /* --------------------------------- End Of File ------------------------------ */
复制代码
sd_lpc.c
  1. /**************************************************************************//**
  2. * @file     sd.c
  3. * @brief    Drivers for SD/MMC/SDHC
  4. * @version  1.0
  5. * @date     18. Nov. 2010
  6. *
  7. * @note
  8. *   Card initilization flow and some code snippets are inspired from ChaN.
  9. *
  10. ******************************************************************************/

  11. #include "stm32f4xx_conf.h"
  12. #include "sd_lpc.h"
  13. #include "diskio.h"

  14. #define SD_SPI               SPI4
  15.      
  16. /* Command definitions in SPI bus mode */
  17. #define GO_IDLE_STATE           0
  18. #define SEND_OP_COND            1
  19. #define SWITCH_FUNC             6
  20. #define SEND_IF_COND            8
  21. #define SEND_CSD                9
  22. #define SEND_CID                10
  23. #define STOP_TRANSMISSION       12
  24. #define SEND_STATUS             13
  25. #define SET_BLOCKLEN            16
  26. #define READ_SINGLE_BLOCK       17
  27. #define READ_MULTIPLE_BLOCK     18
  28. #define WRITE_SINGLE_BLOCK      24
  29. #define WRITE_MULTIPLE_BLOCK    25
  30. #define APP_CMD                 55
  31. #define READ_OCR                58
  32. #define CRC_ON_OFF              59

  33. /* Application specific commands supported by SD.
  34. All these commands shall be preceded with APP_CMD (CMD55). */
  35. #define SD_STATUS               13
  36. #define SD_SEND_OP_COND         41

  37. /* R1 response bit flag definition */
  38. #define R1_NO_ERROR         0x00
  39. #define R1_IN_IDLE_STATE    0x01
  40. #define R1_ERASE_RESET      0x02
  41. #define R1_ILLEGAL_CMD      0x04
  42. #define R1_COM_CRC_ERROR    0x08
  43. #define R1_ERASE_SEQ_ERROR  0x10
  44. #define R1_ADDRESS_ERROR    0x20
  45. #define R1_PARA_ERROR       0x40
  46. #define R1_MASK             0x7F

  47. /* The sector size is fixed to 512bytes in most applications. */
  48. #define SECTOR_SIZE 512

  49. /* Global variables */
  50. uint8_t CardType;          /* card type */
  51. CARDCONFIG CardConfig;      /* Card configuration */

  52. /* Local variables */
  53. static volatile WORD Timer1, Timer2;        /* 100Hz decrement timer stopped at zero (disk_timerproc()) */
  54. static volatile DSTATUS Stat = STA_NOINIT;        /* Disk status */

  55. #define SPI_CS_High()         GPIO_SetBits(GPIOD,GPIO_Pin_1)
  56. #define SPI_CS_Low()          GPIO_ResetBits(GPIOD,GPIO_Pin_1)

  57. #define SPI_CLOCKRATE_HIGH      8000000
  58. #define SPI_CLOCKRATE_LOW       400000
  59. #define SPI_ConfigClockRate (SPI_CLOCKRATE_HIGH)

  60. extern uint8_t dgSpiRw(uint8_t dataW);
  61. #define SPI_RecvByte() dgSpiRw(0xFF)
  62. #define SPI_SendByte(x) dgSpiRw(x)

  63. /** Select the card */
  64. #define SD_Select()  do {SPI_CS_Low();} while (0)
  65. /** DeSelect the card */
  66. #define SD_DeSelect() do { SPI_CS_High ();SPI_RecvByte();} while (0)


  67. /*-----------------------------------------------------------------------*/
  68. /* Initialize Disk Drive                                                  */
  69. /*-----------------------------------------------------------------------*/
  70. DSTATUS disk_initialize (
  71.         BYTE drv                /* Physical drive number (0) */
  72. )
  73. {
  74.         if (drv) return STA_NOINIT;                        /* Supports only single drive */
  75.         if (Stat & STA_NODISK) return Stat;        /* No card in the socket */

  76.         if (FS_SD_Init() && SD_ReadConfiguration())
  77.                 Stat &= ~STA_NOINIT;

  78.         return Stat;
  79. }

  80. /*-----------------------------------------------------------------------*/
  81. /* Miscellaneous Functions                                               */
  82. /*-----------------------------------------------------------------------*/
  83. DRESULT disk_ioctl (
  84.         BYTE drv,                /* Physical drive number (0) */
  85.         BYTE ctrl,                /* Control code */
  86.         void *buff                /* Buffer to send/receive control data */
  87. )
  88. {
  89.         DRESULT res;
  90.         BYTE n, *ptr = buff;

  91.         if (drv) return RES_PARERR;
  92.         if (Stat & STA_NOINIT) return RES_NOTRDY;

  93.         res = RES_ERROR;

  94.         switch (ctrl) {
  95.         case CTRL_SYNC :                /* Make sure that no pending write process */
  96.         SD_Select();
  97.                 if (SD_WaitForReady() == SD_TRUE)
  98.                         res = RES_OK;
  99.                 break;

  100.         case GET_SECTOR_COUNT :        /* Get number of sectors on the disk (DWORD) */
  101.                 *(DWORD*)buff = CardConfig.sectorcnt;
  102.                 res = RES_OK;
  103.                 break;

  104.         case GET_SECTOR_SIZE :        /* Get R/W sector size (WORD) */
  105.                 *(WORD*)buff = CardConfig.sectorsize;        //512;
  106.                 res = RES_OK;
  107.                 break;

  108.         case GET_BLOCK_SIZE :        /* Get erase block size in unit of sector (DWORD) */
  109.                 *(DWORD*)buff = CardConfig.blocksize;
  110.                 res = RES_OK;
  111.                 break;

  112.         case MMC_GET_TYPE :                /* Get card type flags (1 byte) */
  113.                 *ptr = CardType;
  114.                 res = RES_OK;
  115.                 break;

  116.         case MMC_GET_CSD :                /* Receive CSD as a data block (16 bytes) */
  117.                 for (n=0;n<16;n++)
  118.                         *(ptr+n) = CardConfig.csd[n];
  119.                 res = RES_OK;
  120.                 break;

  121.         case MMC_GET_CID :                /* Receive CID as a data block (16 bytes) */
  122.                 for (n=0;n<16;n++)
  123.                         *(ptr+n) = CardConfig.cid[n];
  124.                 res = RES_OK;
  125.                 break;

  126.         case MMC_GET_OCR :                /* Receive OCR as an R3 resp (4 bytes) */
  127.                 for (n=0;n<4;n++)
  128.                         *(ptr+n) = CardConfig.ocr[n];
  129.                 res = RES_OK;
  130.                 break;

  131.         case MMC_GET_SDSTAT :        /* Receive SD status as a data block (64 bytes) */
  132.                 for (n=0;n<64;n++)
  133.             *(ptr+n) = CardConfig.status[n];
  134.         res = RES_OK;   
  135.                 break;

  136.         default:
  137.                 res = RES_PARERR;
  138.         }

  139.     SD_DeSelect();

  140.         return res;
  141. }

  142. /*-----------------------------------------------------------------------*/
  143. /* Read Sector(s)                                                        */
  144. /*-----------------------------------------------------------------------*/
  145. DRESULT disk_read (
  146.         BYTE drv,                        /* Physical drive number (0) */
  147.         BYTE *buff,                        /* Pointer to the data buffer to store read data */
  148.         DWORD sector,                /* Start sector number (LBA) */
  149.         UINT count                        /* Sector count (1..255) */
  150. )
  151. {
  152.         if (drv || !count) return RES_PARERR;
  153.         if (Stat & STA_NOINIT) return RES_NOTRDY;

  154.         if (SD_ReadSector (sector, buff, count) == SD_TRUE)       
  155.                 return RES_OK;
  156.         else
  157.                 return RES_ERROR;
  158. }

  159. /*-----------------------------------------------------------------------*/
  160. /* Get Disk Status                                                       */
  161. /*-----------------------------------------------------------------------*/
  162. DSTATUS disk_status (
  163.         BYTE drv                /* Physical drive number (0) */
  164. )
  165. {
  166.         if (drv) return STA_NOINIT;                /* Supports only single drive */

  167.         return Stat;
  168. }

  169. /*-----------------------------------------------------------------------*/
  170. /* Write Sector(s)                                                       */
  171. /*-----------------------------------------------------------------------*/
  172. #if _READONLY == 0
  173. DRESULT disk_write (
  174.         BYTE drv,                        /* Physical drive number (0) */
  175.         const BYTE *buff,        /* Pointer to the data to be written */
  176.         DWORD sector,                /* Start sector number (LBA) */
  177.         UINT count                        /* Sector count (1..255) */
  178. )
  179. {
  180.         if (drv || !count) return RES_PARERR;
  181.         if (Stat & STA_NOINIT) return RES_NOTRDY;
  182. //        if (Stat & STA_PROTECT) return RES_WRPRT;

  183.         if ( SD_WriteSector(sector, buff, count) == SD_TRUE)
  184.                 return RES_OK;
  185.         else
  186.                 return         RES_ERROR;

  187. }
  188. #endif /* _READONLY == 0 */


  189. /*-----------------------------------------------------------------------*/
  190. /* Device timer function  (Platform dependent)                           */
  191. /*-----------------------------------------------------------------------*/
  192. /* This function must be called from timer interrupt routine in period
  193. /  of 10 ms to generate card control timing.
  194. */
  195. void disk_timerproc (void)
  196. {
  197.     static uint8_t Cnt;
  198.     WORD n;
  199.    
  200.     Cnt++;
  201.     if(Cnt < 10)
  202.         return;
  203.     Cnt=0;
  204.    
  205.         n = Timer1;                                                /* 100Hz decrement timer stopped at 0 */
  206.         if (n) Timer1 = --n;
  207.         n = Timer2;
  208.         if (n) Timer2 = --n;               
  209. }


  210. /**
  211.   * @brief  Initializes the memory card.
  212.   *
  213.   * @param  None
  214.   * @retval SD_TRUE: Init OK.
  215.   *         SD_FALSE: Init failed.
  216.   *
  217.   * Note: Refer to the init flow at http://elm-chan.org/docs/mmc/sdinit.png
  218.   */
  219. SD_BOOL FS_SD_Init (void)
  220. {
  221.     uint32_t i;
  222.     uint8_t  r1, buf[4];
  223.     SPI_InitTypeDef   SPI_InitStructure;

  224.     /* Set card type to unknown */
  225.     CardType = CARDTYPE_UNKNOWN;

  226.     /* Init SPI interface */
  227.       

  228.       /*!< SD_SPI Periph clock enable */
  229.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI4, ENABLE);
  230.         RCC_AHB2PeriphResetCmd(RCC_APB2Periph_SPI4, ENABLE);
  231.         RCC_AHB2PeriphResetCmd(RCC_APB2Periph_SPI4, DISABLE);
  232.         
  233.       /*!< SD_SPI Config */
  234.       SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  235.       SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  236.       SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  237.       SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  238.       SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  239.       SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  240.       SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;

  241.       SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  242.       SPI_InitStructure.SPI_CRCPolynomial = 7;
  243.       SPI_Init(SD_SPI, &SPI_InitStructure);
  244.       
  245.       SPI_Cmd(SD_SPI, ENABLE); /*!< SD_SPI enable */

  246.     /* Before reset, Send at least 74 clocks at low frequency
  247.     (between 100kHz and 400kHz) with CS high and DI (MISO) high. */
  248.     SD_DeSelect();
  249.     //SPI_ConfigClockRate (SPI_CLOCKRATE_LOW);
  250.     for (i = 0; i < 10; i++)    SPI_SendByte (0xFF);

  251.     /* Send CMD0 with CS low to enter SPI mode and reset the card.
  252.     The card will enter SPI mode if CS is low during the reception of CMD0.
  253.     Since the CMD0 (and CMD8) must be sent as a native command, the CRC field
  254.     must have a valid value. */
  255.     if (SD_SendCommand (GO_IDLE_STATE, 0, NULL, 0) != R1_IN_IDLE_STATE) // CMD0
  256.     {
  257.         goto  init_end;
  258.     }

  259.     /* Now the card enters IDLE state. */

  260.     /* Card type identification Start ... */

  261.     /* Check the card type, needs around 1000ms */   
  262.     r1 = SD_SendCommand (SEND_IF_COND, 0x1AA, buf, 4);  // CMD8
  263.     if (r1 & 0x80) goto init_end;

  264.     Timer1 = 100; // 1000ms
  265.     if (r1 == R1_IN_IDLE_STATE) { /* It's V2.0 or later SD card */
  266.         if (buf[2]!= 0x01 || buf[3]!=0xAA) goto init_end;

  267.         /* The card is SD V2 and can work at voltage range of 2.7 to 3.6V */

  268.         do {
  269.             r1 = SD_SendACommand (SD_SEND_OP_COND, 0x40000000, NULL, 0);  // ACMD41
  270.             if      (r1 == 0x00) break;
  271.             else if (r1 > 0x01)  goto init_end;            
  272.         } while (Timer1);

  273.         if (Timer1 && SD_SendCommand (READ_OCR, 0, buf, 4)==R1_NO_ERROR)  // CMD58
  274.             CardType = (buf[0] & 0x40) ? CARDTYPE_SDV2_HC : CARDTYPE_SDV2_SC;
  275.          
  276.     } else { /* It's Ver1.x SD card or MMC card */

  277.         /* Check if it is SD card */
  278.         if (SD_SendCommand (APP_CMD, 0, NULL, 0) & R1_ILLEGAL_CMD)
  279.         {   
  280.             CardType = CARDTYPE_MMC;
  281.             while (Timer1 && SD_SendCommand (SEND_OP_COND, 0, NULL, 0));
  282.         }  
  283.         else
  284.         {   
  285.             CardType = CARDTYPE_SDV1;
  286.             while (Timer1 && SD_SendACommand (SD_SEND_OP_COND, 0, NULL, 0));
  287.         }

  288.         if (Timer1 == 0) CardType = CARDTYPE_UNKNOWN;
  289.     }

  290.     /* For SDHC or SDXC, block length is fixed to 512 bytes, for others,
  291.     the block length is set to 512 manually. */
  292.     if (CardType == CARDTYPE_MMC ||
  293.         CardType == CARDTYPE_SDV1 ||
  294.         CardType == CARDTYPE_SDV2_SC )
  295.     {
  296.         if (SD_SendCommand (SET_BLOCKLEN, SECTOR_SIZE, NULL, 0) != R1_NO_ERROR)
  297.             CardType = CARDTYPE_UNKNOWN;
  298.     }

  299. init_end:              
  300.    SD_DeSelect();

  301.     if (CardType == CARDTYPE_UNKNOWN)
  302.     {
  303.         return (SD_FALSE);
  304.     }
  305.     else     /* Init OK. use high speed during data transaction stage. */
  306.     {
  307.         //SPI_ConfigClockRate (SPI_CLOCKRATE_HIGH);
  308.         return (SD_TRUE);
  309.     }
  310. }


  311. /**
  312.   * @brief  Wait for the card is ready.
  313.   *
  314.   * @param  None
  315.   * @retval SD_TRUE: Card is ready for read commands.
  316.   *         SD_FALSE: Card is not ready
  317.   */
  318. SD_BOOL SD_WaitForReady (void)
  319. {
  320.     Timer2 = 50;    // 500ms
  321.     SPI_RecvByte(); /* Read a byte (Force enable DO output) */
  322.     do {
  323.         if (SPI_RecvByte () == 0xFF) return SD_TRUE;
  324.     } while (Timer2);

  325.     return SD_FALSE;   
  326. }

  327. /**
  328.   * @brief  Send a command and receive a response with specified format.
  329.   *
  330.   * @param  cmd: Specifies the command index.
  331.   * @param  arg: Specifies the argument.
  332.   * @param  buf: Pointer to byte array to store the response content.
  333.   * @param  len: Specifies the byte number to be received after R1 response.
  334.   * @retval Value below 0x80 is the normal R1 response (0x0 means no error)
  335.   *         Value above 0x80 is the additional returned status code.
  336.   *             0x81: Card is not ready
  337.   *             0x82: command response time out error
  338.   */
  339. uint8_t SD_SendCommand (uint8_t cmd, uint32_t arg, uint8_t *buf, uint32_t len)
  340. {
  341.     uint32_t r1,i;
  342.     uint8_t crc_stop;

  343.     /* The CS signal must be kept low during a transaction */
  344.     SD_Select();

  345.     /* Wait until the card is ready to read (DI signal is High) */
  346.     if (SD_WaitForReady() == SD_FALSE) return 0x81;

  347.     /* Prepare CRC7 + stop bit. For cmd GO_IDLE_STATE and SEND_IF_COND,
  348.     the CRC7 should be valid, otherwise, the CRC7 will be ignored. */
  349.     if      (cmd == GO_IDLE_STATE)  crc_stop = 0x95; /* valid CRC7 + stop bit */
  350.     else if (cmd == SEND_IF_COND)   crc_stop = 0x87; /* valid CRC7 + stop bit */
  351.     else                            crc_stop = 0x01; /* dummy CRC7 + Stop bit */

  352.     /* Send 6-byte command with CRC. */
  353.     SPI_SendByte (cmd | 0x40);
  354.     SPI_SendByte (arg >> 24);
  355.     SPI_SendByte (arg >> 16);
  356.     SPI_SendByte (arg >> 8);
  357.     SPI_SendByte (arg);
  358.     SPI_SendByte (crc_stop); /* Valid or dummy CRC plus stop bit */

  359.    
  360.     /* The command response time (Ncr) is 0 to 8 bytes for SDC,
  361.     1 to 8 bytes for MMC. */
  362.     for (i = 8; i; i--)
  363.     {
  364.         r1 = SPI_RecvByte ();
  365.         if (r1 != 0xFF) break;   /* received valid response */      
  366.     }
  367.     if (i == 0)  return (0x82); /* command response time out error */

  368.     /* Read remaining bytes after R1 response */
  369.     if (buf && len)
  370.     {
  371.         do {   
  372.             *buf++ = SPI_RecvByte ();
  373.         } while (--len);
  374.     }

  375.     return (r1);
  376. }

  377. /**
  378.   * @brief  Send an application specific command for SD card
  379.   *         and receive a response with specified format.
  380.   *
  381.   * @param  cmd: Specifies the command index.
  382.   * @param  arg: Specifies the argument.
  383.   * @param  buf: Pointer to byte array to store the response content.
  384.   * @param  len: Specifies the byte number to be received after R1 response.
  385.   * @retval Value below 0x80 is the normal R1 response(0x0 means no error)
  386.   *         Value above 0x80 is the additional returned status code.
  387.   *             0x81: Card is not ready
  388.   *             0x82: command response time out error
  389.   *
  390.   * Note: All the application specific commands should be precdeded with APP_CMD
  391.   */
  392. uint8_t SD_SendACommand (uint8_t cmd, uint32_t arg, uint8_t *buf, uint32_t len)
  393. {
  394.     uint8_t r1;

  395.     /* Send APP_CMD (CMD55) first */
  396.         r1 = SD_SendCommand(APP_CMD, 0, NULL, 0);
  397.         if (r1 > 1) return r1;   
  398.    
  399.     return (SD_SendCommand (cmd, arg, buf, len));
  400. }

  401. /**
  402.   * @brief  Read single or multiple sector(s) from memory card.
  403.   *
  404.   * @param  sect: Specifies the starting sector index to read
  405.   * @param  buf:  Pointer to byte array to store the data
  406.   * @param  cnt:  Specifies the count of sectors to read
  407.   * @retval SD_TRUE or SD_FALSE.
  408.   */
  409. SD_BOOL SD_ReadSector (uint32_t sect, uint8_t *buf, uint32_t cnt)
  410. {
  411.     SD_BOOL flag;

  412.     /* Convert sector-based address to byte-based address for non SDHC */
  413.     if (CardType != CARDTYPE_SDV2_HC) sect <<= 9;

  414.     flag = SD_FALSE;

  415.     if (cnt > 1) /* Read multiple block */
  416.     {
  417.                 if (SD_SendCommand(READ_MULTIPLE_BLOCK, sect, NULL, 0) == R1_NO_ERROR)
  418.         {            
  419.                         do {
  420.                                 if (SD_RecvDataBlock(buf, SECTOR_SIZE) == SD_FALSE) break;
  421.                                 buf += SECTOR_SIZE;
  422.                         } while (--cnt);

  423.                         /* Stop transmission */
  424.             SD_SendCommand(STOP_TRANSMISSION, 0, NULL, 0);                               

  425.             /* Wait for the card is ready */
  426.             if (SD_WaitForReady() && cnt==0) flag = SD_TRUE;
  427.         }
  428.     }
  429.     else   /* Read single block */
  430.     {        
  431.         if ((SD_SendCommand(READ_SINGLE_BLOCK, sect, NULL, 0)==R1_NO_ERROR) &&
  432.             SD_RecvDataBlock(buf, SECTOR_SIZE)==SD_TRUE)   
  433.             flag = SD_TRUE;        
  434.     }

  435.     /* De-select the card */
  436.     SD_DeSelect();

  437.     return (flag);
  438. }

  439. /**
  440.   * @brief  Write single or multiple sectors to SD/MMC.
  441.   *
  442.   * @param  sect: Specifies the starting sector index to write
  443.   * @param  buf: Pointer to the data array to be written
  444.   * @param  cnt: Specifies the number sectors to be written
  445.   * @retval SD_TRUE or SD_FALSE
  446.   */
  447. SD_BOOL SD_WriteSector (uint32_t sect, const uint8_t *buf, uint32_t cnt)
  448. {
  449.     SD_BOOL flag;

  450.     /* Convert sector-based address to byte-based address for non SDHC */
  451.     if (CardType != CARDTYPE_SDV2_HC) sect <<= 9;

  452.     flag = SD_FALSE;
  453.     if (cnt > 1)  /* write multiple block */
  454.     {
  455.         if (SD_SendCommand (WRITE_MULTIPLE_BLOCK, sect, NULL, 0) == R1_NO_ERROR)
  456.         {
  457.             do {
  458.                 if (SD_SendDataBlock (buf, 0xFC, SECTOR_SIZE) == SD_FALSE)  break;
  459.                 buf += SECTOR_SIZE;
  460.             } while (--cnt);

  461.             /* Send Stop Transmission Token. */
  462.             SPI_SendByte (0xFD);
  463.         
  464.             /* Wait for complete */
  465.             if (SD_WaitForReady() && cnt==0) flag = SD_TRUE;
  466.         }
  467.     }
  468.     else  /* write single block */
  469.     {
  470.    
  471.         if ( (SD_SendCommand (WRITE_SINGLE_BLOCK, sect, NULL, 0) == R1_NO_ERROR) &&
  472.             (SD_SendDataBlock (buf, 0xFE, SECTOR_SIZE) == SD_TRUE))
  473.             flag = SD_TRUE;
  474.     }

  475.     /* De-select the card */
  476.     SD_DeSelect();

  477.     return (flag);
  478. }

  479. /**
  480.   * @brief  Read card configuration and fill structure CardConfig.
  481.   *
  482.   * @param  None
  483.   * @retval SD_TRUE or SD_FALSE.
  484.   */
  485. SD_BOOL SD_ReadConfiguration ()
  486. {
  487.     uint8_t buf[16];
  488.     uint32_t i, c_size, c_size_mult, read_bl_len;
  489.     SD_BOOL retv;
  490.   
  491.     retv = SD_FALSE;

  492.     /* Read OCR */
  493.     if (SD_SendCommand(READ_OCR, 0, CardConfig.ocr, 4) != R1_NO_ERROR) goto end;

  494.     /* Read CID */
  495.     if ((SD_SendCommand(SEND_CID, 0, NULL, 0) != R1_NO_ERROR) ||
  496.         SD_RecvDataBlock (CardConfig.cid, 16)==SD_FALSE) goto end;

  497.     /* Read CSD */
  498.     if ((SD_SendCommand(SEND_CSD, 0, NULL, 0) != R1_NO_ERROR) ||
  499.         SD_RecvDataBlock (CardConfig.csd, 16)==SD_FALSE) goto end;

  500.     /* sector size */
  501.     CardConfig.sectorsize = 512;
  502.    
  503.     /* sector count */
  504.     if (((CardConfig.csd[0]>>6) & 0x3) == 0x1) /* CSD V2.0 (for High/eXtended Capacity) */
  505.     {
  506.         /* Read C_SIZE */
  507.         c_size =  (((uint32_t)CardConfig.csd[7]<<16) + ((uint32_t)CardConfig.csd[8]<<8) + CardConfig.csd[9]) & 0x3FFFFF;
  508.         /* Calculate sector count */
  509.        CardConfig.sectorcnt = (c_size + 1) * 1024;

  510.     } else   /* CSD V1.0 (for Standard Capacity) */
  511.     {
  512.         /* C_SIZE */
  513.         c_size = (((uint32_t)(CardConfig.csd[6]&0x3)<<10) + ((uint32_t)CardConfig.csd[7]<<2) + (CardConfig.csd[8]>>6)) & 0xFFF;
  514.         /* C_SIZE_MUTE */
  515.         c_size_mult = ((CardConfig.csd[9]&0x3)<<1) + ((CardConfig.csd[10]&0x80)>>7);
  516.         /* READ_BL_LEN */
  517.         read_bl_len = CardConfig.csd[5] & 0xF;
  518.         /* sector count = BLOCKNR*BLOCK_LEN/512, we manually set SECTOR_SIZE to 512*/
  519.         //CardConfig.sectorcnt = (c_size+1)*(1<<read_bl_len) * (1<<(c_size_mult+2)) / 512;
  520.         CardConfig.sectorcnt = (c_size+1) << (read_bl_len + c_size_mult - 7);        
  521.     }

  522.     /* Get erase block size in unit of sector */
  523.     switch (CardType)
  524.     {
  525.         case CARDTYPE_SDV2_SC:
  526.         case CARDTYPE_SDV2_HC:
  527.             if ((SD_SendACommand (SD_STATUS, 0, buf, 1) !=  R1_NO_ERROR) ||
  528.                 SD_RecvDataBlock(buf, 16) == SD_FALSE) goto end;      /* Read partial block */   
  529.             for (i=64-16;i;i--) SPI_RecvByte();  /* Purge trailing data */            
  530.             CardConfig.blocksize = 16UL << (buf[10] >> 4); /* Calculate block size based on AU size */
  531.             break;
  532.         case CARDTYPE_MMC:
  533.             //CardConfig.blocksize = ((uint16_t)((CardConfig.csd[10] & 124) >> 2) + 1) * (((CardConfig.csd[11] & 3) << 3) + ((CardConfig.csd[11] & 224) >> 5) + 1);
  534.             CardConfig.blocksize = ((uint16_t)((CardConfig.csd[10] & 124) >> 2) + 1) * (((CardConfig.csd[10] & 3) << 3) + ((CardConfig.csd[11] & 224) >> 5) + 1);
  535.             break;
  536.         case CARDTYPE_SDV1:
  537.             CardConfig.blocksize = (((CardConfig.csd[10] & 63) << 1) + ((uint16_t)(CardConfig.csd[11] & 128) >> 7) + 1) << ((CardConfig.csd[13] >> 6) - 1);
  538.             break;
  539.         default:
  540.             goto end;               
  541.     }

  542.     retv = SD_TRUE;
  543. end:
  544.     SD_DeSelect ();

  545.     return retv;
  546. }

  547. /**
  548.   * @brief  Receive a data block with specified length from SD/MMC.
  549.   *
  550.   * @param  buf: Pointer to the data array to store the received data
  551.   * @param  len: Specifies the length (in byte) to be received.
  552.   *              The value should be a multiple of 4.
  553.   * @retval SD_TRUE or SD_FALSE
  554.   */
  555. SD_BOOL SD_RecvDataBlock (uint8_t *buf, uint32_t len)
  556. {
  557.     uint8_t datatoken;
  558.     uint32_t i;

  559.     /* Read data token (0xFE) */
  560.         Timer1 = 10;   /* Data Read Timerout: 100ms */
  561.         do {                                                       
  562.                 datatoken = SPI_RecvByte ();
  563.         if (datatoken == 0xFE) break;
  564.         } while (Timer1);
  565.         if(datatoken != 0xFE) return (SD_FALSE);        /* data read timeout */

  566.     /* Read data block */
  567. #ifdef USE_FIFO
  568.     SPI_RecvBlock_FIFO (buf, len);
  569. #else
  570.     for (i = 0; i < len; i++) {
  571.         buf[i] = SPI_RecvByte ();
  572.     }
  573. #endif

  574.     /* 2 bytes CRC will be discarded. */
  575.     SPI_RecvByte ();
  576.     SPI_RecvByte ();

  577.     return (SD_TRUE);
  578. }

  579. /**
  580.   * @brief  Send a data block with specified length to SD/MMC.
  581.   *
  582.   * @param  buf: Pointer to the data array to store the received data
  583.   * @param  tkn: Specifies the token to send before the data block
  584.   * @param  len: Specifies the length (in byte) to send.
  585.   *              The value should be 512 for memory card.
  586.   * @retval SD_TRUE or SD_FALSE
  587.   */
  588. SD_BOOL SD_SendDataBlock (const uint8_t *buf, uint8_t tkn, uint32_t len)
  589. {
  590.     uint8_t recv;
  591.     uint32_t i;
  592.    
  593.     /* Send Start Block Token */
  594.     SPI_SendByte (tkn);

  595.     /* Send data block */
  596. #ifdef USE_FIFO
  597.     SPI_SendBlock_FIFO (buf, len);
  598. #else
  599.     for (i = 0; i < len; i++)
  600.     {
  601.       SPI_SendByte (buf[i]);
  602.     }
  603. #endif

  604.     /* Send 2 bytes dummy CRC */
  605.     SPI_SendByte (0xFF);
  606.     SPI_SendByte (0xFF);

  607.     /* Read data response to check if the data block has been accepted. */
  608.     if (( (SPI_RecvByte ()) & 0x0F) != 0x05)
  609.         return (SD_FALSE); /* write error */

  610.     /* Wait for wirte complete. */
  611.     Timer1 = 20;  // 200ms
  612.     do {
  613.         recv = SPI_RecvByte();
  614.         if (recv == 0xFF) break;  
  615.     } while (Timer1);

  616.     if (recv == 0xFF) return SD_TRUE;       /* write complete */
  617.     else              return (SD_FALSE);    /* write time out */

  618. }

  619. /* --------------------------------- End Of File ------------------------------ */
复制代码
演示程序:
IDE : IAR ARM8.11
操作系统 : freeRTOS
文件系统 : FATFS0.12

freertos-bbs-fatfs.rar (5 MB, 下载次数: 37)
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条



手机版|小黑屋|与非网

GMT+8, 2024-5-20 10:26 , Processed in 0.120629 second(s), 16 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.