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

📄 omap730iic.c

📁 OMAP730 I^2C驱动源码
💻 C
字号:
//------------------------------------------------------------------------------
//
//  Function:  I2C_Open
//
//  Called by device manager to open a device for reading and/or writing.
//
DWORD I2C_Open()
{
    DWORD rc = (DWORD)NULL;
    I2C_INSTANCE *pInstance = &g_Instance;

    // Set cookie
    g_Instance.pDevice = &g_device;
    
    // Done...
    rc = (DWORD)pInstance;    
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  I2C_Init
//
//  Called by device manager to initialize device.
//
DWORD I2C_Init()
{
    DWORD rc = (DWORD)NULL;
    I2C_DEVICE *pDevice = &g_device;
    g_pTimerRegs = OALPAtoUA(OMAP730_TIMER32K_REGS_PA);
    OUTREG32(&g_pTimerRegs->TVR, 0xFFFFFF);
    SETREG32(&g_pTimerRegs->CR, CR_TRB);
    while ((INREG32(&g_pTimerRegs->CR) & CR_TRB) != 0);
    SETREG32(&g_pTimerRegs->CR, CR_TSS|CR_INT_EN|CR_ARL);
    // Map I2C controller
    pDevice->pI2CRegs = OALPAtoUA(OMAP730_I2C_REGS_PA);
    
    // Check if we get correct context
    if (pDevice->pI2CRegs == NULL) {
        OALMSG(OAL_ERROR, (L"ERROR: I2C_Init: pDevice->pI2CRegs == NULL\r\n"));
        goto clean;
    }
    I2C_Reset(pDevice);
    I2C_Open();

    // Return non-null value
    rc = (DWORD)pDevice;
   	OALMSG(0, (L"-I2C_Init(rc = 0x%08x)\r\n", rc));
    
clean:	
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  I2C_Close
//
//  This function closes the device context.
//
BOOL I2C_Close(DWORD context)
{
    BOOL rc = FALSE;
    I2C_INSTANCE *pInstance = (I2C_INSTANCE*)context;

    // Check if we get correct context
    if (pInstance == NULL) {
        DEBUGMSG (ZONE_ERROR, (L"ERROR: I2C_Read: "
            L"Incorrect context paramer\r\n"
        ));
        goto cleanUp;
    }

    // Done...
    rc = TRUE;

cleanUp:
    OALMSG(OAL_INFO, (L"-I2C_Close(rc = %d)\r\n", rc));
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  I2C_Deinit
//
//  Called by device manager to uninitialize device.
//
BOOL I2C_Deinit(DWORD context)
{
    BOOL rc = FALSE;
    I2C_DEVICE *pDevice = (I2C_DEVICE*)context;

    // Check if we get correct context
    if (pDevice == NULL ) {
        DEBUGMSG (ZONE_ERROR, (L"ERROR: I2C_Deinit: "
            L"Incorrect context paramer\r\n"
        ));
        goto cleanUp;
    }
   
    I2C_Close(context);

    // Done
    rc = TRUE;

cleanUp:
    OALMSG(OAL_ERROR, (L"-I2C_Deinit(rc = %d)\r\n", rc));
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  I2C_Read
//
//  This function reads data from the device identified by the open context.
//
DWORD I2C_Read(DWORD context, PVOID pBuffer, DWORD size)
{
    DWORD rc = 0;    
    I2C_INSTANCE *pInstance = &g_Instance;
    I2C_DEVICE *pDevice;
    OMAP730_I2C_REGS *pI2CRegs;
    DWORD base;
    UCHAR *pData;
    USHORT count;
    USHORT con, stat;

    DEBUGMSG(ZONE_I2C&&ZONE_FUNCTION, (
        L"+I2C_Read(0x%08x, 0x%08x, %d\r\n", context, pBuffer, size
        ));
   
    // Check if we get correct context
    if (pInstance == NULL)
        {
        DEBUGMSG (ZONE_ERROR, (L"ERROR: I2C_Read: "
            L"Incorrect context paramer\r\n"
            ));
            goto clean;
        }

    pDevice = &g_device;
    pI2CRegs = pDevice->pI2CRegs;

    // Make sure I2C device is enabled...
    if ((INREG16(&pI2CRegs->CON) & I2C_CON_EN) == 0)
    {
        // after a NACK the only way to recover
        OUTREG16(&pI2CRegs->CON, I2C_CON_EN|I2C_CON_MST);
        // Wait until resetting is done
        while ((INREG16(&pI2CRegs->SYSS) & I2C_SYSS_RDONE) == 0);
        // Clear all interrupts
        SETREG16(&pI2CRegs->STAT, 0x3F);
    }

    // I2C slave address
    OUTREG16(&pI2CRegs->SA, pInstance->address);

    // Set up CON register
    con = I2C_CON_EN | I2C_CON_MST | I2C_CON_STP | I2C_CON_STT;
    if (pInstance->addrSize == 10) con |= I2C_CON_XA;

retry:
    // Start transaction
    pData = (UCHAR*)pBuffer;
    count = (USHORT)size;

    // Wait until bus isn't free - don't set CNT register before this.
    // When CNT register is set when bus is busy it holds busy bit high.
    base = OALGetTickCount();
    while ((INREG16(&pI2CRegs->STAT) & I2C_STAT_BB) != 0) 
    {   
        if ((OALGetTickCount() - base) > I2C_TimeOut)
        {
            I2C_Reset(pDevice);
            OALMSG(OAL_ERROR, (L"ERROR: I2C_Read: "
                L"Bus remains locked -- resetting I2C controller 0x%02x\r\n",
                pInstance->address
                ));
            goto clean;
        }
        OALStall(1000);
    }

    // Number of buffer to be transmitted
    OUTREG16(&pI2CRegs->CNT, count);
    // Clear bits
    OUTREG16(&pI2CRegs->STAT, I2C_STAT_AL|I2C_STAT_NACK|I2C_STAT_RRDY);
    // Start transaction
    OUTREG16(&pI2CRegs->CON, con);

    // Receive all expected data
    while (count > 0)
    {
        do
        {
            // Get status
            stat = INREG16(&pI2CRegs->STAT);
            // Clear bits
            OUTREG16(&pI2CRegs->STAT, I2C_STAT_AL|I2C_STAT_NACK|I2C_STAT_RRDY);
            // Lost arbitration? Wait for empty bus...
            if ((stat & I2C_STAT_AL) != 0) goto retry;
            // No ACK? Exit... device may not be on the bus
            if ((stat & I2C_STAT_NACK) != 0)
            {
                I2C_Reset(pDevice);
                OALMSG(OAL_ERROR, (L"ERROR: I2C_Read: "
                    L"No ACK from slave device with address 0x%02x\r\n",
                        pInstance->address
                    ));
                goto clean;
            }
            
            // This should not happen
            if ((stat & I2C_STAT_RRDY) == 0)
            {
                OALMSG(OAL_ERROR, (L"I2C_Read: --325-----This should not happen---------\r\n" ));
            }
            else
            {
                break;
            }
            
        }while(1);
        
        // Clear the bit
        OUTREG16(&pI2CRegs->STAT, I2C_STAT_RRDY);
        // Depending on amount of data remaining
        if (count > 1)
        {
            *(USHORT*)pData = INREG16(&pI2CRegs->DATA);
            count -= 2;
            pData += 2;
        }
        else 
        {
            *pData = (UCHAR)INREG16(&pI2CRegs->DATA);
            count -= 1;
            pData += 1;
        }
       if( count > dcount)
	       OALStall(8000);
    }  
    
    // We read all buffer
    rc = size;

clean:
   return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  I2C_Write
//
//  This function writes data to the device.
//
DWORD I2C_Write(DWORD context, PVOID pBuffer, DWORD size)
{
    DWORD rc = -1;
    I2C_DEVICE *pDevice;
    I2C_INSTANCE *pInstance = &g_Instance;
    OMAP730_I2C_REGS *pI2CRegs;
    DWORD base;
    UCHAR *pData;
    USHORT count;
    USHORT con, stat;

     // Check if we get correct context
    if (pInstance == NULL)
    {
    DEBUGMSG (ZONE_ERROR, (L"ERROR: I2C_Read: "
        L"Incorrect context paramer\r\n"
    ));
    goto clean;
    }
    
    pDevice = &g_device;
    pI2CRegs = pDevice->pI2CRegs;
    OALMSG(0, (L"I2C_Write: correct context paramer, pDevice = 0x%x\r\n", pDevice));
  
    // Make sure I2C device is enabled...
    if ((INREG16(&pI2CRegs->CON) & I2C_CON_EN) == 0)
        {
            // after a NACK the only way to recover
            OUTREG16(&pI2CRegs->CON, I2C_CON_EN|I2C_CON_MST);
            // Wait until resetting is done
            while ((INREG16(&pI2CRegs->SYSS) & I2C_SYSS_RDONE) == 0);
            // Clear all interrupts
            SETREG16(&pI2CRegs->STAT, 0x3F);
        }

    // I2C slave address
    OUTREG16(&pI2CRegs->SA, pInstance->address);

    // Set up CON register
    con = I2C_CON_EN | I2C_CON_MST | I2C_CON_TRX | I2C_CON_STP | I2C_CON_STT;
    if (pInstance->addrSize == 10) con |= I2C_CON_XA;

retry:
    OALMSG(0, (L"I2C_Write: ----------retry-----------\r\n" ));

    pData = (UCHAR*)pBuffer;
    count = (USHORT)size;

    // Wait until bus isn't free - don't set CNT register before this.
    // When CNT register is set when bus is busy it holds busy bit high.
    base = OALGetTickCount();
    while ((INREG16(&pI2CRegs->STAT) & I2C_STAT_BB) != 0) 
    {
        if ((OALGetTickCount() - base) > I2C_TimeOut)
        {
            I2C_Reset(pDevice);
            OALMSG(OAL_ERROR, (L"ERROR: I2C_Write: "
                L"Bus remains locked -- resetting I2C controller 0x%02x\r\n",
                pInstance->address
                ));
            goto clean;
        }
        OALStall(1000);
    }

    // Number of buffer to be transmitted
    OUTREG16(&pI2CRegs->CNT, count);

    // Clear bit
    OUTREG16(&pI2CRegs->STAT, I2C_STAT_AL|I2C_STAT_NACK|I2C_STAT_XRDY);

    // Start transaction
    OUTREG16(&pI2CRegs->CON, con);

    // Send all data
    while (count > 0)
    {
        do
        {
            // Get status
            stat = INREG16(&pI2CRegs->STAT); 
            
            // Clear bits
            OUTREG16(&pI2CRegs->STAT, I2C_STAT_AL|I2C_STAT_NACK|I2C_STAT_XRDY);
            
            // Lost arbitration? Retry...
            if ((stat & I2C_STAT_AL) != 0)
    			{
    				OALMSG(OAL_ERROR,(L"I2C:AL failed\r\n"));
    				goto retry;
            	}
            // No ACK? Exit... device may not be on the bus
            if ((stat & I2C_STAT_NACK) != 0)
            {
                I2C_Reset(pDevice);
                OALMSG(OAL_ERROR, (L"ERROR: I2C_Write: "
                    L"No ACK from slave device with address 0x%02x\r\n",
                    pInstance->address
                ));
                goto clean;
            }

            // This should not happen...
            if ((stat & I2C_STAT_XRDY) == 0) 
            {
                OALMSG(OAL_ERROR, (L"ERROR:I2C_Write: -------This should not happen...-------\r\n" ));
            }
            else
            {
                break;
            }
        }while(1);
        
        // Clear the bit
        OUTREG16(&pI2CRegs->STAT, I2C_STAT_XRDY);
        
        // Depending on data amount
        if (count > 1) {
            OUTREG16(&pI2CRegs->DATA, *(USHORT*)pData);
            count -= 2;
            pData += 2;
        } else {
            OUTREG16(&pI2CRegs->DATA, *pData);
            count -= 1;
            pData += 1;
        }
	
    	if( count> dcount)
    		OALStall(500);
    }

    // We wrote all buffer
    rc = size;
clean:
    return rc;
}

//------------------------------------------------------------------------------

BOOL I2C_SetSlaveAddress(DWORD context, DWORD size, DWORD address)
{
    BOOL rc = FALSE;
    I2C_INSTANCE *pInstance = (I2C_INSTANCE *)context;
    g_Instance = *pInstance;

    // Check if we get correct context
    if (pInstance == NULL) {
        OALMSG(OAL_ERROR, (L"ERROR: I2C_SetSlaveAddress: "
            L"Incorrect context paramer 0x%x\r\n", pInstance
        ));
        goto cleanUp;
    }

    if (size != 7 && size != 10) {
        OALMSG(OAL_ERROR, (L"ERROR: I2C_SetSlaveAddress: "
            L"Incorrect address size %d (valid values are 7 & 10 bits\r\n", size
        ));
        goto cleanUp;
    }
    g_Instance.addrSize = size;
    g_Instance.address = address;

    rc = TRUE;

cleanUp:
    return rc;
}

⌨️ 快捷键说明

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