/* 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;i<NUM_CAN;i++)
{
canName[0] = '\0';
strcat (canName, CAN_NAME_BASE);
strcat (canName, itos (i));
if(iosDevAdd((DEV_HDR *)&can_chan_dev[i],canName,CanDrvNum) == ERROR)
{
printf("Can device add ERROR !\n");
return ERROR;
}
}
return OK;
}
/******************************************************************************
*CanOpen -- 打开CAN设备
*返回 - 返回设备ID号
*参数:pCan_Dev -- 要打开的CAN设备
remainder -- 文件名,在这里为空
flags -- 设备的打开方式,对于can永远以读写方式打开
*
******************************************************************************/
int CanOpen(Can_DEV *pCan_Dev,UCHAR *remainder,int flags)
{
if(flags != 2)
{
printf("Can device open ERROR !\n");
return ERROR;/*只能以读写的方式打开*/
}
if(remainder[0] != 0)
{
printf("Can device open ERROR !\n");
return ERROR;/*can设备没有文件名*/
}
pCan_Dev->Flag_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;i<nBytes;i++)
{
WriteByte(pCan_Dev,*txbuf,i);
txbuf++;
}
pCan_Dev->tx_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