Пример #1
0
void doDmaRxTransfer(unsigned short usbDevInst, unsigned int length,
                     unsigned char *buff, unsigned int endPoint)
{
    hostPacketDesc *current_bd = 0;
    usbInstance *usbInstance;

    //ASSERT(buff != 0);

    usbInstance = &(cppiInfo.usbInst[usbDevInst]);

    current_bd = getFreeBd();
    //ASSERT(current_bd != 0);

    endPoint = USB_EP_TO_INDEX(endPoint);

    /* Process the BD */
    Cppi41DmaProcessBD(usbDevInst, current_bd, CPDMA_DIR_RX, buff, length, endPoint);

    /* Clean the cache */
    CacheDataCleanBuff((unsigned int)current_bd,sizeof(hostPacketDesc));

    /*Submit the BD */
    pushToSubmitQ(usbDevInst, usbInstance->rxEndPoint[endPoint].submitq, current_bd);

}
Пример #2
0
/**
 * \brief   This function sends the write command to MMCSD card.
 *
 * \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
 * \param    nblks         It determines the number of blocks to be written
 *
 * \returns  1 - successfull written of data.
 *           0 - failure to write the data.
 **/
unsigned int MMCSDWriteCmdSend(mmcsdCtrlInfo *ctrl, void *ptr, unsigned int block,
                               unsigned int nblks)
{
    mmcsdCardInfo *card = ctrl->card;
    unsigned int status = 0;
    unsigned int address;
    mmcsdCmd cmd;

    /*
     * Address is in blks for high cap cards and in actual bytes
     * for standard capacity cards
     */

    if (card->highCap)
    {
        address = block;
    }
    else
    {
        address = block * card->blkLen;
    }
#ifdef CACHE
    /* Clean the data cache. */
    CacheDataCleanBuff((unsigned int) ptr, (512 * nblks));
#endif
    ctrl->xferSetup(ctrl, 0, ptr, 512, nblks);

    cmd.flags = SD_CMDRSP_WRITE | SD_CMDRSP_DATA | (ctrl->dmaEnable << SD_CMDRSP_DMAEN_OFFSET);
    cmd.arg = address;
    cmd.nblks = nblks;

    if (nblks > 1)
    {
        cmd.idx = SD_CMD(25);
    }
    else
    {
        cmd.idx = SD_CMD(24);
    }


    status = ctrl->cmdSend(ctrl, &cmd);

    if (status == 0)
    {
        return 0;
    }

    status = ctrl->xferStatusGet(ctrl);

    if (status == 0)
    {
        return 0;
    }

    while (!MMCSDWaitCardReadyForData(ctrl));

    return 1;
}
Пример #3
0
/**
 * 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, &param);
		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, &param);
////		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


  }
Пример #4
0
/**
 * Read or write block(s) from MMC/SD card. The implementation follows
 * '26.3.5 MMC/SD Mode Single-Block Read Operation Using EDMA' and
 * '26.3.3 MMC/SD Mode Single-Block Write Operation Using EDMA' in 'spruh82a'.
 * @param  mmcsdCtrlInfo It holds the mmcsd control information.
 * @param  ptr           It determines the address to store or fetch the data
 * @param  block         It determines from which block data to be read or written (block >= 0)
 * @param  nblks         It determines the number of blocks to be read or written (nblks >= 1)
 * @retval 1             success
 * @retval 0             fail
 */
static
unsigned int
MMCSDReadWriteCmdSend(mmcsdCtrlInfo *ctrl, void *ptr, unsigned int block, unsigned int nblks, bool_t rx) {
	unsigned int status = 0; // 0 for failure

	/**
	 * Handle unaligned READ operation using data_recv_buf
	 */
	if (rx && ((unsigned int)ptr % SOC_EDMA3_ALIGN_SIZE) != 0) {
		static uint8_t data_recv_buf[MMCSD_MAX_BLOCK_LEN * 8] __attribute__((aligned(SOC_EDMA3_ALIGN_SIZE)));
#define DATA_RECV_BUF_MAX_BLOCKS (sizeof(data_recv_buf) / MMCSD_MAX_BLOCK_LEN)

		for (unsigned int i = 0; i < nblks; i += DATA_RECV_BUF_MAX_BLOCKS) {
			unsigned int blocks_to_process = (i + DATA_RECV_BUF_MAX_BLOCKS <= nblks) ? DATA_RECV_BUF_MAX_BLOCKS : nblks - i;
			status = MMCSDReadWriteCmdSend(ctrl, data_recv_buf, block + i, blocks_to_process, rx);
			memcpy(ptr + i * MMCSD_MAX_BLOCK_LEN, data_recv_buf, MMCSD_MAX_BLOCK_LEN * blocks_to_process);
			if (status == 0) break;
		}
		goto error_exit;
	}

#if defined(DEBUG_MMCSD)
	syslog(LOG_NOTICE, "%s(): %s %d block(s), ptr=%p", __FUNCTION__, rx ? "Read" : "Write", nblks, ptr);
#endif

	/* 1. Write the card's relative address to the MMC argument registers (MMCARGH and MMCARGL). */
	volatile struct st_mmcsd *mmc = (struct st_mmcsd *)ctrl->memBase;
	if (!ctrl->card->highCap) { // Only SDHC card is supported by now.
		syslog(LOG_ERROR, "%s(): Standard capacity SD card is not supported, please use an SDHC card!", __FUNCTION__);
		goto error_exit;
	}
	mmc->MMCARGHL = block;
#if 0
	mmcsdCardInfo *card = ctrl->card;
	unsigned int address;
	/*
	 * 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;
#endif

	/* 2. Read card CSD to determine the card's maximum block length. */
	// TODO: This step is unnecessary for SDHC card

	/* 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. */
	// TODO: This step is unnecessary for SDHC card

	/* 4. Reset the FIFO (FIFORST bit in MMCFIFOCTL). */
	mmc->MMCFIFOCTL |= MMCSD_MMCFIFOCTL_FIFORST;
	mmc->MMCFIFOCTL &= ~MMCSD_MMCFIFOCTL_FIFORST;

	/* 5. Set the FIFO direction (FIFODIR bit in MMCFIFOCTL). */
	if (rx) // FIFO to receive
		mmc->MMCFIFOCTL &= ~MMCSD_MMCFIFOCTL_FIFODIR;
	else	// FIFO to send
		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). */
#if defined(DEBUG_MMCSD) && 0
	syslog(LOG_NOTICE, "%s(): Set up DMA", __FUNCTION__);
#endif
	if (rx) {
		CacheDataCleanBuff(ptr, MMCSD_MAX_BLOCK_LEN * nblks); // Clean 'data_recv_buf'
		arm926_drain_write_buffer();                              // Memory barrier for 'data_recv_buf'
		ctrl->xferSetup(ctrl, 1, ptr, MMCSD_MAX_BLOCK_LEN, nblks);
	} else {
		data_cache_clean_buffer(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);
	}

	/* 9. Use MMCCMD to send the READ_BLOCK/WRITE_BLOCK command to the card. */
#if defined(DEBUG_MMCSD) && 0
	syslog(LOG_NOTICE, "%s(): Send READ/WRITE command", __FUNCTION__);
#endif
	mmcsdCmd cmd;
	if (rx) {
		cmd.flags = SD_CMDRSP_R1 | SD_CMDRSP_READ | SD_CMDRSP_DATA;
		cmd.idx = SD_CMD(17);
		cmd.nblks = nblks;
		if (nblks > 1) {
			cmd.flags |= SD_CMDRSP_ABORT;
			cmd.idx = SD_CMD(18);
		} else {
			cmd.idx = SD_CMD(17);
		}
	} else {
		cmd.flags = SD_CMDRSP_R1 | SD_CMDRSP_WRITE | SD_CMDRSP_DATA;
		cmd.idx = SD_CMD(24);
		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;
	}

	/* 10. Set the DMATRIG bit in MMCCMD to trigger the first data transfer. */
	// TODO: This step has already been done by last step.
	//mmc->MMCCMD |= MMCSD_MMCCMD_DMATRIG;

	/* 11. Wait for DMA sequence to complete. */
#if defined(DEBUG_MMCSD) && 0
	syslog(LOG_NOTICE, "%s(): Wait for DMA sequence to complete", __FUNCTION__);
#endif
	status = ctrl->xferStatusGet(ctrl);

	if (status == 0) {
		assert(false);
		goto error_exit;
	}
	if (rx) { // Copy data received
		CacheDataInvalidateBuff((unsigned int) ptr, MMCSD_MAX_BLOCK_LEN * nblks); // Invalidate the data cache.
	}

    /* 12. Use the MMC status register 0 (MMCST0) to check for errors. */
	if (rx || nblks == 1) {
#if defined(DEBUG_MMCSD) && 0
	syslog(LOG_NOTICE, "%s(): Wait for DATDNE", __FUNCTION__);
#endif
		ctrl->waitMMCST0(ctrl, MMCSD_MMCST0_DATDNE);
	}

	/* 13. Use MMCCMD to send the STOP_TRANSMISSION command. */
	if (cmd.nblks > 1) {
#if defined(DEBUG_MMCSD) && 0
	syslog(LOG_NOTICE, "%s(): Send STOP_TRANSMISSION", __FUNCTION__);
#endif
		status = MMCSDStopCmdSend(ctrl);
		assert(status != 0);

		ctrl->waitMMCST0(ctrl, MMCSD_MMCST0_BSYDNE);
		//while(HWREG(ctrl->memBase + MMCSD_MMCST1) & MMCSD_MMCST1_BUSY);
	}

error_exit:
	return status;
}
Пример #5
0
/**
 * Read 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 to where data has to read
 * @param  block         It determines from which block data to be read (block >= 0)
 * @param  nblks         It determines the number of blocks to be read (nblks >= 1)
 * @retval 1             success
 * @retval 0             fail
 */
unsigned int
MMCSDReadCmdSend(mmcsdCtrlInfo *ctrl, void *ptr, unsigned int block, unsigned int nblks) {

	// TODO: workaround for buggy READ_MULTI_BLOCK
	if (nblks > 1) {
		for (unsigned int i = 0; i < nblks; ++i) {
			unsigned int res = MMCSDReadCmdSend(ctrl, ptr + i * MMCSD_MAX_BLOCK_LEN, block + i, 1);
			assert(res == 1);
		}
		return 1;
	}
	assert(nblks == 1);

#if defined(DEBUG)
//	UARTprintf("----\r\n");
//	UARTprintf("%s(0x%x)\r\n", __FUNCTION__, ctrl);
//	syslog(LOG_ERROR, "----");
	syslog(LOG_ERROR, "%s(ctrl=0x%p,ptr=0x%p,block=%d,nblks=%d)", __FUNCTION__, ctrl, ptr, block, nblks);
#endif
	assert(nblks * MMCSD_MAX_BLOCK_LEN <= sizeof(data_recv_buf));
//	MMCSDDataTimeoutSet(ctrl->memBase, 0x0, 0x3FFFFFF);// Infinite wait for CMD response, maximum wait for data transfer
//	cmdTimeout = 0; // TODO: fix this (refactoring)
//	for(int i = 0; i < sizeof(data_recv_buf); ++i) data_recv_buf[i] = 0xFF; // Fill data_recv_buf for debug


	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:

	/* 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. */
	// 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 receive (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(data_recv_buf, sizeof(data_recv_buf)); // Clean 'data_recv_buf'
	arm926_drain_write_buffer();                              // Memory barrier for 'data_recv_buf'
	ctrl->xferSetup(ctrl, 1, data_recv_buf/*ptr*/, MMCSD_MAX_BLOCK_LEN, nblks);

	/* 9. Use MMCCMD to send the READ_BLOCK command to the card. */
#if defined(DEBUG)
	syslog(LOG_ERROR, "%s(): Use MMCCMD to send the READ_BLOCK/READ_MULTI_BLOCK command to the card.", __FUNCTION__);
#endif
//	ercd = clr_flg(MMCSD_ISR_FLG, ~(MMCSD_ISR_FLGPTN_DATATIMEOUT)); // Clear data time-out flag
//	mmc->MMCIM |= MMCSD_MMCIM_ETOUTRD; // Enable data time-out interrupt
	assert(ercd == E_OK);
	mmcsdCmd cmd;
	cmd.flags = SD_CMDRSP_R1 | SD_CMDRSP_READ | SD_CMDRSP_DATA;
	cmd.arg = address;
	cmd.nblks = nblks;
	if (nblks > 1) {
		cmd.flags |= SD_CMDRSP_ABORT;
		cmd.idx = SD_CMD(18);
	} else {
		cmd.idx = SD_CMD(17);
	}
	status = MMCSDCmdSend(ctrl, &cmd);
	if (status == 0) {
		syslog(LOG_ERROR, "%s(): MMCSDCmdSend() failed.", __FUNCTION__);
		goto error_exit;
	}

	/* 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; }

	/* Invalidate the data cache. */
	CacheDataInvalidateBuff((unsigned int) data_recv_buf/*ptr*/, (MMCSD_MAX_BLOCK_LEN * nblks));

    /* 12. Use the MMC status register 0 (MMCST0) to check for errors. */
	// TODO: check this
#if 0
	syslog(LOG_ERROR, "%s(): MMCST0: 0x%08x", __FUNCTION__, mmc->MMCST0);
	syslog(LOG_ERROR, "%s(): MMCST1: 0x%08x", __FUNCTION__, mmc->MMCST1);
	syslog(LOG_ERROR, "%s(): MMCNBLK: %d", __FUNCTION__, mmc->MMCNBLK);
	syslog(LOG_ERROR, "%s(): MMCNBLC: %d", __FUNCTION__, mmc->MMCNBLC);
#endif


	assert(sizeof(data_recv_buf) >= MMCSD_MAX_BLOCK_LEN * nblks);
	memcpy(ptr, data_recv_buf, MMCSD_MAX_BLOCK_LEN * nblks);

	  // TODO: ertl-liyixiao
#if defined(DEBUG)
	syslog(LOG_ERROR, "%s sector: %d, count: %d\n", __FUNCTION__, block, nblks);
	  for(int i = 0; i < MMCSD_MAX_BLOCK_LEN * nblks;) {
		  //((uint8_t*)ptr)[i] = ((uint8_t*)ptr)[i];
		  uint8_t *val = ((uint8_t*)ptr) + i;
		  syslog(LOG_ERROR, "%02x %02x %02x %02x %02x", val[0], val[1], val[2], val[3], val[4]);
		  //printf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x \n",
		  //	  val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], val[12], val[13], val[14], val[15]);
		  i += 5;
	  }
#endif

#if 0 // TODO: !IMPORTANT! STOP_TRANSMISSION must not be sent since MMCSD_MMCNBLK has been set to the exact number.
	/* Send a STOP_TRANSMISSION after reading multiple blocks */
	if (cmd.nblks > 1) {
		status = MMCSDStopCmdSend(ctrl);
		assert(status != 0); // TODO: check status
	}
#endif

error_exit:

//	mmc->MMCIM &= ~MMCSD_MMCIM_ETOUTRD; // Disable data time-out interrupt TODO: fix me

	return status;

#if 0


  // TODO: -- ertl-liyixiao
#ifdef CACHE_SUPPORTED
  /* Clean the data cache. */
  CacheDataCleanBuff((unsigned int) ptr, (MMCSD_MAX_BLOCK_LEN * nblks));
#endif
  mmcsd_reset_fifo(true);

  /* Send a STOP */
  if (cmd.nblks > 1)
  {
    status = MMCSDStopCmdSend(ctrl);

    if (status == 0)
    {
#if DEBUG_PRINT
      UARTprintf("%s(0x%x):MMCSDStopCmdSend() returned 0\r\n", __FUNCTION__, ctrl);
#endif
      return 0;
    }
  }

#endif
}
Пример #6
0
void doDmaTxTransfer(unsigned short usbDevInst, unsigned char *buff,
                     unsigned int length, unsigned int endPoint)
{
    hostPacketDesc *current_bd = 0;

    unsigned int numOfBlocks =0;
    unsigned int residue;
    unsigned int i;
    usbInstance *usbInstance;

    usbInstance = &(cppiInfo.usbInst[usbDevInst]);

    endPoint = USB_EP_TO_INDEX(endPoint);

    /*This code segment will take care of the transparent mode transaction */
    if(CPDMA_MODE_SET_TRANSPARENT == usbInstance->txEndPoint[endPoint].mode)
    {
        /* If the data length is less than the USB packet size */
        if(length < USB_PACKET_LENGTH)
        {
            /*get a free db from the BD pool     */
            current_bd = getFreeBd();
            //ASSERT(current_bd != 0);
            //ASSERT(buff != 0);

            /*Clean the cache so that buffer will have proper data */
            CacheDataCleanBuff((unsigned int)buff, length);

            /*This API will initialize the BD fields */
            Cppi41DmaProcessBD(usbDevInst, current_bd, CPDMA_DIR_TX, buff, length, endPoint);

            current_bd->packetId = EOP;

            /*Clean the cache so that bd  will have proper data */
            CacheDataCleanBuff((unsigned int)current_bd,sizeof(hostPacketDesc));

            /*Submit the BD to the queue for transaction     */
            pushToSubmitQ(usbDevInst, usbInstance->txEndPoint[endPoint]
                          .submitq, current_bd);
        }

        /*If the length is more than packet size, then packetize it  */
        else
        {
            numOfBlocks = length / USB_PACKET_LENGTH;
            residue = length -  (numOfBlocks * USB_PACKET_LENGTH);

            for(i=0; i < numOfBlocks; i++)
            {
                /*get a free db from the BD pool     */
                current_bd = getFreeBd();
                //ASSERT(current_bd != 0);
                //ASSERT(buff != 0);

                CacheDataCleanBuff((unsigned int)&buff[i*USB_PACKET_LENGTH],
                                   USB_PACKET_LENGTH);

                /*This API will initialize the BD fields */
                Cppi41DmaProcessBD(usbDevInst, current_bd, CPDMA_DIR_TX,
                                   &buff[i*USB_PACKET_LENGTH], USB_PACKET_LENGTH, endPoint);

                /*Set the packet id to identify the packet position */
                if(numOfBlocks == 1)
                    current_bd->packetId = EOP;
                else if(i==0)
                    current_bd->packetId = SOP;
                else if((numOfBlocks != 1) && (i < (numOfBlocks -1)))
                    current_bd->packetId = MOP;
                else if(i == (numOfBlocks -1) && residue == 0)
                    current_bd->packetId = EOP;
                else
                    current_bd->packetId = MOP;

                CacheDataCleanBuff((unsigned int)current_bd,sizeof(hostPacketDesc));

                /*Submit the BD to the queue for transaction     */
                pushToSubmitQ(usbDevInst, usbInstance->txEndPoint[endPoint]
                              .submitq, current_bd);
            }

            /*If there are some remaining data then send it also */
            if(residue)
            {
                /*get a free db from the BD pool     */
                current_bd = getFreeBd();
                //ASSERT(current_bd != 0);

                CacheDataCleanBuff((unsigned int)&buff[i*USB_PACKET_LENGTH], residue);

                /*This API will initialize the BD fields */
                Cppi41DmaProcessBD(usbDevInst, current_bd, CPDMA_DIR_TX,
                                   &buff[i*USB_PACKET_LENGTH], residue, endPoint);

                current_bd->packetId = EOP;

                /*This API will initialize the BD fields */
                CacheDataCleanBuff((unsigned int)current_bd,sizeof(hostPacketDesc));

                /*Submit the BD to the queue for transaction     */
                pushToSubmitQ(usbDevInst, usbInstance->txEndPoint[endPoint]
                              .submitq, current_bd);
            }

        }
    }

    /*This segment of the code will take care of GRNIS mode of transaction */
    else if(usbInstance->txEndPoint[endPoint].mode == CPDMA_MODE_SET_GRNDIS)
    {
        /*get a free db from the BD pool     */
        current_bd = getFreeBd();
        //ASSERT(current_bd != 0);

        CacheDataCleanBuff((unsigned int)buff, length);

        /*This API will initialize the BD fields */
        Cppi41DmaProcessBD(usbDevInst, current_bd, CPDMA_DIR_TX, buff, length, endPoint);

        current_bd->packetId = EOP;

        CacheDataCleanBuff((unsigned int)current_bd,sizeof(hostPacketDesc));

        /*Submit the BD to the queue for transaction     */
        pushToSubmitQ(usbDevInst, usbInstance->txEndPoint[endPoint]
                      .submitq, current_bd);
    }

}
Пример #7
0
unsigned int MMCSDCardInit(mmcsdCtrlInfo *ctrl)
{

    mmcsdCardInfo *card = ctrl->card;
    unsigned int retry = 0xFFFF;
    unsigned int status = 0;
    unsigned int khz;
    mmcsdCmd cmd;

    memset(ctrl->card, 0, sizeof(mmcsdCardInfo));

    card->ctrl = ctrl;

	/* CMD0 - reset card */
	status = MMCSDCardReset(ctrl);

	if (status == 0)
	{
		card->error = 1;
		return 0;
	}
	//mmc card initialization


    ctrl->card->cardType = MMCSD_CARD_MMC;
    //open drain для команд инициализации
    HWREG(ctrl->memBase + MMCHS_CON) |= MMCHS_CON_OD;

    //Set SD_SYSCTL[25] SRC
    //bit to 0x1 and wait until it returns to 0x0
    HWREG(ctrl->memBase + MMCHS_SYSCTL) |= MMCHS_SYSCTL_SRC;
    while(!(HWREG(ctrl->memBase + MMCHS_SYSCTL) & MMCHS_SYSCTL_SRC));
    while(HWREG(ctrl->memBase + MMCHS_SYSCTL) & MMCHS_SYSCTL_SRC);

   /* CMD1 - SEND_OP_COND */
    retry = RETRY; //с потолка
    cmd.idx = SD_CMD(1);
    cmd.flags = 0;
    cmd.arg = 0x40ff8080;/////карта больше 2 Гб?
    cmd.rsp[0] = 0;
do{
	status = ctrl->cmdSend(ctrl, &cmd);
	if (status == 0) {
    	card->error = 1;
    	return status; //если нет ответа, можно выходить
	}
	//добавил задержку для кривой eMMC СОТА
	delay(10);

} while (!(cmd.rsp[0] & ((unsigned int)BIT(31))) && retry--);

	if (0xffffffff == retry) //карта до 2 Гб?
	{
		retry = RETRY; //c потолка
        cmd.arg = 0x00ff8080; //волшебная цыфорка
		do{
			status = ctrl->cmdSend(ctrl, &cmd);
			if (status == 0) {
		    	card->error = 1;
		    	return status; //если нет ответа, можно выходить
			}
			//добавил задержку для кривой eMMC СОТА
			delay(10);
		} while (!(cmd.rsp[0] & ((unsigned int)BIT(31))) && retry--);

	}
	if (0xffffffff == retry) {
    	card->error = 1;
		return 0;
	}

	//сохраняем OCR
    card->ocr = cmd.rsp[0];
    card->highCap = (card->ocr & SD_OCR_HIGH_CAPACITY) ? 1 : 0;

   /* CMD2 - ALL_SEND_CID */
    cmd.idx = SD_CMD(2);
    cmd.flags = SD_CMDRSP_136BITS;
    cmd.arg = 0;
	status = ctrl->cmdSend(ctrl, &cmd);
	if (status == 0) {
    	card->error = 1;
    	return status; //если нет ответа, можно выходить
	}

	//Сохраняем CID карты
    memcpy(card->raw_cid, cmd.rsp, 16);

  /* CMD3 - SET_RELATIVE_ADDR */
    cmd.idx = SD_CMD(3);
    cmd.flags = 0;
    cmd.arg = 2 << 16;
	status = ctrl->cmdSend(ctrl, &cmd);
	if (status == 0) {
    	card->error = 1;
    	return status; //если нет ответа, можно выходить
	}

    card->rca = 2; //тупо

    //вырубаем open drain для команд инициализации
    HWREG(ctrl->memBase + MMCHS_CON) &= ~MMCHS_CON_OD;


    /* Send CMD9, to get the card specific data */
     cmd.idx = SD_CMD(9);
     cmd.flags = SD_CMDRSP_136BITS;
     cmd.arg = card->rca << 16;

		status = ctrl->cmdSend(ctrl, &cmd);
		if (status == 0) {
	    	card->error = 1;
	    	return status; //если нет ответа, можно выходить
		}

     memcpy(card->raw_csd, cmd.rsp, 16);

     card->sd_ver =  SD_CARD_CSD_VERSION(card);
     card->tranSpeed = SD_CARD0_TRANSPEED(card);

     //Меняем тактовую частоту на повыше
     //если где-то еще используется - запихнуть в функцию
     switch (card->tranSpeed & 0x00000007) {
     case 0:
    	 khz = 100e3;
    	 break;
     case 1:
      	 khz = 1000e3;
       	 break;
     case 2:
       	 khz = 10000e3;
      	 break;
     case 3:
       	 khz = 100000e3;
      	 break;
     default:
         UARTPuts("TRAN_SPEED incorrect value read", -1);
         card->error = 1;
    	 return 0;
     }
     switch ((card->tranSpeed) >> 3) {
     case 1:
    	 ctrl->opClk = 1 * khz;
    	 break;
     case 2:
    	 ctrl->opClk = 1.2 * khz;
    	 break;
     case 3:
    	 ctrl->opClk = 1.3 * khz;
    	 break;
     case 4:
    	 ctrl->opClk = 1.5 * khz;
    	 break;
     case 5:
    	 ctrl->opClk = 2 * khz;
    	 break;
     case 6:
    	 ctrl->opClk = 2.6 * khz;
    	 break;
     case 7:
    	 ctrl->opClk = 3 * khz;
    	 break;
     case 8:
    	 ctrl->opClk = 3.5 * khz;
    	 break;
     case 9:
    	 ctrl->opClk = 4 * khz;
    	 break;
     case 10:
    	 ctrl->opClk = 4.5 * khz;
    	 break;
     case 11:
    	 ctrl->opClk = 5.2 * khz;
    	 break;
     case 12:
    	 ctrl->opClk = 5.5 * khz;
    	 break;
     case 13:
    	 ctrl->opClk = 6 * khz;
    	 break;
     case 14:
    	 ctrl->opClk = 7 * khz;
    	 break;
     case 15:
    	 ctrl->opClk = 8 * khz;
    	 break;
     default:
         UARTPuts("TRAN_SPEED incorrect value read", -1);
         card->error = 1;
    	 return 0;
     }
     status = ctrl->busFreqConfig(ctrl, ctrl->opClk);

     if (status != 0) //эта функция возвращает ноль при успехе
     {
    	 card->error = 1;
         UARTPuts("HS MMC/SD TRAN_SPEED freqval set failed\n\r", -1);
         return 0;
     }

    //если спецификация вер. 4.0 и выше
     if (card->sd_ver > 3)
	 {
         /* Send CMD7 select card */
          cmd.idx = SD_CMD(7);
          cmd.flags = 0; //ответ R1
          cmd.arg = card->rca << 16;

  		status = ctrl->cmdSend(ctrl, &cmd);
 		if (status == 0) {
 			card->error = 1;
 			return status;
 		}

#if 0 //говнокод
 		if ((cmd.rsp[0] & BIT(25))) //если карта залочена стираем нафиг с нее все
 		{
 			//устанавливаем длину блока 1 байт
 	        /* Send CMD16 */
 	        cmd.idx = SD_CMD(16);
 	        cmd.flags = 0; //ответ R1
 	        cmd.arg = 1; //1 байт длина блока
 	   		status = ctrl->cmdSend(ctrl, &cmd);
 	 		if (status == 0) {
 	 			card->error = 1;
 	 			return status;
 	 		}

 	  		dataBuffer[0] = BIT(3); //Force-erase bit
 	  		dataBuffer[1] = 0; //Force-erase bit
 	  		dataBuffer[2] = 0; //Force-erase bit
 	  		dataBuffer[3] = BIT(3); //Force-erase bit

#ifdef CACHE
		  /* Invalidate the data cache. */
 			CacheDataCleanBuff((unsigned int)dataBuffer, 4);
#endif
 			ctrl->xferSetup(ctrl, 0/*0 - WRITE*/, dataBuffer, 1, 1); //Achtung! посылка одного байта
 			cmd.idx = SD_CMD(42);
 			cmd.flags = SD_CMDRSP_WRITE | SD_CMDRSP_DATA | (ctrl->dmaEnable << SD_CMDRSP_DMAEN_OFFSET);
 			cmd.arg = 0;
 			cmd.nblks = 1;
 			cmd.data = (signed char*)dataBuffer;
 			status = ctrl->cmdSend(ctrl, &cmd);
 	 		if (status == 0) {
 	 			card->error = 1;
 	 			return status;
 	 		}

 			status = ctrl->xferStatusGet(ctrl);

// 			if (status == 0) return 0;

 			//проверяем статус карты
 	        cmd.idx = SD_CMD(13);
 	        cmd.flags = 0; //ответ R1
 	        cmd.arg = card->rca << 16; //1 байт длина блока
 	   		status = ctrl->cmdSend(ctrl, &cmd);
 	 		if (status == 0) {
 	 			card->error = 1;
 	 			return status;
 	 		}


			//ждем пока карта не снимет busy!
	        while (!(HWREG(ctrl->memBase + MMCHS_PSTATE) & (unsigned int)BIT(20)));

 			//возвращаем длину блока в нормальное состояние
 	        /* Send CMD16 */
 	        cmd.idx = SD_CMD(16);
 	        cmd.flags = 0; //ответ R1
 	        cmd.arg = 512; //512 байт длина блока
 	   		status = ctrl->cmdSend(ctrl, &cmd);
 	 		if (status == 0) {
 	 			card->error = 1;
 	 			return status;
 	 		}
	  		while(1);
 		}
#endif

    	 //надо затянуть EXT_CSD
		  ctrl->xferSetup(ctrl, 1, dataBuffer, 512, 1);
		  cmd.idx = SD_CMD(8);
		  cmd.flags = SD_CMDRSP_READ | SD_CMDRSP_DATA | (ctrl->dmaEnable << SD_CMDRSP_DMAEN_OFFSET);
		  cmd.arg = 0;
		  cmd.nblks = 1;
		  cmd.data = (signed char*)dataBuffer;
		  status = ctrl->cmdSend(ctrl, &cmd);
	 		if (status == 0) {
	 			card->error = 1;
	 			return status;
	 		}

		  status = ctrl->xferStatusGet(ctrl);
	 		if (status == 0) {
	 			card->error = 1;
	 			return status;
	 		}
#ifdef CACHE
		  /* Invalidate the data cache. */
		  CacheDataInvalidateBuff((unsigned int)dataBuffer, DATA_RESPONSE_WIDTH);
#endif
	}
     else
     {
    	 UARTPuts("Old Slowpoke eMMC card\n\r", -1);
     }

     //разное определение размера карты для highCap карт  и обычных карт
     if (!(card->highCap))
     { //не факт, что работает для !highCap
		 card->blkLen = 1 << (SD_CARD0_RDBLKLEN(card));
		 card->size = SD_CARD0_SIZE(card);
		 card->nBlks = card->size / card->blkLen;

    /* Set data block length to 512 (for byte addressing cards) */
		 if (card->blkLen != 512)
		 {
			 cmd.idx = SD_CMD(16);
			 cmd.flags = 0; //resp R1
			 cmd.arg = 512;
			 status = ctrl->cmdSend(ctrl, &cmd);

		 		if (status == 0) {
		 			card->error = 1;
		 			return status;
		 		}
			 else
			 {
				 card->blkLen = 512;
			 }

		 }
     }
     else //highcap - берем sector size из EXT_CSD
     {
		  //надо сохранить нужную инфу из EXT_CSD на будущее
		  //пока только SEC_COUNT
		 card->blkLen = 512;
		 card->nBlks = (dataBuffer[212] << 0) |
				  (dataBuffer[213] << 8) |
				  (dataBuffer[214] << 16) |
				  (dataBuffer[215] << 24);
		 card->size = card->nBlks; //для highcap карты размер в секторах
     }
     card->busWidth = 1;
#if 0 //деселект рабочий но забили на него - карта у нас одна
     //deselect card
     /* Send CMD7 select card */
    cmd.idx = SD_CMD(7);
    cmd.flags = SD_CMDRSP_NONE; //ответ R1
    cmd.arg = 0; //rca = 0
	status = ctrl->cmdSend(ctrl, &cmd);
		if (status == 0) return status;
#endif
	//end emmc initialization
    return 1;
}