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

📄 i2c_app.c

📁 大名鼎鼎的mpc8260的bsp源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* mbxI2c.c - I2C bus interface for PPC 8xx */

/* Copyright 1998-2001 Wind River Systems, Inc. */
/* Copyright 1997,1998,1999 Motorola, Inc., All Rights Reserved */

/*
modification history
--------------------
01k,30jan02,dtr  Removing inline asm for diab compatibility.
01j,16oct01,dtr  Putting in fix for SPR65678 plus mod history.
01g,09apr01,rip  added KEYED_REG unlock/lock wrappers (SPR 65678)
01i,16sep01,dat  Use of WRS_ASM macro
01h,10mar00,rcs  merge mot's latest version
01g,17aug99,rhk  fixed memory autosizing problem in routine mbxI2cMemcConfig.
01f,16mar99,rhk  fixed potential SROM parsing problem in mbxI2cSromValueGet.
01e,11mar99,srr  add 32/64/128 MB onboard/DIMM DRAM support.
01d,25mar98,map  code cleanup
01c,21nov97,rhk  cleanup to comply with WRS code review
01b,27sep97,scb  Modified for crystal or 1:1 oscillator input clock.
01a,17jun97,scb  written by rb, integrated by scb.
*/

/*
DESCRIPTION

This module implements the I2c bus access functions for PPC 8xx, and 
includes initilization of DPRAM from values in SROM.

This module is linked in with others to create the compressed bootrom image,
and also separately included in sysLib.c to make routines available to
sysHwInit().  It is thus necessary for this module to be
self-contained. Therefore there are no external references in this module.

The mbxI2cdMain() or mbxI2cdInit() should be called when CPU interrupts are
not enabled, so they should not typically be called after sysHwInit2().  are
executing.  This implies that this routine not be called after
*/

/* includes */

#include "vxWorks.h"            /* types */
#include "intLib.h"
#include "drv/multi/ppc860Siu.h"
#include "drv/sio/ppc860Sio.h"
#include "drv/multi/ppc860Cpm.h"
#include "vxLib.h"
#include "I2c_app.h"             /* I2C I/O definitions */
#include "ads860.h"
#include "semLib.h"
#include "logLib.h"
#include "tickLib.h"



/* externals */
  SEM_ID  semI2CMutex;

/* defines */

#ifndef I2C_DEBUG 
/*#define I2C_DEBUG */
#endif


/* externals */

/* defines */


#define IO_SYNC  __asm__("      sync") /* Macro for all i/o operations to use */
#define IO_ISYNC  __asm__(" isync") /* Macro for all i/o operations to use */

/* I2C IOCTL data macros */

#define I2C_WRITE(registername, data)                                   \
	mbxI2cdIoctl(I2C_IOCTL_W, &registername, sizeof (registername), data)

#define I2C_READ(registername)                   			\
	mbxI2cdIoctl(I2C_IOCTL_R, &registername, sizeof (registername))

#define I2C_OR(registername, data)                			\
	mbxI2cdIoctl(I2C_IOCTL_O, &registername, sizeof (registername), data)

#define I2C_AND(registername, data)               			\
	mbxI2cdIoctl(I2C_IOCTL_A, &registername,sizeof (registername), data)

#define I2C_ANDOR(registername, data1, data2)                            \
	mbxI2cdIoctl(I2C_IOCTL_AO, &registername, sizeof (registername), \
                     data1, data2)

/* typedefs */

/* globals */
/* locals */

LOCAL STATUS mbxI2cdMain();          /* i2c driver main */
/*LOCAL void mbxI2cdAlarm();   */        /* enable alarm */
LOCAL void mbxI2cdCcr();             /* execute i2c command */
LOCAL I2C_DRV_BD *mbxI2cdInit();     /* initialize i2c bus controller */
LOCAL UINT mbxI2cdIoctl();           /* i2c I/O control */
LOCAL void localIntLock();	     /* Disable interrupts */
LOCAL void localIntUnlock();	     /* Reestablish interrupt state */

/* forward declarations */

/******************************************************************************
*
* localIntLock - Disable interrupts
* 
* This function saves the current interrupt state and disables
* interrupts.  localIntLock() and localIntUnlock() support ONLY
* functions within this file.  It is necessary for this file
* to be totally self contained (not access any routines not
* defined in this file) in order to avoid build errors when
* building the compressed boot ROMs.
*
* See also: localIntUnlock()
*
* RETURNS: N/A
*/

LOCAL void localIntLock
    (
    UINT *key
    )
    {
    /*
    __asm__(" mfmsr  4");
    __asm__(" stw    4, 0(3)");
    __asm__(" rlwinm 3, 4, 0, 17, 15");
    __asm__(" mtmsr  3");
    __asm__(" isync");
    */
    }

/******************************************************************************
*
* localIntUnlock - Restore original interrupt state
* 
* This function restores the interrupt state which was in effect
* when localIntLock() was last called with the "key" input
* parameter.  localIntLock() and localIntUnlock() support ONLY
* functions within this file.  It is necessary for this file to
* be totally self contained (not access any routines outside of
* this file) in order to avoid build errors when building the
* compressed boot ROMs.
*
* See also: localIntLock()
*
* RETURNS: N/A
*/

LOCAL void localIntUnlock
    ( 
    UINT key
    )
    {
    /*
    __asm__(" rlwinm 3, 3, 0, 16, 16");
    __asm__(" mfmsr  4");
    __asm__(" or     3, 4, 3");
    __asm__(" mtmsr  3");
    */
    }

/******************************************************************************
*
* mbxI2cdMain - i2c driver main
* 
* This function is the main entry point into the driver,
* the driver is responsible for handling the specified
* command request, the specified command requests are
* local to the module.
*
* Possible command requests (entry points):
*         transmit (put/write) data packet
*         receive (get/read) data packet
* notes:
*      1. error codes are passed back via the control/status word
*         field of the command packet
*
* RETURNS: OK, and ERROR on failure
*/


LOCAL STATUS mbxI2cdMain
    (
    FAST I2C_CMD_PKT *pPckt           /* command packet pointer */
    )
    {
    FAST I2C_DRV_BD *pI2cdrvBd;    /* buffer descriptor pointer */

    FAST SCC_BUF  *pRxbd;          /* RXBD pointer */
    FAST SCC_BUF  *pTxbd;          /* TXBD pointer */

    FAST UINT counter;              /* general purpose counter variable */
    FAST UCHAR *pS;                /* general purpose buffer pointer */
    FAST UCHAR *pD;                /* general purpose buffer pointer */
    int dontCare;
    ULONG	waitTime;

    UINT immrVal = INTERNAL_MEM_MAP_ADDR; /* Base address of Internal Memory */

    /* check transfer size */

    if (pPckt->csword & I2C_IO_C_RDATA) 
	{
        if ((pPckt->dataSize + 1) > I2C_RXBL_MAX) 
	    {
            pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_X_BUF);
            return (ERROR);
            }
        }
    if (pPckt->csword & I2C_IO_C_WDATA) 
	{
        if ((pPckt->dataSize + 1) > I2C_TXBL_MAX) 
	    {
            pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_X_BUF);
            return (ERROR);
            }
        }
    
    /* initialize I2C bus controller */

    pI2cdrvBd = mbxI2cdInit(pPckt, immrVal);

    /* setup pointers to transmit/receive buffer descriptors */

    pRxbd = (SCC_BUF *)&pI2cdrvBd->rxbd[0];
    pTxbd = (SCC_BUF *)&pI2cdrvBd->txbd[0];

    /* perform transmit operation, any operation requires it
     *
     * retrieve character(s) from user's buffer and move to
     * the transmit buffer
     */

    pS = (UCHAR *)pPckt->dataAdrs;
    pD = pTxbd->dataPointer;
    *pD = (UCHAR)(pPckt->devAdrs & 0xFE);
    if (pPckt->csword & I2C_IO_C_RDATA) 
        *pD |= 0x01;

    for (++pD, counter = pPckt->dataSize; counter; counter--) 
        *pD++ = *pS++;

    IO_SYNC;

    /* mask processor interrupts */


  /*  localIntLock(&dontCare);*/

    /*
     * give transmit buffer descriptor to I2C (i.e., transmit
     * the buffer)
     */

    I2C_WRITE(pTxbd->dataLength,pPckt->dataSize + 1);
    I2C_OR(pTxbd->statusMode,CPM_I2C_T_CS_R);

    /*
     * clear the slave address register, we do this due to the fact
     * that the I2C bus controller (i.e., the MPC8xx) will answer to
     * the transmitted buffer if the contents of the slave address
     * register equals the device address that we're communicating
     * with (only on I2C bus write operations)
     */

    *I2ADD(immrVal) = 0x00;
    if (pPckt->csword & I2C_IO_C_RDATA) 
        *I2ADD(immrVal) = (UCHAR)((pPckt->devAdrs & 0xFE) | 0x01);

    IO_SYNC;

    /* issue the start command (i.e., transmit the buffer) */

    *I2COM(immrVal) |= CPM_I2C_COMMAND_STR; 
    IO_SYNC;

    /* 
     * poll for completion
     * enable RTC alarm for 10 seconds and poll for transmit-buffer
     * or transmit-error interrupt
     */
    /* wrap the RTCSC write with unlock/lock code (SPR 65678) */
#if 0	
#ifdef USE_KEYED_REGS
    *RTCSCK(immrVal) = KEYED_REG_UNLOCK_VALUE; /* unlock the RTCSC */
    IO_ISYNC;
    *RTCSC(immrVal) &= ~RTCSC_ALE;       /* disable alarm interrupt */
    *RTCSCK(immrVal) = ~KEYED_REG_UNLOCK_VALUE; /* lock the RTCSC */
#else
    *RTCSC(immrVal) &= ~RTCSC_ALE;       /* disable alarm interrupt */
#endif

    for (mbxI2cdAlarm(immrVal, 10);;) 
	{

        /* check for some type of transmit interrupt condition */

        if (*I2CER(immrVal) & (CPM_I2C_ER_TXE|CPM_I2C_ER_TXB)) 
	    {
            if (*I2CER(immrVal) & (CPM_I2C_ER_TXE)) 
		{
                pPckt->csword |= (I2C_IO_S_ERROR);
                if (pTxbd->statusMode & CPM_I2C_T_CS_NAK) 
                    pPckt->csword |= (I2C_IO_S_T_NAK);

                if (pTxbd->statusMode & CPM_I2C_T_CS_UN) 
                    pPckt->csword |= (I2C_IO_S_T_UN);

                if (pTxbd->statusMode & CPM_I2C_T_CS_CL) 
                    pPckt->csword |= (I2C_IO_S_T_CL);

                }
            #ifdef I2C_DEBUG
            logMsg ("I2c send Error: 0x%x\n", pPckt->csword,0,0,0,0,0);
            #endif

            break;
        }

        /* poll for alarm condition */

        if (*RTCSC(immrVal) & RTCSC_ALR)       
	   {
           pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_T_TO);
           break;
           }
       }

#else
	waitTime = tickGet () + sysClkRateGet () * 10;
	while(tickGet () < waitTime)
		{
	        if (*I2CER(immrVal) & (CPM_I2C_ER_TXE|CPM_I2C_ER_TXB)) 
		    {
	            if (*I2CER(immrVal) & (CPM_I2C_ER_TXE)) 
			{
	                pPckt->csword |= (I2C_IO_S_ERROR);
	                if (pTxbd->statusMode & CPM_I2C_T_CS_NAK) 
	                    pPckt->csword |= (I2C_IO_S_T_NAK);

	                if (pTxbd->statusMode & CPM_I2C_T_CS_UN) 
	                    pPckt->csword |= (I2C_IO_S_T_UN);

	                if (pTxbd->statusMode & CPM_I2C_T_CS_CL) 
	                    pPckt->csword |= (I2C_IO_S_T_CL);

	                }
	            #ifdef I2C_DEBUG
	            logMsg ("I2c send Error: 0x%x\n", pPckt->csword,0,0,0,0,0);
	            #endif
	            break;

	        	}
		if (tickGet() >= waitTime)
			{
		           pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_T_TO);
	            #ifdef I2C_DEBUG
	               logMsg ("timeout I2c send Error: 0x%x\n", pPckt->csword,0,0,0,0,0);
			#endif	
		           break;
			}

		}




#endif
    /* unmask processor interrupts */

  /*  localIntUnlock(dontCare);*/

    /* check for data transfer count mismatch */

    if (!(pPckt->csword & (I2C_IO_S_ERROR))) 
	{
        if (pTxbd->dataLength != (pPckt->dataSize + 1)) 
	    {
            pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_X_CNT);
            pPckt->dataSizeActual = pTxbd->dataLength;
            }
        }

    /* exit on error */

    if (pPckt->csword & (I2C_IO_S_ERROR)) 
	{
        /* disable i2c operation and exit with error status */

        *I2MOD(immrVal) &= ~CPM_I2C_MODE_EN; 
	IO_SYNC;

        return (ERROR);
        }

    /* exit if no receive data is expected */

    if (!(pPckt->csword & I2C_IO_C_RDATA)) 
	{
        /* disable i2c operation and exit with okay status */

        *I2MOD(immrVal) &= ~CPM_I2C_MODE_EN; 
	IO_SYNC;
        return (OK);
        }

    /* poll for completion of receive data */

  /*  localIntLock(&dontCare);*/

    /*
     * enable RTC alarm for 10 seconds and poll for transmit-buffer
     * or transmit-error interrupt
     */
    /* wrap the RTCSC write with unlock/lock code (SPR 65678) */
	#if 0
#ifdef USE_KEYED_REGS
    *RTCSCK(immrVal) = KEYED_REG_UNLOCK_VALUE; /* unlock the RTCSC */
    IO_ISYNC;
    *RTCSC(immrVal) &= ~RTCSC_ALE;       /* Disable alarm interrupt */
    *RTCSCK(immrVal) = ~KEYED_REG_UNLOCK_VALUE; /* lock the RTCSC */
#else
    *RTCSC(immrVal) &= ~RTCSC_ALE;       /* Disable alarm interrupt */
#endif

    for (mbxI2cdAlarm(immrVal, 10);;) 
	{

        /* check for some type of transmit interrupt condition */

        if (*I2CER(immrVal) & (CPM_I2C_ER_BSY|CPM_I2C_ER_RXB)) 
	    {
            if (*I2CER(immrVal) & (CPM_I2C_ER_BSY)) 
                pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_R_BSY);

            if (pRxbd->statusMode & CPM_I2C_R_CS_OV) 
                pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_R_OV);
		#ifdef I2C_DEBUG
		logMsg ("I2c recv Error: 0x%x\n", pPckt->csword,0,0,0,0,0);
		#endif
            break;
            }

        /* poll for alarm condition */

        if (*RTCSC(immrVal) & RTCSC_ALR)       
	    {
            pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_R_TO);
            break;
            }
        }
#else
	waitTime = tickGet () + sysClkRateGet () * 10;
	while(tickGet () < waitTime)
		{
	        /* check for some type of transmit interrupt condition */

	        if (*I2CER(immrVal) & (CPM_I2C_ER_BSY|CPM_I2C_ER_RXB)) 
		    {
	            if (*I2CER(immrVal) & (CPM_I2C_ER_BSY)) 
	                pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_R_BSY);

	            if (pRxbd->statusMode & CPM_I2C_R_CS_OV) 
	                pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_R_OV);
			#ifdef I2C_DEBUG
			logMsg ("I2c recv Error: 0x%x\n", pPckt->csword,0,0,0,0,0);
			#endif
	            break;
	            }

	        /* poll for alarm condition */

	        if (tickGet () >= waitTime)       
		    {
	            pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_R_TO);
			#ifdef I2C_DEBUG
			logMsg ("timeout I2c recv Error: 0x%x\n", pPckt->csword,0,0,0,0,0);
			#endif
	            break;
	            }

		}



#endif
    /* disable i2c operation */

    *I2MOD(immrVal) &= ~CPM_I2C_MODE_EN; 

⌨️ 快捷键说明

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