⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs_mmc.c

📁 keil arm flash fs 最新版 在Keil arm下使用
💻 C
字号:
/*----------------------------------------------------------------------------
 *      R T L  -  F l a s h   F i l e   S y s t e m
 *----------------------------------------------------------------------------
 *      Name:    FS_MMC.C 
 *      Purpose: MultiMedia and SD Flash Card Interface
 *      Rev.:    V3.22
 *----------------------------------------------------------------------------
 *      This code is part of the RealView Run-Time Library.
 *      Copyright (c) 2004-2008 KEIL - An ARM Company. All rights reserved.
 *---------------------------------------------------------------------------*/

#include "File_Config.h"

/* SD/MMC Commands */
#define GO_IDLE_STATE    (0x40 + 0)
#define SEND_OP_COND     (0x40 + 1)
#define SEND_CSD         (0x40 + 9)
#define SEND_CID         (0x40 + 10)
#define STOP_TRAN        (0x40 + 12)
#define SET_BLOCKLEN     (0x40 + 16)
#define READ_BLOCK       (0x40 + 17)
#define READ_MULT_BLOCK  (0x40 + 18)
#define WRITE_BLOCK      (0x40 + 24)
#define WRITE_MULT_BLOCK (0x40 + 25)
#define APP_CMD          (0x40 + 55)
#define CRC_ON_OFF       (0x40 + 59)
#define SD_SEND_OP_COND  (0x40 + 41)

/* Wait timeouts, in multiples of 1 byte send over SPI */
#define WR_TOUT           400000        /* ~ 200 ms with SPI clk 20MHz */
#define STOP_TOUT         100000        /* ~  50 ms with SPI clk 20MHz */
#define CMD_TOUT          1000          /* ~ 0.5 ms with SPI clk 20MHz */

/* Local variables */
static U8 CardType;

/*----------------------------------------------------------------------------
 *      MMC Driver Functions
 *----------------------------------------------------------------------------
 *  Required functions for MMC driver module:
 *   - BOOL mmc_init        ()
 *   - BOOL mmc_read_sect   (U32 sect, U8 *buf, U32 cnt)
 *   - BOOL mmc_write_sect  (U32 sect, U8 *buf, U32 cnt)
 *   - BOOL mmc_read_config (MMCFG *cfg)
 *---------------------------------------------------------------------------*/


/* Local Function Prototypes */
static U8   mmc_command     (U8 cmd, U32 arg);
static BOOL mmc_read_bytes  (U8 cmd, U32 arg, U8 *buf, U32 len);
static BOOL mmc_read_block  (U8 cmd, U32 arg, U8 *buf, U32 cnt);
static BOOL mmc_write_block (U8 cmd, U32 arg, U8 *buf, U32 cnt);

/*--------------------------- mmc_init --------------------------------------*/

BOOL mmc_init (void) {
   /* Initialize and enable the Flash Card. */
   U32 i,r1;

   /* Initialize SPI interface and enable Flash Card SPI mode. */
   spi_init ();

   spi_ss (1);
   spi_hi_speed (__FALSE);

   /* Send SPI Command with card not selected at 400 KBit. */
   for (i = 0; i < 16; i++) {
      spi_send (0xFF);
   }

   /* Reset the card, send CMD0. */
   spi_ss (0);
   r1 = mmc_command (GO_IDLE_STATE, 0);
   for (i = 0; i < 100; i++) {
      if (r1 == 0x01) {
         break;
      }
      r1 = spi_send (0xFF);
   }
   spi_ss (1);
   if (r1 != 0x01) {
      /* Failed to Reset Flash Card. */
      return (__FALSE);
   }
   spi_hi_speed (__TRUE);

   CardType = CARD_NONE;
   /* Check if SD card, send ACMD41 */
   for (i = 0; i < 50000; i++) {
      spi_ss (0);
      r1 = mmc_command (APP_CMD, 0);
      spi_ss (1);
      if (r1 & 0x04) {
         /* Illegal Command. */
         break;
      }
      if (r1 == 0x01) {
         spi_ss (0);
         r1 = mmc_command (SD_SEND_OP_COND, 0);
         spi_ss (1);
         if (r1 == 0x00) {
            /* OK, SD card initialized. */
            CardType = CARD_SD;
            break;
         }
      }
   }
   if (CardType == CARD_NONE) {
      /* Initialize MMC Card, send CMD1. */
      for (i = 0; i < 50000; i++) {
         spi_ss (0);
         r1 = mmc_command (SEND_OP_COND, 0);
         spi_ss (1);
         if (r1 != 0x01) {
            break;
         }
      }
      if (r1 != 0x00) {
         /* Failed to Initialize the card. */
         return (__FALSE);
      }
      CardType = CARD_MMC;
   }

   /* Set block length in the Flash Card to 512 bytes. */
   spi_ss (0);
   r1 = mmc_command (SET_BLOCKLEN, 512);
   spi_ss (1);
   if (r1 != 0x00) {
      return (__FALSE);
   }
   /* Turn Off CRC option. */
   spi_ss (0);
   r1 = mmc_command (CRC_ON_OFF, 0);
   spi_ss (1);
   if (r1 != 0x00) {
      return (__FALSE);
   }
   /* Success, card initialized. */
   return (__TRUE);
}


/*--------------------------- mmc_command -----------------------------------*/

static U8 mmc_command (U8 cmd, U32 arg) {
   /* Send a Command to Flash card and get a Response. */
   U32 r1,i;

   spi_send (0xFF);
   spi_send (cmd);
   spi_send (arg >> 24);
   spi_send (arg >> 16);
   spi_send (arg >> 8);
   spi_send (arg);
   /* Checksum, should only be valid for the first command.CMD0 */
   spi_send (0x95);
   
   /* Response will come after 1 - 8 retries. */
   for (i = 0; i < 8; i++) {
      r1 = spi_send (0xFF);
      if (r1 != 0xFF) {
         break;
      }
   }
   return (r1);
}


/*--------------------------- mmc_read_block --------------------------------*/

static BOOL mmc_read_block (U8 cmd, U32 arg, U8 *buf, U32 cnt) {
   /* Read a 'cnt' of data blocks from Flash Card. */
   U32 i;

   if (mmc_command (cmd, arg) != 0x00) {
      /* R1 status error. */
      return (__FALSE);
   }

   for (  ; cnt; buf += 512, cnt--) {
      for (i = CMD_TOUT; i; i--) {
         if (spi_send (0xFF) == 0xFE) {
            /* Data Start token. */
            break;
         }
      }
      if (i == 0) {
         /* Sector Read Tiomeout. */
         return (__FALSE);
      }

      for (i = 0; i < 512; i++) {
         buf[i] = spi_send (0xFF);
      }
      /* Read also a 16-bit CRC. */
      spi_send (0xFF);
      spi_send (0xFF);
   }
   return (__TRUE);
}


/*--------------------------- mmc_read_bytes --------------------------------*/

static BOOL mmc_read_bytes (U8 cmd, U32 arg, U8 *buf, U32 len) {
   /* Read a 'len' bytes from Flash Card. */
   U32 i;

   if (mmc_command (cmd, arg) != 0x00) {
      /* R1 status error. */
      return (__FALSE);
   }

   for (i = CMD_TOUT; i; i--) {
      if (spi_send (0xFF) == 0xFE) {
         /* Data Start token. */
         break;
      }
   }
   if (i == 0) {
      /* Data Read Tiomeout. */
      return (__FALSE);
   }

   for (i = 0; i < len; i++) {
      buf[i] = spi_send (0xFF);
   }
   /* Read also a 16-bit CRC. */
   spi_send (0xFF);
   spi_send (0xFF);
   return (__TRUE);
}


/*--------------------------- mmc_write_block -------------------------------*/

static BOOL mmc_write_block (U8 cmd, U32 arg, U8 *buf, U32 cnt) {
   /* Write a 'cnt' of data blocks to Flash Card. */
   U32 i;
   U8  tkn;

   if (mmc_command (cmd, arg) != 0x00) {
      /* R1 status error. */
      return (__FALSE);
   }

   /* Select token, for single write or multiple write. */
   tkn = 0xFE;
   if (cnt > 1) {
      tkn = 0xFC;
   }

   for (  ; cnt; buf += 512, cnt--) {
      /* Send Data Start token. */
      spi_send (tkn);
      /* Send data. */
      for (i = 0; i < 512; i++) {
         spi_send (buf[i]);
      }
      /* Send also a 16-bit CRC. */
      spi_send (0xFF);
      spi_send (0xFF);
      /* Check data response. */
      if ((spi_send (0xFF) & 0x0F) != 0x05) {
         return (__FALSE);
      }
      /* Wait while Flash Card is busy. */
      for (i = WR_TOUT; i; i--) {
         if (spi_send (0xFF) == 0xFF) {
            /* Sector Write finished. */
            break;
         }
      }
      if (i == 0) {
         /* Sector Write Tiomeout. */
         return (__FALSE);
      }
   }
   return (__TRUE);
}


/*--------------------------- mmc_read_sect ---------------------------------*/

BOOL mmc_read_sect (U32 sect, U8 *buf, U32 cnt) {
   /* Read single/multiple sectors from Flash Memory Card. */
   U32  i;
   BOOL retv;

   spi_ss (0);
   if (cnt > 1) {
      /* Multiple Block Read. */
      retv = mmc_read_block (READ_MULT_BLOCK, sect * 512, buf, cnt);

      mmc_command (STOP_TRAN, 0);
      /* Wait while Flash Card is busy. */
      for (i = STOP_TOUT; i; i--) {
         if (spi_send (0xFF) == 0xFF) {
            goto x;
         }
      }
      retv = __FALSE;
   }
   else {
      /* Single Block Read. */
      retv = mmc_read_block (READ_BLOCK, sect * 512, buf, 1);
   }
x: spi_ss (1);
   return (retv);
}


/*--------------------------- mmc_write_sect --------------------------------*/

BOOL mmc_write_sect (U32 sect, U8 *buf, U32 cnt) {
   /* Write a 512 byte sector to Flash Card. */
   U32  i;
   BOOL retv;

   spi_ss (0);
   if (cnt > 1) {
      /* Multiple Block Write. */
      retv = mmc_write_block (WRITE_MULT_BLOCK, sect * 512, buf, cnt);

      mmc_command (STOP_TRAN, 0);
      /* Wait while Flash Card is busy. */
      for (i = STOP_TOUT; i; i--) {
         if (spi_send (0xFF) == 0xFF) {
            goto x;
         }
      }
      retv = __FALSE;
   }
   else {
      /* Single Block Write. */
      retv = mmc_write_block (WRITE_BLOCK, sect * 512, buf, 1);
   }
x: spi_ss (1);
   return (retv);
}


/*--------------------------- mmc_read_config -------------------------------*/

BOOL mmc_read_config (MMCFG *cfg) {
   /* Read MMC/SD Card device configuration. */
   U8 buf[16],*bp;
   BOOL retv;
   U32 v,m;

   /* Read the CID - Card Identification. */
   spi_ss (0);
   retv = mmc_read_bytes (SEND_CID, 0, buf, 16);
   spi_ss (1);
   if (retv == __FALSE) {
      /* Read CID failed. */
      return (__FALSE);
   }
   /* CID register structure for SD is different than for MMC Card. */
   if (CardType == CARD_SD) {
      bp = &buf[9];
   }
   else {
      bp = &buf[10];
   }
   cfg->sernum = bp[0]<<24 | bp[1]<<16 | bp[2]<<8 | bp[3];

   /* Read the CSD - Card Specific Data. */
   spi_ss (0);
   retv = mmc_read_bytes (SEND_CSD, 0, buf, 16);
   spi_ss (1);
   if (retv == __FALSE) {
      /* Read CSD failed. */
      return (__FALSE);
   }
   /* Read Block length */
   v = buf[5] & 0x0F;
   cfg->read_blen = 1 << v;

   /* Write Block length */
   v = ((buf[12] << 8 | buf[13]) >> 6) & 0x0F;
   cfg->write_blen = 1 << v;

   /* Total Number of blocks */
   v = ((buf[6] << 16 | buf[7] << 8 | buf[8]) >> 6) & 0x0FFF;
   m = ((buf[9] << 8  | buf[10]) >> 7) & 0x07;
   cfg->blocknr = (v + 1) << (m + 2);

   return (__TRUE);
}

/*----------------------------------------------------------------------------
 * end of file
 *---------------------------------------------------------------------------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -