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

📄 ffs_port_mmc.c

📁 The Fat Fs module is a middleware that written in ANSI C. There is no platform dependence, so long a
💻 C
📖 第 1 页 / 共 2 页
字号:
*    initialise the MMC/SD-card and get some card-data
************************************************************
*/
FFS_SIZE *FFSPort_MediaInit(void)
{
    U32 c_size, s_speed, s_div;
    U16 c_size_mult;
    U08 i;

    FFSp_ver = FFSp_MARK_MMC;                              // mark as normal MMC-card at start-up
    for(i = 0; i < 0xFF; i++) { _NOP(); _NOP(); _NOP(); }  // wait for a stable card, 1ms (says MMC)
    if(FFSPort_MediaDetect()) return(NULL);                // media present ?
    FFSPort_MMC_ReInit();                                  // reinit interface (clock)
    for(i = 0; i < 10; i++) FFSPort_MMC_Send(0xFF);        // start MMC/SD in SPI-Mode, card-reset (74+ ckl)
    i = 0;                                                 // set IDLE_MODE (repeat)
    while((MMCWriteCMD(MMC_GO_IDLE_STATE, 0, 1) != MMC_R1_IDLE_STATE) && (i < 0xFF)) i++;
    if(i == 0xFF) return(NULL);                            // TimeOut error
    // After CMD0 the SPI interface is initialized in the CRC OFF mode in default.
    // But the CMD8 CRC verification is always enabled.
    i = MMCWriteCMD_Rx(SD_SEND_IF_COND, 0x1AA, (U08 OS_HUGE *)FFSp_data, 4); // send CMD8 to see it is SD & extended card and expand ACMD41 (R1-part of R7)
    // for not-MMC4.x and not-SD2.x cards CMD8 is unknown -- for MMC4.x cards CMD8 is not allowed here (in front of CMD1 / CMD58)    
    if(i <= MMC_R1_IDLE_STATE) {                           // ================== SD 2.00 ==================
        FFSp_ver = FFSp_MARK_SD;                           // mark as SD-card
        if(!(FFSp_data[2] & 0x01) || (FFSp_data[3] != 0xAA)) return(NULL);  // check CMD8 R7-response -> unsupported card
        c_size = 0;                                        // repeat ACMD41 - HCS (High Capacity Support) bit is in the argument of ACMD41 (SD 2.00)
        while(((MMCWriteCMD(MMC_APP_CMD, 0, 1) > MMC_R1_IDLE_STATE ) ||             
               (MMCWriteCMD(SD_SEND_OP_COND_ACMD41, 1UL << 30, 1) !=  FFS_NO_ERR)) && (c_size < 0xFFFF)) c_size++;
        if(c_size == 0xFFFF) return(NULL);                 // TimeOut error
        i = MMCWriteCMD_Rx(MMC_READ_OCR, 0, (U08 OS_HUGE *)FFSp_data, 4);
        if(i != FFS_NO_ERR) return(NULL);                  // send CMD58 (check R1-part of R3) ..
        FFSp_ver |= (FFSp_data[0] & 0x40) >> 6;            // and copy CCS-bit from R3 (SDHC-card)
    } else {                                               // ============= SD 1.xx / (HD-)MMC ============
        // why some SD 1.xx cards response with "bullshit" on CMD8 (like 0x82) but the rest is functional ???
//        if(i & ~(MMC_R1_ILLEGAL_COM | MMC_R1_IDLE_STATE)) return(NULL); // more R1-flags than IDLE & ILLEGAL_CMD -> unsupported card
        c_size = 0; i = MMC_R1_ILLEGAL_COM;                // repeat ACMD41 - HCS (High Capacity Support) bit is NOT in the argument of ACMD41 (SD 1.xx)
        while(((MMCWriteCMD(MMC_APP_CMD, 0, 1) > MMC_R1_IDLE_STATE ) ||             
               (i = MMCWriteCMD(SD_SEND_OP_COND_ACMD41, 0, 1) !=  FFS_NO_ERR)) && (c_size < 0xFFFF)) {
            if(i & MMC_R1_ILLEGAL_COM) break;
            c_size++;
        }
        if(c_size == 0xFFFF) return(NULL);                 // TimeOut error
        if(i & MMC_R1_ILLEGAL_COM) {                       // ================== (HD-)MMC =================
            FFSp_ver = FFSp_MARK_MMC;                      // be shure is marked as MMC-card
            c_size = 0; s_div = 1UL << 30;                 // send MMC_OP_MODE w/wo HD-support (repeat)
            while(((i = MMCWriteCMD(MMC_SEND_OP_COND, s_div, 1)) != FFS_NO_ERR) && (c_size < 0xFFFF)) {
                c_size++;
                if(i & (MMC_R1_PARAMETER | MMC_R1_ADDRESS)) s_div = 0;  // switch back to normal MMC
            }
            if(c_size == 0xFFFF) return(NULL);             // TimeOut error
            if(s_div) {                                    // if possible HD-MMC ..
                i = MMCWriteCMD_Rx(MMC_READ_OCR, 0, (U08 OS_HUGE *)FFSp_data, 4);
                if(i != FFS_NO_ERR) return(NULL);          // .. send CMD58 (check R1-part of R3) ..
                FFSp_ver |= ((FFSp_data[0] & 0x60) == 0x40)? FFSp_MARK_HDMMC : FFSp_MARK_MMC;
            }                                              // .. and test bit30/29 from R3 (HD-MMC card)
        } else {                                           // ================== SD 1.xx ==================
            FFSp_ver = FFSp_MARK_SD;                       // mark as SD-card
        }
    }
    /***********   get needed card information  ***********/
    i = MMCReadBlock(MMC_SEND_CID, 0, (U08 OS_HUGE *)FFSp_data, 16);              // read CID for vendor- & product- ID
    if(i != FFS_NO_ERR) return(NULL);
    FFS_values.vp_id = ((U32)FFSp_data[0] << 16) | (((U16)FFSp_data[2] << 8) | FFSp_data[1]);
    FFS_values.flags = 0;                                                         // copy vendor- & product-ID plus WP-bit=0
    i = MMCReadBlock(MMC_SEND_CSD, 0, (U08 OS_HUGE *)FFSp_data, 16);              // read CSD for card-speed & card-size
    if(i != FFS_NO_ERR) return(NULL);
    if((FFSp_ver == FFSp_MARK_SDHC) && (!(FFSp_data[0] & 0x3C))) {                // doublecheck if SDHC-card with new CSD response ..
        FFSp_ver = (FFSp_data[0] & 0xC0)? FFSp_MARK_SDHC : FFSp_MARK_SD;          // SD-card plus .. scan of CSD-version (for SDHC cards)
    }
    for(s_speed = 1, i = FFSp_data[3] & 0x07; i > 0; s_speed *= 10, i--);         // (TRAN_SPEED_tu*10)
    s_speed *= (U32)(MMC_m[((FFSp_data[3] >> 3) & 0x0F) -1]) * 10000;             // (TRAN_SPEED_tu*10) * (TRAN_SPEED_tv*10) * 10000 = x (in Hz)
    s_speed  = FFSPort_MMC_SetBR(s_speed);                                        // set max-speed in Hz and return used-speed
    // We calculate timings for High Capacity SD Memory Cards too, since we don't use a timer (for 100ms and 250ms).
    // We use the fixed values of TAAC , NSAC and R2W_FACTOR of a SDHC-card to get clock-based time-out's !!!
    for(s_div = 1000, i = 7 - (FFSp_data[1] & 0x07); i > 0; s_div *= 10, i--);    // for: 1 / (TAAC_tu*10)
    c_size   = s_speed * (U32)(MMC_m[((FFSp_data[1] >> 3) & 0x0F) - 1]);          // as:  (TAAC_tv*10) * Fop
    MMC_Nac  = (10UL * (c_size / s_div) + 100UL * (U32)(FFSp_data[2])) / 8 + 1;   // 10 * ( ((TAAC_tv*10) * Fop) / (TAAC_tu*10) + 100 * NSAC) / 8
    MMC_Nbs  = MMC_Nac * (U32)((FFSp_data[12] >> 2) & 0x07);                      // Nac * R2W

    // some SD-cards have (in comparison with other cards) extrem low timings declared 
    // but are not running stable with it -> so we can fix this by adding extra timing
    MMC_Nac *= 5;                                          // expand timeouts to a "normal" range
    MMC_Nbs *= 5;

    switch(FFSp_ver) {
        case FFSp_MARK_MMC:                                // ******************** normal MMC-cards *********************
        case FFSp_MARK_SD:                                 // ********************* normal SD-cards *********************
            // the maximum capacity can be 4GB, defined by CSD structure and 32bit byte-addressing
            // this is possible on: C_SIZE_MULT   C_SIZE   READ_BL_LEN
            //                        2^(7+2)   *  2^12  *    2^11
            //                         512      *  4096  *    2048      = 4GB
            c_size      = ((U16)(FFSp_data[6] & 0x03) << 10) | ((U16)FFSp_data[7] << 2) | (FFSp_data[8] >> 6);
            c_size_mult = 0x0001 << (2+(((FFSp_data[9] & 0x03) << 1) | (FFSp_data[10] >> 7)));
            FFSp_sshift = FFSp_data[5] & 0x0F;                         // get READ_BL_LEN as shift-value
            FFS_values.sectorsize = 0x0001UL << FFSp_sshift;           // copy BytsPerSec from READ_BL_LEN
            FFS_values.maxsectors = ((U32)c_size + 1) * c_size_mult;   // get calculated MaxSectors
#ifdef MMC_EXT_CSD_CHECK
            if(FFSp_ver == FFSp_MARK_MMC) {                            // only for MMC-cards ...
                s_speed = MMCHandle_ExtCsd(FFSp_ver, s_speed, c_size, c_size_mult); 
                if(s_speed != 0) {                                     // if EXT_CSD supported and a new speed set -> we have to recalculate the timings
                    for(s_div = 1000, i = 7 - (FFSp_data[1] & 0x07); i > 0; s_div *= 10, i--);    // for: 1 / (TAAC_tu*10)
                    s_speed *= (U32)(MMC_m[((FFSp_data[1] >> 3) & 0x0F) - 1]);                    // as:  (TAAC_tv*10) * Fop
                    MMC_Nac  = (10UL * (s_speed / s_div) + 100UL * (U32)(FFSp_data[2])) / 8 + 1;  // 10 * ( ((TAAC_tv*10) * Fop) / (TAAC_tu*10) + 100 * NSAC) / 8
                    MMC_Nbs  = MMC_Nac * (U32)((FFSp_data[12] >> 2) & 0x07);                      // Nac * R2W
                    i = MMCReadBlock(MMC_SEND_EXTCSD, 0, (U08 OS_HUGE *)FFSp_exCSD, 512);         // read EXT_CSD again for resync card-internally
                }
            }
#endif
            break;
        case FFSp_MARK_SDHC:                               // ***************** highcapacity SDHC-cards *****************
            // the maximum capacity can be 2TB, defined by CSD 2.0 structure and 32bit block-addressing 
            // actual as maximum defined are 32GB (upper 6bit of C_SIZE should be zero says SD 2.00)
            if((FFSp_data[5] & 0x0F) != 9) return(NULL);           // control READ_BL_LEN - must be "9" on SDHC-cards
            FFSp_sshift = 0;                                       // code-compatibility -> no shift needed
            FFS_values.sectorsize = 0x0001UL << 9;                 // set BytsPerSec fix
            c_size = ((U32)(FFSp_data[7] & 0x3F) << 16) | ((U32)FFSp_data[8] << 8) | (FFSp_data[9]);
            FFS_values.maxsectors = (c_size+1) << 10;              // get MaxSectors -> mcap=(csize+1)*512k -> msec=mcap/BytsPerSec(fix)
            break;
        case FFSp_MARK_HDMMC:                              // ****************** high density MMC-cards *****************
            FFSp_sshift = 1;                                       // mark as invalid for HD-MMC (for a following check later)
#ifdef MMC_EXT_CSD_CHECK
            c_size      = ((U16)(FFSp_data[6] & 0x03) << 10) | ((U16)FFSp_data[7] << 2) | (FFSp_data[8] >> 6);
            c_size_mult = 0x0001 << (2+(((FFSp_data[9] & 0x03) << 1) | (FFSp_data[10] >> 7)));
            s_speed = MMCHandle_ExtCsd(FFSp_ver, s_speed, c_size, c_size_mult); 
            if(s_speed != 0) {                                     // if EXT_CSD supported and a new speed set -> we have to recalculate the timings
                if(FFSp_sshift != 0) return(NULL);                 // no valid HD-MMC marks in EXT_CSD
                for(s_div = 1000, i = 7 - (FFSp_data[1] & 0x07); i > 0; s_div *= 10, i--);    // for: 1 / (TAAC_tu*10)
                s_speed *= (U32)(MMC_m[((FFSp_data[1] >> 3) & 0x0F) - 1]);                    // as:  (TAAC_tv*10) * Fop
                MMC_Nac  = (10UL * (s_speed / s_div) + 100UL * (U32)(FFSp_data[2])) / 8 + 1;  // 10 * ( ((TAAC_tv*10) * Fop) / (TAAC_tu*10) + 100 * NSAC) / 8
                MMC_Nbs  = MMC_Nac * (U32)((FFSp_data[12] >> 2) & 0x07);                      // Nac * R2W
                i = MMCReadBlock(MMC_SEND_EXTCSD, 0, (U08 OS_HUGE *)FFSp_exCSD, 512);         // read EXT_CSD again for resync card-internally
            } else return(NULL);                                                              // not MMC4.x or EXT_CSD not supported
            break;
#else
            // !!! here in Germany I can't get any HD-MMC cards, so actual this code does not support HD-MMC cards !!!
            // what is todo: - read extended-CSD
            //               - check EXT_CSD_REV and CARD_TYPE
            //               - read maxsectors = SEC_COUNT
            //               - set clock (normal /highspeed) and recalculate the timings
            return(NULL); 
            //lint -unreachable
//            break;
#endif
        default:                                           // ***** unknown type of MMC/SD-card *****
            return(NULL);
            //lint -unreachable
//            break;
    }
    if(FFS_values.sectorsize != 512) {                     // if (actual) blocks of card greater 512-bytes (never on HD-MMC- and SDHC-cards)
        i = MMCWriteCMD(MMC_SET_BLOCKLEN, 512, 1);         // set blocklength of transfers to 512 to be shure (all cards must support this value)
        if(i == FFS_NO_ERR) {
            FFS_values.maxsectors *= (FFS_values.sectorsize / 512);
            FFS_values.sectorsize  = 512;                  // recalculate maxsectors, set sectorsize
            FFSp_sshift            = 9;                    // and set shift manually (possible only on none HD-MMC- and SDHC-cards)
        }
    }
    return(&FFS_values);                                   // return the card-size infos
}

/*
************************************************************
*            read a hole sector from the MMC/SD
************************************************************
*/
U08 FFSPort_ReadSector(U32 sector, U08 OS_HUGE *buff)
{
    U08 res;

    res = FFSPort_MediaDetect();
	if(res != FFS_NO_ERR) return(res);                     // media present ?
    res = MMCReadBlock(MMC_READ_SINGLE_BLOCK, sector << FFSp_sshift, buff, FFS_values.sectorsize);
    if(res != FFS_NO_ERR) return(MMCReadStatus(res));      // read a hole sector and ...
    return(FFS_NO_ERR);                                    // ... read status if was an error
}

/*
************************************************************
*            write a hole sector to the MMC/SD
************************************************************
*/
U08 FFSPort_WriteSector(U32 sector, U08 OS_HUGE *buff)
{
    U32 i;
    U08 res;

    res = FFSPort_MediaDetect();
	if(res != FFS_NO_ERR) return(res);                     // media present ?
    if(FFSPort_MMC_WP()) return(FFS_WR_PROTECT);           // device is write protect
    res = MMCWriteCMD(MMC_WRITE_SINGLE_BLOCK, sector << FFSp_sshift, 0);
    if(res != FFS_NO_ERR) {
        FFSPort_MMC_CS_OFF; return(MMCReadStatus(res));    // cmd24 R1-error -> WriteProtect ?
    }
    FFSPort_MMC_Send(0xFF);                                // wait "Nwr" in front of wr-data
    FFSPort_MMC_Send(0xFE);                                // send startbyte
#ifdef USE_MMC_DMA
    FFSPort_MMC_TxBlock(buff, FFS_values.sectorsize);      // write datablock via DMA to MMC
#else
    for(i = 0; i < FFS_values.sectorsize; i++) {
        FFSPort_MMC_Send(buff[i]);                         // send datablock to MMC
    }
#endif
    FFSPort_MMC_Send(0xFF); FFSPort_MMC_Send(0xFF);        // write dummy CRC16 to MMC
    res = FFSPort_MMC_Send(0xFF);                          // get data-response (no "Nxx")
    switch(res & MMC_DR_MASK) {                            // mask data-response code
        case MMC_DR_REJECT_WRITE_ERROR:                    // ** data rejected due to a write error
            FFSPort_MMC_CS_OFF;                            //    disable MMC-interface
            return(MMCReadStatus(res));                    //    read status & return the error
            //lint -unreachable
//            break;
        case MMC_DR_ACCEPT:                                // ** data accepted
            i = 0;                                         //    wait "Nbusy" while busy
            while((FFSPort_MMC_Send(0xFF) != 0xFF) && (i < MMC_Nbs)) i++;
            if(i < MMC_Nbs) break;                         //    if error - too long busy
            //lint -fallthrough
        case MMC_DR_REJECT_CRC:                            // ** data rejected due to a CRC error
        default:
            FFSPort_MMC_CS_OFF;                            //    disable MMC-interface
            return(FFS_PORT_ERR);                          //    error
            //lint -unreachable
//            break;
    }
    FFSPort_MMC_CS_OFF;                                    // disable MMC-interface
    return(FFS_NO_ERR);                                    // no error
}



⌨️ 快捷键说明

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