📄 candrv.c
字号:
#include <stdio.h>
#include <iosLib.h>
#include <semlib.h>
#include <stdlib.h>
#include <string.h>
#include "can20b.h"
#include "configInum.h"
typedef struct {
DEV_HDR pCANHDR; /*这个数据结构必须放在设备描述符的最初部分*/
/*其余与驱动有关数据*/
}CAN_DEV;/*CAN设备描述符*/
CAN_DEV Can_Dev_List[2];
int CanDrvNum=0;
BYTE Can0_Open,Can1_Open;
#define DevName1 "can0"
#define DevName2 "can1"
/*接收缓冲区*/
static BYTE rBuf[2][MAX_MSG_LENGTH];
/*接收状态变量*/
static volatile int rfirst[2]={0,0},rnext[2]={0,0};
/*发送缓冲区*/
static BYTE sBuf[2][MAX_MSG_LENGTH];
/*发送状态变量*/
static volatile int sfirst[2]={0,0},snext[2]={0,0};
static unsigned char tr_com=TR_Bit;
/*CAN控制器寄存器内存映射位置*/
static volatile unsigned char *gSeg;
#define XBYTE gSeg
/*错误状态:
0: 无错误
0x10: 段设置错误
0x12: IRQ号设置错误
0x20: 控制器0 总线脱离
0x21: 控制器1 总线脱离
0x22: 控制器0 总线错误
0x23: 控制器1 总线错误
0x30: 控制器0 接收缓冲区满
0x31: 控制器1 接收缓冲区满
0x200|(port<<8)|ArbLostCapReg值:仲裁丢失
0x0400|(port<<8)|ErrCodeCapReg值:总线错误中断中错误码
0x0600|(port<<8):error passive
*/
int can_err_no[2];
IMPORT BYTE sysInumTbl[]; /* IRQ vs intNum table */
static BYTE port=0;
static BYTE div_reg_val[2];
/* CAN 控制器配置*/
static CANCFG canPara[2];
static SEM_ID sem_can[2];/*信号量,控制接收*/
static MSG_Q_ID canMsgQue[2]; /* 消息队列*/
static void can0_isr();
static void can1_isr();
static BYTE canr(BYTE port,int addr);
static void canw(BYTE port,int addr,BYTE v);
static void canNormalRun(BYTE port);
static int canInitHW();
static int canConfig(BYTE port,CANCFG cfg);
static int canSendMsg(BYTE port,CANMSG msg);
static int canReceiveMsg(BYTE port,CANMSG *msg_ptr);
static BYTE canExitHW(BYTE port);
int CanOpen(CAN_DEV *CANDev,char *remainder,int mode);
int CanRead(CAN_DEV *CANDev,char *buffer,int nBytes);
int CanWrite(CAN_DEV *CANDev,char *buffer,int nBytes);
int CanIoctl(CAN_DEV *CANDev,int requestCode,int arg);
int CanClose(CAN_DEV *CANDev);
/************************************************************
* canDrv- driver initialization routine
*
* canDrv() initializes the driver. It installs the driver via
* iosDrvInstall. It may allocate data structures, connetct ISRs,
* and initialize hardware.
*/
void CanDrv()
{
CanDrvNum=iosDrvInstall(0,0,CanOpen,CanClose,\
CanRead,CanWrite,CanIoctl);
}
/************************************************************
*
* Called to add a device called <name> to be serviced by this driver.
* Other driver-dependent arguments may include buffer sizes,device
* addresses... The routine adds the device to the I/O system by calling
* iosDevAdd. It may also allocate and initialize data structures for the
* device, initialize semaphores, initialize device hardware, and so on.
*/
void CanDevCreate()
{
int status;
status = iosDevAdd (&(Can_Dev_List[0].pCANHDR), DevName1, CanDrvNum);
status = iosDevAdd (&(Can_Dev_List[1].pCANHDR), DevName2, CanDrvNum);
Can0_Open=0;
Can1_Open=0;
canInitHW();
}
/************************************************************
*
* The following routines implement the basic I/O functions. The xxOpen()
* return value is meaningful only to this driver, and is passed back as an
* argument to the other I/O routines.
*/
int CanOpen(CAN_DEV *CANDev,char *remainder, int mode)
{
/*serial devices should have no file name part*/
if (remainder[0] != 0)
{
return (ERROR);
}
else
{
if((strcmp(CANDev->pCANHDR.name,"can0"))==0){
if(Can0_Open==0){
Can0_Open=1;
return ((int) CANDev);
}
if(Can0_Open==1){
return -1;
}
}
if((strcmp(CANDev->pCANHDR.name,"can1"))==0){
if(Can1_Open==0){
Can1_Open=1;
return ((int) CANDev);
}
if(Can1_Open==1){
return -1;
}
}
}
}
/*从指定的CAN控制器接收消息包
port:CAN控制器--0,控制器0;1,控制器1
msg_ptr:指向消息结构变量,返回消息
返回值:1,成功;0,无消息
*/
int CanRead(CAN_DEV *CANDev, char *buffer, int nBytes)
{
BYTE Result=0,v;
if((strcmp(CANDev->pCANHDR.name,"can0"))==0){
v=canr(port,StatusReg);
canNormalRun(0);
Result=canReceiveMsg(0,(CANMSG *)buffer);
return Result;
}
if((strcmp(CANDev->pCANHDR.name,"can1"))==0){
v=canr(port,StatusReg);
canNormalRun(1);
Result=canReceiveMsg(1,(CANMSG *)buffer);
return Result;
}
}
/*由指定的CAN控制器发送消息包
port:CAN控制器--0,控制器0;1,控制器1
msg:要发送的消息
返回值:1,成功;0,失败
*/
int CanWrite(CAN_DEV *CANDev, char *buffer, int nBytes)
{
BYTE Result=0,v;
CANMSG S_MSG;
if((strcmp(CANDev->pCANHDR.name,"can0"))==0){
v=canr(0,StatusReg);
canNormalRun(0);
S_MSG=(*((CANMSG *)buffer));
Result=canSendMsg(0,S_MSG);
return Result;
}
if((strcmp(CANDev->pCANHDR.name,"can1"))==0){
v=canr(1,StatusReg);
canNormalRun(1);
S_MSG=(*((CANMSG *)buffer));
Result=canSendMsg(1,S_MSG);
return Result;
}
}
int CanIoctl(CAN_DEV *CANDev, int requestCode, int arg)
{
CANCFG CAN_CONFIG;
BYTE v;
switch(requestCode)
{
case CAN_INIT:
if((strcmp(CANDev->pCANHDR.name,"can0"))==0){
CAN_CONFIG= (*((CANCFG *)arg));
canConfig(0,CAN_CONFIG);
}
if((strcmp(CANDev->pCANHDR.name,"can1"))==0){
CAN_CONFIG= (*((CANCFG *)arg));
canConfig(1,CAN_CONFIG);
}
break;
defaut:
break;
}
return 1;
}
int CanClose(CAN_DEV *CANDev)
{
BYTE v;
if((strcmp(CANDev->pCANHDR.name,"can0"))==0){
canExitHW(0);
Can0_Open=0;
}
if((strcmp(CANDev->pCANHDR.name,"can1"))==0){
canExitHW(1);
Can1_Open=0;
}
return 0;
}
/*对板子的运行进行系统配置
seg:板子的寄存器段设置
irq0:控制器0的irq号
irq1:控制器1的irq号
返回值:1,成功;0,失败
*/
static int canInitHW()
{
BYTE v;
BYTE port;
int ll;
can_err_no[0]=0;
can_err_no[1]=0;
gSeg=(unsigned char *)(BASE_ADDR<<4); /* CAN控制器基地址设置*/
canw(port,ModeControlReg,0x01);
v=canr(0,ModeControlReg);
for(port=0;port<2;port++){
/* test the can basic segment address */
ll=0;
v=canr(port,ModeControlReg);
while((v & RM_RR_Bit ) == ClrByte){
canw(port,ModeControlReg,v|RM_RR_Bit);
v=canr(port,ModeControlReg);
ll++;
if(ll>100000){
logMsg("Can't go into reset mode\n",0,0,0,0,0,0);
can_err_no[port]=0x10; /*段错误*/
return 0;
}
}; /* end of while((v & */
/* 设置工作模式为CAN2.0B (PeliCAN) */
div_reg_val[port]=CBP_Bit | DivBy2;
canw(port,ClockDivideReg, div_reg_val[port]);
/* 清中断使能*/
/* 设置验收码*/
canw(port,AcceptCodeReg , ClrByte);
/* 设置验收屏蔽码*/
canw(port,AcceptMaskReg , DontCare);
/*2.0B,缺省的速率设置*/
canw(port,BusTiming0Reg , SJW_500k_16 | Presc_500k_16);
canw(port,BusTiming1Reg , TSEG1_500k_16 | TSEG2_500k_16);
/* 输出控制*/
canw(port,OutControlReg , Tx1Float | Tx0PshPull | NormalMode);
/* create the semaphore */
sem_can[port]=semCCreate(SEM_Q_FIFO,0);
/* 创建消息队列*/
canMsgQue[port] = msgQCreate(MAX_MSGS, MAX_MSG_LENGTH, MSG_Q_FIFO);
}
/* 连接中断服务程序 */
sysIntLock();
intConnect(INUM_TO_IVEC(INT_NUM_GET(CAN0_INT_NUMBER)),can0_isr,0);
intConnect(INUM_TO_IVEC(INT_NUM_GET(CAN1_INT_NUMBER)),can1_isr,0);
sysIntUnlock();
sysIntEnablePIC(CAN0_INT_NUMBER);
sysIntEnablePIC(CAN1_INT_NUMBER);
/*状态初始化*/
rfirst[port]=0;
sfirst[port]=0;
rnext[port]=0;
snext[port]=0;
return 1;
}
/* canConfig, 设置控制器的屏蔽接收码和传输速率
port:CAN控制器--0,控制器0;1,控制器1
cfg:配置结构
返回值:1,成功;0,失败
*/
static int canConfig(BYTE port,CANCFG cfg)
{
BYTE v;
BYTE *buf;
int msg_num=0;
/*设置复位状态*/
while(((v=canr(port,ModeControlReg)) & RM_RR_Bit ) == ClrByte){
v|=RM_RR_Bit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -