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

📄 i2c8260.c

📁 Embedded Planet公司的ep8260单板计算机的BSP包(VxWorks)
💻 C
字号:
/* i2c8260.c - I2C bus interface for PPC 8260 */

/*
modification history
--------------------
01a,05dec01,gev  written
*/

/*
DESCRIPTION

This module implements the I2c bus access functions for PPC 8260.

*/
/* includes */

#include "vxWorks.h"            /* types */
#include "intLib.h"
#include "config.h"             /* mbx860 BSP definitions */
#include "vxLib.h"
#include "m8260cp.h"
#include "i2c8260.h"             /* I2C I/O definitions */

#define PPC8260_DPR_I2C(dprbase)      ((VINT16 *) ((dprbase) + 0x8AFC))

#define IO_SYNC  __asm__("      sync") /* Macro for I/O operations to use */

LOCAL I2C_PARAM		*pI2C;
LOCAL UCHAR		*txbuf1,*txbuf2;;
LOCAL UCHAR		*rxbuf;

LOCAL I2C_DESC		*rxbd;	/* Pointer to BD area of DPRAM */		
LOCAL I2C_DESC		*txbd1;	/* Pointer to BD area of DPRAM */		
LOCAL I2C_DESC		*txbd2;	/* Pointer to BD area of DPRAM */		

/******************************************************************************
* I2CrCmd - execute an I2C related CP 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 I2CrCmd(UINT32 immrVal,UINT32 cmd)
{
volatile UINT32	cpcrVal;
int		intLevel;

	intLevel = intLock();	/* we cannot be interrupted during this */

	/* we wouldn't need to do this first wait if we knew
	   that all other code that issues CP commands waited
	   for CP commands to complete *after* issuance.
	   Since we don't know that, we must wait.
	*/

	/* wait for any pending CP commands to complete */
	while(*M8260_CPCR(immrVal) & M8260_CPCR_FLG)
		;

	/* issue the command to the CP */
	cpcrVal = (M8260_CPCR_OP((UINT8)cmd)
		| M8260_CPCR_SBC(M8260_CPCR_SBC_I2C)
		| M8260_CPCR_PAGE(M8260_CPCR_PAGE_I2C)
		| M8260_CPCR_MCN(0)
		| M8260_CPCR_FLG);

	/* issue command */
	*M8260_CPCR(immrVal) = cpcrVal;
	IO_SYNC;
	/* wait for issued command to complete */
	while(*M8260_CPCR(immrVal) & M8260_CPCR_FLG)
		;

	intUnlock(intLevel);
}

LOCAL STATUS sysI2CInit(void)
{
UINT32	immrVal;

	immrVal = vxImmrGet();

	pI2C = (I2C_PARAM*)sys82xxDpramAlignedMalloc(sizeof(I2C_PARAM),64);
	*PPC8260_DPR_I2C(immrVal) = (UINT16)((UINT32)pI2C);

	*I2MOD(immrVal) = DISABLE_I2C;	/* Disable I2C before initializing it */

	*M8260_IOP_PDPAR(immrVal) |=  (PD14 | PD15);
	*M8260_IOP_PDDIR(immrVal) &= ~(PD14 | PD15);
	*M8260_IOP_PDSO(immrVal)  |=  (PD14 | PD15);
	*M8260_IOP_PDODR(immrVal) |=  (PD14 | PD15);

	/* I2C Parameter RAM */
	pI2C->rfcr = 0x10;
	pI2C->tfcr = 0x10;
	pI2C->mrblr = I2C_BUFF_MAX_LEN;

#if 1
	txbuf1 = sys82xxDpramAlignedMalloc(8 * I2C_BUFF_MAX_LEN,16);
#else
	txbuf1 = cacheDmaMalloc(8 * I2C_BUFF_MAX_LEN);
#endif
	txbuf2 = txbuf1 + I2C_BUFF_MAX_LEN;
	rxbuf  = txbuf2 + I2C_BUFF_MAX_LEN;

	rxbd =  (I2C_DESC*)sys82xxDpramAlignedMalloc(2 * sizeof(I2C_DESC),8);
	txbd1 = (I2C_DESC*)sys82xxDpramAlignedMalloc(2 * sizeof(I2C_DESC),8);
	txbd2 = txbd1 + 1;

	pI2C->rbase = (UINT16)((UINT32)rxbd);
	pI2C->tbase = (UINT16)((UINT32)txbd1); 

	I2CrCmd(immrVal,M8260_CPCR_RT_INIT);		/* Init rx and tx */

	/* I2C Registers */
	*I2ADD(immrVal) = 0x00;		/* Slave address */
	*I2BRG(immrVal) = 0xff /* BRGCLK */;	/* Arbitrary choice of baud rate: BRGCLK/32 */

	*I2CER(immrVal) = CLEAR_I2C_EVENTS;	/* Clear out I2C events */
	*I2CMR(immrVal) = DISABLE_INTERRUPT_I2C; /* Disable interrupts from I2C */
	*I2MOD(immrVal) = ENABLE_I2C;

	return OK;
}

LOCAL BOOL i2cPollReadDone(UINT32 immrVal)
{
UCHAR		event,evdone;
int		timeleft;

	timeleft = 120;
	evdone = (I2C_EV_TXB|I2C_EV_RXB);
	do{
		event = *I2CER(immrVal);
		if(event & (I2C_EV_TXE /* |I2C_EV_BUSY */ )){
			taskDelay(2);
			break;
		}
		if((event & evdone) == evdone){
			break;
		}
		taskDelay(1);
	}while(--timeleft > 0);
	*I2CER(immrVal) = event;
	return (event & evdone) == evdone;
}

LOCAL BOOL i2cPollWriteDone(UINT32 immrVal)
{
UCHAR		event,evdone;
int		timeleft;

	timeleft = 120;
	evdone = (I2C_EV_TXB);
	do{
		event = *I2CER(immrVal);
		if(event & (I2C_EV_TXE /* |I2C_EV_BUSY */ )){
			taskDelay(2);
			break;
		}
		if((event & evdone) == evdone){
			break;
		}
		taskDelay(1);
	}while(--timeleft > 0);

        taskDelay(1);

	*I2CER(immrVal) = event;
	return (event & evdone) == evdone;
}

int i2cReadEEprom(UCHAR devI2CAdr, UCHAR Address, int len, UCHAR *pdata)
{
UINT32		immrVal = vxImmrGet();
int		thisLen,totaLen = 0;

    if(!len) return len;
    do{
	thisLen = (len > I2C_BUFF_MAX_LEN) ? I2C_BUFF_MAX_LEN /* -1 */  : len /* -1 */;
	txbuf1[0] = (char)devI2CAdr;		/* Slave address w/o read bit */
	txbuf1[1] = (char)Address;
	txbuf2[0] = (char)(devI2CAdr|R_BIT);	/* Slave address with read bit */

	txbd1->length = 2;			/* 1 byte slave addr + addr */
	txbd1->data = (char*)txbuf1;  	
	txbd1->status = (READY_BIT | TRANSMIT_START_BIT); 

	txbd2->length = thisLen+1;		/* 1 byte slave addr + len bytes data */
	txbd2->data = (char*)txbuf2;  	
	txbd2->status = (READY_BIT | LAST_BIT | WRAP_BIT | TRANSMIT_START_BIT | INT_BIT); 

	rxbd->length = 0;			/* reset */
	rxbd->data = (char*)rxbuf;		/* point RX BD to first RX buffer address */
	rxbd->status = (READY_BIT | WRAP_BIT | INT_BIT);

	/*  Set master mode and issue start */
        IO_SYNC;
	*I2COM(immrVal) = (MASTER_MODE | START_BIT);
        IO_SYNC;
	if(i2cPollReadDone(immrVal)){
		thisLen = rxbd->length;
		memcpy(pdata,rxbd->data,thisLen);
		len -= thisLen;
		pdata += thisLen;
		totaLen += thisLen;
		Address += thisLen;
	}else{
		len = -1;
	}
    }while(len > 0);
    return totaLen;
}

int i2cReadAT24C02(UCHAR devI2CAdr, UCHAR Address, int len, UCHAR *pdata)
{
    return i2cReadEEprom(devI2CAdr, Address, len, pdata);
}

int i2cWriteAT24C02(UCHAR devI2CAdr, UCHAR Address, int len, UCHAR *pdata)
{
  UINT32  immrVal = vxImmrGet();
  int     x;

  if (!len) return 0;

  for (x=0; x<len; x++)
  {
    txbuf1[0] = (char)devI2CAdr;		/* Slave address w/o read bit */
    txbuf1[1] = (char)Address+x;
    txbuf1[2] = (char)pdata[x];

    txbd1->length = 3;		/* 1 byte slave addr + addr + data */
    txbd1->data = (char*)(&txbuf1[0]);

    txbd1->status = (READY_BIT | LAST_BIT | WRAP_BIT |
                     TRANSMIT_START_BIT | INT_BIT); 

    /*  Set master mode and issue start */
    IO_SYNC;
    *I2COM(immrVal) = (MASTER_MODE | START_BIT);
    IO_SYNC;

    if( ! i2cPollWriteDone(immrVal))
    {
      return -1 * x;
    }
  }

  return x;
}

int i2cReadTemp(UCHAR devI2CAdr,UCHAR Address,UCHAR *pdata)
{
UINT32		immrVal = vxImmrGet();

	txbuf1[0] = (char)devI2CAdr;		/* Slave address w/o read bit */
	txbuf1[1] = (char)Address;		/* only 2 bits have meaning */
	txbuf2[0] = (char)(devI2CAdr|R_BIT);	/* Slave address with read bit */

	txbd1->length = 2;			/* 1 byte slave addr + addr */
	txbd1->data = (char*)txbuf1;  	
	txbd1->status = (READY_BIT | TRANSMIT_START_BIT); 

	txbd2->length = 3;			/* 1 byte slave addr + 2 bytes data */
	txbd2->data = (char*)txbuf2;  	
	txbd2->status = (READY_BIT | LAST_BIT | WRAP_BIT | TRANSMIT_START_BIT | INT_BIT); 

	rxbd->length = 0;			/* reset */
	rxbd->data = (char*)rxbuf;		/* point RX BD to first RX buffer address */
	rxbd->status = (READY_BIT | WRAP_BIT | INT_BIT);

	/*  Set master mode and issue start */
	*I2COM(immrVal) = (MASTER_MODE | START_BIT);
	if(i2cPollReadDone(immrVal)){
		memcpy(pdata,rxbd->data,2);
		return 2;
	}
	return 0;
}

⌨️ 快捷键说明

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