📄 i2c1.c
字号:
* * 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 PRINT ("%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); } } 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 PRINT ("%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 PRINT ("%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 PRINT ("%s(%d): I2C_Stop enter\n", __FILE__, __LINE__);#endif ctrl = I2C_Get_Ctrl (eumbbar); ctrl.msta = 0; I2C_Set_Ctrl (eumbbar, ctrl);#ifdef I2CDBG0 PRINT ("%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 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_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 PRINT ("%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; 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); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -