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

📄 mci_lpc23xx.c

📁 LP236X的教程里面有许多源码例程。我当初可是花钱买来的。希望能帮得上忙。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*----------------------------------------------------------------------------
 *      R T L  -  F l a s h   F i l e   S y s t e m
 *----------------------------------------------------------------------------
 *      Name:    MCI_LPC23XX.C 
 *      Purpose: Multimedia Card Interface Driver for LPC23xx
 *      Rev.:    V3.21
 *----------------------------------------------------------------------------
 *      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>
#include <LPC23xx.h>                 /* LPC23xx/24xx definitions             */
#include "MCI_LPC23xx.h"

/* Local variables */
static U8  CardType;
static U16 CardRCA;
static MMCFG mmc_cfg;

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

/* Local Function Prototypes */
static void mci_set_speed (U32 speed);
static void mci_bus_mode (U32 mode);
static BOOL mci_send_acmd (void);
static BOOL mci_set_address (void);
static BOOL mci_read_cid (void);
static BOOL mci_read_csd (void);
static BOOL mci_select_card (void);
static BOOL mci_set_bus_4bit (void);
static BOOL mci_set_block_len (void);
static BOOL mci_cmd_read_block (U32 block, U32 cnt);
static BOOL mci_cmd_write_block (U32 block, U32 cnt);
static U32  mci_read_status (void);
static BOOL mci_send_stop (void);
static U32  mci_command (U8 cmd, U32 arg, U32 resp, U32 *rp);
static void mci_dma_start (U32 mode, U8 *buf);

/*--------------------------- mci_init --------------------------------------*/

BOOL mci_init (void) {
   /* Initialize and enable the Flash Card. */
   U32 i,rstat,rval[4];

   /* Power Up the MCI and DMA controller. */
   PCONP |= 0x30000000;

   /* MCIPWR pin is active high. */
   /* Required for the silicon rev. 'B' and later. */
   SCS |= 0x08;

   /* Enable MCI Pins on P0,P2. */
   PINSEL1 &= ~0x00003FC0;
   PINSEL1 |=  0x00002A80;
   PINSEL4 &= ~0x0FC00000;
   PINSEL4 |=  0x0A800000;

   /* Clear all pending interrupts. */
   MCI_COMMAND   = 0;
   MCI_DATA_CTRL = 0;
   MCI_CLEAR     = 0x7FF;

   /* Power up, switch on VCC for the Flash Card. */
   MCI_POWER  = 0x02;
   for (i = 0; i < 50000; i++);

   mci_set_speed (LOW_SPEED);

   /* Power on the Flash Card. */
   MCI_POWER |= 0x01;
   for (i = 0; i < 50000; i++);

   /* Reset the card, send CMD0. */
   mci_command (GO_IDLE_STATE, 0, RESP_NONE, NULL);

   /* Set Open Drain output control for MMC */
   mci_bus_mode (OPEN_DRAIN_MODE);

   CardType = CARD_NONE;
   /* First try MMC, send CMD1. */
   for (i = 0; i < 100; i++) {
      rstat = mci_command (SEND_OP_COND, OCR_INDEX, RESP_SHORT, &rval[0]);
      if (!(rstat & MCI_CMD_TIMEOUT) && rval[0] & 0x80000000) {
         CardType = CARD_MMC;
         break;
      }
   }

   if (CardType == CARD_NONE) {
      /* Check for SD card, clear Open Drain output control. */
      mci_bus_mode (PUSH_PULL_MODE);
      for (i = 0; i < 500; i++) {
         if (mci_send_acmd () == __TRUE) {
            rstat = mci_command (SEND_APP_OP_COND, 
                                 OCR_INDEX, RESP_SHORT, &rval[0]);
            if (!(rstat & MCI_CMD_TIMEOUT) && rval[0] & 0x80000000) {
               /* OK, SD card initialized. */
               CardType = CARD_SD;
               break;
            }
         }
      }
   }
   if (CardType == CARD_NONE) {
      /* Failed, no card found. */
      goto fail;
   }

   /* Initialize the Card to SD/MMC mode. */
   if (mci_read_cid () == __FALSE) {
      goto fail;
   }
   if (mci_set_address () == __FALSE) {
      goto fail;
   }

   /* Disable Open Drain mode for MMC. */
   if (CardType == CARD_MMC) {
      mci_bus_mode (PUSH_PULL_MODE);
   }

   /* Data Transfer Mode, end of Card-Identification Mode. */
   mci_set_speed (HIGH_SPEED);

   if (mci_read_csd () == __FALSE) {
      goto fail;
   }
   if (mci_select_card () == __FALSE) {
      goto fail;
   }

   if (CardType == CARD_SD) {
      /* Use wide 4-bit bus for SD */
      MCI_CLOCK |= 0x0800;
      for (i = 0; i < 100; i++);
      if (mci_set_bus_4bit () == __FALSE) {
         /* Failed to enable 4-bit bus. */
         goto fail;
      }
   }
   /* Set block length to 512 bytes. */
   if (mci_set_block_len () == __FALSE) {
fail: MCI_POWER = 0x00;
      return (__FALSE);
   }

   /* Success, card initialized. */
   return (__TRUE);
}


/*--------------------------- mci_set_speed ---------------------------------*/

static void mci_set_speed (U32 speed) {
   /* Set a MCI clock speed to desired value. */
   U32 i,clkdiv;

   if (speed == HIGH_SPEED) {
      /* Max. 25 MBit used for Data Transfer. */
      clkdiv = 0;
   }
   else {
      /* Max. 400 kBit used in Card Initialization. */
      clkdiv = 240;
   }
   MCI_CLOCK = (MCI_CLOCK & ~0xFF) | 0x300 | clkdiv;

   /* delay 3MCLK + 2PCLK before next write */
   for ( i = 0; i < 100; i++ );
}


/*--------------------------- mci_bus_mode ----------------------------------*/

static void mci_bus_mode (U32 mode) {
   /* Set MCI Bus mode to Open Drain or Push Pull. */
   U32 i;

   if (mode == OPEN_DRAIN_MODE) {
      MCI_POWER |= 0x40;
   }
   else {
      MCI_POWER &= ~0x40;
   }
   /* A small delay after switching mode. */
   for (i = 0; i < 100; i++);
}


/*--------------------------- mci_send_acmd ---------------------------------*/

static BOOL mci_send_acmd (void) {
   /* Send CMD55 to enable ACMD */
   U32 arg,rstat,rval;

   arg = 0;
   if (CardType == CARD_SD) {
      /* Use address from SET_RELATIVE_ADDR. */
      arg = CardRCA << 16;
   }
   rstat = mci_command (APP_CMD, arg, RESP_SHORT, &rval);
   if (rstat == 0 && (rval & STAT_ACMD_ENABLE)) {
      return (__TRUE);
   }
   return (__FALSE);
}


/*--------------------------- mci_set_address -------------------------------*/

static BOOL mci_set_address (void) {
   /* Set Relative Address, send CMD3 after CMD2. */
   U32 i,arg,rstat,rval;

   arg = 0;
   if (CardType == CARD_MMC) {
      /* Fix the RCA address for MMC card. */
      arg = 0x00010000;
   }

   for (i = 0; i < 20; i++) {
      rstat = mci_command (SET_RELATIVE_ADDR, arg, RESP_SHORT, &rval);
      if (!(rstat & MCI_CMD_TIMEOUT) && (rval & 0x0F00) == 0x0500) {
         /* Response is back and correct. */
         CardRCA = rval >> 16;
         return (__TRUE);
      }
   }
   return (__FALSE);
}


/*--------------------------- mci_read_cid ----------------------------------*/

static BOOL mci_read_cid (void) {
   /* Check CID, send CMD2 after CMD1 (MMC) or ACMD41 (SD). */
   U32 i,rstat,v,rval[4];

   for (i = 0; i < 20; i++) {
      rstat = mci_command (ALL_SEND_CID, 0, RESP_LONG, &rval[0]);
      if (!(rstat & MCI_CMD_TIMEOUT)) {
         /* Response is back and correct. */
         if (CardType == CARD_SD) {
            /* Serial Number for SD Card. */
            v = (rval[2] << 8)  | (rval[3] >> 24);
         }
         else {
            /* Serial Number for MMC Card. */
            v = (rval[2] << 16) | (rval[3] >> 16);
         }
         mmc_cfg.sernum = v;
         return (__TRUE);
      }
   }
   mmc_cfg.sernum = 0;
   return (__FALSE);
}


/*--------------------------- mci_read_csd ----------------------------------*/

static BOOL mci_read_csd (void) {
   /* Send Card Specific Data, send CMD9 after CMD3. */
   U32 i,arg,rstat,v,m,rval[4];

   arg = 0x00010000;
   if (CardType == CARD_SD) {
      /* Use address from SET_RELATIVE_ADDR. */
      arg = CardRCA << 16;
   }

   for (i = 0; i < 20; i++) {
      rstat = mci_command (SEND_CSD, arg, RESP_LONG, &rval[0]);
      if (rstat == 0) {
         /* Response is back and correct, Read Block length */
         v = (rval[1] >> 16) & 0x0F;
         mmc_cfg.read_blen = 1 << v;

         /* Write Block length */
         v = (rval[3] >> 22) & 0x0F;
         mmc_cfg.write_blen = 1 << v;

         /* Total Number of blocks */
         v = ((rval[1] << 2) | (rval[2] >> 30)) & 0x0FFF;
         m =  (rval[2] >> 15) & 0x07;
         mmc_cfg.blocknr = (v + 1) << (m + 2);

         /* File Format information */
         v = (rval[3] >> 8) & 0x83;
         switch (v) {
            case 0x00:
            case 0x03:
               mmc_cfg.format = HDD_TYPE;
               break;
            case 0x01:
               mmc_cfg.format = FLOPPY_TYPE;
               break;
            default:
               mmc_cfg.format = UNKNOWN_TYPE;
               break;
         }
         return (__TRUE);
      }
   }
   return (__FALSE);
}


/*--------------------------- mci_select_card -------------------------------*/

static BOOL mci_select_card (void) {
   /* Select the Card, send CMD7 after CMD9, inter-change state */
   /* between STBY and TRANS after this command. */
   U32 i,arg,rstat,rval;

   arg = 0x00010000;
   if (CardType == CARD_SD) {
      /* Use address from SET_RELATIVE_ADDR. */
      arg = CardRCA << 16;
   }

   for (i = 0; i < 20; i++) {
      rstat = mci_command (SELECT_CARD, arg, RESP_SHORT, &rval);
      if (rstat == 0 && (rval & 0x0F00) == 0x0700) {
         /* Should be in STBY state now and ready. */
         return (__TRUE);
      }
   }
   return (__FALSE);
}


/*--------------------------- mci_set_bus_4bit ------------------------------*/

static BOOL mci_set_bus_4bit (void) {
   /* Select 4-bit bus width for SD Card. */
   U32 i,rstat,rval;

⌨️ 快捷键说明

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