www.pudn.com > CANdrv.rar > CANDrv.c
/* CANDrv.c - MC523x Flexcan communication driver */
/* Copyright 2005 ZHUHAI UNITECH POWER TECHNOLOGY CO.,LTD */
/*
modification history
--------------------
*/
/*
DESCRIPTION
This is the driver for the Flexcan contained in the 523X.
*/
#include "vxWorks.h"
#include "iosLib.h"
#include "intLib.h"
#include "errno.h"
#include "CANDrv.h"
#include "string.h"
int Tx_count;
int Rx_count;
int CanDrvNum = 0;
Tx_count=0;
Rx_count=0;
Can_DEV can_chan_dev[NUM_CAN];
LOCAL STATUS InitCan(Can_DEV *);
LOCAL STATUS WriteByte(Can_DEV *,UCHAR ,int );
LOCAL STATUS CanBaudSet (Can_DEV *, UINT);
LOCAL STATUS CanTxIDSet (Can_DEV *,UINT);
LOCAL STATUS CanRxIDSet (Can_DEV *,UINT);
LOCAL STATUS CheckBusStatus(Can_DEV *);
LOCAL void CanTxInterrupt (Can_DEV *);
LOCAL void CanRxInterrupt (Can_DEV *);
/******************************************************************************
*CanDrv -- CAN驱动安装程序
*返回 - 安装成功返回OK,否则返回ERROR
*参数:无
******************************************************************************/
STATUS CanDrv(void)
{
if(CanDrvNum > 0)
{
printf("Can driver has been installed!\n");
return OK;//已经安装驱动
}
if((CanDrvNum = iosDrvInstall(0,0,CanOpen,CanClose,CanRead,CanWrite,CanIoctl)) == ERROR)
{
printf("Can driver install ERROR!\n");
return ERROR;
}
#if NUM_CAN == 2
intConnect(INUM_TO_IVEC(CAN0_MB0_INTVEC),Can0TxInterrupt,0);
intConnect(INUM_TO_IVEC(CAN0_MB1_INTVEC),Can0RxInterrupt,0);
intConnect(INUM_TO_IVEC(CAN1_MB0_INTVEC),Can1TxInterrupt,0);
intConnect(INUM_TO_IVEC(CAN1_MB1_INTVEC),Can1RxInterrupt,0);
#else
intConnect(INUM_TO_IVEC(CAN0_MB0_INTVEC),Can0TxInterrupt,0);
intConnect(INUM_TO_IVEC(CAN0_MB1_INTVEC),Can0RxInterrupt,0);
#endif
printf("Can driver has been installed successfully !\n");
return OK;
}
/******************************************************************************
*itos -- 将一个整数转换为字符
*返回 - 转换后的字符串指针
*参数:val -- 要转换的整数
******************************************************************************/
static char * itos (int val)
{
static char str [20];
char strtmp [20];
str [0] = '\0';
if (val == 0)
return "0";
while (val != 0)
{
strcpy (strtmp, str);
str[0] = '0' + (val % 10);
str[1] = '\0';
strcat (str, strtmp);
val = val - (val %= 10);
}
return str;
}
/******************************************************************************
*CanDevCreate -- CAN设备创建函数
*返回 - 创建成功返回OK,否则返回ERROR
*参数:无
*
******************************************************************************/
STATUS CanDevCreate()
{
char canName[20];
int i;
if(CanDrvNum == 0)
{
return ERROR;
}
for(i=0;iFlag_canOpen = CAN_YES; /*打开CAN设备*/
/*使MB0和MB1不参与仲裁与配匹*/
CANDEV_WRITE(pCan_Dev->txcode,
TX_NOTENABLE | DEFAULT_LENGTH);
CANDEV_WRITE(pCan_Dev->rxcode,
RX_NOTENABLE | DEFAULT_LENGTH);
/*清除发送缓冲区数据*/
CANDEV_WRITE(pCan_Dev->txdata0,0x00);
CANDEV_WRITE(pCan_Dev->txdata1,0x00);
CANDEV_WRITE(pCan_Dev->txdata2,0x00);
CANDEV_WRITE(pCan_Dev->txdata3,0x00);
CANDEV_WRITE(pCan_Dev->txdata4,0x00);
CANDEV_WRITE(pCan_Dev->txdata5,0x00);
CANDEV_WRITE(pCan_Dev->txdata6,0x00);
CANDEV_WRITE(pCan_Dev->txdata7,0x00);
/*清除接收缓冲区数据*/
CANDEV_WRITE(pCan_Dev->rxdata0,0x00);
CANDEV_WRITE(pCan_Dev->rxdata1,0x00);
CANDEV_WRITE(pCan_Dev->rxdata2,0x00);
CANDEV_WRITE(pCan_Dev->rxdata3,0x00);
CANDEV_WRITE(pCan_Dev->rxdata4,0x00);
CANDEV_WRITE(pCan_Dev->rxdata5,0x00);
CANDEV_WRITE(pCan_Dev->rxdata6,0x00);
CANDEV_WRITE(pCan_Dev->rxdata7,0x00);
/*接收使能*/
CANDEV_WRITE(pCan_Dev->rxcode,
RX_ENABLE | DEFAULT_LENGTH);
printf("Can device has been opened !\n");
return((int)pCan_Dev);
}
/******************************************************************************
*CanOpen -- 关闭CAN设备
*返回 - 无
*参数:pCan_Dev -- 要关闭的CAN设备
*
******************************************************************************/
int CanClose(Can_DEV *pCan_Dev)
{
if(pCan_Dev->Flag_canOpen == CAN_NO)
{
printf("Can device has been closed !\n");
return OK;
}
pCan_Dev->Flag_canOpen = CAN_NO; /*关闭CAN设备*/
CANDEV_WRITE(pCan_Dev->txcode,
TX_NOTENABLE | DEFAULT_LENGTH);
CANDEV_WRITE(pCan_Dev->rxcode,
RX_NOTENABLE | DEFAULT_LENGTH);
/*初始化发送缓冲区指针及发送计数器*/
pCan_Dev->ptx = pCan_Dev->tx_Buff;
pCan_Dev->tx_number = 0;
pCan_Dev->tx_length =0;
/*初始化接收缓冲区指针及接收计数器*/
pCan_Dev->prx_write = pCan_Dev->rx_Buff;
pCan_Dev->prx_read = pCan_Dev->rx_Buff;
pCan_Dev->rx_number = 0;
pCan_Dev->rx_length = 0;
printf("Can device has been closed !\n");
return OK;
}
/******************************************************************************
*
* CanWrite -- CAN发送函数
* 返回: 成功返回已写入的字节数, 否则返回0
*参数说明:
pChan -- 需要控制的设备
buffer -- 写缓冲区
someArg -- 写字节数
******************************************************************************/
int CanWrite(Can_DEV *pCan_Dev,UCHAR *buffer,UINT16 nBytes)
{
int i;
int j;
UCHAR *txbuf;
txbuf = buffer;
if(pCan_Dev->Flag_canOpen == CAN_NO)
{
printf("Can device hasn't been opened !\n");
return 0;/*如果设备没有打开返回0*/
}
if(nBytes > MAX_TX_BUFFER)
{
printf("要发送的字节数大于发送缓冲区长度 !\n");
return 0; /*要发送的字节数大于发送缓冲区*/
}
/*
if( ERROR == semTake(pCan_Dev->tx_semSync, 50) )
{
printf("Cann't Take The TX Sem.\n\r");
return 0;
}
*/
//semTake(pCan_Dev->tx_semSync,WAIT_FOREVER);/*等待发送中断释放信号量*/
/*如果需发送的字节数小于或等于8,不用复制到设备的发送缓冲区中,直接发送
否则将所有数据复制到设备缓冲区中,先发送前8个字节,剩余的在设备的缓冲区中用中断发送*/
if(nBytes <= 8)
{
j = 0;
while(CheckBusStatus(pCan_Dev) != OK) //检查CAN总线是否在空闲状态
{
j++;
if(j >= 40000) break;
}
if(j >= 40000)
{
printf("Can bus is always busy !\n");
return 0;//总线一直忙
}
CANDEV_WRITE(pCan_Dev->txcode, /*INACTIVE发送*/
TX_NOTENABLE);
for(i=0;itx_number = 0;
pCan_Dev->tx_length = nBytes;
pCan_Dev->ptx = pCan_Dev->tx_Buff;
CANDEV_WRITE(pCan_Dev->txcode, /*ACTIVE发送*/
TX_ENABLE | pCan_Dev->tx_length);
printf("Has been transmitted!\n");
}
else
{
/*复制数据到设备的发送缓冲区中*/
for(i = 0;i < nBytes;i++,txbuf++)
{
pCan_Dev->tx_Buff[i] = *txbuf;
}
pCan_Dev->ptx = pCan_Dev->tx_Buff;
pCan_Dev->ptx += 8;/*发送指针往后移8个字节*/
pCan_Dev->tx_number = nBytes -8;
pCan_Dev->tx_length = 8;
j = 0;
while(CheckBusStatus(pCan_Dev) != OK) //检查CAN总线是否在空闲状态
{
j++;
if(j >= 40000) break;
}
if(j >= 40000)
{
pCan_Dev->ptx = pCan_Dev->tx_Buff;
pCan_Dev->tx_number = 0;
pCan_Dev->tx_length = 0;
printf("Can bus is always busy !\n");
return 0;//总线一直忙
}
CANDEV_WRITE(pCan_Dev->txcode, /*INACTIVE发送*/
TX_NOTENABLE);
txbuf = buffer;
for(i=0;i<8;i++)
{
WriteByte(pCan_Dev,*txbuf,i);
txbuf++;
}
CANDEV_WRITE(pCan_Dev->txcode, /*ACTIVE发送*/
TX_ENABLE | pCan_Dev->tx_length);
printf("Has been transmitted!\n");
}
return nBytes;
}
/******************************************************************************
*
* CanRead -- CAN接收函数
* 返回: 成功返回已读的字节数, 否则返回0
*参数说明:
pChan -- 需要控制的设备
buffer -- 读缓冲区
someArg -- 读字节数
******************************************************************************/
int CanRead(Can_DEV *pCan_Dev,UCHAR *buffer,UINT16 nBytes)
{
UINT16 i;
UCHAR *rx_buff;
rx_buff = buffer;
i = 0;
if(pCan_Dev->Flag_canOpen == CAN_NO)
{
printf("Can device is not been opened !\n");
return 0;
}
if( ERROR == semTake(pCan_Dev->rx_semSync, 50) )
{
//printf("Cann't Take The RX Sem.\n");
return 0;
}
//semTake(pCan_Dev->rx_semSync,WAIT_FOREVER);/*等待接收中断释放信号量*/
while((pCan_Dev->prx_read != pCan_Dev->prx_write)&&(i < nBytes))
{
*rx_buff = *pCan_Dev->prx_read;
rx_buff++;
pCan_Dev->prx_read++;
i++;
if((pCan_Dev->prx_read - pCan_Dev->rx_Buff) == MAX_RX_BUFFER )
{
pCan_Dev->prx_read = pCan_Dev->rx_Buff;
}
}
return(i);
}
/******************************************************************************
*
* CAN控制函数
*
* 返回:
* 成功返回OK, 设备错误返回ERROR, 不支持返回ERROR
*
*参数说明:
* pChan -- 需要控制的设备
* request -- 请求的功能
* someArg -- 控制参数
******************************************************************************/
int CanIoctl
(
Can_DEV * pChan, /* device to control */
int request, /* request code */
void * someArg /* some argument */
)
{
STATUS result = OK;
int arg = (int)someArg;
if(pChan->Flag_canOpen != CAN_YES) return ERROR;/*如果设备没有打开返回0*/
switch (request)
{
case CAN_BAUD_SET:
if (CanBaudSet(pChan, arg) != OK)
result = ERROR;
break;
case CAN_BAUD_GET:
*(int *)arg = pChan->baudRate;
return (OK);
case CAN_TXID_SET:
if (CanTxIDSet(pChan, arg) != OK)
result = ERROR;
break;
case CAN_TXID_GET:
*(int *)arg = pChan->TxID;
return (OK);
case CAN_RXID_SET:
if (CanRxIDSet(pChan, arg) != OK)
result = ERROR;
break;
case CAN_RXID_GET:
*(int *)arg = pChan->RxID;
return (OK);
default:
return (ERROR);
}
printf("CanIoctl funtion has been set \n");
return (result);
}
/******************************************************************************
*
* CanBaudSet - 改变can设备的波特率
*设置can的波特率,设置时不使能中断
*波特率只能为1M 500K 250K 125K 100K 75K 50K
*
* 返回:OK或者ERROR
*
******************************************************************************/
LOCAL STATUS CanBaudSet
(
Can_DEV * pcan_chan,
UINT32 baud
)
{
register int i;
i = 0;
if (!baud)
return (ERROR);
if (baud != pcan_chan->baudRate)
{
UINT32 val;
int oldlevel;
switch(baud)
{
case 1000000:
val = 0x045B2005;
break;
case 500000:
val = ((PRESDIV1(baud)) << 24)| CTRL_RJW | CTRL_PSEG1 | CTRL_PSEG2 | CTRL_CLK_SRC | CTRL_SMP | CTRL_PROPSEG;
break;
case 125000:
val = ((PRESDIV1(baud)) << 24)| CTRL_RJW | CTRL_PSEG1 | CTRL_PSEG2 | CTRL_CLK_SRC | CTRL_SMP | CTRL_PROPSEG;
break;
case 100000:
val = ((PRESDIV1(baud)) << 24)| CTRL_RJW | CTRL_PSEG1 | CTRL_PSEG2 | CTRL_CLK_SRC | CTRL_SMP | CTRL_PROPSEG;
break;
case 75000:
val = ((PRESDIV1(baud)) << 24)| CTRL_RJW | CTRL_PSEG1 | CTRL_PSEG2 | CTRL_CLK_SRC | CTRL_SMP | CTRL_PROPSEG;
break;
case 50000:
val = ((PRESDIV1(baud)) << 24)| CTRL_RJW | CTRL_PSEG1 | CTRL_PSEG2 | CTRL_CLK_SRC | CTRL_SMP | CTRL_PROPSEG;
break;
default:
return ERROR;
}
oldlevel = intLock ();
/*设置FRZ和HALT位,使CAN进入Freeze模式,进入管理模式*/
CANDEV_WRITE(pcan_chan->mcr,
MCR_MENE | MCR_FRZ | MCR_HALT | MCR_SUPV | MCR_MAXMB);
while((CANDEV_READ(pcan_chan->mcr) & 0x01000000) == 0x00000000) //等待can进入Freeze模式
{
i++;
if(i >= 40000)
{
return ERROR;
}
}
CANDEV_WRITE(pcan_chan->ctrl,val);
/*退出FREEZE模式,退出管理模式*/
CANDEV_WRITE(pcan_chan->mcr,
MCR_MENE | MCR_MAXMB);
pcan_chan->baudRate = baud;
intUnlock (oldlevel);
}
return (OK);
}
/******************************************************************************
*
* CanIDTxSet - 改变can信息缓冲区MB0的ID
*设置信息缓冲区ID,设置时理论上可以不用使该CAN进入FREEZE模式
*但为了安全起见,还是考虑进入FREEZE模式并且不使能中断
*
* 返回:OK或者ERROR
*
******************************************************************************/
LOCAL STATUS CanTxIDSet
(
Can_DEV *pcan_chan,
UINT32 Id
)
{
register int i;
UINT32 MbufId;
int oldlevel;
i = 0;
if((Id ==0) || (Id > 2047))
{
printf("The TXID number is too large!\n");
return ERROR;
}
if(Id != pcan_chan->TxID)
{
MbufId = Id << 18;
oldlevel = intLock ();
/*设置FRZ和HALT位,使CAN进入Freeze模式,进入管理模式*/
CANDEV_WRITE(pcan_chan->mcr,
MCR_MENE | MCR_FRZ | MCR_HALT | MCR_SUPV | MCR_MAXMB);
while((CANDEV_READ(pcan_chan->mcr) & 0x01000000) == 0x00000000) //等待can进入Freeze模式
{
i++;
if(i >= 40000)
{
printf("CAN didn't enter into freeze mode!");
return ERROR;
}
}
CANDEV_WRITE(pcan_chan->txcode,
TX_NOTENABLE | DEFAULT_LENGTH);
CANDEV_WRITE(pcan_chan->txID,MbufId); //写发送缓冲区ID
/*退出FREEZE模式,退出管理模式*/
CANDEV_WRITE(pcan_chan->mcr,
MCR_MENE | MCR_MAXMB);
pcan_chan->TxID = Id;
intUnlock (oldlevel);
}
return OK;
}
/******************************************************************************
*
* CanIDRxSet - 改变can信息缓冲区MB1的ID
*设置信息缓冲区ID,设置时理论上可以不用使该CAN进入FREEZE模式
*但为了安全起见,还是考虑进入FREEZE模式并且不使能中断
*
* 返回:OK或者ERROR
*
******************************************************************************/
LOCAL STATUS CanRxIDSet
(
Can_DEV *pcan_chan,
UINT32 Id
)
{
register int i;
i = 0;
if((Id ==0) || (Id > 2047))
{
printf("The RXID number is too large!\n");
return ERROR;
}
if(Id != pcan_chan->RxID)
{
UINT32 MbufId;
int oldlevel;
MbufId = Id << 18;
oldlevel = intLock ();
/*设置FRZ和HALT位,使CAN进入Freeze模式,进入管理模式*/
CANDEV_WRITE(pcan_chan->mcr,
MCR_MENE | MCR_FRZ | MCR_HALT | MCR_SUPV | MCR_MAXMB);
while((CANDEV_READ(pcan_chan->mcr) & 0x01000000) == 0x00000000) //等待can进入Freeze模式
{
i++;
if(i >= 40000)
{
printf("CAN didn't enter into freeze mode!");
return ERROR;
}
}
CANDEV_WRITE(pcan_chan->rxcode,
RX_NOTENABLE | DEFAULT_LENGTH);
CANDEV_WRITE(pcan_chan->rxID,MbufId);//写接收缓冲区ID
CANDEV_WRITE(pcan_chan->rxcode,
RX_ENABLE | DEFAULT_LENGTH);
/*退出FREEZE模式,退出管理模式*/
CANDEV_WRITE(pcan_chan->mcr,
MCR_MENE | MCR_MAXMB);
pcan_chan->RxID = Id;
intUnlock (oldlevel);
}
return OK;
}
/******************************************************************************
*
* CanDevInit - can设备初始化程序
*初始化CAN设备结构寄存器地址,并调用Initcan函数对CAN寄存器进行初始化
*
*返回:无
*
*参数:无
******************************************************************************/
void CanDevInit (void)
{
int i;
for(i=0;imcr,
MCR_MENE | MCR_FRZ | MCR_HALT | MCR_SUPV | MCR_MAXMB);
while((CANDEV_READ(pcan_chan->mcr) & MCR_FRZACK) == 0x00000000) //等待can进入Freeze模式
{
i++;
if(i >= 40000)
{
return ERROR;
}
}
/*配置S_CLK的预除因子,时钟源及时间分额数量*/
CANDEV_WRITE(pcan_chan->ctrl,
CTRL_PRESDIV | CTRL_RJW | CTRL_PSEG1 | CTRL_PSEG2 | CTRL_CLK_SRC | CTRL_SMP | CTRL_PROPSEG);
/*初始化MB0作为发送缓冲区,MB1作为接收缓冲区*/
CANDEV_WRITE(pcan_chan->txcode,
TX_NOTENABLE | DEFAULT_LENGTH);
CANDEV_WRITE(pcan_chan->rxcode,
RX_NOTENABLE | DEFAULT_LENGTH);
/*初始化发送缓冲区及接收缓冲区ID*/
CANDEV_WRITE(pcan_chan->txID,(pcan_chan->TxID)<<18);
CANDEV_WRITE(pcan_chan->rxID,(pcan_chan->RxID)<<18);
/*清除发送缓冲区数据*/
CANDEV_WRITE(pcan_chan->txdata0,0x00);
CANDEV_WRITE(pcan_chan->txdata1,0x00);
CANDEV_WRITE(pcan_chan->txdata2,0x00);
CANDEV_WRITE(pcan_chan->txdata3,0x00);
CANDEV_WRITE(pcan_chan->txdata4,0x00);
CANDEV_WRITE(pcan_chan->txdata5,0x00);
CANDEV_WRITE(pcan_chan->txdata6,0x00);
CANDEV_WRITE(pcan_chan->txdata7,0x00);
/*清除接收缓冲区数据*/
CANDEV_WRITE(pcan_chan->rxdata0,0x00);
CANDEV_WRITE(pcan_chan->rxdata1,0x00);
CANDEV_WRITE(pcan_chan->rxdata2,0x00);
CANDEV_WRITE(pcan_chan->rxdata3,0x00);
CANDEV_WRITE(pcan_chan->rxdata4,0x00);
CANDEV_WRITE(pcan_chan->rxdata5,0x00);
CANDEV_WRITE(pcan_chan->rxdata6,0x00);
CANDEV_WRITE(pcan_chan->rxdata7,0x00);
/*不用的缓冲区2~15全部作为接受缓冲区,并且不使能和清零缓冲区的数据*/
/*MB2*/
CANDEV_WRITE(pcan_chan->mb2code,
TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb2ID,0);
CANDEV_WRITE(pcan_chan->mb2data0,0x00);
CANDEV_WRITE(pcan_chan->mb2data1,0x00);
CANDEV_WRITE(pcan_chan->mb2data2,0x00);
CANDEV_WRITE(pcan_chan->mb2data3,0x00);
CANDEV_WRITE(pcan_chan->mb2data4,0x00);
CANDEV_WRITE(pcan_chan->mb2data5,0x00);
CANDEV_WRITE(pcan_chan->mb2data6,0x00);
CANDEV_WRITE(pcan_chan->mb2data7,0x00);
/*MB3*/
CANDEV_WRITE(pcan_chan->mb3code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb3ID,0);
CANDEV_WRITE(pcan_chan->mb3data0,0x00);
CANDEV_WRITE(pcan_chan->mb3data1,0x00);
CANDEV_WRITE(pcan_chan->mb3data2,0x00);
CANDEV_WRITE(pcan_chan->mb3data3,0x00);
CANDEV_WRITE(pcan_chan->mb3data4,0x00);
CANDEV_WRITE(pcan_chan->mb3data5,0x00);
CANDEV_WRITE(pcan_chan->mb3data6,0x00);
CANDEV_WRITE(pcan_chan->mb3data7,0x00);
/*MB4*/
CANDEV_WRITE(pcan_chan->mb4code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb4ID,0);
CANDEV_WRITE(pcan_chan->mb4data0,0x00);
CANDEV_WRITE(pcan_chan->mb4data1,0x00);
CANDEV_WRITE(pcan_chan->mb4data2,0x00);
CANDEV_WRITE(pcan_chan->mb4data3,0x00);
CANDEV_WRITE(pcan_chan->mb4data4,0x00);
CANDEV_WRITE(pcan_chan->mb4data5,0x00);
CANDEV_WRITE(pcan_chan->mb4data6,0x00);
CANDEV_WRITE(pcan_chan->mb4data7,0x00);
/*MB5*/
CANDEV_WRITE(pcan_chan->mb5code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb5ID,0);
CANDEV_WRITE(pcan_chan->mb5data0,0x00);
CANDEV_WRITE(pcan_chan->mb5data1,0x00);
CANDEV_WRITE(pcan_chan->mb5data2,0x00);
CANDEV_WRITE(pcan_chan->mb5data3,0x00);
CANDEV_WRITE(pcan_chan->mb5data4,0x00);
CANDEV_WRITE(pcan_chan->mb5data5,0x00);
CANDEV_WRITE(pcan_chan->mb5data6,0x00);
CANDEV_WRITE(pcan_chan->mb5data7,0x00);
/*MB8*/
CANDEV_WRITE(pcan_chan->mb6code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb6ID,0);
CANDEV_WRITE(pcan_chan->mb6data0,0x00);
CANDEV_WRITE(pcan_chan->mb6data1,0x00);
CANDEV_WRITE(pcan_chan->mb6data2,0x00);
CANDEV_WRITE(pcan_chan->mb6data3,0x00);
CANDEV_WRITE(pcan_chan->mb6data4,0x00);
CANDEV_WRITE(pcan_chan->mb6data5,0x00);
CANDEV_WRITE(pcan_chan->mb6data6,0x00);
CANDEV_WRITE(pcan_chan->mb6data7,0x00);
/*MB7*/
CANDEV_WRITE(pcan_chan->mb7code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb7ID,0);
CANDEV_WRITE(pcan_chan->mb7data0,0x00);
CANDEV_WRITE(pcan_chan->mb7data1,0x00);
CANDEV_WRITE(pcan_chan->mb7data2,0x00);
CANDEV_WRITE(pcan_chan->mb7data3,0x00);
CANDEV_WRITE(pcan_chan->mb7data4,0x00);
CANDEV_WRITE(pcan_chan->mb7data5,0x00);
CANDEV_WRITE(pcan_chan->mb7data6,0x00);
CANDEV_WRITE(pcan_chan->mb7data7,0x00);
/*MB8*/
CANDEV_WRITE(pcan_chan->mb8code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb8ID,0);
CANDEV_WRITE(pcan_chan->mb8data0,0x00);
CANDEV_WRITE(pcan_chan->mb8data1,0x00);
CANDEV_WRITE(pcan_chan->mb8data2,0x00);
CANDEV_WRITE(pcan_chan->mb8data3,0x00);
CANDEV_WRITE(pcan_chan->mb8data4,0x00);
CANDEV_WRITE(pcan_chan->mb8data5,0x00);
CANDEV_WRITE(pcan_chan->mb8data6,0x00);
CANDEV_WRITE(pcan_chan->mb8data7,0x00);
/*MB9*/
CANDEV_WRITE(pcan_chan->mb9code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb9ID,0);
CANDEV_WRITE(pcan_chan->mb9data0,0x00);
CANDEV_WRITE(pcan_chan->mb9data1,0x00);
CANDEV_WRITE(pcan_chan->mb9data2,0x00);
CANDEV_WRITE(pcan_chan->mb9data3,0x00);
CANDEV_WRITE(pcan_chan->mb9data4,0x00);
CANDEV_WRITE(pcan_chan->mb9data5,0x00);
CANDEV_WRITE(pcan_chan->mb9data6,0x00);
CANDEV_WRITE(pcan_chan->mb9data7,0x00);
/*MB10*/
CANDEV_WRITE(pcan_chan->mb10code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb10ID,0);
CANDEV_WRITE(pcan_chan->mb10data0,0x00);
CANDEV_WRITE(pcan_chan->mb10data1,0x00);
CANDEV_WRITE(pcan_chan->mb10data2,0x00);
CANDEV_WRITE(pcan_chan->mb10data3,0x00);
CANDEV_WRITE(pcan_chan->mb10data4,0x00);
CANDEV_WRITE(pcan_chan->mb10data5,0x00);
CANDEV_WRITE(pcan_chan->mb10data6,0x00);
CANDEV_WRITE(pcan_chan->mb10data7,0x00);
/*MB11*/
CANDEV_WRITE(pcan_chan->mb11code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb11ID,0);
CANDEV_WRITE(pcan_chan->mb11data0,0x00);
CANDEV_WRITE(pcan_chan->mb11data1,0x00);
CANDEV_WRITE(pcan_chan->mb11data2,0x00);
CANDEV_WRITE(pcan_chan->mb11data3,0x00);
CANDEV_WRITE(pcan_chan->mb11data4,0x00);
CANDEV_WRITE(pcan_chan->mb11data5,0x00);
CANDEV_WRITE(pcan_chan->mb11data6,0x00);
CANDEV_WRITE(pcan_chan->mb11data7,0x00);
/*MB12*/
CANDEV_WRITE(pcan_chan->mb12code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb12ID,0);
CANDEV_WRITE(pcan_chan->mb12data0,0x00);
CANDEV_WRITE(pcan_chan->mb12data1,0x00);
CANDEV_WRITE(pcan_chan->mb12data2,0x00);
CANDEV_WRITE(pcan_chan->mb12data3,0x00);
CANDEV_WRITE(pcan_chan->mb12data4,0x00);
CANDEV_WRITE(pcan_chan->mb12data5,0x00);
CANDEV_WRITE(pcan_chan->mb12data6,0x00);
CANDEV_WRITE(pcan_chan->mb12data7,0x00);
/*MB13*/
CANDEV_WRITE(pcan_chan->mb13code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb13ID,0);
CANDEV_WRITE(pcan_chan->mb13data0,0x00);
CANDEV_WRITE(pcan_chan->mb13data1,0x00);
CANDEV_WRITE(pcan_chan->mb13data2,0x00);
CANDEV_WRITE(pcan_chan->mb13data3,0x00);
CANDEV_WRITE(pcan_chan->mb13data4,0x00);
CANDEV_WRITE(pcan_chan->mb13data5,0x00);
CANDEV_WRITE(pcan_chan->mb13data6,0x00);
CANDEV_WRITE(pcan_chan->mb13data7,0x00);
/*MB14*/
CANDEV_WRITE(pcan_chan->mb14code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb14ID,0);
CANDEV_WRITE(pcan_chan->mb14data0,0x00);
CANDEV_WRITE(pcan_chan->mb14data1,0x00);
CANDEV_WRITE(pcan_chan->mb14data2,0x00);
CANDEV_WRITE(pcan_chan->mb14data3,0x00);
CANDEV_WRITE(pcan_chan->mb14data4,0x00);
CANDEV_WRITE(pcan_chan->mb14data5,0x00);
CANDEV_WRITE(pcan_chan->mb14data6,0x00);
CANDEV_WRITE(pcan_chan->mb14data7,0x00);
/*MB15*/
CANDEV_WRITE(pcan_chan->mb15code,TX_NOTENABLE | 0);
CANDEV_WRITE(pcan_chan->mb15ID,0);
CANDEV_WRITE(pcan_chan->mb15data0,0x00);
CANDEV_WRITE(pcan_chan->mb15data1,0x00);
CANDEV_WRITE(pcan_chan->mb15data2,0x00);
CANDEV_WRITE(pcan_chan->mb15data3,0x00);
CANDEV_WRITE(pcan_chan->mb15data4,0x00);
CANDEV_WRITE(pcan_chan->mb15data5,0x00);
CANDEV_WRITE(pcan_chan->mb15data6,0x00);
CANDEV_WRITE(pcan_chan->mb15data7,0x00);
/*设置ID屏蔽寄存器,检查所有的标准格式的ID位*/
CANDEV_WRITE(pcan_chan->rxgmask,0x1FFFFFFF);
/*屏蔽除MBO和MB1外的所有中断*/
CANDEV_WRITE(pcan_chan->imask,0x0003);
/*清除中断标志*/
CANDEV_WRITE(pcan_chan->iflag,0xFFFF);
/*退出FREEZE模式,退出管理模式*/
CANDEV_WRITE(pcan_chan->mcr,
MCR_MENE | MCR_MAXMB);
intUnlock (oldlevel);
/*创建发送接收信号量*/
printf("Create Sem...\n\r");
pcan_chan->tx_semSync = semBCreate(SEM_Q_FIFO,SEM_FULL); /*发送信号量初始状态为满*/
if(pcan_chan->tx_semSync == NULL)
{
printf("tx_semSync creat error\n");
return ERROR;
}
pcan_chan->rx_semSync = semBCreate(SEM_Q_FIFO,SEM_EMPTY);/*接收信号量初始状态为空*/
if(pcan_chan->rx_semSync == NULL)
{
printf("rx_semSync creat error\n");
return ERROR;
}
printf("Done.\n\r");
return OK;
}
/******************************************************************************
*
* WriteByte - 写字节到Flex_can的信息缓冲区中
*
*返回:成功返回OK,否则返回ERROR
*
*参数:
pcan_chan -- 要写入字节的can设备
byte -- 要写入的字节
num -- 该字节在信息缓冲区中的位置
******************************************************************************/
LOCAL STATUS WriteByte(Can_DEV *pcan_chan,UCHAR byte,int num)
{
if(num >= 8) return ERROR;
switch (num)
{
case 0:
CANDEV_WRITE(pcan_chan->txdata0,byte);
break;
case 1:
CANDEV_WRITE(pcan_chan->txdata1,byte);
break;
case 2:
CANDEV_WRITE(pcan_chan->txdata2,byte);
break;
case 3:
CANDEV_WRITE(pcan_chan->txdata3,byte);
break;
case 4:
CANDEV_WRITE(pcan_chan->txdata4,byte);
break;
case 5:
CANDEV_WRITE(pcan_chan->txdata5,byte);
break;
case 6:
CANDEV_WRITE(pcan_chan->txdata6,byte);
break;
case 7:
CANDEV_WRITE(pcan_chan->txdata7,byte);
break;
default:
return ERROR;
}
return OK;
}
/******************************************************************************
*
* Can0TxInterrupt - Flex_can0模块发送中断函数,调用相应的中断例程
*
*返回:无
*
*参数:无
******************************************************************************/
void Can0TxInterrupt (void)
{
UINT16 intStatus;
//logMsg("#can0 Tx Int!T#", 1, 2, 3, 4, 5, 6);
intStatus = CANDEV_READ(can_chan_dev[0].iflag);/*读中断状态标志*/
if((intStatus & 0x0001) == 0x0001)
{
CanTxInterrupt(&can_chan_dev[0]);
}
else
{
logMsg("#can0 Tx vacant Int!T#", 1, 2, 3, 4, 5, 6);
}
/*
if(intStatus & CAN0_TX_INT_STATUS)
{
CanTxInterrupt(&can_chan_dev[0]);
}
if(intStatus & CAN0_RX_INT_STATUS)
{
CanRxInterrupt(&can_chan_dev[0]);
}
*/
CANDEV_WRITE(can_chan_dev[0].iflag,0x0001);/*清除中断状态标志*/
}
/******************************************************************************
*
* Can0RxInterrupt - Flex_can0模块接收中断函数,调用相应的中断例程
*
*返回:无
*
*参数:无
******************************************************************************/
void Can0RxInterrupt (void)
{
UINT16 intStatus;
Rx_count++;
///logMsg("#can0 Rx Int!T#", 1, 2, 3, 4, 5, 6);
intStatus = CANDEV_READ(can_chan_dev[0].iflag);/*读中断状态标志*/
if((intStatus & 0x0002) == 0x0002)
{
CanRxInterrupt(&can_chan_dev[0]);
}
else
{
//logMsg("#can0 Rx vacant Int!T#", 1, 2, 3, 4, 5, 6);
}
/*
if(intStatus & CAN0_TX_INT_STATUS)
{
CanTxInterrupt(&can_chan_dev[0]);
}
if(intStatus & CAN0_RX_INT_STATUS)
{
CanRxInterrupt(&can_chan_dev[0]);
}
*/
CANDEV_WRITE(can_chan_dev[0].iflag,0x0002);/*清除中断状态标志*/
}
/******************************************************************************
*
* Can1TxInterrupt - Flex_can1模块发送中断函数,调用相应的中断例程
*
*返回:无
*
*参数:无
******************************************************************************/
void Can1TxInterrupt (void)
{
UINT16 intStatus;
Tx_count++;
//logMsg("#can1 Tx Int!T#", 1, 2, 3, 4, 5, 6);
intStatus = CANDEV_READ(can_chan_dev[1].iflag);/*读中断状态标志*/
if((intStatus & 0x0001) == 0x0001)
{
CanTxInterrupt(&can_chan_dev[1]);
}
else
{
//logMsg("#can1 Tx vacant Int!T#", 1, 2, 3, 4, 5, 6);
}
/*
if(intStatus & CAN1_TX_INT_STATUS)
{
CanTxInterrupt(&can_chan_dev[1]);
}
if(intStatus & CAN1_RX_INT_STATUS)
{
logMsg("#T****T#", 1, 2, 3, 4, 5, 6);
CanRxInterrupt(&can_chan_dev[1]);
}
*/
CANDEV_WRITE(can_chan_dev[1].iflag,0x0001);/*清除中断状态标志*/
}
/******************************************************************************
*
* Can1RxInterrupt - Flex_can1模块接收中断函数,调用相应的中断例程
*
*返回:无
*
*参数:无
******************************************************************************/
void Can1RxInterrupt (void)
{
UINT16 intStatus;
//logMsg("#can1 Rx Int!T#", 1, 2, 3, 4, 5, 6);
intStatus = CANDEV_READ(can_chan_dev[1].iflag);/*读中断状态标志*/
if((intStatus & 0x0002) == 0x0002)
{
CanRxInterrupt(&can_chan_dev[1]);
}
else
{
//logMsg("#can1 Rx vacant Int!T#", 1, 2, 3, 4, 5, 6);
}
/*
if(intStatus & CAN1_TX_INT_STATUS)
{
CanTxInterrupt(&can_chan_dev[1]);
}
if(intStatus & CAN1_RX_INT_STATUS)
{
logMsg("#T****T#", 1, 2, 3, 4, 5, 6);
CanRxInterrupt(&can_chan_dev[1]);
}
*/
CANDEV_WRITE(can_chan_dev[1].iflag,0x0002);/*清除中断状态标志*/
}
/******************************************************************************
*
* CanTxInterrupt - Flex_can模块发送中断服务函数
*
*返回:无
*
*参数:
pcan_chan -- 需要发送服务的CAN设备
******************************************************************************/
LOCAL void CanTxInterrupt (Can_DEV *pcan_chan)
{
UINT16 i;
UINT16 j;
UINT32 count;
UCHAR ch;
if(pcan_chan->tx_number == 0)
{
pcan_chan->ptx = pcan_chan->tx_Buff;/*重新定位发送指针,为下一次发送做准备*/
CANDEV_WRITE(pcan_chan->txcode,
TX_NOTENABLE | DEFAULT_LENGTH);
semGive(pcan_chan->tx_semSync); /*释放信号量*/
return;
}
if(( pcan_chan->tx_number > 0) && ( pcan_chan->tx_number <= 8))
{
count = 0;
while(CheckBusStatus(pcan_chan) != OK) //检查CAN总线是否在空闲状态
{
count++;
if(count >= 40000) break;
}
if(count >= 40000) /*如果总线一直忙,则清发送缓冲区,由上层协议决定是否重发*/
{
//logMsg("#bus is busy!T#", 1, 2, 3, 4, 5, 6);
pcan_chan->ptx = pcan_chan->tx_Buff;/*重新定位发送指针,为下一次发送做准备*/
pcan_chan->tx_number = 0;
CANDEV_WRITE(pcan_chan->txcode,
TX_NOTENABLE | DEFAULT_LENGTH);
semGive(pcan_chan->tx_semSync); /*释放信号量*/
return;
}
CANDEV_WRITE(pcan_chan->txcode,
TX_NOTENABLE | DEFAULT_LENGTH);/*INACTIVE发送*/
j = pcan_chan->tx_number;
for(i = 0;i < j;i++)
{
ch = *pcan_chan->ptx;
WriteByte(pcan_chan,ch,i);
pcan_chan->ptx++;
}
pcan_chan->tx_length = j;
pcan_chan->tx_number = 0;
CANDEV_WRITE(pcan_chan->txcode, /*ACTIVE发送*/
TX_ENABLE | pcan_chan->tx_length);
return;
}
if( pcan_chan->tx_number > 8)
{
count = 0;
while(CheckBusStatus(pcan_chan) != OK) //检查CAN总线是否在空闲状态
{
count++;
if(count >= 40000) break;
}
if(count >= 40000) /*如果总线一直忙,则清发送缓冲区,由上层协议决定是否重发*/
{
//logMsg("#bus is busy!T#", 1, 2, 3, 4, 5, 6);
pcan_chan->ptx = pcan_chan->tx_Buff;/*重新定位发送指针,为下一次发送做准备*/
pcan_chan->tx_number = 0;
CANDEV_WRITE(pcan_chan->txcode,
TX_NOTENABLE | DEFAULT_LENGTH);
semGive(pcan_chan->tx_semSync); /*释放信号量*/
return;
}
CANDEV_WRITE(pcan_chan->txcode,
TX_NOTENABLE | DEFAULT_LENGTH);/*INACTIVE发送*/
j = 8;
for(i = 0;i < j;i++)
{
ch = *pcan_chan->ptx;
WriteByte(pcan_chan,ch,i);
pcan_chan->ptx++;
}
pcan_chan->tx_length = j;
pcan_chan->tx_number -= j;
CANDEV_WRITE(pcan_chan->txcode, /*ACTIVE发送*/
TX_ENABLE | pcan_chan->tx_length);
return;
}
}
/******************************************************************************
*
* CanRxInterrupt - Flex_can模块接收中断服务函数
*
*返回:无
*
*参数:
pcan_chan -- 需要发送服务的CAN设备
******************************************************************************/
LOCAL void CanRxInterrupt (Can_DEV *pcan_chan)
{
UINT16 c_s_word; /*控制/状态信息字*/
UINT32 freeRunTimer; /*控制/状态信息字*/
//UINT32 id; /*ID*/
UINT16 i,j;
c_s_word = CANDEV_READ(pcan_chan->rxcode); /*读控制/状态字 锁定该信息缓冲区*/
//id = CANDEV_READ(pcan_chan->rxID); /*信息ID*/
j = c_s_word & 0x000F; /*获取接收数据长度*/
/*写数据到接收缓冲区中*/
for(i = 0;i < j;i++)
{
switch (i)
{
case 0:
if((pcan_chan->prx_write+1) != pcan_chan->prx_read)
{
*pcan_chan->prx_write = CANDEV_READ(pcan_chan->rxdata0);
pcan_chan->prx_write++;
if((pcan_chan->prx_write - pcan_chan->rx_Buff) == MAX_RX_BUFFER)
{//接收指针回绕
if(pcan_chan->prx_read == pcan_chan->rx_Buff)
{
pcan_chan->prx_write = pcan_chan->prx_write-1;
}
else
{
pcan_chan->prx_write = pcan_chan->rx_Buff;
}
}
}
break;
case 1:
if((pcan_chan->prx_write+1) != pcan_chan->prx_read)
{
*pcan_chan->prx_write = CANDEV_READ(pcan_chan->rxdata1);
pcan_chan->prx_write++;
if((pcan_chan->prx_write - pcan_chan->rx_Buff) == MAX_RX_BUFFER)
{//接收指针回绕
if(pcan_chan->prx_read == pcan_chan->rx_Buff)
{
pcan_chan->prx_write = pcan_chan->prx_write-1;
}
else
{
pcan_chan->prx_write = pcan_chan->rx_Buff;
}
}
}
break;
case 2:
if((pcan_chan->prx_write+1) != pcan_chan->prx_read)
{
*pcan_chan->prx_write = CANDEV_READ(pcan_chan->rxdata2);
pcan_chan->prx_write++;
if((pcan_chan->prx_write - pcan_chan->rx_Buff) == MAX_RX_BUFFER)
{//接收指针回绕
if(pcan_chan->prx_read == pcan_chan->rx_Buff)
{
pcan_chan->prx_write = pcan_chan->prx_write-1;
}
else
{
pcan_chan->prx_write = pcan_chan->rx_Buff;
}
}
}
break;
case 3:
if((pcan_chan->prx_write+1) != pcan_chan->prx_read)
{
*pcan_chan->prx_write = CANDEV_READ(pcan_chan->rxdata3);
pcan_chan->prx_write++;
if((pcan_chan->prx_write - pcan_chan->rx_Buff) == MAX_RX_BUFFER)
{//接收指针回绕
if(pcan_chan->prx_read == pcan_chan->rx_Buff)
{
pcan_chan->prx_write = pcan_chan->prx_write-1;
}
else
{
pcan_chan->prx_write = pcan_chan->rx_Buff;
}
}
}
break;
case 4:
if((pcan_chan->prx_write+1) != pcan_chan->prx_read)
{
*pcan_chan->prx_write = CANDEV_READ(pcan_chan->rxdata4);
pcan_chan->prx_write++;
if((pcan_chan->prx_write - pcan_chan->rx_Buff) == MAX_RX_BUFFER)
{//接收指针回绕
if(pcan_chan->prx_read == pcan_chan->rx_Buff)
{
pcan_chan->prx_write = pcan_chan->prx_write-1;
}
else
{
pcan_chan->prx_write = pcan_chan->rx_Buff;
}
}
}
break;
case 5:
if((pcan_chan->prx_write+1) != pcan_chan->prx_read)
{
*pcan_chan->prx_write = CANDEV_READ(pcan_chan->rxdata5);
pcan_chan->prx_write++;
if((pcan_chan->prx_write - pcan_chan->rx_Buff) == MAX_RX_BUFFER)
{//接收指针回绕
if(pcan_chan->prx_read == pcan_chan->rx_Buff)
{
pcan_chan->prx_write = pcan_chan->prx_write-1;
}
else
{
pcan_chan->prx_write = pcan_chan->rx_Buff;
}
}
}
break;
case 6:
if((pcan_chan->prx_write+1) != pcan_chan->prx_read)
{
*pcan_chan->prx_write = CANDEV_READ(pcan_chan->rxdata6);
pcan_chan->prx_write++;
if((pcan_chan->prx_write - pcan_chan->rx_Buff) == MAX_RX_BUFFER)
{//接收指针回绕
if(pcan_chan->prx_read == pcan_chan->rx_Buff)
{
pcan_chan->prx_write = pcan_chan->prx_write-1;
}
else
{
pcan_chan->prx_write = pcan_chan->rx_Buff;
}
}
}
break;
case 7:
if((pcan_chan->prx_write+1) != pcan_chan->prx_read)
{
*pcan_chan->prx_write = CANDEV_READ(pcan_chan->rxdata7);
pcan_chan->prx_write++;
if((pcan_chan->prx_write - pcan_chan->rx_Buff) == MAX_RX_BUFFER)
{//接收指针回绕
if(pcan_chan->prx_read == pcan_chan->rx_Buff)
{
pcan_chan->prx_write = pcan_chan->prx_write-1;
}
else
{
pcan_chan->prx_write = pcan_chan->rx_Buff;
}
}
}
break;
default:
break;
}
}
pcan_chan->rx_number += j;
pcan_chan->rx_length =j;
freeRunTimer = CANDEV_READ(pcan_chan->timer);/*读自由运行时间,释放该信息缓冲区*/
CANDEV_WRITE(pcan_chan->rxcode,
RX_ENABLE | DEFAULT_LENGTH);/*使能接收,为下一次接收做准备*/
semGive(pcan_chan->rx_semSync); /*释放信号量*/
}
/******************************************************************************
*
* CheckBusStatus - 检查can总线状态
*读can的ERRSTAT寄存器,IDLE位是否为1
*
* 返回:总线空闲返回OK,否则返回ERROR
*
******************************************************************************/
LOCAL STATUS CheckBusStatus(Can_DEV *pcan_chan)
{
UINT32 Status;
Status = CANDEV_READ(pcan_chan->errstat);
if((Status & 0x00000080) == 0x00000080)
{
return OK;
}
else
{
return ERROR;
}
}