📄 mmcfs.c
字号:
//****************************************************************************//// MMCFS.C - File system driver for the external MMC FLASH.//// Copyright (c) 2001 Cirrus Logic, Inc.////****************************************************************************#include "globals.h"#include "../hwport.h"#include "../hwdefs.h"#include "mmc.h"//****************************************************************************//// The following four values must be defined in the section of hwport.h for// the selected board to tell the MMC code the GPIO being used for the CMD and// DAT pins (this is dependent upon how the MMC card is wired into the board)://// HwPortABCD_MMC_CMD - The bit in the HwPortABCD register for the MMC// CMD pin.// - or -// HwPortE_MMC_CMD - The bit in the HwPortE register for the MMC CMD pin.//// HwPortABCD_MMC_CMD_Shift - The number of bits to shift the HwPortABCD// register value to get the MMC CMD bit in the// least significant bit.// - or -// HwPortE_MMC_CMD_Shift - The number of bits to shift the HwPortE// register value to get the MMC CMD bit in the// least significant bit.//// HwPortABCD_MMC_DAT - The bit in the HwPortABCD register for the MMC// DAT pin.// - or -// HwPortE_MMC_DAT - The bit in the HwPortE register for the MMC DAT pin.//// HwPortABCD_MMC_DAT_Shift - The number of bits to shift the HwPortABCD// register value to get the MMC DAT bit in the// least significant bit.// - or -// HwPortE_MMC_DAT_Shift - The number of bits to shift the HwPortE// register value to get the MMC DAT bit in the// least significant bit.////****************************************************************************//****************************************************************************//// Determine the register, bit, and shift required to access the command line// of the MMC bus.////****************************************************************************#ifdef HwPortABCD_MMC_CMD#define MMC_CMD_PORT HwPortABCD#define MMC_CMD_DIR HwDdrABCD#define MMC_CMD_BIT HwPortABCD_MMC_CMD#define MMC_CMD_SHIFT HwPortABCD_MMC_CMD_Shift#endif#ifdef HwPortE_MMC_CMD#define MMC_CMD_PORT HwPortE#define MMC_CMD_DIR HwDdrE#define MMC_CMD_BIT HwPortE_MMC_CMD#define MMC_CMD_SHIFT HwPortE_MMC_CMD_Shift#endif//****************************************************************************//// Determine the register, bit, and shift required to access the data line of// the MMC bus.////****************************************************************************#ifdef HwPortABCD_MMC_DAT#define MMC_DAT_PORT HwPortABCD#define MMC_DAT_DIR HwDdrABCD#define MMC_DAT_BIT HwPortABCD_MMC_DAT#define MMC_DAT_SHIFT HwPortABCD_MMC_DAT_Shift#endif#ifdef HwPortE_MMC_DAT#define MMC_DAT_PORT HwPortE#define MMC_DAT_DIR HwDdrE#define MMC_DAT_BIT HwPortE_MMC_DAT#define MMC_DAT_SHIFT HwPortE_MMC_DAT_Shift#endif//****************************************************************************//// Only include this code if we have MMC data and command lines defined.////****************************************************************************#if defined(MMC_DAT_PORT) && defined(MMC_CMD_PORT)//****************************************************************************//// A macro to make the MMC command line an output.////****************************************************************************#if MMC_CMD_SHIFT >= 24#define MMCCmdOutput pulPtr[MMC_CMD_DIR >> 2] &= ~MMC_CMD_BIT#else#define MMCCmdOutput pulPtr[MMC_CMD_DIR >> 2] |= MMC_CMD_BIT#endif//****************************************************************************//// A macro to make the MMC command line an input.////****************************************************************************#if MMC_CMD_SHIFT >= 24#define MMCCmdInput pulPtr[MMC_CMD_DIR >> 2] |= MMC_CMD_BIT#else#define MMCCmdInput pulPtr[MMC_CMD_DIR >> 2] &= ~MMC_CMD_BIT#endif//****************************************************************************//// A macro to make the MMC data line an output.////****************************************************************************#if MMC_DAT_SHIFT >= 24#define MMCDatOutput pulPtr[MMC_DAT_DIR >> 2] &= ~MMC_DAT_BIT#else#define MMCDatOutput pulPtr[MMC_DAT_DIR >> 2] |= MMC_DAT_BIT#endif//****************************************************************************//// A macro to make the MMC data line an input.////****************************************************************************#if MMC_DAT_SHIFT >= 24#define MMCDatInput pulPtr[MMC_DAT_DIR >> 2] |= MMC_DAT_BIT#else#define MMCDatInput pulPtr[MMC_DAT_DIR >> 2] &= ~MMC_DAT_BIT#endif//****************************************************************************//// The name of these drives.////****************************************************************************static const unsigned short pusDriveName1[] ={ 'M', 'u', 'l', 't', 'i', 'M', 'e', 'd', 'i', 'a', 'C', 'a', 'r', 'd', ' ', '1', '\0'};static const unsigned short pusDriveName2[] ={ 'M', 'u', 'l', 't', 'i', 'M', 'e', 'd', 'i', 'a', 'C', 'a', 'r', 'd', ' ', '2', '\0'};//****************************************************************************//// The persistent state of the MMC driver.////****************************************************************************static struct{ // // The number of MMC cards found. // unsigned short usNumCards; // // The currently selected MMC card. // unsigned short usCurrent; // // The persistent state of the FAT layer used for the first MMC card. // tFAT sFAT1; // // The persistent state of the FAT layer used for the second MMC card. // tFAT sFAT2;} sMMC;//****************************************************************************//// MMCClock clocks the MMC bus the given number of times.////****************************************************************************static voidMMCClock(unsigned long ulCount){ volatile unsigned long *pulPtr = (unsigned long *)HwMMCAddress; // // Loop while there are more clocks cycles to create. // while(ulCount--) { // // Clock the MMC bus. // *pulPtr = 0; }}//****************************************************************************//// MMCGetCRC7 computes the CRC7 value for the given MMC command.////****************************************************************************static unsigned charMMCGetCRC7(unsigned char *pucCommand){ unsigned long ulByte, ulBit, ulValue; unsigned char ucCRC7 = 0; // // Loop through the five bytes in the command. // for(ulByte = 0; ulByte < 5; ulByte++) { // // Get this byte. // ulValue = pucCommand[ulByte]; // // Loop through the eight bits in this byte. // for(ulBit = 0; ulBit < 8; ulBit++) { // // Shift the running CRC7 up by one bit. // ucCRC7 <<= 1; // // Compute the next iteration of the CRC7. // ucCRC7 ^= ((((ulValue << ulBit) ^ ucCRC7) & 0x80) ? 0x09 : 0x00); } } // // Return the computed CRC7 value. // return(ucCRC7 & 0x7f);}//****************************************************************************//// MMCGetCRC16 computes the CRC16 value for the data buffer.////****************************************************************************static unsigned shortMMCGetCRC16(unsigned long *pulBuffer, unsigned long bIsByteSwapped){ unsigned long ulIdx, ulByte, ulBit, ulValue, ulWord; unsigned short usCRC16 = 0; // // Loop through the 128 words in the data buffer. // for(ulIdx = 0; ulIdx < 128; ulIdx++) { // // Get this word. // ulWord = pulBuffer[ulIdx]; // // Byte swap this word if it is byte swapped in memory. // if(bIsByteSwapped) { ulWord = (((ulWord >> 24) & 0x000000ff) | ((ulWord >> 8) & 0x0000ff00) | ((ulWord << 8) & 0x00ff0000) | ((ulWord << 24) & 0xff000000)); } // // Loop through the four bytes in this word. // for(ulByte = 0; ulByte < 4; ulByte++) { // // Get this byte, shifting it up by eight bits so that it lines up // with the MSB of the running CRC16. // ulValue = (ulWord >> (ulByte * 8)) << 8; // // Loop through the eight bits in this byte. // for(ulBit = 0; ulBit < 8; ulBit++) { // // Compute the next iteration of the CRC16. // if((usCRC16 ^ (ulValue << ulBit)) & 0x8000) { usCRC16 = (usCRC16 << 1) ^ 0x1021; } else { usCRC16 <<= 1; } } } } // // Return the computed CRC16 value. // return(usCRC16);}//****************************************************************************//// MMCSendCommand constructs and sends a command to the MMC bus.////****************************************************************************static voidMMCSendCommand(unsigned char ucCmd, unsigned long ulArg){ unsigned char ucCommand[6]; // // Construct the MMC command packet. // ucCommand[0] = 0x40 | (ucCmd & 0x3f); ucCommand[1] = (ulArg & 0xff000000) >> 24; ucCommand[2] = (ulArg & 0x00ff0000) >> 16; ucCommand[3] = (ulArg & 0x0000ff00) >> 8; ucCommand[4] = ulArg & 0x000000ff; ucCommand[5] = (MMCGetCRC7(ucCommand) << 1) | 0x01; // // Send the command packet to the MMC bus. // MMCWriteCommand(ucCommand);}//****************************************************************************//// MMCInit initializes the MMC cards, performing isolation of the cards on the// MMC bus and assigning unique relative addresses to each card found.////****************************************************************************static unsigned longMMCInit(void){ volatile unsigned long *pulPtr = (unsigned long *)HwBaseAddress; unsigned long ulAddress; unsigned char ucRes[18]; // // Initially, there are no cards. // sMMC.usNumCards = 0; // // The maximum MMC clock during enumeration is 400kHz, so slow down the // clock to meet this spec. // pulPtr[HwMMCMemConfig >> 2] &= ~HwMMCMemValue; // // Clock the MMC bus for a bit to clear out any residual state. // MMCClock(100); // // Put the MMC cards into idle mode. // MMCSendCommand(GO_IDLE_STATE, 0x00000000); // // Clock the MMC bus for a bit. // MMCClock(60); // // Inform the MMC cards of the operating voltage. // do { // // Tell the MMC cards that they will be operating in the 3.1V to 3.2V // range. // MMCSendCommand(SEND_OP_COND, OCR_31_32); if(MMCReadResponse(ucRes, 6) == 0) { // // No response was read, so there are no MMC cards. // return(0); } // // Clock the MMC bus. // MMCClock(8); } while((ucRes[1] & 0x80) == 0); // // Clock the MMC bus. // MMCClock(100); // // Set the address of the first MMC card found. // ulAddress = 0x00010000; // // Get the CIDs until we've found all the MMC cards. // while(1) { // // Get the CID from the MMC card(s). // MMCSendCommand(ALL_SEND_CID, 0x00000000); // // Read back the CID. // if(MMCReadResponse(ucRes, 17) == 0) { break; } // // Clock the MMC bus. // MMCClock(8); // // Set the relative address of this MMC card. // MMCSendCommand(SET_RELATIVE_ADDR, ulAddress); if(MMCReadResponse(ucRes, 6) == 0) { break; } // // Clock the MMC bus. // MMCClock(8); // // Select this MMC card. // MMCSendCommand(SELECT_CARD, ulAddress); if(MMCReadResponse(ucRes, 6) == 0) { break; } // // Clock the MMC bus. // MMCClock(8);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -