📄 i2c_app.c
字号:
IO_SYNC;
/* unmask processor interrupts */
/* localIntUnlock(dontCare);*/
/*
* check for data transfer count mismatch, on match copy receive
* buffer to caller's
*/
if (!(pPckt->csword & (I2C_IO_S_ERROR)))
{
if (pRxbd->dataLength != (pPckt->dataSize + 1))
{
pPckt->csword |= (I2C_IO_S_ERROR|I2C_IO_S_X_CNT);
pPckt->dataSizeActual = pRxbd->dataLength;
return (ERROR);
}
else
{
/*
* retrieve character(s) from driver's buffer and move to
* user's buffer
*/
pS = (pRxbd->dataPointer + 1);
pD = (UCHAR *)pPckt->dataAdrs;
for (counter = pRxbd->dataLength - 1; counter; counter--)
*pD++ = *pS++;
IO_SYNC;
}
}
else
return (ERROR);
return (OK);
}
/******************************************************************************
*
* mbxI2cdInit - initialize I2C bus controller
*
* This component's purpose is to initialize the I2C bus
* controller.
*
* RETURNS: I2C buffer descriptor pointer
*/
LOCAL I2C_DRV_BD * mbxI2cdInit
(
FAST I2C_CMD_PKT *pPckt, /* command packet pointer */
FAST UINT immrVal /* Base address of Internal Memory Regs */
)
{
FAST I2C_DRV_BD *pI2cdrvBd; /* buffer descriptor pointer */
FAST SCC_BUF *pBd; /* TXBD/RXBD pointer */
FAST I2C_PARAM *pI2cPram; /* parameter RAM pointer */
FAST USHORT varWork; /* the old general purpose variable */
FAST UINT varDiv; /* clock divide variable */
FAST UINT varBdi; /* buffer descriptor index variable */
FAST UINT varBa; /* buffer allocation variable */
UINT dprbase = (UINT)DPRAM(immrVal); /* Dual-Ported RAM base address */
int dontCare;
/*
* setup local pointers and variables
* initialize the base address to all buffers
*/
pI2cdrvBd = (I2C_DRV_BD *)DPRAM_I2C_BD;
varBa = (UINT)((UCHAR *)DPRAM_I2C_BUFFER);
/* mask processor interrupts */
/* localIntLock(&dontCare);*/
/* disable i2c operation */
*I2MOD(immrVal) &= ~CPM_I2C_MODE_EN;
IO_SYNC;
/* initialize I2C specifics:
* first, initialize the I2C clock (keep below 100khz)
*
* MAX_MPU_SPEED is the likely maximum MPU speed for an MPC
* for the near future. We could call mpc8xx_clk_value()
* here to determine the actual speed but to do so causes
* very slow accesses to SROM contents. Using MAX_MPU_SPEED
* instead here is ugly but since the I2C clock frequency is
* legitimately variable, it works for all the supported
* speeds and is much faster than calculating the clock speed
* for every SROM access.
*/
varDiv = (MAX_MPU_SPEED) / 16;
varDiv /= I2C_CLK_SPD; /* divide by I2C bus clock - 10khz */
varDiv /= 2;
varDiv -= 3;
*I2BRG(immrVal) = (UCHAR)varDiv;
*I2MOD(immrVal) = (CPM_I2C_MODE_PDIV_BRGCLK16);
IO_SYNC;
/* enable the I2CSDA/I2CSCL pins */
*PBPAR(immrVal) |= PORT_B_PINS_I2C;
IO_SYNC;
*PBDIR(immrVal) |= PORT_B_PINS_I2C;
IO_SYNC;
*PBODR(immrVal) |= PORT_B_PINS_I2C;
IO_SYNC;
/* initialize receive buffers */
pBd = (SCC_BUF *)&pI2cdrvBd->rxbd[0];
for (varBdi = 0; varBdi < (I2C_DRV_NBDS-1); varBdi++, pBd++)
{
I2C_WRITE(pBd->dataLength,0x0000);
I2C_WRITE(pBd->dataPointer,varBa);
varWork = (CPM_I2C_R_CS_E|CPM_I2C_R_CS_I);
I2C_WRITE(pBd->statusMode,varWork);
varBa += I2C_RXBL_MAX; /* update buffer allocation variable */
}
I2C_WRITE(pBd->dataLength,0x0000);
I2C_WRITE(pBd->dataPointer,varBa);
varWork = (CPM_I2C_R_CS_E|CPM_I2C_R_CS_I|CPM_I2C_R_CS_W);
I2C_WRITE(pBd->statusMode,varWork);
varBa += I2C_RXBL_MAX; /* update buffer allocation variable */
/* initialize transmit buffers */
pBd = (SCC_BUF *)&pI2cdrvBd->txbd[0];
for (varBdi = 0; varBdi < (I2C_DRV_NBDS-1); varBdi++, pBd++)
{
I2C_WRITE(pBd->dataLength,0x0000);
I2C_WRITE(pBd->dataPointer,varBa);
varWork = (CPM_I2C_T_CS_I|CPM_I2C_T_CS_L|CPM_I2C_T_CS_S);
I2C_WRITE(pBd->statusMode,varWork);
varBa += I2C_TXBL_MAX; /* update buffer allocation variable */
}
I2C_WRITE(pBd->dataLength,0x0000);
I2C_WRITE(pBd->dataPointer,varBa);
varWork = (CPM_I2C_T_CS_I|CPM_I2C_T_CS_L|CPM_I2C_T_CS_S|CPM_I2C_T_CS_W);
I2C_WRITE(pBd->statusMode,varWork);
varBa += I2C_TXBL_MAX; /* update buffer allocation variable */
/* initialize parameter RAM specifics */
#if 1 /*have patch*/
pI2cPram = (I2C_PARAM *)PPC860_DPR_I2C_PATCH(dprbase);
#else /*no patch*/
pI2cPram = (I2C_PARAM *)PPC860_DPR_I2C(dprbase);
#endif
/*ori*/
/* pI2cPram = (I2C_PARAM *)PPC860_DPR_I2C(dprbase);*/
pI2cPram->rbase =
(USHORT)((UINT)&pI2cdrvBd->rxbd[0] - (UINT)DPRAM(immrVal));
pI2cPram->tbase =
(USHORT)((UINT)&pI2cdrvBd->txbd[0] - (UINT)DPRAM(immrVal));
pI2cPram->rfcr = 0x15;
pI2cPram->tfcr = 0x15;
pI2cPram->mrblr = I2C_RXBL_MAX;
pI2cPram->ris = 0x00000000;
pI2cPram->rbptr = pI2cPram->rbase;
pI2cPram->tis = 0x00000000;
pI2cPram->tbptr = pI2cPram->tbase;
/* issue initialize Rx and Tx parameters command */
if (!PPC860_I2C_PATCH_INSTALLED)
mbxI2cdCcr (immrVal, CPM_CR_OPCODE_INIT_RT);
/*
* clear any previous interrupt status
* disable all interrupts (polled mode)
*/
I2C_WRITE(*I2CER(immrVal),I2C_INT_CLR);
I2C_WRITE(*I2CMR(immrVal),I2C_INT_DSBL);
/*
* configure to master mode
* enable i2c operation
*/
*I2COM(immrVal) = CPM_I2C_COMMAND_MS;
IO_SYNC;
*I2MOD(immrVal) |= CPM_I2C_MODE_EN;
IO_SYNC;
/* unmask processor interrupts */
/* localIntUnlock(dontCare);*/
return (pI2cdrvBd); /* return buffer descriptor pointer */
}
/******************************************************************************
*
* mbxI2cdIoctl - I/O control
*
* This component's purpose is to perform the specified action
* as requested by the passed arguments:
*
* argument #1 = input/output control flag
* I2C_IOCTL_W = write
* I2C_IOCTL_R = read
* I2C_IOCTL_O = read/or/write
* I2C_IOCTL_A = read/and/write
* I2C_IOCTL_AO = read/and/or/write
* argument #2 = address of register
* argument #3 = register size in bytes (1/2/4)
* argument #4 = data to write #1 (na for read)
* argument #5 = data to write #2 (na for read)
*
* RETURNS: readdata, if read operation
*/
LOCAL UINT mbxI2cdIoctl
(
FAST UINT ioctlflg, /* io control flag */
FAST UINT pReg, /* register pointer */
FAST UINT size, /* register size (1/2/4 bytes) */
FAST UINT wdata1, /* write data #1 */
FAST UINT wdata2 /* write data #2 */
)
{
FAST UINT rdata;
FAST UCHAR *pReg1;
FAST USHORT *pReg2;
FAST UINT *pReg4;
rdata = 0; /* make the compiler happy */
switch (size)
{
case 1:
pReg1 = (UCHAR *)pReg;
if(ioctlflg == I2C_IOCTL_W) /* write */
*pReg1 = wdata1;
else if(ioctlflg == I2C_IOCTL_R) /* read */
rdata = *pReg1;
else if(ioctlflg == I2C_IOCTL_O) /* read/or/write */
*pReg1 |= wdata1;
else if(ioctlflg == I2C_IOCTL_A) /* read/and/write */
*pReg1 &= wdata1;
else if(ioctlflg == I2C_IOCTL_AO) /* read/and/or/write */
*pReg1 = (*pReg1 & wdata1) | wdata2;
break;
case 2:
pReg2 = (USHORT *)pReg;
if(ioctlflg == I2C_IOCTL_W) /* write */
*pReg2 = wdata1;
else if(ioctlflg == I2C_IOCTL_R) /* read */
rdata = *pReg2;
else if(ioctlflg == I2C_IOCTL_O) /* read/or/write */
*pReg2 |= wdata1;
else if(ioctlflg == I2C_IOCTL_A) /* read/and/write */
*pReg2 &= wdata1;
else if(ioctlflg == I2C_IOCTL_AO) /* read/and/or/write */
*pReg2 = (*pReg2 & wdata1) | wdata2;
break;
case 4:
pReg4 = (UINT *)pReg;
if(ioctlflg == I2C_IOCTL_W) /* write */
*pReg4 = wdata1;
else if(ioctlflg == I2C_IOCTL_R) /* read */
rdata = *pReg4;
else if(ioctlflg == I2C_IOCTL_O) /* read/or/write */
*pReg4 |= wdata1;
else if(ioctlflg == I2C_IOCTL_A) /* read/and/write */
*pReg4 &= wdata1;
else if(ioctlflg == I2C_IOCTL_AO) /* read/and/or/write */
*pReg4 = (*pReg4 & wdata1) | wdata2;
break;
}
/* synchronize all data */
IO_SYNC;
return (rdata);
}
/******************************************************************************
*
* mbxI2cdCcr - execute channel command
*
* This component's purpose is to execute the command
* passed. The channel command register is read prior
* to execution to verify that there are no outstanding
* commands, this is done by waiting for a zero status.
* The channel command register is also read after the command
* execution to insure command completion prior to returning.
*
* RETURNS: N/A
*/
LOCAL void mbxI2cdCcr
(
FAST UINT immrVal, /* Base address of Internal Memory Regs */
FAST UINT cmd /* command to execute */
)
{
/* wait for any pending commands to complete */
while (*CPCR(immrVal) & CPM_CR_FLG)
;
/* issue command */
*CPCR(immrVal) = (cmd | CPM_CR_CHANNEL_I2C | CPM_CR_FLG);
IO_SYNC;
/* wait for issued command to complete */
while (*CPCR(immrVal) & CPM_CR_FLG)
;
}
/******************************************************************************
* mbxI2cdAlarm - enable alarm
*
* This component's purpose is to initialize the alarm feature
* of the RTC. It's the caller's responsibility to the handle
* the event (i.e., if the interrupt is enabled).
*
* RETURNS: N/A
*/
#if 0
LOCAL void mbxI2cdAlarm
(
FAST UINT immrVal, /* Base address of Internal Memory Regs */
FAST UINT timeout /* timeout value in seconds */
)
{
/* clear any possible pending alarm event */
/* SPR 65678, unlock/lock wrapper around RTCSC write */
#ifdef USE_KEYED_REGS
*RTCSCK(immrVal) = KEYED_REG_UNLOCK_VALUE;
IO_ISYNC;
*RTCSC(immrVal) |= RTCSC_ALR;
*RTCSCK(immrVal) = ~KEYED_REG_UNLOCK_VALUE;
#else
*RTCSC(immrVal) |= RTCSC_ALR;
#endif
IO_SYNC;
/*
* add timeout to current RTC value and store into the
* alarm seconds counter
*/
/* SPR 65678 */
#ifdef USE_KEYED_REGS
*RTCALK(immrVal) = KEYED_REG_UNLOCK_VALUE;
IO_ISYNC;
*RTCAL(immrVal) = *RTC(immrVal) + timeout;
*RTCALK(immrVal) = ~KEYED_REG_UNLOCK_VALUE;
#else
*RTCAL(immrVal) = *RTC(immrVal) + timeout;
#endif
}
#endif
UINT I2CWrite( UINT i2cDevAdrs, unsigned char *pBuf, int len)
{
I2C_CMD_PKT i2cp; /* command packet */
/* reset eeprom internal address index */
i2cp.csword = (I2C_IO_C_WDATA);
i2cp.devAdrs = i2cDevAdrs;
i2cp.dataAdrs = (UINT)pBuf;
i2cp.dataSize = len;
/* call the MPC8xx I2C bus device driver, exit on error */
semTake(semI2CMutex,WAIT_FOREVER);
mbxI2cdMain(&i2cp);
semGive(semI2CMutex);
if (i2cp.csword & I2C_IO_S_ERROR)
{
return ((UINT)-1);
}
else
return OK;
}
UINT I2CRead( UINT i2cDevAdrs, unsigned char *pBuf, int len)
{
I2C_CMD_PKT i2cp; /* command packet */
/* reset internal address index */
i2cp.csword = (I2C_IO_C_WDATA);
i2cp.dataAdrs = pBuf;
i2cp.devAdrs = i2cDevAdrs;
i2cp.dataSize = 1;
/* call the MPC8xx I2C bus device driver, exit on error */
semTake(semI2CMutex,WAIT_FOREVER);
mbxI2cdMain(&i2cp);
semGive(semI2CMutex);
if (i2cp.csword & I2C_IO_S_ERROR)
{
return ((UINT)-1);
}
else
{
i2cp.csword = (I2C_IO_C_RDATA);
i2cp.devAdrs = i2cDevAdrs;
i2cp.dataAdrs = (UINT)(pBuf );
i2cp.dataSize = len;
semTake(semI2CMutex,WAIT_FOREVER);
mbxI2cdMain(&i2cp);
semGive(semI2CMutex);
return (i2cp.dataSizeActual);
}
if (i2cp.csword & I2C_IO_S_ERROR)
{
return ((UINT)-1);
}
else
return OK;
}
UINT I2CKBRead( UINT i2cDevAdrs, unsigned char *pBuf, int len)
{
I2C_CMD_PKT i2cp; /* command packet */
/* call the MPC8xx I2C bus device driver, exit on error */
i2cp.csword = (I2C_IO_C_RDATA);
i2cp.devAdrs = i2cDevAdrs;
i2cp.dataAdrs = (UINT)(pBuf );
i2cp.dataSize = len;
semTake(semI2CMutex,WAIT_FOREVER);
mbxI2cdMain(&i2cp);
semGive(semI2CMutex);
if (i2cp.csword & I2C_IO_S_ERROR)
return ((UINT)-1);
else
return (i2cp.dataSizeActual);
}
void I2CInit(void)
{
semI2CMutex = semBCreate(SEM_Q_FIFO,SEM_FULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -