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

📄 sdhc_core.cpp

📁 NXP LPC3000系列 wince BSP包
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	}

	// Get sysintr value for DMA channel interrupt
	m_dmaRXinfo = dmaGetInfo(m_dmaRXCtl);

	// Save DMA buffer data
	m_dmaRXBuffPhy = m_dmaRXinfo->pBuffPhy;
	m_dmaRXBuffVirt = m_dmaRXinfo->pBuffVirt;
	m_dmaRXBuffSizeBytes = m_dmaRXinfo->buffSize;

	DEBUGMSG(SDHC_INIT_ZONE, 
		(TEXT("sdCardController: INIT: DMA RX buffer PHY 0x%x VIRT 0x%x Size %d\r\n"),
		m_dmaRXBuffPhy, m_dmaRXBuffVirt, m_dmaRXBuffSizeBytes));

	// Reset command and data events
	ResetEvent(m_eventSD0);

	// Start command thread
    m_SD0ThreadKill = FALSE;
	m_SD0ThreadDone = FALSE;
	m_SD0InterruptThread =  CreateThread(NULL, 0,
		(LPTHREAD_START_ROUTINE) StartSD0Thread, this, 0, &threadID);
	if (m_SD0InterruptThread == NULL)
	{
		DEBUGMSG(SDHC_ERROR_ZONE,
			(TEXT("SDHCInitializeImpl: Error creating command thread!\r\n")));
        goto exitInit;
    }

	m_hardwareInitialized = TRUE;

exitInit:
	return m_hardwareInitialized;
}

//------------------------------------------------------------------------------
//
// sdHwShutdown
//
// Shuts down the hardware when a card is removed
//
void sdCardController::sdHwShutdown(void)
{
	int to;

	// Clear controller state
	sdCardEnableClocks(TRUE);
	sdCardClearController();
	m_pSDCardRegs->sd_power = (SD_OPENDRAIN_EN | SD_POWER_OFF_MODE); // Power off state, open drain mode
	m_pSDCardRegs->sd_clock = (SD_CLKDIV_MASK | SD_SDCLK_PWRSAVE); // Slowest/no clock, 1 bit mode

	// Stop command thread
	m_SD0ThreadKill = TRUE;
	to = 20;
	while ((to > 0) && (m_SD0ThreadDone == FALSE))
	{
		SetEvent(m_eventSD0);
		Sleep(50);
	}

	// Return DMA resources from DMA driver
	if (m_dmaTXCtl != 0)
	{
		dmaDisable(m_dmaTXCtl);
		dmaDeAllocate(m_dmaTXCtl);
		m_dmaTXCtl = 0;
	}
	if (m_dmaRXCtl != 0)
	{
		dmaDisable(m_dmaRXCtl);
		dmaDeAllocate(m_dmaRXCtl);
		m_dmaRXCtl = 0;
	}

	// Disable SD card controller clocks
	sdCardEnableClocks(FALSE);

	m_hardwareInitialized = FALSE;
}

//********************************************************************
// System threads
//********************************************************************

