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

📄 mmc.c

📁 Interfacing to an MMC/SD card via SPI (for microcontroller)
💻 C
字号:
//*****************************************************************************//// Author       : Pascal Stang - Copyright (C) 2004// Modified     : Tony Ward, Cyan Technology, March 2006//// This code is distributed under the GNU Public License//        which can be found at http://www.gnu.org/licenses/gpl.txt////   TWard March 2006 - Ported to the eCOG1k Microcontroller under CyanIDE//*****************************************************************************#include <ecog.h>#include <ecog1.h>#include "mmc.h"// include project-specific hardware configuration#include "mmcConf.h"#include "spi.h"        // include spi bus support// Functionsvoid mmcInit(void){       MMC_CS_Clr = 1;    MMC_CS_En = 1;       fd.dusart.spi_frame_ctrl.tx_slave_sel = 0;     }unsigned int mmcReset (void){    unsigned int retry;    unsigned int r1 = 0;    int i;    retry = 0;       LED0_Clr = 1;   // Turn off until we succeed.       do    {        // Enable transmit and receive        // NB we need internal CS0 signal for us to receive data without running CS Assert        rg.dusart.spi_ctrl = DUSART_SPI_CTRL_RX_EN_MASK | DUSART_SPI_CTRL_TX_EN_MASK;        // Specs indicate 74 cycles are required (without CS) before reading        fd.dusart.spi_frame_ctrl.tx_slave_sel = 1;    // Assert CS0 internally        for (i = 0; i < 10; i++)            spiTransferByte(0xff);        rg.dusart.spi_ctrl = DUSART_SPI_CTRL_RX_DIS_MASK | DUSART_SPI_CTRL_TX_DIS_MASK;        fd.dusart.spi_frame_ctrl.tx_slave_sel = 0;    // De-assert CS0 internally        // resetting card, go to SPI mode        r1 = mmcSendCommand(MMC_GO_IDLE_STATE, 0);#ifdef MMC_DEBUG        printf("MMC_GO_IDLE_STATE: R1=0x%x\r\n", r1);#endif        // do retry counter        retry++;        if (retry > 10)            return -1;    }    while (r1 != 0x01);    // When we arrive here, the reset command has been accepted and we need to wait    // for the idle state (LSbit) bit to go low    retry = 0;    do    {        // initializing card for operation        r1 = mmcSendCommand(MMC_SEND_OP_COND, 0);        #ifdef MMC_DEBUG        printf("MMC_SEND_OP_COND: R1=0x%x\r\n", r1);        #endif        // do retry counter        // Allow a small delay while between retries waiting for intitialisation        for (i = 0; i < 30000; i++)            nop();   // approximately 25ms        retry++;        if (retry > 100)            return -1;       }    while (r1);    // Okay, we are now alive and the card is initialised    // TODO: check card parameters for voltage compliance    // before issuing initialize command       // turn off CRC checking to simplify communication    r1 = mmcSendCommand(MMC_CRC_ON_OFF, 0);#ifdef MMC_DEBUG    printf("MMC_CRC_ON_OFF: R1=0x%x\r\n", r1);#endif    // set block length to 512 bytes    r1 = mmcSendCommand(MMC_SET_BLOCKLEN, 512);#ifdef MMC_DEBUG    printf("MMC_SET_BLOCKLEN: R1=0x%x\r\n", r1);#endif    LED0_Set = 1;   // We are up and running, turn the LED back on       // return success    return (0);}unsigned int mmcSendCommand(unsigned int cmd, unsigned long arg){    unsigned int r1;    // assert chip select    spiAssertCS();    // issue the command    r1 = mmcCommand(cmd, arg);    // release chip select    spiDeassertCS();    return (r1);}unsigned int mmcRead(unsigned long sector, unsigned char *buffer){    unsigned int r1;    unsigned int i;    // assert chip select    // NB an additional step is required to enable CS internally       spiAssertCS();    // issue command    r1 = mmcCommand(MMC_READ_SINGLE_BLOCK, sector << 9);#ifdef MMC_DEBUG    printf("MMC Read Block R1=0x%x\r\n", r1);#endif    // check for valid response    if(r1 != 0x00)    {        spiDeassertCS();        return (r1);    }    // wait for block start    while (spiTransferByte(0xFF) != MMC_STARTBLOCK_READ);    // read in data    for (i = 0; i < 0x200; i++)    {        *buffer++ = spiTransferByte(0xFF);    }    // read 16-bit CRC    spiTransferByte(0xFF);    spiTransferByte(0xFF);    // release chip select    spiDeassertCS();      // return success    return 0;}unsigned int mmcWrite(unsigned long sector, unsigned char *buffer){    unsigned int r1;    unsigned int i;    // assert chip select    spiAssertCS();    // issue command    r1 = mmcCommand(MMC_WRITE_BLOCK, sector<<9);#ifdef MMC_DEBUG    printf("MMC Write Block R1=0x%x\r\n", r1);#endif    // check for valid response    if (r1 != 0x00)    {        return (r1);        spiDeassertCS();    }    // send dummy    spiTransferByte(0xFF);    // send data start token    spiTransferByte(MMC_STARTBLOCK_WRITE);    // write data    for (i = 0; i < 0x200; i++)    {        spiTransferByte(*buffer++);    }    // write 16-bit CRC (dummy values)    spiTransferByte(0xFF);    spiTransferByte(0xFF);    // read data response token    r1 = spiTransferByte(0xFF);    if ((r1&MMC_DR_MASK) != MMC_DR_ACCEPT)    {        spiDeassertCS();        return (r1);          }#ifdef MMC_DEBUG    printf("Data Response Token=0x%x\r\n", r1);#endif    // wait until card not busy    while(!spiTransferByte(0xFF));    // release chip select    spiDeassertCS();    // return success       return (0);}unsigned int mmcCommand(unsigned int cmd, unsigned long arg){    unsigned int r1;    unsigned int retry = 0;        // send command    spiTransferByte(cmd | 0x40);    spiTransferByte(arg >> 24);    spiTransferByte(arg >> 16);    spiTransferByte(arg >> 8);    spiTransferByte(arg);    spiTransferByte(0x95);    // crc valid only for MMC_GO_IDLE_STATE    // end command    // wait for response    // if more than 8 retries, card has timed-out    // return the received 0xFF    while ((r1 = spiTransferByte(0xFF)) == 0xFF)    {        if (retry++ > 8)            break;    }    // Add an additonal 8 clock ticks to finish off work (SD card specs)    spiTransferByte(0xff);    // return response    return (r1);}

⌨️ 快捷键说明

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