📄 i2c1.c
字号:
***************************************************/static I2CStatus I2C_Slave_Xmit( unsigned int eumbbar ){ unsigned int val; 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 PRINT( "%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 PRINT( "%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 */{#ifdef I2CDBG0 PRINT( "%s(%d): I2C_Init enter\n", __FILE__, __LINE__ );#endif I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar ); unsigned int tmp; /* 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 PRINT( "%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 );#ifdef I2CDBG0 PRINT( "%s(%d): get stat = 0x%08x\n", __FILE__, __LINE__, temp );#endif I2C_STAT stat; 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 PRINT( "%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 PRINT( "%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 ){#ifdef I2CDBG0 PRINT( "%s(%d): I2C_ISR\n", __FILE__, __LINE__ );#endif I2C_STAT stat = I2C_Get_Stat( eumbbar ); I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar ); /* 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 PRINT( "%s(%d): set stat = 0x%08x\n", __FILE__, __LINE__, s.val );#endif store_runtime_reg( eumbbar, I2CSR, s.val );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -