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

📄 sja1000.c

📁 can总线c语言 canopen 源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/* sja1000.c - implementation of CAN API for Philips SJA1000 *//* Copyright 2001 Wind River Systems, Inc. *//*modification history--------------------22aug02,lsg modified for WindNet CAN 1,209nov01,dnb modified for integration into Tornado12jul01,jac written*//*DESCRIPTIONThis module contains the functions, specific to the Philips SJA1000 CANcontroller, that implement the interface defined in the wnCAN.hheader file.*//* includes */#include <vxWorks.h>#include <errnoLib.h>#include <taskLib.h>#include <intLib.h>#include <iv.h>#include <sysLib.h>#include <CAN/wnCAN.h>#include <CAN/canController.h>#include <CAN/canBoard.h>#ifdef INCLUDE_SJA1000#include <CAN/sja1000.h>#include <CAN/sja1000Offsets.h>/* forward declarations */const WNCAN_ChannelType g_sja1000chnType[SJA1000_MAX_MSG_OBJ] = { WNCAN_CHN_RECEIVE,WNCAN_CHN_TRANSMIT};/*   In Pelican mode, the addresses of the transmit and receive buffers are   identical. Access to the correct register depends on the access operation:   write for accessing the transmit buffer, and read for accessing the receive   buffer. Also, the address of the start of the msg data changes depending   on whether the CAN Id is standard or extended; therefore, a SJA1000_WriteData()   operation requires a copy of the data until SJA1000_Tx() is called at which   time the frame format is known. Because read operations on the transmit   buffer (SJA1000_ReadData(), SJA1000_ReadID()) are also not possible,   a local tranmit message data stucture is necessary to store the transmit data.   Copies to and from this data structure represents additional overhead.*//************************************************************************** SJA1000_Init - intitialize the CAN controller** This function initializes the CAN controller and makes default selections.* 1. Puts the CAN controller into reset mode* 2. Disables interrupts at the CAN controller level as well as channel level* 3. Sets bit timing values according to values stored in the CAN controller*    struct. If user has changed these values before init is called, the*    default bit timing values are set to a baud rate of 250K* 4. Clears error counters* 5. Sets local and global receive masks to don't care (accept all)* 6. Makes all channels inactive in hardware* 7. The CAN controller has now been initialized but will not participate*    in CAN bus communication. In order to bring the CAN controller online,*    and enable active participation in CAN bus activity, CAN_Start must*    be called following CAN_Init.** Call these functions in this order:* 1. CAN_Open* 2. CAN_Init* 3. CAN_Start** RETURNS: OK, or ERROR** ERRNO:   N/A**/static STATUS SJA1000_Init(struct WNCAN_Device *pDev){    UCHAR        value;    STATUS       retCode = OK;    unsigned int i;	/* Put the controller into reset mode */	pDev->pBrd->canOutByte(pDev, SJA1000_MOD, MOD_RM);		/* set controller to Pelican mode */	value = pDev->pBrd->canInByte(pDev, SJA1000_CDR);	value |= 0x80;	pDev->pBrd->canOutByte(pDev, SJA1000_CDR, value);		/* set the mode register: 0001001 (0x9)	reset             = 1   (reset mode)	listen only       = 0   (normal)	self test         = 0   (ack required for successful TX)	acceptance filter = 1   (single 32 bit filter)	sleep mode        = 0   */	pDev->pBrd->canOutByte(pDev, SJA1000_MOD, 0x09);		/* set command register to zero */	pDev->pBrd->canOutByte(pDev, SJA1000_CMR ,0);		/* set the error warning limit to 96 */	pDev->pBrd->canOutByte(pDev, SJA1000_EWLR, 0x60);		/* disable all interrupts */	pDev->pBrd->canOutByte(pDev, SJA1000_IER, 0x0);		/* btr0 and btr1 */	value = (pDev->pCtrl->sjw << 6) | pDev->pCtrl->brp;	pDev->pBrd->canOutByte(pDev, SJA1000_BTR0, value);	if(pDev->pCtrl->samples)		value = 0x80 | (pDev->pCtrl->tseg2 << 4) | pDev->pCtrl->tseg1;		else		value = (pDev->pCtrl->tseg2 << 4) | pDev->pCtrl->tseg1;			pDev->pBrd->canOutByte(pDev, SJA1000_BTR1, value);    		/* set output control */	pDev->pBrd->canOutByte(pDev, SJA1000_OCR, 0xfb);		/* reset receive error counter */	pDev->pBrd->canOutByte(pDev, SJA1000_RXERR, 0x0);		/* reset transmit error counter */	pDev->pBrd->canOutByte(pDev, SJA1000_TXERR, 0x0);		/* Set all acceptance code registers to 0xFF. Received messages must	have these bits set. */	pDev->pBrd->canOutByte(pDev, SJA1000_ACR0, 0xff);	pDev->pBrd->canOutByte(pDev, SJA1000_ACR1, 0xff);	pDev->pBrd->canOutByte(pDev, SJA1000_ACR2, 0xff);	pDev->pBrd->canOutByte(pDev, SJA1000_ACR3, 0xff);		/* Set the acceptance mask registers to don't care. The acceptance 	mask register defines which bits of the acceptance code register 	matter:	1 = don't care (message bit may be one or zero), 0 = must match . 	*/	pDev->pBrd->canOutByte(pDev, SJA1000_AMR0, 0xff);	pDev->pBrd->canOutByte(pDev, SJA1000_AMR1, 0xff);	pDev->pBrd->canOutByte(pDev, SJA1000_AMR2, 0xff);	pDev->pBrd->canOutByte(pDev, SJA1000_AMR3, 0xff);		/*	* The controller is not brought out of reset here. CAN_Start must	* be called in order to do that and enable CAN communication on the	* bus	*/		/* free all channels */	for (i = 0; i < SJA1000_MAX_MSG_OBJ; i++)		pDev->pCtrl->chnMode[i] = WNCAN_CHN_INVALID;		     return retCode;}/************************************************************************** SJA1000_GetBusStatus - get the bus status** This function returns the status of the CAN bus. The bus is * either in a WNCAN_BUS_OFF, WNCAN_BUS_WARN, or WNCAN_BUS_OK state.** WNCAN_BUS_OFF: CAN controller is in BUS OFF state* A CAN node is bus off when the transmit error count is greater than* or equal to 256* WNCAN_BUS_WARN: CAN controller is in ERROR WARNING state* A CAN node is in error warning state when the number of transmit errors* equals or exceeds 96, or the number of receive errors equals or exceeds* 96* WNCAN_BUS_OK: CAN controller is in ERROR ACTIVE state* A CAN node in error active state can normally take part in bus communication* and sends an ACTIVE ERROR FLAG when an error has been detected. ** RETURNS: status of the CAN bus = WNCAN_BUS_OK, WNCAN_BUSWARN, * WNCAN_BUS_OFF** ERRNO: N/A**/static WNCAN_BusStatus SJA1000_GetBusStatus(struct WNCAN_Device *pDev){    UCHAR regStatus;    WNCAN_BusStatus retStat;    /* read the status register */    regStatus = pDev->pBrd->canInByte(pDev, SJA1000_SR);    if(regStatus & SR_BS)        retStat = WNCAN_BUS_OFF;    else if(regStatus & SR_ES)        retStat = WNCAN_BUS_WARN;    else        retStat = WNCAN_BUS_OK;    return retStat;}/************************************************************************** SJA1000_Start - Bring CAN controller online** This function is called to bring the CAN controller online. The CAN controller* can now participate in transmissions and receptions on the CAN bus.* This function must be called after CAN_Init has been called to initialize and* bring the CAN controller up in a known state.** RETURNS: OK always** ERRNO:   N/A**/static void SJA1000_Start(struct WNCAN_Device *pDev){	struct TxMsg *pTxMsg;	UCHAR value;	UCHAR i;    	/* Clear the controller reset */	value = pDev->pBrd->canInByte(pDev, SJA1000_MOD);	value &= ~0x1;	pDev->pBrd->canOutByte(pDev, SJA1000_MOD, value);	/* Wait until the controller comes out of reset */	while(pDev->pBrd->canInByte(pDev, SJA1000_MOD) != value) {};	/* Wait for Bus OK or taskDelay(1)*/	if(SJA1000_GetBusStatus != WNCAN_BUS_OK)		taskDelay(1);	/* Initialize the TX frame info. This can only be done when	the controller is not in reset. */	pDev->pBrd->canOutByte(pDev, SJA1000_SFF, 0);	/* Initialize the TX msg data structure */	pTxMsg = (struct TxMsg *)pDev->pCtrl->csData;	pTxMsg->id  = 0;	pTxMsg->ext = 0;	pTxMsg->rtr = 0;	pTxMsg->len = 0;	for(i = 0 ; i < 8 ; i++)		pTxMsg->data[i] = 0;}/************************************************************************** SJA1000_Stop - Put CAN controller offline** Disables communication between CAN controller and the CAN bus** RETURNS: OK always** ERRNO:   N/A**/static void SJA1000_Stop(struct WNCAN_Device *pDev){    /* Stop the SJA1000 controller*/	/* Put the controller into reset mode */	pDev->pBrd->canOutByte(pDev, SJA1000_MOD, MOD_RM);}/************************************************************************** SJA1000_SetBitTiming - Set bit timing** This function sets the baud rate of the controller. The selection* of the input parameters should be based on an established set of * recommendations for the particular application.* This function sets the bit timing values in the hardware as well as the* controller structure, so that the bit timing values are not lost if Init* is called again. The function will preserve the state of the CAN controller.* i.e. if the CAN controller is online when the function is called, then the * CAN controller will be online when the function exits. ** bit time = 1 + (tseg1 + 1) + (tseg2+1) time quanta * The interpretation of tseg1 are tseg2 are according to the controller's * definition and hence can be written to directly using this function.** In all cases so far, tseg2 refers to the segment of bit time after the sample* point. However, in some controllers tseg1 refers to the segment of bit time* after the end of sync seg upto the sample point.                     *  ---------------------------------------------------------* |    |                    |                              |  *  sync <--------tseg1 --->^|^<---------tseg2 ------------->*                          sample point * ** RETURNS: OK, or ERROR** ERRNO:   S_can_invalid_parameter**/static STATUS SJA1000_SetBitTiming(    struct WNCAN_Device *pDev,    UCHAR tseg1,    UCHAR tseg2,    UCHAR brp,    UCHAR sjw,    BOOL  samples){    UCHAR       value;    STATUS      retCode;	    retCode = OK;  /* assume success */	    /* qualify parameters */    if((sjw > 0x03) || (brp > 0x3f) || (tseg1 > 15) ||		(tseg1 < 2) || (tseg2 > 7) || (tseg2 < 1))    {        errnoSet(S_can_invalid_parameter);        retCode = ERROR;    }    else    {		/* Check if controller is in reset mode */        /* if not, enable change configuration */        value = pDev->pBrd->canInByte(pDev, SJA1000_MOD);						if((value & 0x01) == 0)			pDev->pBrd->canOutByte(pDev, SJA1000_MOD, value | 0x01);		        pDev->pCtrl->brp = brp;        pDev->pCtrl->sjw = sjw;        pDev->pBrd->canOutByte(pDev, SJA1000_BTR0, (sjw << 6) | brp);		        pDev->pCtrl->tseg1 = tseg1;        pDev->pCtrl->tseg2 = tseg2;		        if(samples)		{			/*three sample mode*/			pDev->pCtrl->samples = 1;			pDev->pBrd->canOutByte(pDev, SJA1000_BTR1, (0x80 | (tseg2 << 4) | 				tseg1));		}        else					{			/*one sample mode*/			pDev->pCtrl->samples = 0;			pDev->pBrd->canOutByte(pDev, SJA1000_BTR1, (tseg2 << 4) | tseg1);		}						/*restore original state of controller*/		if((value & 0x01) == 0)		{			pDev->pBrd->canOutByte(pDev, SJA1000_MOD, value);						/* Wait until the controller comes out of reset */			while(pDev->pBrd->canInByte(pDev, SJA1000_MOD) != value) {};						/* Wait for Bus OK or a task delay of 1*/						if(SJA1000_GetBusStatus != WNCAN_BUS_OK)				taskDelay(1);								}		    }	    return retCode;}/**************************************************************************** SJA1000_GetBaudRate: Returns baud rate by recalculating bit timing * parameters** RETURNS: baud rate in bps** ERRNO:   N/A*/static UINT SJA1000_GetBaudRate      (      struct WNCAN_Device *pDev,	  UINT   *samplePoint      ){	ULONG             sysClkFreq;                USHORT            num_time_quanta;	UCHAR		  brp, tseg1, tseg2;        UCHAR 		  value;	value = pDev->pBrd->canInByte(pDev, SJA1000_CDR);	value = value & 0x7;		sysClkFreq = (pDev->pBrd->xtalFreq / (2 + 2*value));	brp = (pDev->pBrd->canInByte(pDev, SJA1000_BTR0) & 0x3f) + 1;	tseg1 = pDev->pBrd->canInByte(pDev, SJA1000_BTR1);	tseg2 = ((tseg1 & 0xf0) >> 4) + 1;	tseg1 = (tseg1 & 0x0f) + 1;	/*Calculate baud rate*/	num_time_quanta = 1 + tseg1 + tseg2;	 *samplePoint = ((1 + tseg1) * 100)/num_time_quanta;	return( sysClkFreq / (num_time_quanta * brp));}/************************************************************************** SJA1000_SetIntMask - enable controller level interrupts on the CAN*                      controller** This function enables the specified list of controller level interrupts* on the CAN controller. Interrupts are not enabled at the CAN board level* or at the CPU level.* The interrupt masks available are:* WNCAN_INT_ERROR : enables interrupts due to errors on the CAN bus*                   This may be implemented as a single or multiple*                   interrupt sources on the CAN controller.* WNCAN_INT_BUS_OFF: enables interrupt indicating bus off condition  * WNCAN_INT_WAKE_UP: enables interrupt on wake up* All interrupt masks that need to be enabled must be specified in the list* passed to the function, in order to be set, every time the function* is called. ** RETURNS: OK or ERROR** ERRNO:   S_can_invalid_parameter**/static STATUS SJA1000_SetIntMask(struct WNCAN_Device *pDev, WNCAN_IntType intMask){    int         oldLevel;    UCHAR       value=0;	STATUS      retCode = OK;	/*	return error if masks other than error, busoff and wakeup	are passed to the function	*/	if((intMask > (WNCAN_INT_ERROR | WNCAN_INT_BUS_OFF | WNCAN_INT_WAKE_UP)) &&		(intMask != WNCAN_INT_ALL)) 	{		errnoSet(S_can_invalid_parameter);		retCode = ERROR;        	}	else	{		value = pDev->pBrd->canInByte(pDev, SJA1000_IER);				/*Enable all error interreupts. Bus error,  data overrun*/		if(intMask & WNCAN_INT_ERROR)			value |= IER_BEIE;		else			value &= ~IER_BEIE;						if(intMask & WNCAN_INT_WAKE_UP)			value |= IER_WUIE;		else			value &= ~IER_WUIE;							/*			The error warning interrupt is generated when errors on the bus exceed			warning limits and if the controller becomes bus off. The interrupt 			is also raised when the controller goes into error active state from 			being bus offf		*/		if(intMask & WNCAN_INT_BUS_OFF)			value |= IER_EIE;		else			value &= ~IER_EIE;						oldLevel = intLock();				pDev->pBrd->canOutByte(pDev, SJA1000_IER, value);				intUnlock(oldLevel);	}    return retCode;}/***************************************************************************   * SJA1000_EnableInt - enable interrupts from the CAN device to the CPU.** This function enables interrupts from the CAN controller to reach the* CPU. Typically, enables a global interrupt mask bit at the CPU level.** RETURNS: N/A** ERRNO:   N/A**/static void SJA1000_EnableInt(struct WNCAN_Device *pDev){    int         oldLevel;    UCHAR       value=0;	value = pDev->pBrd->canInByte(pDev, SJA1000_IER);	/*Enable RxIE*/	value |= 0x01;	        oldLevel = intLock();    pDev->pBrd->canOutByte(pDev, SJA1000_IER, value);    intUnlock(oldLevel);    return;}/************************************************************************** SJA1000_DisableInt -  disable interrupts from the CAN device to the CPU** This function disables interrupts from the CAN controller from reaching the* CPU. Typically, disables a global interrupt mask bit at the CPU level.** RETURNS: N/A

⌨️ 快捷键说明

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