//------------------------------------------------------------------------------
//
// sdCDThread
//
// SD card detection and signal thread
//
DWORD sdCardController::sdCDThread(void)
{
    DWORD waitStatus;
	PSD_BUS_REQUEST pRequest;

	// Set thread priority from configured priority
    CeSetThreadPriority(GetCurrentThread(),
		m_dwCardDetectIstThreadPriority);

	// Card initially not installed
	m_cardInserted = FALSE;

	// Thread should run at least once
	SetEvent(m_hCardInsertInterruptEvent);

	// Loop until requested to stop
    while (m_DetectThreadKill == FALSE)
    {
        waitStatus = WaitForSingleObject(m_hCardInsertInterruptEvent,
			INFINITE);
        if (waitStatus != WAIT_OBJECT_0) {
			DEBUGMSG(SDHC_ERROR_ZONE,
				(TEXT("SDHC: Detect thread error\r\n")));
            m_detectThreadDone = TRUE;
			return 0;
        }
		else if (m_DetectThreadKill == FALSE)
		{
			// Allows detect signal to debounce
		    Sleep(750);

		    DEBUGMSG(SDHC_SDBUS_INTERACT_ZONE,
				(TEXT("SD card insertion(1)/removal(0) = %d/%d\r\n"),
				sdHwCardInserted(m_pGPIORegs), m_cardInserted));

			// Has the state changed?
			if (m_cardInserted != sdHwCardInserted(m_pGPIORegs))
			{
				// Get new card insertion state
				m_cardInserted = sdHwCardInserted(m_pGPIORegs);

				// Update card dection logic to new state
				sdHwUpdateDetectState(m_pGPIORegs, m_pINTCRegs);

				SDHCDAcquireHCLock(m_pHCContext);

				// Insert or removal event?
				if (m_cardInserted != FALSE)
				{
					// Initialize hardware and tell host that device is inserted
					m_savedCardAddr = 0xFFFFFFFF;
					if (sdHwSetup() == TRUE)
					{
						SDHCDIndicateSlotStateChange(m_pHCContext, (UCHAR) 0,
							DeviceInserted);
					}
					else
					{
					    DEBUGMSG(SDHC_ERROR_ZONE, (TEXT("Error initializing hardware on insertion\r\n")));
						sdHwShutdown();
						sdHwSlotPowerControl(m_pGPIORegs, FALSE);
						sdCardEnableClocks(FALSE);
						m_cardInserted = FALSE;
					}
				}
				else
				{
					// Tell host that device is removed
					SDHCDIndicateSlotStateChange(m_pHCContext, (UCHAR) 0,
						DeviceEjected);

			        // Get the current request  
			        pRequest = SDHCDGetAndLockCurrentRequest(m_pHCContext, (UCHAR) 0);
			        if (pRequest != NULL)
					{
						SDHCDIndicateBusRequestComplete(m_pHCContext,
							pRequest, SD_API_STATUS_DEVICE_REMOVED);
						DEBUGMSG(SDHC_ERROR_ZONE, 
			                (TEXT("Card Removal Detected - Canceling current request: 0x%08X, command: %d\r\n"), 
			                pRequest, pRequest->CommandCode));
			        }

					// Shutdown hardware
					sdHwShutdown();

					// Disable slot power and clocking
					sdCardEnableClocks(FALSE);
					sdHwSlotPowerControl(m_pGPIORegs, FALSE);
				}

				SDHCDReleaseHCLock(m_pHCContext);
			}
		}

	    InterruptDone(m_dwSysintrCD);
	}

	// Thread has exited flag
	m_detectThreadDone = TRUE;

	DEBUGMSG(SDHC_INIT_ZONE, (TEXT("SDHC: Detect thread shutdown\r\n")));

	return 0;
}

//------------------------------------------------------------------------------
//
// sdCheckBusyStatus
//
// Checks busy status after write commands
//
SD_API_STATUS sdCardController::sdCheckBusyStatus(void)
{
	UINT32 reg, mask, val;
	SD_API_STATUS status = SD_API_STATUS_UNSUCCESSFUL;
	int tries = 400;

	if (m_ProgCheckFlag == TRUE)
	{
		// Check for ready status
		mask = 0x1F00;
		val = 0x0900;
	}
	else if (m_TranCheckFlag == TRUE)
	{
		mask = 0x1F00;
		val = 0x0900;
		Sleep(60); // TBD hack
	}
	m_ProgCheckFlag = FALSE;
	m_TranCheckFlag = FALSE;

	while (tries > 0)
	{
		// Submit new SDMMC command to check status, command interrupt
		// may call this function again
		sdCmdSMSetup(13, m_savedCardAddr, ResponseR1);
		InterruptDone(m_dwSysIntr0);
		m_pSDCardRegs->sd_cmd |= SD_CPST_EN;

		WaitForSingleObject(m_eventSD0, INFINITE);
		m_pSDCardRegs->sd_cmd = 0;

		reg = m_pSDCardRegs->sd_status;

		// Has the transfer occurred error-free?
		if ((reg & (SD_CMD_CRC_FAIL | SD_CMD_TIMEOUT)) != 0)
		{
			status = SD_API_STATUS_RESPONSE_TIMEOUT;
			tries = 0;
		}
		else
		{
			// Response received, verify it
			reg = m_pSDCardRegs->sd_resp [0];
			if ((reg & mask) == val)
			{
				// Program complete
				tries = 0;
				status = SD_API_STATUS_SUCCESS;
			}
			else
			{
				Sleep(2);
			}
		}

		tries--;
	}

	m_pSDCardRegs->sd_cmd = 0;
	m_pSDCardRegs->sd_mask0 = 0;
	m_pSDCardRegs->sd_clear = 0xFFFFF;

	return status;
}

//------------------------------------------------------------------------------
//
// sdSD0Thread
//
// SD command and data handler thread
//
DWORD sdCardController::sdSD0Thread(void)
{
    DWORD waitStatus;
	SD_API_STATUS status;
	UINT32 tmp;
	PSD_BUS_REQUEST pRequest = NULL;

	// Set thread priority from configured priority
    CeSetThreadPriority(GetCurrentThread(),
		m_SD0IstThreadPriority);

	while (m_SD0ThreadKill == FALSE)
	{
        waitStatus = WaitForSingleObject(m_eventSD0, INFINITE);
        if (waitStatus != WAIT_OBJECT_0) {
			DEBUGMSG(SDHC_ERROR_ZONE,
				(TEXT("SDHC: Command thread error\r\n")));
            m_SD0ThreadDone = TRUE;
			return 0;
        }
		else if (m_SD0ThreadKill == FALSE)
		{
			// Get current bus request
			pRequest = SDHCDGetAndLockCurrentRequest(m_pHCContext, 0);
			if (pRequest == NULL)
			{
				// This should never happen
				status = SD_API_STATUS_INVALID_DEVICE_REQUEST;
				DEBUGMSG(1, (TEXT("sdCardController::no req 0x%08x 0x%08x 0x%08xr\n"),
					m_pSDCardRegs->sd_status, m_pSDCardRegs->sd_mask0,
					m_pSDCardRegs->sd_clear));

				// Better stop everything
				m_pSDCardRegs->sd_cmd = 0;
				m_pSDCardRegs->sd_dctrl = 0;
				m_pSDCardRegs->sd_mask0 = 0;
				m_pSDCardRegs->sd_clear = 0xFFFFF;
			}
			else
			{
				// Get current status and clear status
				tmp = m_pSDCardRegs->sd_status;

				// Command handler?
				if ((tmp & m_SD0CmdMask) != 0)
				{
					sdCardHandleCommand(tmp, pRequest);
				}

				// Data handler?
				tmp = m_pSDCardRegs->sd_status;
				if ((tmp & m_SD1DataMask) != 0)
				{
					sdCardHandleData(tmp, pRequest);
				}

				// If either of the requests is still pending, don't complete
				// the bus request yet
				if ((m_cmdStatus != SD_API_STATUS_PENDING) &&
					(m_dataStatus != SD_API_STATUS_PENDING))
				{
					status = SD_API_STATUS_SUCCESS;
					if (m_cmdStatus != SD_API_STATUS_SUCCESS)
					{
						status = m_cmdStatus;
					}
					else if (m_dataStatus != SD_API_STATUS_SUCCESS)
					{
						status = m_dataStatus;
					}

					CompleteBusDataRequest(status, pRequest);
				}
				else
				{
					SDHCDUnlockRequest(m_pHCContext, pRequest);
				}
			}
		}

		InterruptDone(m_dwSysIntr0);
	}

	// Thread has exited flag
	m_SD0ThreadDone = TRUE;

	DEBUGMSG(SDHC_INIT_ZONE, (TEXT("SDHC: Command thread shutdown\r\n")));

	return 0;
}

void sdCardController::sdCardHandleData(UINT32 reg, PSD_BUS_REQUEST pRequest)
{
	// Stop state machine and DMA
	m_pSDCardRegs->sd_dctrl &= ~SD_DATATRANSFER_EN;
	m_pSDCardRegs->sd_mask0 &= ~m_SD1DataMask;
	m_pSDCardRegs->sd_clear = m_SD1DataMask;

	if (m_TransferClass == SD_READ)
	{
		dmaDisable(m_dmaRXCtl);
	}
	else
	{
		dmaDisable(m_dmaTXCtl);
	}
	m_dataStatus = SD_API_STATUS_SUCCESS;

	// Check error statuses
	if ((reg & (SD_FIFO_RXDATA_OFLOW | SD_STARTBIT_ERR |
		SD_FIFO_TXDATA_UFLOW | SD_DATA_CRC_FAIL |
		SD_DATA_TIMEOUT)) != 0)
	{
		if ((reg & SD_DATA_CRC_FAIL) != 0)
		{
			DEBUGMSG(SDHC_ERROR_ZONE,
				(TEXT("SDHC: Data CRC error: SD status=0x%x\r\n"), reg));
		}
		if ((reg & SD_DATA_TIMEOUT) != 0)
		{
			DEBUGMSG(SDHC_ERROR_ZONE,
				(TEXT("SDHC: Data timeout error: SD status=0x%x\r\n"), reg));
		}
		if ((reg & SD_FIFO_RXDATA_OFLOW) != 0)
		{
			DEBUGMSG(SDHC_ERROR_ZONE,
				(TEXT("SDHC: Data overflow error: SD status=0x%x\r\n"), reg));
		}
		if ((reg & SD_STARTBIT_ERR) != 0)
		{
			DEBUGMSG(SDHC_ERROR_ZONE,
				(TEXT("SDHC: Data start error: SD status=0x%x\r\n"), reg));
		}
		if ((reg & SD_FIFO_TXDATA_UFLOW) != 0)
		{
			DEBUGMSG(SDHC_ERROR_ZONE,
				(TEXT("SDHC: Data underflow error: SD status=0x%x\r\n"), reg));
		}

		m_dataStatus = SD_API_STATUS_UNSUCCESSFUL;
	}
	else if (m_TransferClass == SD_READ)
	{
		// Copy DMA data to buffer if this was a read
		SDPerformSafeCopy((void *) m_readbuff, (void *) m_dmaRXBuffVirt,
			m_xferSize);
	}

	m_pSDCardRegs->sd_cmd &= ~SD_CPST_EN;
}

void sdCardController::sdCardHandleCommand(UINT32 reg, PSD_BUS_REQUEST pRequest)
{
	// Clear the SD command interrupt
	m_pSDCardRegs->sd_mask0 &= ~m_SD0CmdMask;
	m_pSDCardRegs->sd_clear = m_SD0CmdMask;

	// Has the transfer occurred error-free?
	if ((reg & (SD_CMD_CRC_FAIL | SD_CMD_TIMEOUT)) != 0)
	{
		// Command timeout
		if ((reg & SD_CMD_TIMEOUT) != 0)
		{
			m_cmdStatus = SD_API_STATUS_RESPONSE_TIMEOUT;
			m_dataStatus = SD_API_STATUS_UNSUCCESSFUL;
			DEBUGMSG(SDHC_ERROR_ZONE,
				(TEXT("SDHC: Command timeout error: SD status = 0x%x\r\n"), reg));
		}
		else
		{
			// Ignore the CRC error on ACMD41 and CMD1
			if ((m_CommandCode == 1) || (m_CommandCode == 41))
			{
				// CRC error on OCR requests, the response register will not
				// have the right status, so read it here instead
				m_cmdStatus = SD_API_STATUS_SUCCESS;
				sdRespCopy(pRequest->CommandResponse.ResponseBuffer);
			}
			else
			{
				m_cmdStatus = SD_API_STATUS_CRC_ERROR;
				m_dataStatus = SD_API_STATUS_UNSUCCESSFUL;
				DEBUGMSG(SDHC_ERROR_ZONE,
					(TEXT("SDHC: Command  CRC error: SD status = 0x%x\r\n"), reg));
			}
		}
	}
	else
	{
		// Command completed successfully
		m_cmdStatus = SD_API_STATUS_SUCCESS;

		if (m_TransferClass == SD_WRITE)
		{
			// Start data state machine
			m_pSDCardRegs->sd_dctrl |= SD_DATATRANSFER_EN;
		}

		// Capture card address
		if (m_savedCardAddr == 0xFFFFFFFF)
		{
			if (m_CommandCode == 9)
			{
				m_savedCardAddr = m_CommandArgument;
				DEBUGMSG(SDHC_INIT_ZONE,
					(TEXT("SDHC: Saved card address 0x%x\r\n"), m_savedCardAddr));
			}
		}
	}

	// Copy response
	if (m_cmdStatus == SD_API_STATUS_SUCCESS)
	{
		sdRespCopy(pRequest->CommandResponse.ResponseBuffer);

		// Shut down command state machine?
		if (m_TransferClass == SD_COMMAND)
		{
			m_pSDCardRegs->sd_cmd &= ~SD_CPST_EN;

⌨️ 快捷键说明

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