/* ** This configures the PaRAM set for the Dummy Transfer. */ static void TxDummyPaRAMConfEnable(void) { EDMA3CCPaRAMEntry dummyPaRAMSet; EDMA3GetPaRAM(SOC_EDMA30CC_0_REGS, DUMMY_CH_NUM, &dummyPaRAMSet); dummyPaRAMSet.aCnt = 1; dummyPaRAMSet.bCnt = 0; dummyPaRAMSet.cCnt = 0; dummyPaRAMSet.srcAddr = 0; dummyPaRAMSet.destAddr = 0; dummyPaRAMSet.srcBIdx = 0; dummyPaRAMSet.destBIdx = 0; dummyPaRAMSet.srcCIdx = 0; dummyPaRAMSet.destCIdx = 0; dummyPaRAMSet.linkAddr = 0xFFFFu; dummyPaRAMSet.bCntReload = 0; dummyPaRAMSet.opt = 0; EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, DUMMY_CH_NUM, &dummyPaRAMSet); }
/** * Write block(s) from MMC/SD card. The implementation follows * '26.3.5 MMC/SD Mode Single-Block Read Operation Using EDMA' in 'spruh82a'. * @param mmcsdCtrlInfo It holds the mmcsd control information. * @param ptr It determines the address from where data has to written * @param block It determines to which block data to be written (block >= 0) * @param nblks It determines the number of blocks to be written (nblks >= 1) * @retval 1 success * @retval 0 fail */ unsigned int MMCSDWriteCmdSend(mmcsdCtrlInfo *ctrl, void *ptr, unsigned int block, unsigned int nblks) { // TODO: workaround for buggy WRITE_MULTI_BLOCK if (nblks > 1) { for (unsigned int i = 0; i < nblks; ++i) { unsigned int res = MMCSDWriteCmdSend(ctrl, ptr + i * MMCSD_MAX_BLOCK_LEN, block + i, 1); assert(res == 1); } return 1; } assert(nblks == 1); unsigned int status = 1; // 1 for success volatile struct st_mmcsd *mmc = ctrl->memBase; ER ercd; /* 1. Write the card's relative address to the MMC argument registers (MMCARGH and MMCARGL). */ mmcsdCardInfo *card = ctrl->card; unsigned int address; /* * TODO: check this -- ertl-liyixiao * Address is in blks for high cap cards and in actual bytes * for standard capacity cards */ assert(card->highCap); if (card->highCap) address = block; else address = block * card->blkLen; mmc->MMCARGHL = address; /* 2. Read card CSD to determine the card's maximum block length. */ // TODO: // syslog(LOG_ERROR, "card->raw_csd[0]: 0x%08x", card->raw_csd[0]); // syslog(LOG_ERROR, "card->raw_csd[1]: 0x%08x", card->raw_csd[1]); // syslog(LOG_ERROR, "card->raw_csd[2]: 0x%08x", card->raw_csd[2]); // syslog(LOG_ERROR, "card->raw_csd[3]: 0x%08x", card->raw_csd[3]); syslog(LOG_ERROR, "MMCCTL: 0x%08x", mmc->MMCCTL); /* 3. Use the MMC command register (MMCCMD) to send the SET_BLOCKLEN command (if the block length is different than the length used in the previous operation). The block length must be a multiple of 512 bytes and less then the maximum block length specified in the CSD. */ syslog(LOG_ERROR, "MMCCTL: 0x%08x", mmc->MMCCTL); syslog(LOG_ERROR, "MMCCLK: 0x%08x", mmc->MMCBLEN); // TODO: /* 4. Reset the FIFO (FIFORST bit in MMCFIFOCTL). */ mmc->MMCFIFOCTL |= MMCSD_MMCFIFOCTL_FIFORST; mmc->MMCFIFOCTL &= ~MMCSD_MMCFIFOCTL_FIFORST; /* 5. Set the FIFO direction to send (FIFODIR bit in MMCFIFOCTL). */ mmc->MMCFIFOCTL |= MMCSD_MMCFIFOCTL_FIFODIR; /* 6. Set the access width (ACCWD bits in MMCFIFOCTL). */ mmc->MMCFIFOCTL &= ~MMCSD_MMCFIFOCTL_ACCWD; mmc->MMCFIFOCTL |= (MMCSD_MMCFIFOCTL_ACCWD_4BYTES << MMCSD_MMCFIFOCTL_ACCWD_SHIFT); // => 4 bytes /* 7. Set the FIFO threshold (FIFOLEV bit in MMCFIFOCTL). */ mmc->MMCFIFOCTL |= MMCSD_MMCFIFOCTL_FIFOLEV; // => 64 bytes /* 8. Set up DMA (DMA size needs to be greater than or equal to FIFOLEV setting). */ CacheDataCleanBuff((unsigned int) ptr, (MMCSD_MAX_BLOCK_LEN * nblks)); // Clean data buffer to send arm926_drain_write_buffer(); // Memory barrier for data buffer to send ctrl->xferSetup(ctrl, 0, ptr, MMCSD_MAX_BLOCK_LEN, nblks); { syslog(LOG_ERROR, "origSrcAddr: 0x%08x", ptr); EDMA3CCPaRAMEntry param; EDMA3GetPaRAM(&EDMA3_CC0, EDMA3_CHA_MMCSD0_TX, ¶m); syslog(LOG_ERROR, "srcAddr: 0x%08x", param.srcAddr); } /* 9. Use MMCCMD to send the WRITE_BLOCK command to the card. */ #if defined(DEBUG) syslog(LOG_ERROR, "%s(): Use MMCCMD to send the WRITE_BLOCK/WRITE_MULTI_BLOCK command to the card.", __FUNCTION__); #endif mmcsdCmd cmd; cmd.flags = SD_CMDRSP_R1 | SD_CMDRSP_WRITE | SD_CMDRSP_DATA; cmd.arg = address; cmd.nblks = nblks; if (nblks > 1) { cmd.idx = SD_CMD(25); cmd.flags |= SD_CMDRSP_ABORT; } else { cmd.idx = SD_CMD(24); } status = MMCSDCmdSend(ctrl, &cmd); if (status == 0) { syslog(LOG_ERROR, "%s(): MMCSDCmdSend() failed.", __FUNCTION__); goto error_exit; } // CPU Mode // uint32_t *buf = ptr; // Assume uint32_t is little-endian // while (1) { // EDMA3CCPaRAMEntry param; //// syslog(LOG_ERROR, "MMCSD0.MMCST0: 0x%08x", MMCSD0.MMCST0); //// syslog(LOG_ERROR, "MMCSD0.MMCST1: 0x%08x", MMCSD0.MMCST1); //// syslog(LOG_ERROR, "EDMA3_CC0.ER: 0x%08x", EDMA3_CC0.ER); //// syslog(LOG_ERROR, "EDMA3_CC0.EMR: 0x%08x", EDMA3_CC0.EMR); //// syslog(LOG_ERROR, "EDMA3_CC0.SER: 0x%08x", EDMA3_CC0.SER); // EDMA3GetPaRAM(&EDMA3_CC0, EDMA3_CHA_MMCSD0_TX, ¶m); //// syslog(LOG_ERROR, "origSrcAddr: 0x%08x", ptr); // syslog(LOG_ERROR, "srcAddr: 0x%08x", param.srcAddr); //// syslog(LOG_ERROR, "CCNT: %d", param.cCnt); // // tslp_tsk(1000); // } /* 10. Set the DMATRIG bit in MMCCMD to trigger the first data transfer. */ #if DEBUG_PRINT // syslog(LOG_ERROR, "%s(): Set the DMATRIG bit, MMCCMD: 0x%08x=>0x%08x", __FUNCTION__, mmc->MMCCMD, mmc->MMCCMD | MMCSD_MMCCMD_DMATRIG); #endif // mmc->MMCCMD /*|*/= MMCSD_MMCCMD_DMATRIG; /* 11. Wait for DMA sequence to complete. */ status = ctrl->xferStatusGet(ctrl); if (status == 0) { assert(false); goto error_exit; } error_exit: return status; #if 0 mmcsdCardInfo *card = ctrl->card; unsigned int status = 0; unsigned int address; mmcsdCmd cmd; #if DEBUG_PRINT UARTprintf("----\r\n"); UARTprintf("%s(0x%x)\r\n", __FUNCTION__, ctrl); #endif }
void EDMAAppEDMA3Test() { volatile unsigned int index = 0u; volatile unsigned int count = 0u; EDMA3CCPaRAMEntry paramSet; unsigned char data = 0u; volatile unsigned int retVal = 0u; unsigned int isTestPassed = false; unsigned int numEnabled = 0u; unsigned int aCount = EDMAAPP_MAX_ACOUNT; unsigned int bCount = EDMAAPP_MAX_BCOUNT; unsigned int cCount = EDMAAPP_MAX_CCOUNT; /* Initalize source and destination buffers */ for (count = 0u; count < (aCount * bCount * cCount); count++) { SrcBuff[count] = data++; /* ** No need to initialize the destination buffer as it is ** being invalidated. */ } /* Request DMA channel and TCC */ retVal = EDMA3RequestChannel(EDMAAPP_EDMACC_BASE_ADDRESS, EDMAAPP_DMA_CH_TYPE, EDMAAPP_DMA_CH_NUM, EDMAAPP_DMA_TCC_NUM, EDMAAPP_DMA_EVTQ); /* Registering Callback Function */ EDMAAppCallbackFxn[EDMAAPP_DMA_TCC_NUM] = &EDMAAppCallback; if(TRUE == retVal) { /* Fill the PaRAM Set with transfer specific information */ paramSet.srcAddr = (unsigned int)(SrcBuff); paramSet.destAddr = (unsigned int)(DstBuff); paramSet.aCnt = (unsigned short)aCount; paramSet.bCnt = (unsigned short)bCount; paramSet.cCnt = (unsigned short)cCount; /* Setting up the SRC/DES Index */ paramSet.srcBIdx = (short)aCount; paramSet.destBIdx = (short)aCount; if(EDMA3_SYNC_A == EDMAAPP_DMA_SYNC_TYPE) { /* A Sync Transfer Mode */ paramSet.srcCIdx = (short)aCount; paramSet.destCIdx = (short)aCount; } else { /* AB Sync Transfer Mode */ paramSet.srcCIdx = ((short)aCount * (short)bCount); paramSet.destCIdx = ((short)aCount * (short)bCount); } /* Configure the paramset with NULL link */ paramSet.linkAddr = (unsigned short)0xFFFFu; paramSet.bCntReload = (unsigned short)0u; paramSet.opt = 0u; /* Src & Dest are in INCR modes */ paramSet.opt &= ~(EDMA3CC_OPT_SAM | EDMA3CC_OPT_DAM); /* Program the TCC */ paramSet.opt |= ((EDMAAPP_DMA_TCC_NUM << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC); /* Enable Intermediate & Final transfer completion interrupt */ paramSet.opt |= (1u << EDMA3CC_OPT_ITCINTEN_SHIFT); paramSet.opt |= (1u << EDMA3CC_OPT_TCINTEN_SHIFT); if(EDMA3_SYNC_A == EDMAAPP_DMA_SYNC_TYPE) { paramSet.opt &= ~EDMA3CC_OPT_SYNCDIM; } else { /* AB Sync Transfer Mode */ paramSet.opt |= (1u << EDMA3CC_OPT_SYNCDIM_SHIFT); } /* Now, write the PaRAM Set. */ EDMA3SetPaRAM(EDMAAPP_EDMACC_BASE_ADDRESS, EDMAAPP_DMA_CH_NUM, ¶mSet); EDMA3GetPaRAM(EDMAAPP_EDMACC_BASE_ADDRESS, EDMAAPP_DMA_CH_NUM, ¶mSet); } /* ** Since the transfer is going to happen in Manual mode of EDMA3 ** operation, we have to 'Enable the Transfer' multiple times. ** Number of times depends upon the Mode (A/AB Sync) ** and the different counts. */ if(TRUE == retVal) { /* Need to activate next param */ if(EDMA3_SYNC_A == EDMAAPP_DMA_SYNC_TYPE) { numEnabled = bCount * cCount; } else { /* AB Sync Transfer Mode */ numEnabled = cCount; } for(index = 0u; index < numEnabled; index++) { IrqRaised = EDMAAPP_IRQ_STATUS_XFER_INPROG; /* ** Now enable the transfer as many times as calculated above. */ retVal = EDMA3EnableTransfer(EDMAAPP_EDMACC_BASE_ADDRESS, EDMAAPP_DMA_CH_NUM, EDMAAPP_DMA_TRIG_MODE); /* Wait for the Completion ISR. */ while(EDMAAPP_IRQ_STATUS_XFER_INPROG == IrqRaised) { /* ** Wait for the Completion ISR on Master Channel. ** You can insert your code here to do something ** meaningful. */ } /* Check the status of the completed transfer */ if(IrqRaised < (int)EDMAAPP_IRQ_STATUS_XFER_INPROG) { /* Some error occured, break from the FOR loop. */ ConsoleUtilsPrintf("\r\nEDMA3Test: Event Miss Occured!!!\r\n"); /* Clear the error bits first */ EDMA3ClearErrorBits(EDMAAPP_EDMACC_BASE_ADDRESS, EDMAAPP_DMA_CH_NUM, EDMAAPP_DMA_EVTQ); break; } } } /* Match the Source and Destination Buffers. */ if(TRUE == retVal) { for(index = 0u; index < (aCount * bCount * cCount); index++) { if(SrcBuff[index] != DstBuff[index]) { isTestPassed = false; ConsoleUtilsPrintf("EDMA3Test: Data write-read matching FAILED.\r\n"); ConsoleUtilsPrintf("The mismatch happened at index : %d\r\n", ((int)index + 1u)); break; } } if(index == (aCount * bCount * cCount)) { isTestPassed = true; ConsoleUtilsPrintf("EDMA3Test: Data write-read matching PASSED.\r\n"); } /* Free the previously allocated channel. */ retVal = EDMA3FreeChannel(EDMAAPP_EDMACC_BASE_ADDRESS, EDMAAPP_DMA_CH_TYPE, EDMAAPP_DMA_CH_NUM, EDMAAPP_DMA_TRIG_MODE, EDMAAPP_DMA_TCC_NUM, EDMAAPP_DMA_EVTQ); /* Unregister Callback Function */ EDMAAppCallbackFxn[EDMAAPP_DMA_TCC_NUM] = NULL; if(TRUE != retVal) { ConsoleUtilsPrintf("EDMA3Test: EDMA3_DRV_freeChannel() FAILED.\r\n"); } } if(true == isTestPassed) { ConsoleUtilsPrintf("EDMA3Test PASSED.\r\n"); } else { ConsoleUtilsPrintf("EDMA3Test FAILED\r\n"); } }