📄 sdhc_core.cpp
字号:
//*********************************************************************
//* Software that is described herein is for illustrative purposes only
//* which provides customers with programming information regarding the
//* products. This software is supplied "AS IS" without any warranties.
//* NXP Semiconductors assumes no responsibility or liability for the
//* use of the software, conveys no license or title under any patent,
//* copyright, or mask work right to the product. NXP Semiconductors
//* reserves the right to make changes in the software without
//* notification. NXP Semiconductors also make no representation or
//* warranty that such application will be suitable for the specified
//* use without further testing or modification.
//*
//* Copyright NXP Semiconductors
//*********************************************************************
//
// sdhc_core.cpp
//
// SDHC controller driver implementation
//
#include <SDCardDDK.h>
#include "SDHC.h"
#include <nkintr.h>
#include "bsp.h"
#include "intr.h"
#define IndicateBusRequestComplete(pRequest, status) \
SDHCDIndicateBusRequestComplete(m_pHCContext, \
(pRequest), (status))
// Instance counter
int sdCardController::instance = 0;
//------------------------------------------------------------------------------
//
// StartDetectThread
//
// Start the detect thread with the passed class
//
static void StartDetectThread(class sdCardController *pSdCardClass)
{
pSdCardClass->sdCDThread();
}
//------------------------------------------------------------------------------
//
// StartSD0Thread
//
// Start the command thread with the passed class
//
static void StartSD0Thread(class sdCardController *pSdCardClass)
{
pSdCardClass->sdSD0Thread();
}
//------------------------------------------------------------------------------
//
// SDHCInitialize
//
// SDHC callback function
//
SD_API_STATUS SDHCInitialize(PSDCARD_HC_CONTEXT pHCContext)
{
class sdCardController *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);
return pController->SDHCInitializeImpl();
}
//------------------------------------------------------------------------------
//
// SDHCDeinitialize
//
// SDHC callback function
//
SD_API_STATUS SDHCDeinitialize(PSDCARD_HC_CONTEXT pHCContext)
{
class sdCardController *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);
return pController->SDHCDeinitializeImpl();
}
//------------------------------------------------------------------------------
//
// SDHCCancelIoHandler
//
// SDHC callback function
//
BOOLEAN SDHCCancelIoHandler(PSDCARD_HC_CONTEXT pHCContext,
DWORD Slot,
PSD_BUS_REQUEST pRequest)
{
class sdCardController *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);
return pController->SDHCCancelIoHandlerImpl((UCHAR)Slot, pRequest);
}
//------------------------------------------------------------------------------
//
// SDHCSlotOptionHandler
//
// SDHC callback function
//
SD_API_STATUS SDHCSlotOptionHandler(PSDCARD_HC_CONTEXT pHCContext,
DWORD SlotNumber,
SD_SLOT_OPTION_CODE Option,
PVOID pData,
ULONG OptionSize)
{
class sdCardController *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);
return pController->SDHCSlotOptionHandlerImpl((UCHAR)SlotNumber,
Option, pData, OptionSize );
}
//------------------------------------------------------------------------------
//
// SDHCBusRequestHandler
//
// SDHC callback function
//
SD_API_STATUS SDHCBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext,
DWORD Slot,
PSD_BUS_REQUEST pRequest)
{
class sdCardController *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);
return pController->SDHCBusRequestHandlerImpl(pRequest);
}
//********************************************************************
// Class constructor and destructor functions
//********************************************************************
//------------------------------------------------------------------------------
//
// sdCardController
//
// Constructor
//
sdCardController::sdCardController(void)
{
// Multilpe instances of this class aren't really allowed
instance++;
if (instance == 1)
{
// Set initial class values here
sdCardSetInitialValues();
}
}
//------------------------------------------------------------------------------
//
// ~sdCardController
//
// Destructor
//
sdCardController::~sdCardController()
{
instance--;
}
//------------------------------------------------------------------------------
//
// sdCardSetInitialValues
//
// Setup initial driver values - this function is called when the
// driver is first instantiated or when the driver is destroyed, it
// will setup initial values for all class objects
//
void sdCardController::sdCardSetInitialValues(void)
{
// Access to registers
m_pGPIORegs = NULL;
m_pSDCardRegs = NULL;
m_pSDCardRegs = NULL;
m_pClkPwrRegs = NULL;
// SD host context and handle data
m_hParentBus = NULL;
m_pHCContext = NULL;
m_registeredWithBusDriver = FALSE;
m_PowerState = D4;
// Card detect IRQ, sysIntr, events, threads, etc.
m_dwSDCDIrq = MAPPED_INTROAL_VAL;
m_dwSysintrCD = SYSINTR_UNDEFINED;
m_hCardInsertInterruptEvent = INVALID_HANDLE_VALUE;
m_DetectThreadKill = FALSE;
m_detectThreadDone = FALSE;
m_cardInserted = FALSE;
// Comnmand IRQ, sysIntr, event, thread, etc.
m_dwIrq0 = OAL_INTR_IRQ_SD0;
m_dwSysIntr0 = SYSINTR_UNDEFINED;
m_eventSD0 = INVALID_HANDLE_VALUE;
m_SD0ThreadKill = FALSE;
m_SD0ThreadDone = FALSE;
// DMA driver handle
m_dmaTXCtl = m_dmaRXCtl = 0;
m_hardwareInitialized = FALSE;
}
//********************************************************************
// SDHC initialization and de-init functions. Sets up hardware and
// functions that are used whether a card is installed or not.
//********************************************************************
//------------------------------------------------------------------------------
//
// sdCardGetRegistrySettings
//
// Read the registry settings
//
BOOL sdCardController::sdCardGetRegistrySettings(LPCTSTR pszActiveKey)
{
CReg regDevice;
HKEY hKeyDevice = NULL;
BOOL fRet = FALSE;
DEBUGMSG(SDHC_INIT_ZONE,
(TEXT("sdCardController: INFO: SDHC Active RegPath: %s\r\n"),
pszActiveKey));
hKeyDevice = OpenDeviceKey(pszActiveKey);
if ((hKeyDevice == NULL) || (!regDevice.Open(hKeyDevice, NULL)))
{
DEBUGMSG(SDHC_ERROR_ZONE,
(TEXT("sdCardController: ERROR: Failed to open device key\r\n")));
goto error;
}
// Thread priorities
m_dwCardDetectIstThreadPriority =
regDevice.ValueDW(SHC_DETECT_THREAD_PRIORITY_KEY, SHC_DETECT_THREAD_PRIORITY_DEF);
m_dwSD0IstThreadPriority =
regDevice.ValueDW(SHC_SD0_THREAD_PRIORITY_KEY, SHC_SD0_THREAD_PRIORITY_DEF);
DEBUGMSG(SDHC_INIT_ZONE,
(TEXT("REGISTRY: m_dwCardDetectIstThreadPriority: %x\r\n"),
m_dwCardDetectIstThreadPriority));
DEBUGMSG(SDHC_INIT_ZONE,
(TEXT("REGISTRY: m_dwSD0IstThreadPriority: %x\r\n"),
m_dwSD0IstThreadPriority));
// Additional data timeout clocks
m_dataTimeout = regDevice.ValueDW(SHC_DATA_TIMEOUT_KEY, SHC_DATA_TIMEOUT_DEF);
DEBUGMSG(SDHC_INIT_ZONE,
(TEXT("REGISTRY: m_dataTimeout: %x\r\n"),
m_dataTimeout));
// Maximum clock frequency
m_dwMaxClockRate = regDevice.ValueDW(SHC_FREQUENCY_MAX_KEY, SHC_FREQUENCY_MAX_DEF);
DEBUGMSG(SDHC_INIT_ZONE,
(TEXT("REGISTRY: m_dwMaxClockRate: %d\r\n"),
m_dwMaxClockRate));
fRet = TRUE;
error:
if (hKeyDevice)
{
RegCloseKey(hKeyDevice);
}
return fRet;
}
//------------------------------------------------------------------------------
//
// sdInit
//
// Initialize class and context
//
DWORD sdCardController::sdInit(LPCTSTR pszActiveKey)
{
SD_API_STATUS status;
DWORD dwRet = 0;
DEBUGMSG(SDHC_INIT_ZONE, (TEXT("SDHC +Init\r\n")));
// Setup initial driver values
sdCardSetInitialValues();
// Get registry settings
if (sdCardGetRegistrySettings(pszActiveKey) == FALSE)
{
DEBUGMSG(SDHC_ERROR_ZONE,
(TEXT("SDHC: Failed to get registry settings\r\n")));
goto initfail;
}
// Open the parent bus driver handle
m_hParentBus = CreateBusAccessHandle(pszActiveKey);
if (m_hParentBus == NULL)
{
DEBUGMSG(SDHC_ERROR_ZONE,
(TEXT("SDHC: Failed to obtain parent bus handle\r\n")));
goto initfail;
}
// Allocate the context for 1 slot
status = SDHCDAllocateContext(1, &m_pHCContext);
if (!SD_API_SUCCESS(status)) {
DEBUGMSG(SDHC_ERROR_ZONE,
(TEXT("SDHC: Failed to allocate context : 0x%08X\r\n"),
status));
goto initfail;
}
// Set our extension
m_pHCContext->pHCSpecificContext = this;
//
// Set the SDHC driver function callbacks
// Set the host controller name
SDHCDSetHCName(m_pHCContext, TEXT("SDHC"));
// set init handler
SDHCDSetControllerInitHandler(m_pHCContext,
(PSD_INITIALIZE_CONTROLLER) &SDHCInitialize);
// set deinit handler
SDHCDSetControllerDeinitHandler(m_pHCContext,
(PSD_DEINITIALIZE_CONTROLLER) &SDHCDeinitialize);
// set the Send packet handler
SDHCDSetBusRequestHandler(m_pHCContext,
(PSD_BUS_REQUEST_HANDLER) &SDHCBusRequestHandler);
// set the cancel I/O handler
SDHCDSetCancelIOHandler(m_pHCContext,
(PSD_CANCEL_REQUEST_HANDLER) &SDHCCancelIoHandler);
// set the slot option handler
SDHCDSetSlotOptionHandler(m_pHCContext,
(PSD_GET_SET_SLOT_OPTION) &SDHCSlotOptionHandler);
// Register the host controller with the bus driver
status = SDHCDRegisterHostController(m_pHCContext);
if (!SD_API_SUCCESS(status)) {
DEBUGMSG(SDHC_ERROR_ZONE,
(TEXT("SDHC Failed to register host controller: %0x08X\r\n"),status));
goto cleanup;
}
m_registeredWithBusDriver = TRUE;
// Return the controller context
dwRet = (DWORD) this;
initfail:
cleanup:
if (dwRet == 0)
{
if (m_pHCContext)
{
sdCardFreeHostContext();
}
// Restore initial driver status
sdCardSetInitialValues();
}
return dwRet;
}
//------------------------------------------------------------------------------
//
// sdCardFreeHostContext
//
// Free host context
//
void sdCardController::sdCardFreeHostContext(void)
{
// Deregister the host controller with the bust driver if needed
if (m_registeredWithBusDriver)
{
SDHCDDeregisterHostController(m_pHCContext);
}
// De-init hardware
if (m_hardwareInitialized != FALSE)
{
sdHwShutdown();
}
// Return system resources
SDHCDeinitializeImpl();
// Free up bus handle
if (m_hParentBus != NULL)
{
m_PowerState = D4;
UpdateDevicePowerState();
CloseBusAccessHandle(m_hParentBus);
m_hParentBus = NULL;
}
// Cleanup the host context
if (m_pHCContext != NULL)
{
SDHCDDeleteContext(m_pHCContext);
m_pHCContext = NULL;
}
}
//********************************************************************
// Hardware setup functions - These functions are called whenever a
// card is inserted or removed to initialize or de-init specific
// system resources
//********************************************************************
//------------------------------------------------------------------------------
//
// sdHwSetup
//
// Hardware setup - sets up the hardware when a card is initially
// inserted into the device
//
BOOL sdCardController::sdHwSetup(void)
{
DWORD threadID;
// Hardware not yet initialized
m_hardwareInitialized = FALSE;
// Enable slot power and clocking
sdHwSlotPowerControl(m_pGPIORegs, TRUE);
sdCardEnableClocks(TRUE);
Sleep(100);
// Set the initial SD card setup
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
// Take controller out of power OFF state, leave in open drain mode, enable
// low power clock mode
m_pSDCardRegs->sd_power = (SD_OPENDRAIN_EN | SD_POWER_ON_MODE);
m_pSDCardRegs->sd_clock |= (SD_SDCLK_PWRSAVE | SD_SDCLK_EN);
// Enable and setup TX DMA for the SD card controller
m_dmaTXStp.dmaCh = DMAC_SDCARD_TXCH;
m_dmaTXStp.perID = DMA_PERID_SDCARD;
m_dmaTXStp.SrcInc = 1;
m_dmaTXStp.DestInc = 0;
m_dmaTXStp.SrcWidth = DMAC_CHAN_SRC_WIDTH_32;
m_dmaTXStp.DestWidth = DMAC_CHAN_DEST_WIDTH_32;
m_dmaTXStp.SrcBurstSize = DMAC_CHAN_SRC_BURST_8;
m_dmaTXStp.DestBurstSize = DMAC_CHAN_DEST_BURST_8;
m_dmaTXStp.perFlowSource = DMAC_CHAN_FLOW_P_M2P;
m_dmaTXStp.destPeripheral = DMAC_DEST_PERIP(DMA_PERID_SDCARD);
m_dmaTXStp.srcPeripheral = DMAC_SRC_PERIP(DMA_PERID_SDCARD);
m_dmaTXCtl = dmaAllocate(&m_dmaTXStp, (64 * 1024)); // 64K of buffers
if (m_dmaTXCtl == 0)
{
// Couldn't setup DMA
DEBUGMSG(SDHC_ERROR_ZONE,
(TEXT("sdCardController: ERROR: Critical error setting up TX DMA\r\n")));
m_dmaTXCtl = 0;
goto exitInit;
}
// Get sysintr value for DMA channel interrupt
m_dmaTXinfo = dmaGetInfo(m_dmaTXCtl);
// Save DMA buffer data
m_dmaTXBuffPhy = m_dmaTXinfo->pBuffPhy;
m_dmaTXBuffVirt = m_dmaTXinfo->pBuffVirt;
m_dmaTXBuffSizeBytes = m_dmaTXinfo->buffSize;
DEBUGMSG(SDHC_INIT_ZONE,
(TEXT("sdCardController: INIT: DMA TX buffer PHY 0x%x VIRT 0x%x Size %d\r\n"),
m_dmaTXBuffPhy, m_dmaTXBuffVirt, m_dmaTXBuffSizeBytes));
// Enable and setup RX DMA for the SD card controller
m_dmaRXStp.dmaCh = DMAC_SDCARD_RXCH;
m_dmaRXStp.perID = DMA_PERID_SDCARD;
m_dmaRXStp.SrcInc = 0;
m_dmaRXStp.DestInc = 1;
m_dmaRXStp.SrcWidth = DMAC_CHAN_SRC_WIDTH_32;
m_dmaRXStp.DestWidth = DMAC_CHAN_DEST_WIDTH_32;
m_dmaRXStp.SrcBurstSize = DMAC_CHAN_SRC_BURST_8;
m_dmaRXStp.DestBurstSize = DMAC_CHAN_DEST_BURST_8;
m_dmaRXStp.perFlowSource = DMAC_CHAN_FLOW_P_P2M;
m_dmaRXStp.destPeripheral = DMAC_DEST_PERIP(DMA_PERID_SDCARD);
m_dmaRXStp.srcPeripheral = DMAC_SRC_PERIP(DMA_PERID_SDCARD);
m_dmaRXCtl = dmaAllocate(&m_dmaRXStp, (64 * 1024)); // 64K of buffers
if (m_dmaRXCtl == 0)
{
// Couldn't setup DMA
DEBUGMSG(SDHC_ERROR_ZONE,
(TEXT("sdCardController: ERROR: Critical error setting up RX DMA\r\n")));
m_dmaRXCtl = 0;
goto exitInit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -