📄 cspiclass.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004-2006, Freescale Semiconductor, Inc. All Rights Reserved
// THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
// BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
// FREESCALE SEMICONDUCTOR, INC.
//
//------------------------------------------------------------------------------
//
// Module: CspiClass.cpp
//
// Interface to CSPI services.
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// INCLUDE FILES
//------------------------------------------------------------------------------
#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include "csp.h"
#include "cspddk.h"
//------------------------------------------------------------------------------
// GLOBAL DEFINITIONS
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// GLOBAL OR STATIC VARIABLES
//------------------------------------------------------------------------------
// this global counter records how many modules are using the cspi
static UINT8 CspiOpenedCounter[] = {0, 0};
static UINT8 CspiSSInit[2][CSPISSMAX] = { 0 };
// set the default CSPI status
static CSPIAVAILSTATUS_C CspiAvailableStatus[] = {CSPIAVAILABLE, CSPIAVAILABLE};
static DWORD CspiSystemInterrupt[] = { SYSINTR_NOP, SYSINTR_NOP };
//------------------------------------------------------------------------------
// STATIC FUNCTION PROTOTYPES
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// EXPORTED FUNCTIONS
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// FUNCTION: CspiClass
//
// DESCRIPTION: This is the constructor of the CSPI class. It memory
// maps the CSPI memory space using VirtualAlloc and
// VirtualCopy functions.
//
// PARAMETERS:
// CspiId -
// The id of cspi set requested in cspiId_c format.
// status -
// returns TRUE/FALSE depending on whether initialzation i
// is successful. If FALSE, the user should delete the class
// to release resources even if the class instance is created.
//
// RETURNS:
// None
//
//------------------------------------------------------------------------------
CspiClass::CspiClass(CSPIID_C CspiId)
{
PHYSICAL_ADDRESS phyAddr;
DRV_FUNCTION_ENTRY();
// Check if the CSPI selected by user is valid or not
if ((CspiId != CSPI1) && (CspiId != CSPI2)){
DEBUGMSG(ZONE_ERROR, (TEXT("CspiClass: Input id error!\r\n")));
return;
}
// Check if the CSPI selected by user is available or not
if (CspiAvailableStatus[CspiId] == CSPINOTAVAILABLE){
DEBUGMSG(ZONE_ERROR, (TEXT("CspiClass: Request cspi not available!\r\n")));
return;
}
Id = CspiId; // save the id
switch (CspiId)
{
case CSPI1:
phyAddr.QuadPart = CSP_BASE_REG_PA_CSPI1;
break;
case CSPI2:
phyAddr.QuadPart = CSP_BASE_REG_PA_CSPI2;
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("CspiClass: cspi id error!\r\n")));
return; // invalid id, should not come here
}
pCspiReg = (CSP_CSPI_REGS *)MmMapIoSpace(phyAddr, sizeof(CSP_CSPI_REGS), FALSE);
if (pCspiReg == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("CspiClass: CSPI%d NULL pointer!\r\n"), CspiId+1));
return;
}
IsGetLock = FALSE;
if(Id == CSPI1)
{
csMutex[Id] = CreateMutex (
NULL, // No security descriptor
FALSE, // Mutex object not owned
TEXT("cspi1Mutex")); // Object name
csEvent[Id] = CreateEvent(NULL, FALSE, FALSE, L"cspi1Event");
}
else
{
csMutex[Id] = CreateMutex (
NULL, // No security descriptor
FALSE, // Mutex object not owned
TEXT("cspi2Mutex")); // Object name
csEvent[Id] = CreateEvent(NULL, FALSE, FALSE, L"cspi2Event");
}
if (CspiOpenedCounter[Id]==0){
Initialize();
CspiOpenedCounter[Id]=1;
}
else // if already inited, increase the counter
CspiOpenedCounter[Id]++;
DRV_FUNCTION_EXIT();
return;
}
//------------------------------------------------------------------------------
//
// FUNCTION: ~CspiClass
//
// DESCRIPTION: This is the destructor of the CSPI class. It frees
// the reserved memory space using VirtualFree function
// and free other resource used. It will also check the
// CspiOpenedCounter, if no other module is using cspi,
// power down the module.
//
// PARAMETERS:
// None
//
// RETURNS:
// None
//------------------------------------------------------------------------------
CspiClass::~CspiClass(void)
{
DRV_FUNCTION_ENTRY();
CspiOpenedCounter[Id]--;
if (CspiOpenedCounter[Id]==0)
{
InterruptDisable(CspiSystemInterrupt[Id]);
// Release sysintr
if (!KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &CspiSystemInterrupt[Id], sizeof(DWORD), NULL, 0, NULL))
DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: Failed to release sysintr.\r\n")));
GPIO_IOCTL_CFG cfg;
HWCLOCK_ID clockId;
DWORD dwTransferred;
// Disable CSPI module pins and hw clocks
if(Id == CSPI1)
{
GPIO_SET_IOCTL_STRUCT(cfg, CSPI1);
clockId = HWCLOCK_ID_CSPI1;
}
else
{
GPIO_SET_IOCTL_STRUCT(cfg, CSPI2);
clockId = HWCLOCK_ID_CSPI2;
}
KernelIoControl(IOCTL_HAL_DISABLE_GPIO, &cfg, sizeof(cfg), NULL, 0, &dwTransferred);
KernelIoControl(IOCTL_HAL_SHUTDOWN_HW_CLK, &clockId, sizeof(clockId), NULL, 0, &dwTransferred);
//CSPISSPORTID_C PortId;
unsigned int PortId;
for(PortId = CSPISS0; PortId < CSPISSMAX; PortId++)
{
if(CspiSSInit[Id][PortId] != 0)
{
ConfigureSSPin((CSPISSPORTID_C)PortId, FALSE);
CspiSSInit[Id][PortId] = 0;
}
}
}
// Delete mutex and interrupt event
if(csMutex[Id])
CloseHandle(csMutex[Id]);
if(csEvent[Id])
CloseHandle(csEvent[Id]);
if (pCspiReg != NULL)
{
MmUnmapIoSpace((void *)pCspiReg, 0);
pCspiReg = NULL;
}
DRV_FUNCTION_EXIT();
return;
}
//------------------------------------------------------------------------------
//
// FUNCTION: Configure
//
// DESCRIPTION: This function is used to configure the cspi register.
//
// PARAMETERS:
// pData -
// It is the pointer including cspi configure data.
//
// RETURNS:
// TRUE -
// Success to configure
//
// FALSE -
// Not get the cspi resource lock, fail to configure
//
//------------------------------------------------------------------------------
BOOL CspiClass::Configure(PCSPICONFIGDATA_T pData)
{
UINT tempRate = 0;
UINT tempRdyCtl = 0;
DRV_FUNCTION_ENTRY();
if (!IsGetLock)
return FALSE;
if (pData->CSPIBITLENGTH < 1)
pData->CSPIBITLENGTH = 1;
else if (pData->CSPIBITLENGTH > 32)
pData->CSPIBITLENGTH = 32;
if (pData->CSPIMODE == CSPI_CONTROLREG_MODE_MASTER)
tempRate = CalculateDivRate(pData->CSPIFREQUENCY);
// set control register
if (tempRate == CSPI_CONTROLREG_DATARATE_DIV3)
OUTREG32(&pCspiReg->CONTROLREG,
CSP_BITFVAL(CSPI_CONTROLREG_MODE, pData->CSPIMODE) |
CSP_BITFVAL(CSPI_CONTROLREG_BITCOUNT, pData->CSPIBITLENGTH-1) |
CSP_BITFVAL(CSPI_CONTROLREG_DATARATE, tempRate ) |
CSP_BITFVAL(CSPI_CONTROLREG_DRCTL, pData->CSPIDRCTL) |
CSP_BITFVAL(CSPI_CONTROLREG_POL, pData->CSPIPOL) |
CSP_BITFVAL(CSPI_CONTROLREG_PHA, pData->CSPIPHA) |
CSP_BITFVAL(CSPI_CONTROLREG_SSCTL, pData->CSPISSCTL) |
CSP_BITFVAL(CSPI_CONTROLREG_SSPOL, pData->CSPISSPOL) |
CSP_BITFVAL(CSPI_CONTROLREG_XCH, CSPI_CONTROLREG_XCH_IDLE) |
CSP_BITFVAL(CSPI_CONTROLREG_SDHC_SPIEN, CSPI_CONTROLREG_SDHC_SPIEN_ENABLE) |
CSP_BITFVAL(CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_DISABLE));
else
OUTREG32(&pCspiReg->CONTROLREG,
CSP_BITFVAL(CSPI_CONTROLREG_MODE, pData->CSPIMODE) |
CSP_BITFVAL(CSPI_CONTROLREG_BITCOUNT, pData->CSPIBITLENGTH-1) |
CSP_BITFVAL(CSPI_CONTROLREG_DATARATE, tempRate ) |
CSP_BITFVAL(CSPI_CONTROLREG_DRCTL, pData->CSPIDRCTL) |
CSP_BITFVAL(CSPI_CONTROLREG_POL, pData->CSPIPOL) |
CSP_BITFVAL(CSPI_CONTROLREG_PHA, pData->CSPIPHA) |
CSP_BITFVAL(CSPI_CONTROLREG_SSCTL, pData->CSPISSCTL) |
CSP_BITFVAL(CSPI_CONTROLREG_SSPOL, pData->CSPISSPOL) |
CSP_BITFVAL(CSPI_CONTROLREG_XCH, CSPI_CONTROLREG_XCH_IDLE) |
CSP_BITFVAL(CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_DISABLE));
DRV_FUNCTION_EXIT();
return TRUE;
}
//------------------------------------------------------------------------------
//
// FUNCTION: ChipSelect
//
// DESCRIPTION: This function is used to select the cspi port.
//
// PARAMETERS:
// PortId -
// It is the port id.
//
// RETURNS:
// TRUE -
// Chip select success
//
// FALSE -
// Not get the cspi resource lock, chip select fail
// configure chip select pin fail
// invalid chip select
//
//------------------------------------------------------------------------------
BOOL CspiClass::ChipSelect(CSPISSPORTID_C PortId)
{
DRV_FUNCTION_ENTRY();
if (!IsGetLock || PortId >= CSPISSMAX)
return FALSE;
// Enable SS pins first time if required.
if(CspiSSInit[Id][PortId] == 0)
{
if(ConfigureSSPin(PortId, TRUE) != TRUE)
return FALSE;
CspiSSInit[Id][PortId] = 1;
}
INSREG32BF(&pCspiReg->CONTROLREG, CSPI_CONTROLREG_CS, PortId);
DRV_FUNCTION_EXIT();
return TRUE;
}
//------------------------------------------------------------------------------
//
// FUNCTION: CspiHwResourceLock
//
// DESCRIPTION: This is the function to lock cspi hardware resource.
//
// PARAMETERS:
// TRUE -
// try to lock the cspi hardware resource
//
// FALSE -
// release the hardware resource
//
// RETURNS:
// None
//------------------------------------------------------------------------------
void CspiClass::CspiHwResourceLock(BOOL bLock)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("CspiHwResourceLock+: bLock(%c)\r\n"), bLock? 'T':'F'));
if(bLock)
{
WaitForSingleObject (csMutex[Id], INFINITE);
IsGetLock = TRUE;
}
else
{
ReleaseMutex(csMutex[Id]);
IsGetLock = FALSE;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("CspiHwResourceLock-\r\n")));
return;
}
//------------------------------------------------------------------------------
//
// FUNCTION: Exchange
//
// DESCRIPTION: This is the function to exchange data.
//
// PARAMETERS:
// pTxBuf -
// Pointer to the buffer which store the transmite data
//
// pRxBuf -
// Pointer to the buffer which store the receive data
//
// NumOfWords -
// Number of words to be sent
//
// RETURNS:
// NumOfWords -
// The number of words sent
//
// FALSE -
// Not get the cspi resource lock, exchange fail
//
//------------------------------------------------------------------------------
UINT8 CspiClass::Exchange (UINT32 *pTxBuf, UINT32 *pRxBuf, UINT8 NumOfWords)
{
UINT i;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Exchange+: pTxBuf(0x%x) pRxBuf(0x%x) NumOfWords(%d)\r\n"), pTxBuf, pRxBuf, NumOfWords));
#ifdef DEBUG
for(i = 0; i < NumOfWords; i++)
DEBUGMSG(ZONE_INFO, (TEXT("TxBuf[%d]:(0x%08x)\r\n"), i, pTxBuf[i]));
#endif
if (!IsGetLock)
return FALSE;
// make sure not doing exchange
INSREG32BF(&pCspiReg->CONTROLREG, CSPI_CONTROLREG_XCH, CSPI_CONTROLREG_XCH_IDLE);
// enable cspi
INSREG32BF(&pCspiReg->CONTROLREG, CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_ENABLE);
if (NumOfWords > CSPI_FIFO_SLOT_MAX)
NumOfWords = CSPI_FIFO_SLOT_MAX;
for (i = 0; i<NumOfWords; i++)
pCspiReg->TXDATA = *pTxBuf++;
// Enable TSHFEEN
INSREG32BF(&pCspiReg->INT, CSPI_INT_TSHFEEN, CSPI_INT_TSHFEEN_ENABLE);
// start exchange
INSREG32BF(&pCspiReg->CONTROLREG, CSPI_CONTROLREG_XCH, CSPI_CONTROLREG_XCH_EN);
// Block while waiting for transfer done if transfer is not yet done
// to avoid unneccessary thread context switches.
if((pCspiReg->INT & CSP_BITFMASK(CSPI_INT_TSHFE)) == 0)
WaitForSingleObject(csEvent[Id], INFINITE);
// Disable TSHFEEN
INSREG32BF(&pCspiReg->INT, CSPI_INT_TSHFEEN, CSPI_INT_TSHFEEN_DISABLE);
InterruptDone(CspiSystemInterrupt[Id]);
// wait until the exchange is finsihed
while ((pCspiReg->CONTROLREG & CSP_BITFMASK(CSPI_CONTROLREG_XCH)) != CSPI_CONTROLREG_XCH_IDLE)
Sleep(0);
for (i=0; i<NumOfWords; i++)
*pRxBuf++ = pCspiReg->RXDATA;
// disable cspi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -