📄 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(0,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]=CANMode_Bit | CBP_Bit | DivBy2;
canw(port,ClockDivideReg, div_reg_val[port]);
/* 清中断使能*/
canw(port,InterruptEnReg,ClrIntEnSJA);
/* 设置验收码*/
canw(port,AcceptCode0Reg , ClrByte);
canw(port,AcceptCode1Reg , ClrByte);
canw(port,AcceptCode2Reg , ClrByte);
canw(port,AcceptCode3Reg , ClrByte);
/* 设置验收屏蔽码*/
canw(port,AcceptMask0Reg , DontCare);
canw(port,AcceptMask1Reg , DontCare);
canw(port,AcceptMask2Reg , DontCare);
canw(port,AcceptMask3Reg , 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;
canw(port,ModeControlReg,v);
}
canPara[port].mode = cfg.mode;
/*设置屏蔽方式*/
if(cfg.filter_num!=2) v|=AFM_Bit;
else v&=(~AFM_Bit);
canw(port,ModeControlReg,v);
/* 设置中断开放情况 */
if(cfg.mode == IRQ_INTERRUPT)
v=RIE_Bit|TIE_Bit|EIE_Bit|DOIE_Bit|WUIE_Bit|EPIE_Bit|ALIE_Bit|BEIE_Bit;
/* else
v=TIE_Bit|EIE_Bit|DOIE_Bit|WUIE_Bit|EPIE_Bit|ALIE_Bit|BEIE_Bit;
canw(port,InterruptEnReg,v);
*/
/* 设置位速率 */
canw(port,BusTiming0Reg ,cfg.bt0);
canw(port,BusTiming1Reg ,cfg.bt1);
/*设置接收屏蔽码*/
if(cfg.filter_num ==0){
/* NO MASK*/
canw(port,AcceptMask0Reg , DontCare);
canw(port,AcceptMask1Reg , DontCare);
canw(port,AcceptMask2Reg , DontCare);
canw(port,AcceptMask3Reg , DontCare);
}
else {
canw(port,AcceptCode0Reg , cfg.acc_code[0]);
canw(port,AcceptCode1Reg , cfg.acc_code[1]);
canw(port,AcceptCode2Reg , cfg.acc_code[2]);
canw(port,AcceptCode3Reg , cfg.acc_code[3]);
canw(port,AcceptMask0Reg , cfg.acc_mask[0]);
canw(port,AcceptMask1Reg , cfg.acc_mask[1]);
canw(port,AcceptMask2Reg , cfg.acc_mask[2]);
canw(port,AcceptMask3Reg , cfg.acc_mask[3]);
}
/* 设置输出控制寄存器,*/
canw(port,OutControlReg , Tx1Float | Tx0PshPull | NormalMode);
msg_num=msgQNumMsgs(canMsgQue[port]);
if(msg_num!=0){
buf=malloc(msg_num);
msgQReceive(canMsgQue[port], buf, MAX_MSG_LENGTH, WAIT_FOREVER);
free(buf);
}
return 1;
}
/*启动CAN的正常运行
port:CAN控制器--0,控制器0;1,控制器1
*/
static void canNormalRun(BYTE port)
{
BYTE v;
if(can_err_no[port]==0x10)
return;
canw(port,ClockDivideReg, div_reg_val[port]);
v=canr(port,ModeControlReg);
do {
v&=AFM_Bit;
canw(port,ModeControlReg , v);
/*canw(port,ModeControlReg , v|4);*/
v=canr(port,ModeControlReg);
} while((v & RM_RR_Bit ) != ClrByte);
/*canw(port,ModeControlReg , v|0x04);*/
}
/*由指定的CAN控制器发送消息包
port:CAN控制器--0,控制器0;1,控制器1
msg:要发送的消息
返回值:1,成功;0,失败
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -