|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
MPC880通过IIC发送时,发送描述符已设置中断方式,为什么需要在*I2COM (ulImmrVal) = 0x81启动发送后,要让CPU空跑等待一段时间
(200us)。否则发送数据有问题。我们要在1ms内完成一个计算任务,所以CPU时间太重要。在中断中采用vxworks的信号量的方式,还是要等待
200us,,请问如何解决这个问题?
iic的驱动如下
#include "type.h"
#include <stdio.h>
#include <string.h>
#include "taskLib.h"
#include "ppc860I2C.h"
#include "cachelib.h"
#include "drv/multi/ppc860Siu.h"
#include "drv/multi/ppc860Cpm.h"
#include "arch/ppc/vxPpcLib.h"
#include "Ads88x.h"
#include "semLib.h"
#include "intLib.h"
#include "time.h"
#include "iv.h"
#include "definition.h" /* include the iic switch channel define */
UCHAR g_cI2CPrintfSwitch;
UCHAR *pucI2CRxBuffer;
UCHAR *pucI2CTxBuffer;
UCHAR g_ucCurIICSwitchChnl = 255;
extern UINT32 vxImmrGet (void);
void bspI2CIsr (void);
STATUS iicInit7992 (void);
void iicInitPCA9548 (void);
LONG g_lSendAddr = 1, g_lReceive = 0, g_lTransmit = 0, g_lTxErr = 0, g_lBusy =
0;
SEM_ID g_semTx, g_semRx;
SEM_ID g_semIICen;
#define IIC_AD7992_ISR_TASK_PRI 200
void delay (LONG d)
{
LONG i, j;
for (i = 0; i < d; i++)
for (j = 0; j < 500; j++)
;
}
void iicPpc860I2CInit ()
{
ULONG ulImmrVal;
ulImmrVal = vxImmrIsbGet ();
ulImmrVal &= 0xffff0000;
g_cI2CPrintfSwitch = FALSE; /*TRUE; */
/*PB27 SDA PB26 SCL */
*PBPAR (ulImmrVal) |= PB27 | PB26;
*PBDIR (ulImmrVal) |= PB27 | PB26;
*PBODR (ulImmrVal) |= (PB27 | PB26);
g_semTx = semBCreate (SEM_Q_FIFO, SEM_EMPTY);
if (g_semTx == NULL)
return;
g_semRx = semBCreate (SEM_Q_FIFO, SEM_EMPTY);
if (g_semRx == NULL)
return;
g_semIICen = semBCreate (SEM_Q_FIFO, SEM_FULL);
if (g_semIICen == NULL)
return;
pucI2CRxBuffer = (UCHAR *) (ulImmrVal + M860_I2C_BD_TBASE + 8);
pucI2CTxBuffer = (UCHAR *) (ulImmrVal + M860_I2C_BD_TBASE + 8 + 0x100);
/*Init Param ram */
M860_I2C_16_WR (ulImmrVal + I2C_PARAM_OFFSET + I2C_PARAM_RBASE,
M860_I2C_BD_RBASE);
M860_I2C_16_WR (ulImmrVal + I2C_PARAM_OFFSET + I2C_PARAM_TBASE,
M860_I2C_BD_TBASE);
M860_I2C_8_WR (ulImmrVal + I2C_PARAM_OFFSET + I2C_PARAM_RFCR, 0x10);
M860_I2C_8_WR (ulImmrVal + I2C_PARAM_OFFSET + I2C_PARAM_TFCR, 0x10);
M860_I2C_16_WR (ulImmrVal + I2C_PARAM_OFFSET + I2C_PARAM_MRBLR,
I2C_MAX_BUF_LEN);
/*Init TxBD and RxBD */
M860_I2C_32_WR (ulImmrVal + M860_I2C_BD_RBASE + M860_I2C_BD_ADDR_OFF, pucI2CRxBuffer); /*data */
M860_I2C_32_WR (ulImmrVal + M860_I2C_BD_TBASE + M860_I2C_BD_ADDR_OFF,
pucI2CTxBuffer);
/* RESET ALL REGISTERS */
*I2MOD (ulImmrVal) &= 0x00;
*I2ADD (ulImmrVal) &= 0x00;
*I2BRG (ulImmrVal) &= 0x00;
*I2CER (ulImmrVal) |= 0xFF;
*I2CMR (ulImmrVal) &= 0;
*CPCR (ulImmrVal) &= 0x0000;
*I2COM (ulImmrVal) &= 0x00;
intConnect (IV_I2C, (VOIDFUNCPTR) bspI2CIsr, 0);
/*初始化I2C */
/*初始化I2C */
*I2MOD (ulImmrVal) |= 0x00; /*Disable I2C before init it */
/*f(SCL)=brg/32/(2*(0x4b+3))
0x4b 26k
0x3 343K
0x4 294K
0x12 98K */
*I2BRG (ulImmrVal) |= 0x3;
*I2MOD (ulImmrVal) |= 0x01; /*enable I2C */
*I2ADD (ulImmrVal) |= 0x0e; /*slave addr */
*I2CER (ulImmrVal) |= 0x17;
*I2CMR (ulImmrVal) |= 0x13;
while ((*CPCR (ulImmrVal)) & (0x0001)); /* SPIN UNTIL READY TO ISSUE COMMAND */
*CPCR (ulImmrVal) = (0x0011); /* ISSUE COMMAND */
while ((*CPCR (ulImmrVal)) & (0x0001)); /* SPIN UNTIL COMMAND PROCESSED */
*CISR (ulImmrVal) = (CIMR_I2C);
*CIMR (ulImmrVal) |= (CIMR_I2C);
}
STATUS bspI2CWrite (UCHAR ucSlaveAddr, UCHAR * pucBuf, ULONG ulBufLen)
{
ULONG ulImmrVal = vxImmrIsbGet ();
ULONG i, j;
ULONG ulEvent, ulBDStatus, ulLoopTimes;
ULONG retVal;
if (ulBufLen > (I2C_MAX_BUF_LEN - 1))
return ERROR;
ulImmrVal &= 0xffff0000;
memset (pucI2CRxBuffer, 0, I2C_MAX_BUF_LEN);
pucI2CTxBuffer[0] = (ucSlaveAddr << 1) & 0xfe; /* bit 0=0,w */
for (i = 0; i < ulBufLen; i++)
pucI2CTxBuffer[i + 1] = pucBuf;
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_TBASE + M860_I2C_BD_LEN_OFF,
ulBufLen + 1);
M860_I2C_32_WR (ulImmrVal + M860_I2C_BD_TBASE + M860_I2C_BD_ADDR_OFF,
(&pucI2CTxBuffer[0]));
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_TBASE + M860_I2C_BD_STAT_OFF, 0xbc00); /*ready wrap and last */
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_RBASE + M860_I2C_BD_LEN_OFF, 0);
M860_I2C_32_WR (ulImmrVal + M860_I2C_BD_RBASE + M860_I2C_BD_ADDR_OFF,
&pucI2CRxBuffer[0]);
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_RBASE + M860_I2C_BD_STAT_OFF,
0xb000);
cacheFlush (DATA_CACHE, pucI2CTxBuffer, I2C_MAX_BUF_LEN);
__asm__ volatile (" eieio; sync");
/*taskDelay(1); */
/*longdelay(2); */
/* start the reading */
*I2COM (ulImmrVal) = 0x81;
__asm__ volatile (" eieio; sync");
/*taskDelay(1); */
#if 1
delay (5);
#else
retVal = semTake (g_semTx, 120);
if (retVal == ERROR)
return ERROR;
#endif
M860_I2C_16_RD (ulImmrVal + M860_I2C_BD_TBASE + M860_I2C_BD_STAT_OFF,
ulBDStatus);
if ((ulBDStatus & 0x2) == 0x2)
{
I2C_PRINTF ("\r\nTransmit Underrun");
}
else if ((ulBDStatus & 0x1) == 0x1)
{
I2C_PRINTF ("\r\nTransmit Collision");
}
else if ((ulBDStatus & 0x4) == 0x4)
{
I2C_PRINTF ("\r\nTransmit No Acknowledge");
}
else if ((ulBDStatus & 0x8000) == 0x0)
{
I2C_PRINTF ("\r\nTransmit OK");
return OK;
}
return ERROR;
}
STATUS bspI2CWriteProtect (UCHAR ucSlaveAddr, UCHAR * pucBuf, ULONG ulBufLen)
{
STATUS ret;
ULONG retVal;
retVal = semTake (g_semIICen, WAIT_FOREVER);
if (retVal == ERROR)
return ERROR;
ret = bspI2CWrite (ucSlaveAddr, pucBuf, ulBufLen);
semGive (g_semIICen);
return ret;
}
STATUS bspI2CRead (UCHAR ucSlaveAddr, UCHAR * pucWriteBuf, LONG lWriteBufLen,
UCHAR * pucReadBuf, LONG lReadBufLen)
{
LONG ulImmrVal = vxImmrIsbGet ();
ULONG i, retVal;
if (lWriteBufLen > I2C_MAX_BUF_LEN - 1)
return ERROR;
if (lReadBufLen > I2C_MAX_BUF_LEN - 1)
return ERROR;
ulImmrVal &= 0xffff0000;
memset (pucI2CRxBuffer, 0, I2C_MAX_BUF_LEN);
if (lWriteBufLen > 0)
{
pucI2CTxBuffer[0] = (ucSlaveAddr << 1) & 0xfe; /* bit 0=0,w */
for (i = 0; i < lWriteBufLen; i++)
pucI2CTxBuffer[i + 1] = pucWriteBuf;
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_TBASE + M860_I2C_BD_LEN_OFF,
lWriteBufLen + 1);
/*M860_I2C_32_WR( ulImmrVal + M860_I2C_BD_TBASE + M860_I2C_BD_ADDR_OFF, (&pucI2CTxBuffer[0])); */
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_TBASE + M860_I2C_BD_STAT_OFF, 0xb000); /*ready wrap and last */
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_RBASE + M860_I2C_BD_LEN_OFF, 0);
/*M860_I2C_32_WR( ulImmrVal + M860_I2C_BD_RBASE + M860_I2C_BD_ADDR_OFF, &pucI2CRxBuffer[0]); */
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_RBASE + M860_I2C_BD_STAT_OFF,
0xb000);
/*cacheFlush(DATA_CACHE, pucI2CTxBuffer, I2C_MAX_BUF_LEN); */
__asm__ volatile (" eieio; sync");
/*从整合前移植过来没有这个延时, 会出现i2c 忙或者状态出错等情况. */
/* start the reading */
*I2COM (ulImmrVal) = 0x81;
__asm__ volatile (" eieio; sync");
/*taskDelay(20); */
/* wait 2s */
retVal = semTake (g_semTx, 120);
if (retVal == ERROR)
return ERROR;
}
/* set bit0 to start reading */
/*memset(pucI2CRxBuffer, 0, I2C_MAX_BUF_LEN); */
pucI2CTxBuffer[0] = ((ucSlaveAddr << 1) & 0xfe) | 0x1; /* bit 0=1,r */
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_TBASE + M860_I2C_BD_LEN_OFF,
lReadBufLen + 1);
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_TBASE + M860_I2C_BD_STAT_OFF, 0xbc00); /*ready wrap and last */
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_RBASE + M860_I2C_BD_LEN_OFF, 0);
M860_I2C_16_WR (ulImmrVal + M860_I2C_BD_RBASE + M860_I2C_BD_STAT_OFF,
0xb000);
__asm__ volatile (" eieio; sync");
/*从整合前移植过来没有这个延时, 会出现i2c 忙或者状态出错等情况. */
/* start the reading */
*I2COM (ulImmrVal) = 0x81;
__asm__ volatile (" eieio; sync");
/*taskDelay(20); */
/* wait 2s */
retVal = semTake (g_semRx, 120);
if (retVal == OK)
{
memcpy (pucReadBuf, pucI2CRxBuffer, lReadBufLen);
}
return retVal;
}
void bspI2CIsr (void)
{
ULONG ulImmrVal = vxImmrIsbGet ();
ULONG ucEvent;
ulImmrVal &= 0xffff0000;
ucEvent = *I2CER (ulImmrVal);
if (ucEvent & 0x10)
{
g_lTxErr++;
semGive (g_semTx);
}
if (ucEvent & 0x04)
{
g_lBusy++;
semGive (g_semRx);
}
if (ucEvent & 0x02)
{
g_lTransmit++;
semGive (g_semTx);
}
if (ucEvent & 0x01)
{
g_lReceive++;
semGive (g_semRx);
}
*I2CER (ulImmrVal) = ucEvent;
*CISR (ulImmrVal) = CIMR_I2C;
}
谢谢 |
|