📄 i2c.c
字号:
if ( ByteToXmit > 0 )
{
if ( ByteToXmit == XmitByte )
{
/* no more data to send */
ByteToXmit = 0;
/* do not toggle I2CCR(MTX). Doing so will cause bus-hung
* since current Kahlua design does not give master a way
* to detect slave stop. It is always a good idea for
* master to use timer to prevent the long long delays
*/
return I2CBUFFEMPTY;
}
#ifdef I2CDBG
printf( "%s(%d): xmit 0x%02x\n", __FILE__, __LINE__, *(XmitBuf + XmitByte) );
#endif
val = *(XmitBuf + XmitByte);
val &= 0x000000ff;
store_runtime_reg( eumbbar, I2CDR, val );
XmitByte++;
return I2CSUCCESS;
}
return I2CBUFFEMPTY;
}
/***********************************************
* function: I2C_Slave_Rcv
*
* description: slave reads one byte data
* from master source
*
* return I2CSUCCESS if no error otherwise non-zero
*
* Note: condition must meet when this function is called:
* I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&
* I2CCR(MSTA) == 0 && I2CCR(MTX) = 0
*
***********************************************/
static I2CStatus I2C_Slave_Rcv(unsigned int eumbbar )
{
unsigned int val;
I2C_CTRL ctrl;
if ( ByteToRcv > 0 )
{
val = load_runtime_reg( eumbbar, I2CDR );
*( RcvBuf + RcvByte ) = val & 0xff;
#ifdef I2CDBG
printf( "%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, *(RcvBuf + RcvByte) );
#endif
RcvByte++;
if ( ByteToRcv == RcvByte )
{
if ( RcvBufFulStop == 1 )
{
/* all done */
ctrl = I2C_Get_Ctrl( eumbbar );
ctrl.txak = 1;
I2C_Set_Ctrl( eumbbar, ctrl );
}
ByteToRcv = 0;
return I2CBUFFFULL;
}
return I2CSUCCESS;
}
return I2CBUFFFULL;
}
/****************** Device Control Function *************/
/*********************************************************
* function: I2C_Init
*
* description: Initialize I2C unit with desired frequency divider,
* master's listening address, with interrupt enabled
* or disabled.
*
* note:
********************************************************/
static I2CStatus I2C_Init( unsigned int eumbbar,
unsigned char fdr, /* frequency divider */
unsigned char slave_addr, /* driver's address used for receiving */
unsigned int en_int) /* 1 - enable I2C interrupt
* 0 - disable I2C interrup
*/
{
I2C_CTRL ctrl;
unsigned int tmp;
#ifdef I2CDBG0
printf( "%s(%d): I2C_Init enter\n", __FILE__, __LINE__);
#endif
ctrl = I2C_Get_Ctrl( eumbbar );
/* disable the I2C module before we change everything */
ctrl.men = 0;
I2C_Set_Ctrl( eumbbar, ctrl );
/* set the frequency diver */
tmp = load_runtime_reg( eumbbar, I2CFDR );
tmp = ( tmp & 0xffffffc0 ) | ( fdr & 0x3f );
store_runtime_reg( eumbbar, I2CFDR, tmp );
/* Set our listening (slave) address */
tmp = load_runtime_reg( eumbbar, I2CADR );
tmp = ( tmp & 0xffffff01 ) | ( ( slave_addr & 0x7f) << 1 );
store_runtime_reg( eumbbar, I2CADR, tmp );
/* enable I2C with desired interrupt setting */
ctrl.men = 1;
ctrl.mien = en_int & 0x1;
I2C_Set_Ctrl( eumbbar, ctrl );
#ifdef I2CDBG0
printf( "%s(%d): I2C_Init exit\n", __FILE__, __LINE__ );
#endif
return I2CSUCCESS;
}
/*****************************************
* function I2c_Get_Stat
*
* description: Query I2C Status, i.e., read I2CSR
*
****************************************/
static I2C_STAT I2C_Get_Stat( unsigned int eumbbar )
{
unsigned int temp = load_runtime_reg( eumbbar, I2CSR );
I2C_STAT stat;
#ifdef I2CDBG0
printf( "%s(%d): get stat = 0x%08x\n", __FILE__, __LINE__, temp );
#endif
stat.rsrv0 = ( temp & 0xffffff00 ) >> 8;
stat.mcf = ( temp & 0x00000080 ) >> 7;
stat.maas = ( temp & 0x00000040 ) >> 6;
stat.mbb = ( temp & 0x00000020 ) >> 5;
stat.mal = ( temp & 0x00000010 ) >> 4;
stat.rsrv1 = ( temp & 0x00000008 ) >> 3;
stat.srw = ( temp & 0x00000004 ) >> 2;
stat.mif = ( temp & 0x00000002 ) >> 1;
stat.rxak = ( temp & 0x00000001 );
return stat;
}
/*********************************************
* function: I2c_Set_Ctrl
*
* description: Change I2C Control bits,
* i.e., write to I2CCR
*
********************************************/
static void I2C_Set_Ctrl( unsigned int eumbbar, I2C_CTRL ctrl ) /* new control value */
{
unsigned int temp = load_runtime_reg( eumbbar, I2CCR );
temp &= 0xffffff03;
temp |= ( ( ctrl.men & 0x1 ) << 7 );
temp |= ( ( ctrl.mien & 0x1 ) << 6 );
temp |= ( ( ctrl.msta & 0x1 ) << 5 );
temp |= ( ( ctrl.mtx & 0x1 ) << 4 );
temp |= ( ( ctrl.txak & 0x1 ) << 3 );
temp |= ( ( ctrl.rsta & 0x1 ) << 2 );
#ifdef I2CDBG0
printf( "%s(%d): set ctrl = 0x%08x\n", __FILE__, __LINE__, temp );
#endif
store_runtime_reg( eumbbar, I2CCR, temp );
}
/*****************************************
* function: I2C_Get_Ctrl
*
* description: Query I2C Control bits,
* i.e., read I2CCR
*****************************************/
static I2C_CTRL I2C_Get_Ctrl( unsigned int eumbbar )
{
union {
I2C_CTRL ctrl ;
unsigned int temp;
} s;
s.temp = load_runtime_reg( eumbbar, I2CCR );
#ifdef I2CDBG0
printf( "%s(%d): get ctrl = 0x%08x\n", __FILE__, __LINE__, s.temp );
#endif
return s.ctrl;
}
/****************************************
* function: I2C_Slave_Addr
*
* description: Process slave address phase.
* return I2CSUCCESS if no error
*
* note: Precondition for calling this function:
* I2CSR(MIF) == 1 &&
* I2CSR(MAAS) == 1
****************************************/
static I2CStatus I2C_Slave_Addr( unsigned int eumbbar )
{
I2C_STAT stat = I2C_Get_Stat( eumbbar );
I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar );
if ( stat.srw == 1 )
{
/* we are asked to xmit */
ctrl.mtx = 1;
I2C_Set_Ctrl( eumbbar, ctrl ); /* set MTX */
return I2C_Slave_Xmit( eumbbar );
}
/* we are asked to receive data */
ctrl.mtx = 0;
I2C_Set_Ctrl(eumbbar, ctrl );
(void)load_runtime_reg( eumbbar, I2CDR ); /* do a fake read to start */
return I2CADDRESS;
}
/***********************************************
* function: I2C_ISR
*
* description: I2C Interrupt service routine
*
* note: Precondition:
* I2CSR(MIF) == 1
**********************************************/
static I2CStatus I2C_ISR( unsigned int eumbbar )
{
I2C_STAT stat = I2C_Get_Stat( eumbbar );
I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar );
#ifdef I2CDBG0
printf( "%s(%d): I2C_ISR\n", __FILE__, __LINE__ );
#endif
/* clear MIF */
stat.mif = 0;
/* Now let see what kind of event this is */
if ( stat.mcf == 1 )
{
/* transfer compete */
/* clear the MIF bit */
I2C_Set_Stat( eumbbar, stat );
if ( ctrl.msta == 1 )
{
/* master */
if ( ctrl.mtx == 1 )
{
/* check if this is the address phase for master receive */
if ( MasterRcvAddress == 1 )
{
/* Yes, it is the address phase of master receive */
ctrl.mtx = 0;
/* now check how much we want to receive */
if ( ByteToRcv == 1 && RcvBufFulStop == 1 )
{
ctrl.txak = 1;
}
I2C_Set_Ctrl( eumbbar, ctrl );
(void)load_runtime_reg( eumbbar, I2CDR ); /* fake read first */
MasterRcvAddress = 0;
return I2CADDRESS;
}
/* master xmit */
if ( stat.rxak == 0 )
{
/* slave has acknowledged */
return I2C_Master_Xmit( eumbbar );
}
/* slave has not acknowledged yet, generate a STOP */
if ( XmitBufEmptyStop == 1 )
{
ctrl.msta = 0;
I2C_Set_Ctrl( eumbbar, ctrl );
}
return I2CSUCCESS;
}
/* master receive */
return I2C_Master_Rcv( eumbbar );
}
/* slave */
if ( ctrl.mtx == 1 )
{
/* slave xmit */
if ( stat.rxak == 0 )
{
/* master has acknowledged */
return I2C_Slave_Xmit( eumbbar );
}
/* master has not acknowledged, wait for STOP */
/* do nothing for preventing bus from hung */
return I2CSUCCESS;
}
/* slave rcv */
return I2C_Slave_Rcv( eumbbar );
}
else if ( stat.maas == 1 )
{
/* received a call from master */
/* clear the MIF bit */
I2C_Set_Stat(eumbbar, stat );
/* master is calling us, process the address phase */
return I2C_Slave_Addr( eumbbar );
}
else
{
/* has to be arbitration lost */
stat.mal = 0;
I2C_Set_Stat( eumbbar, stat );
ctrl.msta = 0; /* return to receive mode */
I2C_Set_Ctrl( eumbbar, ctrl );
}
return I2CSUCCESS;
}
/******************************************************
* function: I2C_Set_Stat
*
* description: modify the I2CSR
*
*****************************************************/
static void I2C_Set_Stat( unsigned int eumbbar, I2C_STAT stat )
{
union {
unsigned int val;
I2C_STAT stat;
} s_tmp;
union {
unsigned int val;
I2C_STAT stat;
} s;
s.val = load_runtime_reg( eumbbar, I2CSR );
s.val &= 0xffffff08;
s_tmp.stat = stat;
s.val |= (s_tmp.val & 0xf7);
#ifdef I2CDBG0
printf( "%s(%d): set stat = 0x%08x\n", __FILE__, __LINE__, s.val );
#endif
store_runtime_reg( eumbbar, I2CSR, s.val );
}
void delay( int deciseconds )
{
int j,k;
k = 0xfffff;
for (j = 0; j < deciseconds; j++) {
while (k) {
k = k-1;
}
}
}
void I2cRead (unsigned char addr)
{
unsigned int rc;
rc = I2C_do_transaction(0,I2C_MASTER_RCV,addr,0,256,READ_BUFFER,I2C_NO_STOP,0,I2C_NO_RESTART);
}
void I2cWrite (unsigned char addr)
{
unsigned int rc,i;
for(i=0;i<256;i++)WRITE_BUFFER[i]=i;
rc = I2C_do_transaction(0,I2C_MASTER_XMIT,addr,0,256,WRITE_BUFFER,I2C_NO_STOP,0,I2C_NO_RESTART);
}
unsigned int I2cInit (void)
{
unsigned int rc;
rc = I2C_Initialize(0,0,0);
if(rc)
return 1;
else
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -