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

📄 s3c6400_iic_lib.cpp

📁 Samsung公司S3C6400芯片的BSP源码包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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;

    RETAILMSG (MSG_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 = 1;

	HW_SetRegister(pOpenContext);


    RETAILMSG (MSG_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
    RETAILMSG (MSG_FUNCTION,
              (TEXT("+HW_Close(0x%X)\r\n"),
               pOpenContext));

    RETAILMSG (MSG_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)
{
    RETAILMSG (MSG_FUNCTION,
              (TEXT("+CalculateClockSet(0x%X), Clock(%d)\r\n"),
               pOpenContext, pOpenContext->PDDContextVal.Clock));

	if (((S3C6400_PCLK>>4)/pOpenContext->PDDContextVal.Clock)>0xf)
	{
			pOpenContext->PDDContextVal.ClockSel	=	1;
			pOpenContext->PDDContextVal.ClockDiv	=	((S3C6400_PCLK>>9)/pOpenContext->PDDContextVal.Clock) -1;		//	PCLK/512/freq
	}
	else
	{
			pOpenContext->PDDContextVal.ClockSel	=	0;
			pOpenContext->PDDContextVal.ClockDiv	=	((S3C6400_PCLK>>4)/pOpenContext->PDDContextVal.Clock) -1;		//	PCLK/16/freq
	}

    RETAILMSG (MSG_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;

	if(g_OwnerContext != pOpenContext || pOpenContext->DirtyBit == 1)
	{
	    RETAILMSG (MSG_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 = 0;
	    RETAILMSG (MSG_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
    RETAILMSG (MSG_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))
	{
		RETAILMSG(MSG_ERROR,(TEXT("[IIC ERROR]IIS BUS is busy.\r\n")));
		return FALSE;
	}
	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 = 0xB0;

	if(WaitForSingleObject(g_hTransferDone, TIMEOUT_MS_RX) == WAIT_TIMEOUT)
	{
		RETAILMSG(MSG_ERROR,(TEXT("[IIC ERROR]RX Time out.\r\n")));
		// TODO: Stop all transmit. ?? set register to stop
		retVal = FALSE;
	}

    RETAILMSG (MSG_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

    RETAILMSG (MSG_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))
	{
		RETAILMSG(MSG_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;

	RETAILMSG(MSG_INFO,(TEXT("[IIC TX]Slave Address is 0x%02X\n"),pInData->SlaveAddress));

	g_pIICReg->IICSTAT = 0xf0;

	if(WaitForSingleObject(g_hTransferDone, TIMEOUT_MS) == WAIT_TIMEOUT)
	{
		RETAILMSG(MSG_ERROR,(TEXT("[IIC ERROR]TX Time out.\r\n")));
		// TODO: Stop all transmit. ?? set register to stop
		retVal = FALSE;
	}

    RETAILMSG (MSG_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;
                RETAILMSG(MSG_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;
    }

    //DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("+I2C_IST[%u, %u, %d] \r\n"), pI2C->Mode, pI2C->State, pI2C->DataCount));

	while(pInitContext->State == IIC_RUN)
	{
		DWORD we;
		we = WaitForSingleObject(g_hTransferEvent, dwTimeOut);

		if(pInitContext->State == IIC_FINISH) continue;		// when we destruct IIC thread.

		iicstat = g_pIICReg->IICSTAT;
        if (iicstat & 0x8) {
            RETAILMSG(MSG_ERROR,(TEXT("I2C_IST[0x%x, %d]: bus arbitration failed \r\n"),
                g_OwnerContext, g_uIIC_PT));
        }

        if (iicstat & 0x4) {
            RETAILMSG(MSG_ERROR,(TEXT("I2C_IST[0x%x, %d]: slave address matches IICADD \r\n"),
                g_OwnerContext, g_uIIC_PT));
        }

        if (iicstat & 0x2) {
            RETAILMSG(MSG_ERROR,(TEXT("I2C_IST[0x%x, %d]: received slave address 0x0 \r\n"),
                g_OwnerContext, g_uIIC_PT));
        }

        if (iicstat & 0x1) {
            RETAILMSG(MSG_ERROR,(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)
			{
				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)
			{
				g_pIICReg->IICSTAT = 0x90;
			}

			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];
				RETAILMSG(MSG_THREAD_INFO,(TEXT("[IIC TX THREAD]g_pIICReg->IICDS is 0x%02X\n"),g_pIICReg->IICDS));
			}
			else
			{
				bDone = TRUE;
				g_pIICReg->IICSTAT = 0xd0;		//	Stop Master Tx condition, ACK flag clear
			}

			g_uIIC_PT++;
			g_pIICReg->IICCON &= ~(1<<4);
			break;
		}

        InterruptDone(g_IntrIIC);

        if (bDone) {
            RETAILMSG(MSG_INFO, (TEXT("SetEvent DONE\r\n")));
            SetEvent(g_hTransferDone);
        }
	}

	return ERROR_SUCCESS;
}

⌨️ 快捷键说明

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