📄 i2c.c
字号:
/*
*********************************************************************************
* Copyright (c) 2005 ASIX Electronic Corporation All rights reserved.
*
* This is unpublished proprietary source code of ASIX Electronic Corporation
*
* The copyright notice above does not evidence any actual or intended
* publication of such source code.
*********************************************************************************
*/
/*================================================================================
* Module Name : i2c.c
* Purpose : This module handles the I2C serial interface driver.
* Author : Robin Lee
* Date : 2005-01-10
* Notes :
* $Log: i2c.c,v $
* Revision 1.2 2006/04/14 00:56:42 robin6633
* Fixed the function name error "I2cCmd() -> I2C_Cmd()".
*
* Revision 1.1 2006/04/07 11:38:34 robin6633
* no message
*
*================================================================================
*/
/* INCLUDE FILE DECLARATIONS */
#include <stdio.h>
#include "reg80390.h"
#include "types.h"
#include "i2c.h"
#if I2C_SLAVE_ENABLE
#include "console_debug.h"
#endif
/* STATIC VARIABLE DECLARATIONS */
static U8_T i2cCtrl = 0;
static U8_T i2cEndCond = 0;
static U8_T i2cActF = 0; // indicate the condition of a transfer
static U16_T i2cDataLen = 0; // The I2cPktLen includes address and data
static U16_T i2cDataLenCnt = 0; // Packet's counter of transferring
static U8_T i2cPktDir = 0; // Packet's direction
static I2C_BUF *ptI2cTxBuf = 0;
static I2C_BUF *ptI2cRxBuf = 0;
static U8_T i2cState = 0; // I2C master state flag
static U8_T i2cSlvRxPkt[SLV_MAX_PKT_NUM];
static U8_T i2cSlvTxPkt[SLV_MAX_PKT_NUM];
/* LOCAL SUBPROGRAM DECLARATIONS */
static void i2c_MstStatus(U8_T i2cStatus);
static void i2c_SlvStatus(U8_T i2cStatus);
static void i2c_MasterXmit(U8_T wrData, U8_T mstCmd);
static void i2c_MasterRcvr(U8_T *rdData, U8_T mstCmd);
static void i2c_SlaveXmit(U8_T wrData, U8_T slvCmd);
static void i2c_SlaveRcvr(U8_T *rdData, U8_T slvCmd);
#if I2C_SLAVE_ENABLE
static void i2c_SlvRxProcess(void);
#endif
/* LOCAL SUBPROGRAM BODIES */
/*
*--------------------------------------------------------------------------------
* static void i2c_MstStatus(U8_T i2cStatus)
* Purpose : Checks the interrupt status of I2C master mode.
* Params : i2cStatus - master status when interrupt occured.
* Returns : none
* Note : none
*--------------------------------------------------------------------------------
*/
static void i2c_MstStatus(U8_T i2cStatus)
{
if (i2cPktDir == I2C_MST_XMIT)
{
/* Check the current byte ack */
if ((!(i2cStatus & I2C_NO_ACK)) && (i2cStatus & I2C_INTR_FLAG)
&& (!(i2cStatus & I2C_TIP)) && (i2cStatus & I2C_BUS_BUSY))
{
if (!I2C_FlagChk(I2C_BUSY))
{
I2C_FlagEnb(I2C_RESTART);
}
else
{
if ((i2cCtrl & I2C_10BIT) && (i2cActF & I2C_START_COND))
{
i2c_MasterXmit((U8_T)(ptI2cTxBuf->I2cAddr.TenBitAddr & 0x00FF), I2C_MASTER_GO | I2C_CMD_WRITE);
}
else
{
if (i2cDataLenCnt < (i2cDataLen-1))
{
/* transmit the first data byte */
i2c_MasterXmit(ptI2cTxBuf->I2cData[i2cDataLenCnt], I2C_MASTER_GO | I2C_CMD_WRITE);
i2cDataLenCnt ++;
}
else if (i2cDataLenCnt == (i2cDataLen-1))
{
/* transmit the last data byte */
if (i2cEndCond & I2C_STOP_COND)
{
i2c_MasterXmit(ptI2cTxBuf->I2cData[i2cDataLenCnt], I2C_MASTER_GO | I2C_CMD_WRITE | I2C_STOP_COND);
i2cDataLenCnt = 0;
}
else
{
i2c_MasterXmit(ptI2cTxBuf->I2cData[i2cDataLenCnt], I2C_MASTER_GO | I2C_CMD_WRITE);
i2cDataLenCnt = 0;
EA = 0;
I2C_FlagClr(I2C_BUSY);
EA = 1;
}
}
}
}
/* if (i2cActF & I2C_STOP_COND)
{
i2cDataLenCnt = 0;
EA = 0;
I2C_FlagClr(I2C_BUSY);
EA = 1;
}*/
}
else if (i2cStatus & I2C_NO_ACK)
{
i2cDataLenCnt = 0;
if (i2cActF & I2C_START_COND)
{
/* transmit the STOP condition */
i2c_MasterXmit(0, I2C_MASTER_GO | I2C_STOP_COND);
i2cDataLenCnt = 0;
EA = 0;
I2C_FlagClr(I2C_BUSY);
I2C_FlagEnb(I2C_NACK);
EA = 1;
}
else
{
i2cDataLenCnt = 0;
EA = 0;
I2C_FlagClr(I2C_BUSY);
EA = 1;
}
}
else if (i2cStatus & I2C_ARB_LOST)
{
i2c_MasterXmit(0, I2C_MASTER_GO | I2C_STOP_COND);
i2cDataLenCnt = 0;
EA = 0;
I2C_FlagClr(I2C_BUSY);
I2C_FlagEnb(I2C_NACK);
printf("I2C arbitration lost\n\r");
EA = 1;
}
else if (i2cStatus & I2C_TIP)
{
i2cDataLenCnt = 0;
if (i2cActF & I2C_START_COND)
{
I2C_FlagClr(I2C_BUSY);
/* transmit the STOP condition */
i2c_MasterXmit(0, I2C_MASTER_GO | I2C_STOP_COND);
}
else
{
/* transmit the STOP condition or repeat START condition */
I2C_PktBuf(ptI2cTxBuf);
}
}
else if ((!(i2cStatus & I2C_NO_ACK)) && (!(i2cStatus & I2C_TIP)) && (!(i2cStatus & I2C_BUS_BUSY)))
{
if (i2cActF & I2C_STOP_COND)
{
i2cDataLenCnt = 0;
EA = 0;
I2C_FlagClr(I2C_BUSY);
EA = 1;
}
}
}
else if (i2cPktDir == I2C_MST_RCVR)
{
/* Check the current byte ack */
if ((!(i2cStatus & I2C_NO_ACK)) && (i2cStatus & I2C_INTR_FLAG)
&& (!(i2cStatus & I2C_TIP)) && (i2cStatus & I2C_BUS_BUSY))
{
if (i2cActF & I2C_START_COND)
{
if (i2cDataLenCnt == (i2cDataLen - 1))
i2c_MasterRcvr(&(ptI2cRxBuf->I2cData[0]), I2C_MASTER_GO | I2C_CMD_READ | I2C_STOP_COND);
else
i2c_MasterRcvr(&(ptI2cRxBuf->I2cData[0]), I2C_MASTER_GO | I2C_CMD_READ);
}
else if (i2cActF & I2C_STOP_COND)
{
I2C_FlagClr(I2C_BUSY);
i2c_MasterRcvr(&(ptI2cRxBuf->I2cData[i2cDataLenCnt]), 0);
}
else
{
if (i2cDataLenCnt < (i2cDataLen - 1))
{
/* reveive the next byte */
i2c_MasterRcvr(&(ptI2cRxBuf->I2cData[i2cDataLenCnt]), I2C_MASTER_GO | I2C_CMD_READ);
}
else if (i2cDataLenCnt == (i2cDataLen - 1))
{
/* receive the last byte */
i2c_MasterRcvr((U8_T *)(&(ptI2cRxBuf->I2cData[i2cDataLenCnt])), I2C_MASTER_GO | I2C_CMD_READ | I2C_STOP_COND);
}
}
}
else if (i2cStatus & I2C_NO_ACK)
{
i2cDataLenCnt = 0;
if (i2cActF & I2C_START_COND)
{
i2c_MasterXmit(0, I2C_MASTER_GO | I2C_STOP_COND);
i2cDataLenCnt = 0;
EA = 0;
I2C_FlagClr(I2C_BUSY);
I2C_FlagEnb(I2C_NACK);
EA = 1;
}
else
{
i2cDataLenCnt = 0;
EA = 0;
I2C_FlagClr(I2C_BUSY);
EA = 1;
}
}
else
{
if (i2cActF & I2C_STOP_COND)
{
I2C_FlagClr(I2C_BUSY);
i2c_MasterRcvr(&(ptI2cRxBuf->I2cData[i2cDataLenCnt]), 0);
}
}
}
}
/*
*--------------------------------------------------------------------------------
* static void i2c_SlvStatus(U8_T i2cStatus)
* Purpose : Handles the interrupt status of I2C slave mode.
* Params : none
* Returns : none
* Note : none
*--------------------------------------------------------------------------------
*/
static void i2c_SlvStatus(U8_T i2cStatus)
{
U8_T devAddr;
if (i2cStatus & I2C_SLV_STOP)
{
if (!(i2cStatus & I2C_SLV_START))
{
if (i2cPktDir == I2C_SLV_RCVR)
{
i2cDataLen = i2cDataLenCnt;
#if I2C_SLAVE_ENABLE
i2c_SlvRxProcess();
#endif
}
i2cDataLenCnt = 0;
i2c_SlaveRcvr(&i2cSlvRxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
}
}
if (i2cStatus & I2C_SLV_NACK)
{
i2c_SlaveRcvr(&devAddr, I2C_RLS);
}
else
{
if (i2cStatus & I2C_SLV_WR)
{
if (i2cStatus & I2C_SLV_START)
{
i2c_SlaveRcvr(&devAddr, I2C_SLAVE_GO);
i2cPktDir = I2C_SLV_RCVR;
i2cDataLenCnt = 0;
}
else if (i2cStatus & I2C_SLV_STOP)
{
i2c_SlaveRcvr(&i2cSlvRxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
i2cDataLen = i2cDataLenCnt;
#if I2C_SLAVE_ENABLE
i2c_SlvRxProcess();
#endif
i2cDataLenCnt = 0;
}
else if (i2cStatus & I2C_SLV_RESTART)
{
i2c_SlaveRcvr(&devAddr, I2C_SLAVE_GO);
i2cPktDir = I2C_SLV_RCVR;
i2cDataLenCnt = 0;
}
else
{
i2c_SlaveRcvr(&i2cSlvRxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
i2cDataLenCnt ++;
}
}
else if (i2cStatus & I2C_SLV_RD)
{
if (i2cStatus & I2C_SLV_STOP)
{
i2c_SlaveRcvr(&devAddr, I2C_SLAVE_GO);
i2cDataLenCnt = 0;
}
else if (i2cStatus & I2C_SLV_START)
{
i2cPktDir = I2C_SLV_XMIT;
i2cDataLenCnt = 0;
#if I2C_SLAVE_ENABLE
i2c_SlvRxProcess();
#endif
i2c_SlaveXmit(i2cSlvTxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
i2cDataLenCnt ++;
}
else if (i2cStatus & I2C_SLV_RESTART)
{
i2cPktDir = I2C_SLV_XMIT;
i2cDataLenCnt = 0;
#if I2C_SLAVE_ENABLE
i2c_SlvRxProcess();
#endif
i2c_SlaveXmit(i2cSlvTxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
i2cDataLenCnt ++;
}
else
{
if (i2cSlvRxPkt[0] == I2C_SLV_BRDM)
{
#if I2C_SLAVE_ENABLE
i2c_SlvRxProcess();
#endif
}
i2c_SlaveXmit(i2cSlvTxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
i2cDataLenCnt ++;
}
}
}
}
#if I2C_SLAVE_ENABLE
/*
*--------------------------------------------------------------------------------
* static void i2c_SlvRxProcess(void)
* Purpose : Handling received command functions in I2C slave mode And replying
* packets corresponding with the received command.
* Params : none
* Returns : none
* Note : none
*--------------------------------------------------------------------------------
*/
static void i2c_SlvRxProcess(void)
{
U8_T slvCmd;
U8_T sfrAddr;
U8_T cmdIndReg, realReg, realLen;
U32_T memAddr, memData;
U16_T i;
slvCmd = i2cSlvRxPkt[0];
if ((slvCmd & 0xF0) == I2C_SLV_SWSFR)
{
realLen = (slvCmd & 0x0F) + 1;
sfrAddr = i2cSlvRxPkt[1];
for (i = 0 ; i < realLen ; i ++)
{
CLI_SfrWr((U32_T)sfrAddr, (U32_T)i2cSlvRxPkt[i + 2]);
}
}
else if ((slvCmd & 0xF0) == I2C_SLV_SRSFR)
{
realLen = (slvCmd & 0x0F) + 1;
sfrAddr = i2cSlvRxPkt[1];
for (i = 0 ; i < realLen ; i ++)
{
CLI_SfrRd((U32_T)sfrAddr, &memData);
i2cSlvTxPkt[i] = (U8_T)memData;
}
}
else if ((slvCmd & 0xF0) == I2C_SLV_IWSFR)
{
cmdIndReg = i2cSlvRxPkt[1];
realReg = i2cSlvRxPkt[2];
realLen = (slvCmd & 0x0F) + 1;
if (cmdIndReg == SFR_I2CCIR)
{
CLI_I2cWr((U32_T)realReg, &i2cSlvRxPkt[3], (U8_T)realLen);
}
else if (cmdIndReg == SFR_SPICIR)
{
CLI_SpiWr((U32_T)realReg, &i2cSlvRxPkt[3], (U8_T)realLen);
}
else if (cmdIndReg == SFR_OWCIR)
{
CLI_OwWr((U32_T)realReg, &i2cSlvRxPkt[3], (U8_T)realLen);
}
else if (cmdIndReg == SFR_CANCIR)
{
CLI_CanWr((U32_T)realReg, &i2cSlvRxPkt[3], (U8_T)realLen);
}
else if (cmdIndReg == SFR_TCIR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -