📄 i2c.c
字号:
* note: this is master receive API
**********************************************************/
static I2CStatus I2C_get( unsigned int eumbbar,
unsigned char rcv_from, /* sender's address */
unsigned char *buffer_ptr, /* pointer of receiving buffer */
unsigned int length, /* length of the receiving buffer */
unsigned int stop_flag, /* 1 - signal STOP when buffer is full
* 0 - no STOP signal when buffer is full
*/
unsigned int is_cnt ) /* 1 - this is a restart, don't check MBB
* 0 - this is a new start, check MBB
*/
{
if ( buffer_ptr == 0 || length == 0 )
{
return I2CERROR;
}
#ifdef I2CDBG0
printf( "%s(%d): I2C_get\n", __FILE__, __LINE__ );
#endif
RcvByte = 0;
ByteToRcv = length;
RcvBuf = buffer_ptr;
RcvBufFulStop = stop_flag;
XmitByte = 0;
ByteToXmit = 0;
XmitBuf = 0;
/* we are the master, start the transaction */
return I2C_Start( eumbbar, rcv_from, RCV, is_cnt );
}
#if 0 /* turn off dead code */
/*********************************************************
* function: I2C_write
*
* description:
* Send a buffer of data to the requiring master.
* If stop_flag is set, after the whole buffer is sent,
* generate a STOP signal provided that the requiring
* receiver doesn't signal the STOP in the middle.
* I2C is the slave performing transmitting.
*
* Note: this is slave xmit API.
*
* due to the current Kahlua design, slave transmitter
* shall not signal STOP since there is no way
* for master to detect it, causing I2C bus hung.
*
* For the above reason, the stop_flag is always
* set, i.e., 0.
*
* programmer shall use the timer on Kahlua to
* control the interval of data byte at the
* master side.
*******************************************************/
static I2CStatus I2C_write( unsigned int eumbbar,
unsigned char *buffer_ptr, /* pointer of data to be sent */
unsigned int length, /* number of byte of in the buffer */
unsigned int stop_flag ) /* 1 - signal STOP when buffer is empty
* 0 - no STOP signal when buffer is empty
*/
{
if ( buffer_ptr == 0 || length == 0 )
{
return I2CERROR;
}
XmitByte = 0;
ByteToXmit = length;
XmitBuf = buffer_ptr;
XmitBufEmptyStop = 0; /* in order to avoid bus hung, ignored the user's stop_flag */
RcvByte = 0;
ByteToRcv = 0;
RcvBuf = 0;
/* we are the slave, just wait for being called, or pull */
/* I2C_Timer_Event( eumbbar ); */
}
/******************************************************
* function: I2C_read
*
* description:
* Receive a buffer of data from the sending master.
* If stop_flag is set, when the buffer is full and the
* sender does not signal STOP, generate a STOP signal.
* I2C is the slave performing receiving.
*
* note: this is slave receive API
****************************************************/
static I2CStatus I2C_read(unsigned int eumbbar,
unsigned char *buffer_ptr, /* pointer of receiving buffer */
unsigned int length, /* length of the receiving buffer */
unsigned int stop_flag ) /* 1 - signal STOP when buffer is full
* 0 - no STOP signal when buffer is full
*/
{
if ( buffer_ptr == 0 || length == 0 )
{
return I2CERROR;
}
RcvByte = 0;
ByteToRcv = length;
RcvBuf = buffer_ptr;
RcvBufFulStop = stop_flag;
XmitByte = 0;
ByteToXmit = 0;
XmitBuf = 0;
/* wait for master to call us, or poll */
/* I2C_Timer_Event( eumbbar ); */
}
#endif /* turn off dead code */
/*********************************************************
* function: I2c_Timer_Event
*
* description:
* if interrupt is not used, this is the timer event handler.
* After each fixed time interval, this function can be called
* to check the I2C status and call appropriate function to
* handle the status event.
********************************************************/
static I2CStatus I2C_Timer_Event( unsigned int eumbbar, I2CStatus (*handler)( unsigned int ) )
{
I2C_STAT stat;
#ifdef I2CDBG0
printf( "%s(%d): I2C_Timer_Event\n", __FILE__, __LINE__ );
#endif
stat = I2C_Get_Stat( eumbbar );
if ( stat.mif == 1 )
{
if ( handler == 0 )
{
return I2C_ISR( eumbbar );
}
else
{
return (*handler)( eumbbar );
}
}
else if (stat.rxak == 1) {
/* printf("tick\n");*/
delay( 50 );
/* {
int x;
for (x = 1000; x > 0; x--)
;
}*/
if (--GlobalTimer <= 0)
return( I2CRCVERROR );
}
return I2CNOEVENT;
}
/****************** Device I/O function *****************/
/******************************************************
* function: I2C_Start
*
* description: Generate a START signal in the desired mode.
* I2C is the master.
*
* Return I2CSUCCESS if no error.
*
* note:
****************************************************/
static I2CStatus I2C_Start( unsigned int eumbbar,
unsigned char slave_addr, /* address of the receiver */
I2C_MODE mode, /* XMIT(1) - put (write)
* RCV(0) - get (read)
*/
unsigned int is_cnt ) /* 1 - this is a restart, don't check MBB
* 0 - this is a new start
*/
{
unsigned int tmp = 0;
I2C_STAT stat;
I2C_CTRL ctrl;
#ifdef I2CDBG0
printf( "%s(%d): I2C_Start addr 0x%x mode %d cnt %d\n", __FILE__, __LINE__ ,
slave_addr,mode,is_cnt);
#endif
ctrl = I2C_Get_Ctrl( eumbbar );
/* first make sure I2C has been initialized */
if ( ctrl.men == 0 )
{
return I2CERROR;
}
/* next make sure bus is idle */
stat = I2C_Get_Stat( eumbbar );
if ( is_cnt == 0 && stat.mbb == 1 )
{
/* sorry, we lost */
return I2CBUSBUSY;
}
else if ( is_cnt == 1 && stat.mif == 1 && stat.mal == 0 )
{
/* sorry, we lost the bus */
return I2CALOSS;
}
/* OK, I2C is enabled and we have the bus */
/* prepare to write the slave address */
ctrl.msta = 1;
ctrl.mtx = 1;
ctrl.txak = 0;
ctrl.rsta = is_cnt; /* set the repeat start bit */
I2C_Set_Ctrl( eumbbar, ctrl );
/* write the slave address and xmit/rcv mode bit */
tmp = load_runtime_reg( eumbbar, I2CDR );
tmp = ( tmp & 0xffffff00 ) | ((slave_addr & 0x007f)<<1) | ( mode == XMIT ? 0x0 : 0x1 );
store_runtime_reg( eumbbar, I2CDR, tmp );
if ( mode == RCV )
{
MasterRcvAddress = 1;
}
else
{
MasterRcvAddress = 0;
}
#ifdef I2CDBG0
printf( "%s(%d): I2C_Start exit\n", __FILE__, __LINE__ );
#endif
/* wait for the interrupt or poll */
return I2CSUCCESS;
}
/***********************************************************
* function: I2c_Stop
*
* description: Generate a STOP signal to terminate the master
* transaction.
* return I2CSUCCESS
*
**********************************************************/
static I2CStatus I2C_Stop( unsigned int eumbbar )
{
I2C_CTRL ctrl;
#ifdef I2CDBG0
printf( "%s(%d): I2C_Stop enter\n", __FILE__, __LINE__ );
#endif
ctrl = I2C_Get_Ctrl(eumbbar );
ctrl.msta = 0;
I2C_Set_Ctrl( eumbbar, ctrl );
#ifdef I2CDBG0
printf( "%s(%d): I2C_Stop exit\n", __FILE__, __LINE__ );
#endif
return I2CSUCCESS;
}
/****************************************************
* function: I2C_Master_Xmit
*
* description: Master sends one byte of data to
* slave target
*
* return I2CSUCCESS if the byte transmitted.
* Otherwise no-zero
*
* Note: condition must meet when this function is called:
* I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && I2CSR(RXAK) == 0
* I2CCR(MSTA) == 1 && I2CCR(MTX) == 1
*
***************************************************/
static I2CStatus I2C_Master_Xmit( unsigned int eumbbar )
{
unsigned int val;
if ( ByteToXmit > 0 )
{
if ( ByteToXmit == XmitByte )
{
/* all xmitted */
ByteToXmit = 0;
if ( XmitBufEmptyStop == 1 )
{
I2C_Stop( eumbbar );
}
return I2CBUFFEMPTY;
}
#ifdef I2CDBG0
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_Master_Rcv
*
* description: master reads one byte data
* from slave source
*
* return I2CSUCCESS if no error
*
* Note: condition must meet when this function is called:
* I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&
* I2CCR(MSTA) == 1 && I2CCR(MTX) == 0
*
***********************************************/
static I2CStatus I2C_Master_Rcv( unsigned int eumbbar )
{
I2C_CTRL ctrl;
unsigned int val;
if ( ByteToRcv > 0 )
{
if ( ByteToRcv - RcvByte == 2 && RcvBufFulStop == 1 )
{
/* master requests more than or equal to 2 bytes
* we are reading 2nd to last byte
*/
/* we need to set I2CCR(TXAK) to generate a STOP */
ctrl = I2C_Get_Ctrl( eumbbar );
ctrl.txak = 1;
I2C_Set_Ctrl( eumbbar, ctrl );
/* Kahlua will automatically generate a STOP
* next time a transaction happens
*/
/* note: the case of master requesting one byte is
* handled in I2C_ISR
*/
}
/* generat a STOP before reading the last byte */
if ( RcvByte + 1 == ByteToRcv && RcvBufFulStop == 1 )
{
I2C_Stop( eumbbar );
}
val = load_runtime_reg( eumbbar, I2CDR );
*(RcvBuf + RcvByte) = val & 0xFF;
#ifdef I2CDBG0
printf( "%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, *(RcvBuf + RcvByte) );
#endif
RcvByte++;
if ( ByteToRcv == RcvByte )
{
ByteToRcv = 0;
return I2CBUFFFULL;
}
return I2CSUCCESS;
}
return I2CBUFFFULL;
}
/****************************************************
* function: I2C_Slave_Xmit
*
* description: Slave sends one byte of data to
* requesting destination
*
* return SUCCESS if the byte transmitted. Otherwise
* No-zero
*
* Note: condition must meet when this function is called:
* I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && I2CSR(RXAK) = 0
* I2CCR(MSTA) == 0 && I2CCR(MTX) == 1
*
***************************************************/
static I2CStatus I2C_Slave_Xmit( unsigned int eumbbar )
{
unsigned int val;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -