This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SDHost with DMA enabled

Hello everyone,

I try to change the sdhost example to support dma transfer, but "SDHOST_INT_DMARD" never occurs. I think I missed something in documentation or with my configuration? Maybe someone could point me in the right direction?

Here's what I've done:

static void _ISRHandler() {
    unsigned long tmp = SDHostIntStatus(SDHOST_BASE);

    MAP_SDHostIntClear(SDHOST_BASE, ALL_IRQS);

    if (tmp & SDHOST_INT_DMARD) {
       (void)osi_SyncObjSignalFromISR(ReadWriteSyncObj);
    }
}

static DRESULT _ReadWithDma(UINT32 cmd, BYTE* buff, DWORD sector, UINT32 ulSize) {
    DRESULT Res = RES_ERROR;

    if (NULL == ReadWriteSyncObj) {
        if (OSI_OK != osi_SyncObjCreate(&ReadWriteSyncObj)) {
            return (RES_NOTRDY);
        }

        MAP_SDHostIntRegister(SDHOST_BASE, _ISRHandler);
    }

    SetupTransfer(UDMA_CH23_SDHOST_RX,
            UDMA_MODE_BASIC,
            ulSize,
            UDMA_SIZE_32,
            UDMA_ARB_8,
            (void *)(SDHOST_BASE + MMCHS_O_DATA),
            UDMA_SRC_INC_NONE,
            (void *)buff,
            UDMA_DST_INC_32);

    if( CardSendCmd((cmd | SDHOST_DMA_EN), sector) == 0 )
    {
        MAP_SDHostIntClear(SDHOST_BASE, ALL_IRQS);
        MAP_SDHostIntEnable(SDHOST_BASE, SDHOST_INT_DMARD);

        (void)osi_SyncObjWait(ReadWriteSyncObj, OSI_WAIT_FOREVER);

        if (CMD_READ_MULTI_BLK == cmd) {
          CardSendCmd(CMD_STOP_TRANS,0);
        }

        Res = RES_OK;
    }

    return (Res);
}

Thanks in advance,

Markus

  • Hi Markus,

    From the above code looks like you have not set the block count. Please use the MAP_SDHostBlockCountSet() API to set the block count.

    And, you might have already noticed, the block size is set to 512 bytes in the example.

    Let me know if this helps.

    Thanks and Regards,
    Praveen
  • Hi Praveen,

    thank your for your response.
    I call MAP_SDHostBlockCountSet() outside of my _ReadWithDma function, but it is in use already. Do you have any other ideas what I could try?

    Markus
  • Hi Markus,

    There are few know issues in SDK 1.0.0 please refer to http://processors.wiki.ti.com/index.php/CC32xx_Summary_of_Known_Issues

    See "Applications Changes". Have you taken those changes ?

    Thanks and Regards,

    Praveen

  • Hi Praveen,
    I use SDK 1.0.0.2 and I cross-checked it in code, just to be sure. I think everything is fine here.

    But am I correct that SDHOST_INT_DMARD should be trigged if read is completely done and data is available in buff?
  • Markus,

    I am not able to re-create your issue.

    I have modified the main.c in SDHost example for DMA support.

    void SDHostIntHandler()
    {
      MAP_SDHostIntClear(SDHOST_BASE, SDHOST_INT_DMARD);
      g_ulDMADone = 1;
    }


    static unsigned long CardReadBlock(CardAttrib_t *Card, unsigned char *pBuffer, unsigned long ulBlockNo, unsigned long ulBlockCount) { unsigned long ulSize; // // SDSC linear address instead of block address // if(Card->ulCapClass == CARD_CAP_CLASS_SDSC) { ulBlockNo = ulBlockNo * 512; } // // Set the number of block on the host // MAP_SDHostBlockCountSet(SDHOST_BASE,ulBlockCount); // // Compute total size in words. // ulSize = (512*ulBlockCount)/4; SetupTransfer(UDMA_CH23_SDHOST_RX,UDMA_MODE_BASIC,ulSize,UDMA_SIZE_32,UDMA_ARB_1, (void *)(SDHOST_BASE + MMCHS_O_DATA),UDMA_SRC_INC_NONE,(void *) pBuffer,UDMA_DST_INC_32); // // Send multi block read command to the card // if( SendCmd(CMD_READ_MULTI_BLK|SDHOST_DMA_EN, ulBlockNo) == 0 ) { #if 0 // // Read out the data. // while(ulSize--) { MAP_SDHostDataRead(SDHOST_BASE,(unsigned long *)pBuffer); pBuffer+=4; } #else g_ulDMADone = 0; while( g_ulDMADone != 1 ) { } #endif // // Send multi block read stop command to the card // SendCmd(CMD_STOP_TRANS,0); // // return success. // return 0; } // // Return error // return 1; }
    And few changes in main()

    //
        // Configure SDHOST
        //
        MAP_SDHostInit(SDHOST_BASE);
    
        //
        // Register Interrupt
        //
        MAP_SDHostIntRegister(SDHOST_BASE, SDHostIntHandler);
    
        //
        // Interrupt Enable
        //
        MAP_SDHostIntEnable(SDHOST_BASE, SDHOST_INT_DMARD);
    
        //
        // Configure card clock to 15 Mhz
        //
        MAP_SDHostSetExpClk(SDHOST_BASE, MAP_PRCMPeripheralClockGet(PRCM_SDHOST),
                                15000000);
    

    Thanks and Regards,

    Praveen

  • Thanks for your reply.

    I changed my sdhost example according to your instructions but still no interrupt on my side. That's a strange behavior!

  • Hi Markus,

    That is strange. But let me paste the whole code. Can you apply these changes to SDK example and let me know.


    static unsigned long CardReadBlock(CardAttrib_t *Card, unsigned char *pBuffer, unsigned long ulBlockNo, unsigned long ulBlockCount) { unsigned long ulSize; // // SDSC linear address instead of block address // if(Card->ulCapClass == CARD_CAP_CLASS_SDSC) { ulBlockNo = ulBlockNo * 512; } // // Set the number of block on the host // MAP_SDHostBlockCountSet(SDHOST_BASE,ulBlockCount); // // Compute total size in words. // ulSize = (512*ulBlockCount)/4; SetupTransfer(UDMA_CH23_SDHOST_RX,UDMA_MODE_BASIC,ulSize,UDMA_SIZE_32,UDMA_ARB_1, (void *)(SDHOST_BASE + MMCHS_O_DATA),UDMA_SRC_INC_NONE,(void *) pBuffer,UDMA_DST_INC_32); // // Send multi block read command to the card // if( SendCmd(CMD_READ_MULTI_BLK|SDHOST_DMA_EN, ulBlockNo) == 0 ) { #if 0 // // Read out the data. // while(ulSize--) { MAP_SDHostDataRead(SDHOST_BASE,(unsigned long *)pBuffer); pBuffer+=4; } #else g_ulDMADone = 0; while( g_ulDMADone != 1 ) { } #endif // // Send multi block read stop command to the card // SendCmd(CMD_STOP_TRANS,0); // // return success. // return 0; } // // Return error // return 1; }
    int main()
    {
        CardAttrib_t sCard;
        unsigned long ulCapacity;
        unsigned long ulAddress;
    
        //
        // Initialize Board configurations
        //
        BoardInit();
    
        //
        // Muxing for Enabling UART_TX and UART_RX.
        //
        PinMuxConfig();
    
        //
        // Initializing the Terminal.
        //
        InitTerm();
    
        //
        // Clearing the Terminal.
        //
        ClearTerm();
    
        //
        // Initialize Udma
        //
        UDMAInit();
    
        //
        // Display the Banner
        //
        Message("\n\n\n\r");
        Message("\t\t   *************************************\n\r");
        Message("\t\t        CC3200 SDHost Demo Application  \n\r");
        Message("\t\t   *************************************\n\r");
        Message("\n\n\n\r");
    
        //
        // Set the SD card clock as output pin
        //
        MAP_PinDirModeSet(PIN_07,PIN_DIR_MODE_OUT);
    
        //
        // Enable Pull up on data
        //
        MAP_PinConfigSet(PIN_06,PIN_STRENGTH_4MA, PIN_TYPE_STD_PU);
    
        //
        // Enable Pull up on CMD
        //
        MAP_PinConfigSet(PIN_08,PIN_STRENGTH_4MA, PIN_TYPE_STD_PU);
    
        //
        // Enable SDHOST
        //
        MAP_PRCMPeripheralClkEnable(PRCM_SDHOST,PRCM_RUN_MODE_CLK);
    
        //
        // Reset SDHOST
        //
        MAP_PRCMPeripheralReset(PRCM_SDHOST);
    
        //
        // Configure SDHOST
        //
        MAP_SDHostInit(SDHOST_BASE);
    
        //
        // Register Interrupt
        //
        MAP_SDHostIntRegister(SDHOST_BASE, SDHostIntHandler);
    
        //
        // Interrupt Enable
        //
        MAP_SDHostIntEnable(SDHOST_BASE, SDHOST_INT_DMARD);
    
        //
        // Configure card clock to 15 Mhz
        //
        MAP_SDHostSetExpClk(SDHOST_BASE, MAP_PRCMPeripheralClockGet(PRCM_SDHOST),
                                15000000);
    
        //
        // Initialize the card
        //
        if( CardInit(&sCard) )
        {
            Message("Error : Failed to initialize the card. Check "
                        "if card is properly inserted \n\r");
        }
        else
        {
            //
            // Print Card Details
            //
            ulCapacity = (sCard.ullCapacity/(1024*1024));
            Message("********************\n\r");
            Message("Card Info \n\r");
            Message("********************\n\r");
            Report("Card Type   : %s \n\r",
                        (sCard.ulCardType == CARD_TYPE_MMC)?"MMC":"SD Card");
            Report("Class       : %s \n\r",
                        (sCard.ulCapClass == CARD_CAP_CLASS_SDHC)?"SDHC":"SDSC");
            Report("Capacity    : %d MB \n\r",ulCapacity);
            Report("Version     : Ver %s \n\r",
                            (sCard.ulVersion  == CARD_VERSION_2)?"2.0":"1.0");
    
            //
            // Select the card
            //
            CardSelect(&sCard);
    
            //
            // Set the block size on the controller.
            //
            MAP_SDHostBlockSizeSet(SDHOST_BASE,512);
    
            Message("\n\rReading first Block.....\n\r");
    
            //
            // Read 1 Block (512 Bytes) from the card
            //
            CardReadBlock(&sCard,g_ucDataBuff,0,1);
    
            //
            // Display the content
            //
            for(ulAddress=0; ulAddress < 512; ulAddress++)
            {
                if(ulAddress%20 == 0)
                {
                    Report("\n\r%0.4x :", ulAddress);
                }
                Report("%2.2x ",g_ucDataBuff[ulAddress]);
            }
    
    #if WRITE_TEST_EN
    
            Message("\n\n\rWriting first Block.....\n\n\r");
            Message("Info : This will corrupt the existing filesystem on the card\n\r");
    
            //
            // Initialize the buffer with pattern
            //
            for(ulAddress = 0; ulAddress < 512; ulAddress++)
            {
              g_ucDataBuff[ulAddress] = ulAddress;
            }
    
            //
            // Write 1 block (512 bytes) to the card
            //
            CardWriteBlock(&sCard,g_ucDataBuff,0,1);
    
    #endif
    
            //
            // de-select the card
            //
            CardDeselect();
        }
    
        //
        // Infinite loop;
        //
        while(1)
        {
    
        }
    }
    

    Thanks and Regards

    Praveen

  • Hi Praveen,

    sorry, I missed the UDMAInit(); in first try.

    Now the behavior is same as in my original code. I get into the interrupt handler, but SDHostIntStatus(SDHOST_BASE) returns (SDHOST_INT_CC | SDHOST_INT_TC) not SDHOST_INT_DMARD. Can you confirm that?
  • Hi,

    My bad, I misunderstood your question initially, though you were not getting interrupts at all.

    There is an issue in SDHostIntStatus(), will be fixed in next SDK update.

    Here is the fix.

    unsigned long
    SDHostIntStatus(unsigned long ulBase)
    {
      unsigned long ulIntStatus;

      //
      // Get DMA done interrupt status
      //
      ulIntStatus = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET);

      ulIntStatus = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_RAW);


      ulIntStatus = (ulIntStatus << 30);

      //
      // Return the status of individual interrupt sources
      //
      ulIntStatus |= (HWREG(ulBase + MMCHS_O_STAT) & 0x3FFFFFFF);

      return(ulIntStatus);
    }

    Thanks and Regards,

    Praveen

  • Hi Praveen,

    it looks promising :-)

    Before we close this let me please ask another short (and hopefully related enough) question.

    I am confused how SDHOST_INT_DEB is related to SDHOST_INT_DTO and SDHOST_INT_DCRC? I had the understanding that every bit is a single case (except SDHOST_INT_ERRI), but then there is this definition:

    #define SDHOST_INT_DTO   0x00100000

    #define SDHOST_INT_DCRC  0x00200000

    #define SDHOST_INT_DEB   0x00300000

  • Markus,

    Thanks for pointing this out we will fix this in the next SDK update.

    Yes. you are right, every bit is a single case.

    #define SDHOST_INT_DEB 0x00400000

    Thanks and Regards,
    Praveen