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

📄 mci.c

📁 at91sam7a3 keil下sdcard驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
    // Disable transmitter and receiver
    WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);

    mciMr = READ_MCI(pMciHw, MCI_MR) & (~(AT91C_MCI_WRPROOF|AT91C_MCI_RDPROOF|AT91C_MCI_BLKLEN | AT91C_MCI_PDCMODE));

    // Command with DATA stage
    if (pCommand->blockSize > 0) {
        // Enable PDC mode and set block size
        if(pCommand->conTrans != MCI_CONTINUE_TRANSFER) {

            WRITE_MCI(pMciHw, MCI_MR, mciMr | AT91C_MCI_PDCMODE |AT91C_MCI_RDPROOF|AT91C_MCI_WRPROOF|(pCommand->blockSize << 16));
        }

        // DATA transfer from card to host
        if (pCommand->isRead) {
            WRITE_MCI(pMciHw, MCI_RPR, (int) pCommand->pData);

            // Sanity check
            if (pCommand->nbBlock == 0)
                pCommand->nbBlock = 1;
            ////////
            if ((pCommand->blockSize & 0x3) != 0) {
                WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);
            }
            else {
                WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4);
            }

            WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);
            mciIer = AT91C_MCI_ENDRX | STATUS_ERRORS;
            // mciIer = AT91C_MCI_RXBUFF | STATUS_ERRORS;
        }

        // DATA transfer from host to card
        else {
            // Sanity check
            if (pCommand->nbBlock == 0)
                pCommand->nbBlock = 1;
            WRITE_MCI(pMciHw, MCI_TPR, (int) pCommand->pData);
            // Update the PDC counter
            if ((pCommand->blockSize & 0x3) != 0) {
                WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);
            }
            else {
                WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4);
            }
            // MCI_BLKE notifies the end of Multiblock command
            mciIer = AT91C_MCI_BLKE | STATUS_ERRORS;
        }
    }
    // No data transfer: stop at the end of the command
    else {
        WRITE_MCI(pMciHw, MCI_MR, mciMr);
        mciIer = AT91C_MCI_CMDRDY | STATUS_ERRORS;
    }
    // Enable MCI clock
    MCI_Enable(pMci, ENABLE);

    // Send the command
    if((pCommand->conTrans != MCI_CONTINUE_TRANSFER)
        || (pCommand->blockSize == 0)) {

        WRITE_MCI(pMciHw, MCI_ARGR, pCommand->arg);
        WRITE_MCI(pMciHw, MCI_CMDR, pCommand->cmd);
    }

    // In case of transmit, the PDC shall be enabled after sending the command
    if ((pCommand->blockSize > 0) && !(pCommand->isRead)) {
        WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);
    }

    // Ignore data error
    mciIer &= ~(AT91C_MCI_UNRE | AT91C_MCI_OVRE \
              | AT91C_MCI_DTOE | AT91C_MCI_DCRCE);

    // Interrupt enable shall be done after PDC TXTEN and RXTEN
    WRITE_MCI(pMciHw, MCI_IER, mciIer);

    return 0;
}

//------------------------------------------------------------------------------
/// Check NOTBUSY and DTIP bits of status register on the given MCI driver.
/// Return value, 0 for bus ready, 1 for bus busy
/// \param pMci  Pointer to a MCI driver instance.
//------------------------------------------------------------------------------
unsigned char MCI_CheckBusy(Mci *pMci)
{
    AT91S_MCI *pMciHw = pMci->pMciHw;
    unsigned int status;

    // Enable MCI clock
    MCI_Enable(pMci, ENABLE);

    status = READ_MCI(pMciHw, MCI_SR);
    // TRACE_DEBUG("status %x\n\r",status);


    if(((status & AT91C_MCI_NOTBUSY)!=0)
        && ((status & AT91C_MCI_DTIP)==0)) {

        // Disable MCI clock
        MCI_Enable(pMci, DISABLE);

        return 0;
    }
    else {
        return 1;
    }
}

//------------------------------------------------------------------------------
/// Check BLKE bit of status register on the given MCI driver.
/// \param pMci  Pointer to a MCI driver instance.
//------------------------------------------------------------------------------
unsigned char MCI_CheckBlke(Mci *pMci)
{
    AT91S_MCI *pMciHw = pMci->pMciHw;
    unsigned int status;

    status = READ_MCI(pMciHw, MCI_SR);
    // TRACE_DEBUG("status %x\n\r",status);

    if((status & AT91C_MCI_BLKE)!=0) {
        return 0;
    }
    else {
        return 1;
    }
}

//------------------------------------------------------------------------------
/// Processes pending events on the given MCI driver.
/// \param pMci  Pointer to a MCI driver instance.
//------------------------------------------------------------------------------
void MCI_Handler(Mci *pMci)
{
    AT91S_MCI *pMciHw = pMci->pMciHw;
    MciCmd *pCommand = pMci->pCommand;
    unsigned int status;
    unsigned char i;
    #if defined(at91rm9200)
    unsigned int mciCr, mciSdcr, mciMr, mciDtor;
    #endif

    SANITY_CHECK(pMci);
    SANITY_CHECK(pMciHw);
    SANITY_CHECK(pCommand);

    // Read the status register
    status = READ_MCI(pMciHw, MCI_SR) & READ_MCI(pMciHw, MCI_IMR);
    // TRACE_DEBUG("status %x\n\r", status);

    // Check if an error has occured
    if ((status & STATUS_ERRORS) != 0) {

        // Check error code
        if ((status & STATUS_ERRORS) == AT91C_MCI_RTOE) {

            pCommand->status = MCI_STATUS_NORESPONSE;
        }
        // if the command is SEND_OP_COND the CRC error flag is always present
        // (cf : R3 response)
        else if (((status & STATUS_ERRORS) != AT91C_MCI_RCRCE)
                  || ((pCommand->cmd != SDCARD_APP_OP_COND_CMD)
                      && (pCommand->cmd != MMC_SEND_OP_COND_CMD))) {

            pCommand->status = MCI_STATUS_ERROR;
        }
    }

    // Check if a transfer has been completed
    if (((status & AT91C_MCI_CMDRDY) != 0)
        || ((status & AT91C_MCI_ENDRX) != 0)
        || ((status & AT91C_MCI_RXBUFF) != 0)
        || ((status & AT91C_MCI_ENDTX) != 0)
        || ((status & AT91C_MCI_BLKE) != 0)
        || ((status & AT91C_MCI_RTOE) != 0)) {

        if (((status & AT91C_MCI_ENDRX) != 0)
            || ((status & AT91C_MCI_RXBUFF) != 0)
            || ((status & AT91C_MCI_ENDTX) != 0)) {

            MCI_Enable(pMci, DISABLE);
        }

        /// On AT91RM9200-EK, if stop transmission, software reset MCI.
        #if defined(at91rm9200)
        if ((pCommand->cmd & AT91C_MCI_TRCMD_STOP) != 0) {
            mciMr = READ_MCI(pMciHw, MCI_MR);
            mciSdcr = READ_MCI(pMciHw, MCI_SDCR);
            mciDtor = READ_MCI(pMciHw, MCI_DTOR);
            WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);
            // TRACE_DEBUG("reset MCI\n\r");

            WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);
            WRITE_MCI(pMciHw, MCI_MR, mciMr);
            WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr);
            WRITE_MCI(pMciHw, MCI_DTOR, mciDtor);
        }
        #endif

        // If no error occured, the transfer is successful
        if (pCommand->status == MCI_STATUS_PENDING) {
            pCommand->status = 0;
        }
#if 0
        if ((status & AT91C_MCI_CMDRDY) != 0)
            TRACE_DEBUG_WP(".");
        if ((status & AT91C_MCI_ENDRX) != 0)
            TRACE_DEBUG_WP("<");
        if ((status & AT91C_MCI_ENDTX) != 0)
            TRACE_DEBUG_WP("-");
        if ((status & AT91C_MCI_BLKE) != 0)
            TRACE_DEBUG_WP(">");
        TRACE_DEBUG_WP("\n\r");
#endif
        // Store the card response in the provided buffer
        if (pCommand->pResp) {
            unsigned char resSize;

            switch (pCommand->resType) {
                case 1:
                resSize = 1;
                break;

                case 2:
                resSize = 4;
                break;

                case 3:
                resSize = 1;
                break;

                case 4:
                resSize = 1;
                break;

                case 5:
                resSize = 1;
                break;

                case 6:
                resSize = 1;
                break;

                case 7:
                resSize = 1;
                break;

                default:
                resSize = 0;
                break;
            }
            for (i=0; i < resSize; i++) {

                pCommand->pResp[i] = READ_MCI(pMciHw, MCI_RSPR[0]);
            }
        }

        // Disable interrupts
        WRITE_MCI(pMciHw, MCI_IDR, READ_MCI(pMciHw, MCI_IMR));

        // Release the semaphore
        pMci->semaphore++;

        // Invoke the callback associated with the current command (if any)
        if (pCommand->callback) {
            (pCommand->callback)(pCommand->status, pCommand);
        }
    }
}

//------------------------------------------------------------------------------
/// Returns 1 if the given MCI transfer is complete; otherwise returns 0.
/// \param pCommand  Pointer to a MciCmd instance.
//------------------------------------------------------------------------------
unsigned char MCI_IsTxComplete(MciCmd *pCommand)
{
    if (pCommand->status != MCI_STATUS_PENDING) {
        if (pCommand->status != 0) {
            TRACE_DEBUG("MCI_IsTxComplete %d\n\r", pCommand->status);
        }
        return 1;
    }
    else {
        return 0;
    }
}

⌨️ 快捷键说明

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