⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can-7202.c

📁 ucos-II+移植到arm+s3c2410的全套代码
💻 C
字号:
#include "../ucos-ii/includes.h"

#include "../inc/sys/lib.h"
#include "../inc/sys/can.h"
#include "../inc/drv/reg2410.h"
#include "../ucos-ii/Uhal/Uhal.h"
#include "../ucos-ii/Uhal/isr.h"

//#define DPRINTF		printf
#define DPRINTF		printfNULL


/********************** Candata *********************************/
#define CAN2410_Isr(n)		(CAN0_OFFSET+n)	//串口中断号

static int CAN_Base[]={CAN0BASE, CAN1BASE};

//#define can_outb(ndev, offset, ch)	_outb(CAN_Base[ndev] + (offset,) (ch))
#define can_outw(ndev, offset, ch)	do{int i; _outw(CAN_Base[ndev] + (offset), (ch)); for(i=0;i<10;i++);}while(0)
//#define can_outl(ndev, offset, ch)	_outl(CAN_Base[ndev] + (offset), (ch))

#define FIRST_MSG				1
#define LAST_MSG				32

//#define can_inb(ndev, offset)	_inb(CAN_Base[ndev] + offset)
__inline unsigned short can_inw(int ndev, int offset)
{
	int i;
	unsigned short temp;

	temp=_inw(CAN_Base[ndev] + offset);
	for(i=0;i<10;i++);
	temp=_inw(CAN_Base[ndev] + offset);
	for(i=0;i<10;i++);
	return temp;
}
//#define can_inl(ndev, offset)	_inl(CAN_Base[ndev] + offset)


/************************************************************\
*	interface x busy检查										*
*	参数: ndev为设备									*
*			n为IF 接口									*
\************************************************************/
__inline int can_IFx_busycheck(int ndev, int n)
{

	int i=0;
	unsigned short comreg = 0;
	int addr[]={IF1ComR, IF2ComR};

	comreg = can_inw( ndev, addr[n-1]);
	while ( (comreg & IFXCom_Busy) && (i<=10))
	{
		udelay(100); //100 microseconds
		i++;
		comreg = can_inw( ndev, addr[n-1]);
	}
	if (i>=10){
		printk("Error Busy-Bit stays set\n");
		return FAIL;
	}

	return OK;
}

/************************************************************\
*	等待发送结束										*
*	参数: ndev为设备									*
*			nMsg为第nMsg接口1-32						*
\************************************************************/
__inline void wait_for_Sendend(int ndev, int nMsg)
{
	U32 txrqst;

	do{
		txrqst=can_inw(ndev, TxRqst2);
		txrqst<<=16;
		txrqst|=can_inw(ndev, TxRqst1);
	}while(txrqst & (1<<(nMsg-1)));

}


/************************************************************\
*	设置CAN2410 CAN总线波特率						*
*	参数: bandrate为所设置的波特率				*
*			IsBackNormal为是否要返回Normal模式		*
\************************************************************/
__inline void CAN2410_SetBandRate(int ndev, CanBandRate bandrate)
{
	//
	// Bit rate calculations.
	//
	//Input clock fre=8MHz
	// In this case, we'll use a speed of 125 kbit/s, 250 kbit/s, 500 kbit/s, 1Mbit/s.
	// one bit will be 1+4+3 = 8 quanta in length.
	//Set Tseg1=4, Tseg2=3, SJW=1
	//
	// 8MHz: setting the prescaler (BRP+1) to 1 => 1 Mbit/s.
	// 4MHz: setting the prescaler (BRP+1) to 2 => 500 kbit/s.
	// 2MHz: setting the prescaler (BRP+1) to 4 => 250 kbit/s.
	// 1MHz: setting the prescaler (BRP+1) to 8 => 125 kbit/s.

	int brp=0;

	switch(bandrate){
	case BandRate_125kbps:
		brp=8;
		break;
	case BandRate_250kbps:
		brp=4;
		break;
	case BandRate_500kbps:
		brp=2;
		break;
	case BandRate_1Mbps:
		brp=1;
		break;
	}
	brp--;

	// Go into configuration mode
	can_outw(ndev, CANControl, CANControl_CCE|CANControl_Init);

	can_outw(ndev, CANBRPExt, 0);
	can_outw(ndev, CANBitTimReg, 
		CANBitTim_BRP(brp)|CANBitTim_SWJ(0)|CANBitTim_TSeg1(3)|CANBitTim_TSeg2(2));

	// Go back into normal mode
	can_outw(ndev, CANControl, 0);
}

/***********************************************************************************\
								发送数据
	参数:
		ndev,设备号
		data,发送数据

	Note: 使用interface 1		利用两个缓冲区乒乓发送
\***********************************************************************************/
__inline int CAN2410_canWrite(int ndev, PCanData data)
{
#undef readMaskCM
#undef writeMaskCM
#undef writeSendMskCM
#define readMaskCM		(IFXMask_Control | IFXMask_Arb | IFXMask_DataA | IFXMask_DataB)
#define writeMaskCM		(IFXMask_Control | IFXMask_Arb | IFXMask_DataA | IFXMask_DataB|IFXMask_WR)
//#define writeSendMskCM	(IFXMask_Control |IFXMask_Arb | IFXMask_DataA | IFXMask_DataB| IFXMask_WR | IFXMask_TxRqst)

	static int nMsg=0;

	unsigned short *pdata;

//	int temp;

//	temp=can_inw(1, MsgVal1);
//	temp=can_inw(1, MsgVal2);

	wait_for_Sendend(ndev, nMsg+1);

	//load Message Object in IF1
	can_IFx_busycheck(ndev, 1);
	can_outw(ndev, IF1ComM, readMaskCM);

	//set interface into nMsg
	can_outw(ndev, IF1ComR, IFXCom_Busy|IFXCom_Msg(nMsg+1));
	can_IFx_busycheck(ndev, 1);

	//setting Message Valid Bit to zero
	can_outw(ndev, IF1Arb2, 0);

	can_outw(ndev, IF1ComM, writeMaskCM);
	can_outw(ndev, IF1ComR, IFXCom_Busy|IFXCom_Msg(nMsg+1));

	can_IFx_busycheck(ndev, 1);
   	//Configuring MO
//	tempreg = can_inw( ndev, IF2ComM);
	//remote enable?
	//define Command Mask
	if(data->rxRTR)
		can_outw(ndev, IF1Mctrl, IFXM_EoB | IFXM_RmtEn | IFXM_NewDat
				| IFXM_TxRqst | IFXM_DLCMask);
	else
		can_outw(ndev, IF1Mctrl, IFXM_EoB | IFXM_NewDat
				| IFXM_TxRqst | IFXM_SETDLC(data->dlc));

	//set Arbitration Bits
	if (data->IsExt){
		can_outw(ndev, IF1Arb1, (U16)(data->id));
		can_outw(ndev, IF1Arb2, IFXARB2_XTD | IFXARB2_MVAL | IFXARB2_TR |IFXARB2_SETEID(data->id>>16));
	}
	else{
		can_outw(ndev, IF1Arb2, IFXARB2_MVAL | IFXARB2_TR | IFXARB2_SETID(data->id<<2));
		can_outw(ndev, IF1Arb1, 0);
	}
	//write Data
	if (data->dlc>0){

		pdata = (unsigned short*)(&data->data[0]);
		can_outw(ndev, IF1DataA1, *pdata);
		pdata = (unsigned short*)(&data->data[2]);
		can_outw(ndev, IF1DataA2, *pdata);
		pdata = (unsigned short*)(&data->data[4]);
		can_outw(ndev, IF1DataB1, *pdata);
		pdata = (unsigned short*)(&data->data[6]);
		can_outw(ndev, IF1DataB2, *pdata);
	}

//	can_outw(ndev, IF1ComM, writeSendMskCM);
	can_outw(ndev, IF1ComM, writeMaskCM);
	can_outw(ndev, IF1ComR, IFXCom_Busy|IFXCom_Msg(nMsg+1));

	nMsg++;
	nMsg&=1;

	return OK;
}

__inline int CAN2410_canRead(int ndev, PCanData data)
{

#undef msgLstReadMaskCM
#undef msgLstWriteMaskCM
#undef readMaskCM
#define msgLstReadMaskCM	(IFXMask_Control)
#define msgLstWriteMaskCM	(IFXMask_Control | IFXMask_WR)
#define readMaskCM			(IFXMask_Arb|IFXMask_Control| IFXMask_ClrIntPnd |IFXMask_TxRqst| IFXMask_DataA | IFXMask_DataB)

	unsigned int nMsg, val;

	nMsg=can_inw(ndev, CANIntReg);
	DPRINTF("nMsg=%d\n", nMsg);
	if(nMsg<1 || nMsg>32)
		return FAIL;

	//Message Lost Check
	can_IFx_busycheck(ndev, 2);

	can_outw(ndev, IF2ComM, msgLstReadMaskCM);
	//set interface into nMsg
	can_outw(ndev, IF2ComR, IFXCom_Busy|IFXCom_Msg(nMsg));

	can_IFx_busycheck(ndev, 2);

	val = can_inw(ndev, IF2Mctrl);

	if (val & IFXM_MsgLst){
		printk("Chip lost a can message\n");

	       //Reset Message Lost Bit
		val &= ~IFXM_MsgLst;
		can_outw(ndev, IF2Mctrl, val);
		can_outw(ndev, IF2ComM, msgLstWriteMaskCM);
		//set interface into nMsg
		can_outw(ndev, IF2ComR, IFXCom_Busy|IFXCom_Msg(nMsg));

		can_IFx_busycheck(ndev, 2);
	}

	//transfer Message Object to IF2 Buffer
	can_outw(ndev, IF2ComM, readMaskCM);
	//set interface into nMsg
	can_outw(ndev, IF2ComR, IFXCom_Busy|IFXCom_Msg(nMsg));
	can_IFx_busycheck(ndev, 2);

	val=can_inw(ndev, IF2Arb2);
	if ( val& IFXARB2_TR)
		return FAIL;

	DPRINTF("Arb2=0x%x\n", val);
	
	if (val & IFXARB2_XTD){	//Externd frame
		val=(can_inw(ndev, IF2Arb2) & IFXARB2_EIDMask)<<16;
		val|=can_inw(ndev, IF2Arb1);
		data->id= val;
	}
	else{
		data->id=(can_inw(ndev, IF2Arb2)&IFXARB2_IDMask)>>2;
	}

	val=can_inw(ndev, IF2Mctrl);
	DPRINTF("Message contrl=0x%x\n", val&(~0xf));
	data->dlc=IFXM_GETDLC(val);

	//remote frame ?
/*	if(data->rxRTR)
		can_outw(ndev, IF1Mctrl, IFXM_EoB | IFXM_TxIE | IFXM_RmtEn | IFXM_NewDat
				| IFXM_TxRqst | IFXM_DLCMask);
	else
		can_outw(ndev, IF1Mctrl, IFXM_EoB | IFXM_TxIE | IFXM_NewDat
				| IFXM_TxRqst | IFXM_DLCMask);
*/

	//??
	can_outw(ndev, IF2Mctrl, val&(~IFXM_IntPnd));

	if (data->dlc==0){
		return OK;
	}

	val = can_inw(ndev, IF2DataA1);
	data->data[0]=val & 0xff;
	data->data[1]=(val>>8) & 0xff;
	val = can_inw(ndev, IF2DataA2);
	data->data[2]=val & 0xff;
	data->data[3]=(val>>8) & 0xff;
	val = can_inw(ndev, IF2DataB1);
	data->data[4]=val & 0xff;
	data->data[5]=(val>>8) & 0xff;
	val = can_inw(ndev, IF2DataB2);
	data->data[6]=val & 0xff;
	data->data[7]=(val>>8) & 0xff;

	return OK;
}


/*********************************************************************\
	2410CAN Mask设置函数
	参数:
		ndev,设备号
		nMsg,Message号
		mask,
	使用interface 1
\*********************************************************************/
static void Can2410_SetMask(int ndev, int nMsg, U32 mask, int ext, int mdir)
{
#undef readMaskCM
#undef writeMaskCM
#define readMaskCM	(IFXMask_Control| IFXMask_Arb| IFXMask_Mask)
#define writeMaskCM	(IFXMask_Control| IFXMask_Arb| IFXMask_Mask|IFXMask_WR)

	//save the old Message number
	U32 tempreg;

	can_IFx_busycheck(ndev, 1);
	//load Message Object in IF1
	can_outw(ndev, IF1ComM, readMaskCM);
	//set interface into nMsg
	can_outw(ndev, IF1ComR, IFXCom_Busy|IFXCom_Msg(nMsg));

	can_IFx_busycheck(ndev, 1);

	//setting Message Valid Bit to zero
/*	can_outw(ndev, IF1Arb2, 0);

	can_outw(ndev, IF1ComM, writeMaskCM);
	can_outw(ndev, IF1ComR, IFXCom_Busy|IFXCom_Msg(nMsg));

	can_IFx_busycheck(ndev, 1);*/
	//setting UMask, MsgVal and Mask Register
	//writing acceptance mask for extended or standart mode
	if (ext){
		can_outw(ndev, IF1Mask2, (mask>>16 & 0x1FFF) | IFXMSK2_MXTD | IFXMSK2_SETMDIR(mdir));
		can_outw(ndev, IF1Mask1, (mask & 0xFFFF));
	}
	else{
		can_outw(ndev, IF1Mask2, ((mask<<2) & 0x1FFC) |IFXMSK2_SETMDIR(mdir));
		can_outw(ndev, IF1Mask1, 0);
	}

	can_outw(ndev, IF1Mctrl, IFXM_RxIE|IFXM_EoB|IFXM_UMask);
	
	//seting Message Valid Bit to one
	can_outw(ndev, IF1Arb2, IFXARB2_MVAL);

	can_outw(ndev, IF1ComM, writeMaskCM);
	can_outw(ndev, IF1ComR, IFXCom_Busy|IFXCom_Msg(nMsg));
}

/*********************************************************************\
	CAN设备初始化函数
	参数:	
		ndev,设备号
		bandrate,CAN波特率
		LoopBack,是否是LoopBack模式
		pfilter,CAN过滤器结构体指针,
					如果为NULL,则接受所有数据

	设置32个Message中,1-2为发送缓冲区,3-32为接受缓冲区
\*********************************************************************/
__inline int init_CAN2410(int ndev, CanBandRate bandrate, BOOL LoopBack, PCanFilter pfilter)
{
	unsigned char i;

	// disable can moduels
	can_outw(ndev, CANEnable, 0);
	udelay(100);
	// Enable can moduels
	can_outw(ndev, CANEnable, CANEnable_En);

	Enable2410_PLL2();
	CAN2410_SetBandRate(ndev, bandrate);

	//set message number 1,2 receive non
	i=FIRST_MSG;
	Can2410_SetMask(ndev, i++, 0x1fffffff, 1, 1);
	Can2410_SetMask(ndev, i++, 0x1fffffff, 1, 1);
	if(!pfilter){
		for(;i<=LAST_MSG;i++){
			Can2410_SetMask(ndev, i, 0, 1, 0);
		}
	}
	else{
		// set all filters to same = pfilter->Filter:
		for(;i<=LAST_MSG;i++){
			Can2410_SetMask(ndev, i, pfilter->Filter, pfilter->IsExt, 0);
		}
	}

   // Clear Status to get better starting
/*	i=32;
	while (i --){
		int val = can_inw(ndev, CANStatus);
		can_outw(ndev, CANStatus, 0);
		val = can_inw(ndev, CANStatus);
		if(val != 0) {
			printk("Initialization ERRROR: Status = 0x%x\n", val);
		}
		else
			break;
	}
	
	if(i == 0) {
		printk("CAN bus Initialization error. Can't clear can Status reg\n");
		return FAIL;
	}*/

	//Open Interrupt
//	can_outw(ndev, CANControl, CANControl_IE|CANControl_DAR);
	can_outw(ndev, CANControl, CANControl_IE|CANControl_EIE/*|CANControl_SIE*/);

	return OK;
}

/*********************************************************************\
	CAN设备查询函数
	参数:	
		ndev,设备号
	返回CANPOLL_Rev/CANPOLL_SendEnd
\*********************************************************************/
static int CAN2410_CanPoll(int ndev)
{
	int ret=0, status, intr;

	intr=can_inw(ndev, CANIntReg);
	DPRINTF("Poll: intr=%d\n", intr);
	status=can_inw(ndev, CANStatus);

	if(intr>0 && intr<33 && (status & CANStatus_TxOk)){	//message object interrupt
		can_IFx_busycheck(ndev, 1);
		can_outw(ndev, IF1ComM, IFXMask_ClrIntPnd);
		//clear interrupt
		can_outw(ndev, IF1ComR, IFXCom_Busy|intr);
	}

	if(status & CANStatus_RxOk){
		can_outw(ndev, CANStatus, status&(~CANStatus_RxOk));
		ret |=CANPOLL_Rev;
	}

	if(status & CANStatus_TxOk){
		can_outw(ndev, CANStatus, status&(~CANStatus_TxOk));
		ret |=CANPOLL_SendEnd;
	}

	return ret;
}

/*int CAN2410_canFlushInput()
{
	return 0;
}*/

#define DefCan2410N(n)	\
	static int s3c2410_can##n##_init(CanBandRate baud, BOOL LoopBack, PCanFilter pfilter)\
	{return init_CAN2410(n,baud, LoopBack, pfilter);}\
	static int s3c2410_can##n##_read(PCanData data){return CAN2410_canRead(n, data);}\
	static int s3c2410_can##n##_write(PCanData data){return CAN2410_canWrite(n, data);}\
	static int s3c2410_can##n##_poll(void){return CAN2410_CanPoll(n);}

/* export can driver */
#define ExportCan2410N(n)	can_driver_t s3c2410_can##n##_driver = {	\
								s3c2410_can##n##_init,	\
								NULL,/*CAN2410_CanOpen*/	\
								NULL,/*CAN2410_CanClose*/	\
								s3c2410_can##n##_read,	\
								s3c2410_can##n##_write,	\
								s3c2410_can##n##_poll,	\
								NULL,/*CAN2410_canFlushInput*/	\
								NULL,/*CAN2410_canFlushoutput*/	\
								CAN2410_Isr(n)}

DefCan2410N(0)
DefCan2410N(1)

ExportCan2410N(0);
ExportCan2410N(1);


/*can_driver_t can2410_driver = {
	init_CAN2410,
	NULL,	//CAN2410_CanOpen
	NULL,	//CAN2410_CanClose
	CAN2410_canRead,
	CAN2410_canWrite,
	CAN2410_CanPoll,
	NULL,	//CAN2410_canFlushInput
	NULL
};*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -