📄 s3c6410_iic_lib.cpp
字号:
// Function Description : IIC device dirver is opened.
// Input : PHW_OPEN_INFO pOpenContext
// Output :The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.1
BOOL HW_Open (PHW_OPEN_INFO pOpenContext)
{
BOOL RetVal = TRUE; // Initialize to success
PHW_INIT_INFO pInitContext = pOpenContext->pInitContext;
DEBUGCHK(pOpenContext!= NULL);
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+HW_Open(0x%X)\r\n"),
pOpenContext));
pOpenContext->PDDContextVal.Clock = DEFAULT_CLOCK;
pOpenContext->PDDContextVal.ModeSel = DEFAULT_MODE;
pOpenContext->PDDContextVal.FilterEnable = DEFAULT_FILTER_ENABLE;
pOpenContext->PDDContextVal.Delay = DEFAULT_DELAY;
CalculateClockSet(pOpenContext);
pOpenContext->DirtyBit = TRUE;
HW_SetRegister(pOpenContext);
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-HW_Open(0x%X)\r\n"),
pOpenContext));
return (RetVal);
}
//////////
// Function Name : HW_Close
// Function Description : IIC device dirver is closed.
// Input : PHW_OPEN_INFO pOpenContext
// Output :The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.1
BOOL HW_Close (PHW_OPEN_INFO pOpenContext)
{
BOOL RetVal = TRUE; // Initialize to success
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+HW_Close(0x%X)\r\n"),
pOpenContext));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-HW_Close(0x%X)\r\n"),
pOpenContext));
return (RetVal);
}
//////////
// Function Name : CalculateClockSet
// Function Description : Calculate clock and save its setting value in ClkSrc, ClkDiv.
// Input : PHW_OPEN_INFO pOpenContext
// Output :
// Version : v1.0
void CalculateClockSet(PHW_OPEN_INFO pOpenContext)
{
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+CalculateClockSet(0x%X), Clock(%d)\r\n"),
pOpenContext, pOpenContext->PDDContextVal.Clock));
DEBUGCHK(pOpenContext->PDDContextVal.Clock!= NULL);
if (((S3C6410_PCLK>>4)/pOpenContext->PDDContextVal.Clock)>0xf)
{
pOpenContext->PDDContextVal.ClockSel = 1;
pOpenContext->PDDContextVal.ClockDiv = ((S3C6410_PCLK>>9)/pOpenContext->PDDContextVal.Clock); // PCLK/512/freq
if(pOpenContext->PDDContextVal.ClockDiv != 0)
pOpenContext->PDDContextVal.ClockDiv -=1;
}
else
{
pOpenContext->PDDContextVal.ClockSel = 0;
pOpenContext->PDDContextVal.ClockDiv = ((S3C6410_PCLK>>4)/pOpenContext->PDDContextVal.Clock); // PCLK/16/freq
if(pOpenContext->PDDContextVal.ClockDiv != 0)
pOpenContext->PDDContextVal.ClockDiv -=1;
}
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-CalculateClockSet(0x%X), ClockSel(%d), ClockDiv(%d)\r\n"),
pOpenContext, pOpenContext->PDDContextVal.ClockSel, pOpenContext->PDDContextVal.ClockDiv));
}
//////////
// Function Name : HW_SetRegister
// Function Description : Set registers when Device Owner is changed.
// Input : PHW_OPEN_INFO pOpenContext
// Output :
// Version : v0.5
VOID HW_SetRegister (PHW_OPEN_INFO pOpenContext)
{
PHW_INIT_INFO pInitContext = pOpenContext->pInitContext;
DEBUGCHK(g_pIICReg!= NULL);
if(g_OwnerContext != pOpenContext || pOpenContext->DirtyBit == TRUE)
{
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+HW_SetRegister(0x%X)\r\n"),
pOpenContext));
g_pIICReg->IICADD = pOpenContext->pInitContext->PDDCommonVal.SlaveAddress;
g_pIICReg->IICSTAT = (g_pIICReg->IICSTAT & ~(0x3<<6)) | (1<<4) | (pOpenContext->PDDContextVal.ModeSel<<6);
g_pIICReg->IICLC = (pOpenContext->PDDContextVal.FilterEnable<<2) | (pOpenContext->PDDContextVal.Delay);
g_pIICReg->IICCON = (pOpenContext->PDDContextVal.ClockSel << 6) | (pInitContext->PDDCommonVal.InterruptEnable << 5) |
(pOpenContext->PDDContextVal.ClockDiv & 0xf);
g_OwnerContext = pOpenContext;
pOpenContext->DirtyBit = FALSE;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-HW_SetRegister(0x%X)\r\n"),
pOpenContext));
}
}
//////////
// Function Name : HW_SetClock
// Function Description : Set clock, this is called by IIC_IOControl
// Input : PHW_OPEN_INFO pOpenContext
// Output :
// Version : v0.5
VOID HW_SetClock (PHW_OPEN_INFO pOpenContext)
{
CalculateClockSet(pOpenContext);
}
//////////
// Function Name : HW_Read
// Function Description : IIC Read Operation, Sync function, so wait for transfer done or time out.
// Input : PHW_OPEN_INFO pOpenContext
// PIIC_IO_DESC pOutData
// Output :
// Version : v0.5
BOOL HW_Read (PHW_OPEN_INFO pOpenContext, PIIC_IO_DESC pInData ,PIIC_IO_DESC pOutData)
{
BOOL retVal = TRUE; // Initialize to success
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+HW_Read(0x%X)\r\n"),
pOpenContext));
HW_SetRegister(pOpenContext);
HW_Write(pOpenContext, pInData);
ResetEvent(g_hTransferDone);
// Wait until IIC bus is free.
if(!WaitForReg((PVOID)&(g_pIICReg->IICSTAT), (1<<5), 0x0, TIMEOUT_MS_RX))
{
DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]IIS BUS is busy.\r\n")));
retVal = FALSE;
goto CleanUp;
}
g_pcIIC_BUFFER = pOutData->Data;
g_uIIC_PT = 0;
g_uIIC_DATALEN = pOutData->Count;
g_pIICReg->IICCON |= (1<<7); // Ack generation Enable
g_pIICReg->IICDS = pInData->SlaveAddress;
g_pIICReg->IICSTAT = MRX_START;
if(WaitForSingleObject(g_hTransferDone, TIMEOUT_MS_RX) == WAIT_TIMEOUT)
{
DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]RX Time out.\r\n")));
retVal = FALSE;
}
CleanUp:
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+HW_Read(0x%X)\r\n"),
pOpenContext));
return retVal;
}
//////////
// Function Name : HW_Write
// Function Description : IIC Write Operation, Sync function, so wait for transfer done or time out.
// Input : PHW_OPEN_INFO pOpenContext
// PIIC_IO_DESC pInData
// Output :
// Version : v0.5
BOOL HW_Write (PHW_OPEN_INFO pOpenContext, PIIC_IO_DESC pInData)
{
BOOL retVal = TRUE; // Initialize to success
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+HW_Write(0x%X)\r\n"),
pOpenContext));
HW_SetRegister(pOpenContext);
ResetEvent(g_hTransferDone);
// Wait until IIC bus is free.
if(!WaitForReg((PVOID)&(g_pIICReg->IICSTAT), (1<<5), 0x0, TIMEOUT_MS_TX))
{
DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]IIC BUS is busy.\r\n")));
return FALSE;
}
g_pcIIC_BUFFER = pInData->Data;
g_uIIC_PT = 0;
g_uIIC_DATALEN = pInData->Count;
g_pIICReg->IICCON |= (1<<7); // Ack generation Enable
g_pIICReg->IICDS = pInData->SlaveAddress;
DEBUGMSG(ZONE_INFO,(TEXT("[IIC TX]Slave Address is 0x%02X\n"),pInData->SlaveAddress));
g_pIICReg->IICSTAT = MTX_START;
if(WaitForSingleObject(g_hTransferDone, TIMEOUT_MS_TX) == WAIT_TIMEOUT)
{
DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]TX Time out.\r\n")));
retVal = FALSE;
}
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-HW_Write(0x%X)\r\n"),
pOpenContext));
return retVal;
}
//////////
// Function Name : WaitForReg
// Function Description : Wait for register value, or time out.
// Input : DWORD dwRegAddress, // address of register for check
// UINT32 tMask, // mask for check position
// UINT32 tWaitForEqual, // compare value.
// DWORD dwTimeout // time out (ms)
// Output : True (the value is set), False (Time out)
// Version : v0.5
BOOL
WaitForReg(
PVOID pRegAddress,
UINT32 tMask,
UINT32 tWaitForEqual,
DWORD dwTimeout
)
{
const DWORD dwStart = GetTickCount();
UINT32 tValue;
BOOL fRet = TRUE;
DWORD dwIteration = 1;
// Verify that reset has completed.
do {
tValue = *(volatile UINT32*)(pRegAddress);
if ( (dwIteration % 16) == 0 ) {
// Check time
DWORD dwCurr = GetTickCount();
// Unsigned arithmetic handles rollover.
DWORD dwTotal = dwCurr - dwStart;
if (dwTotal > dwTimeout) {
// Timeout
fRet = FALSE;
DEBUGMSG(ZONE_WARN , (_T("Timeout (%u ms) waiting for REGISTER & 0x%08x == 0x%08x\r\n"),
dwTimeout, tMask, tWaitForEqual));
break;
}
}
++dwIteration;
} while ((tValue & tMask) != tWaitForEqual);
return fRet;
}
static DWORD
IIC_IST(
LPVOID Context
)
{
static DWORD dwTimeOut = INFINITE;
PHW_INIT_INFO pInitContext = (PHW_INIT_INFO)Context;
BOOL bDone = FALSE;
DWORD iicstat;
if ( !pInitContext )
{
return ERROR_INVALID_PARAMETER;
}
while(pInitContext->State == IIC_RUN)
{
DWORD dwWaitResult;
dwWaitResult = WaitForSingleObject(g_hTransferEvent, dwTimeOut);
if(pInitContext->State == IIC_FINISH) continue; // when we destruct IIC thread.
iicstat = g_pIICReg->IICSTAT;
if (iicstat & ARBITRATION_FAILED)
{
DEBUGMSG(ZONE_ERROR,(TEXT("I2C_IST[0x%x, %d]: bus arbitration failed \r\n"),
g_OwnerContext, g_uIIC_PT));
}
if (iicstat & SLAVE_ADDRESS_MATCHED)
{
DEBUGMSG(ZONE_ERROR,(TEXT("I2C_IST[0x%x, %d]: slave address matches IICADD \r\n"),
g_OwnerContext, g_uIIC_PT));
}
if (iicstat & SLAVE_ADDRESS_ZERO)
{
DEBUGMSG(ZONE_ERROR,(TEXT("I2C_IST[0x%x, %d]: received slave address 0x0 \r\n"),
g_OwnerContext, g_uIIC_PT));
}
if (iicstat & ACK_NOT_RECEIVED)
{
DEBUGMSG(ZONE_ERROR,(TEXT("I2C_IST[0x%x, %d]: ACK NOT received \r\n"),
g_OwnerContext, g_uIIC_PT));
RETAILMSG(1,(TEXT("I2C_IST[0x%x, %d]: ACK NOT received \r\n"),
g_OwnerContext, g_uIIC_PT));
}
switch( (iicstat>>6)&0x3)
{
case Slave_receive:
break;
case Slave_transmit:
break;
case Master_receive:
if (g_uIIC_PT>0)
{
bDone = FALSE;
g_pcIIC_BUFFER[g_uIIC_PT-1] = g_pIICReg->IICDS;
}
g_uIIC_PT++;
if (g_uIIC_PT==g_uIIC_DATALEN)
{
g_pIICReg->IICCON &= ~(1<<7);
}
else if (g_uIIC_PT > g_uIIC_DATALEN)
{
bDone = TRUE;
g_pIICReg->IICSTAT = MRX_STOP;
}
g_pIICReg->IICCON &= ~(1<<4);
break;
case Master_transmit:
if (g_uIIC_PT<g_uIIC_DATALEN)
{
bDone = FALSE;
g_pIICReg->IICDS = g_pcIIC_BUFFER[g_uIIC_PT];
DEBUGMSG(ZONE_IST,(TEXT("[IIC TX THREAD]g_pIICReg->IICDS is 0x%02X\n"),g_pIICReg->IICDS));
}
else
{
bDone = TRUE;
g_pIICReg->IICSTAT = MTX_STOP; // Stop Master Tx condition, ACK flag clear
}
g_uIIC_PT++;
g_pIICReg->IICCON &= ~(1<<4);
break;
}
InterruptDone(g_IntrIIC);
if (bDone)
{
DEBUGMSG(ZONE_INFO, (TEXT("SetEvent DONE\r\n")));
SetEvent(g_hTransferDone);
}
}
return ERROR_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -