📄 sdhc_core.cpp
字号:
}
// 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 + -