📄 toucan.c
字号:
/* toucan.c - implementation of CAN Common Interface for Motorola TouCAN *//* Copyright 2001 Wind River Systems, Inc. *//* modification history --------------------18dec01,lsg 05aug02,lsg modifications for WindNet CAN 1.2*//* DESCRIPTION This file contains the functions, specific to the Motorola TouCAN CAN controller, that implement the interface defined in the wnCAN.h header file. *//* includes */#include <vxWorks.h>#include <errnoLib.h>#include <intLib.h>#include <iv.h>#include <CAN/wnCAN.h>#include <CAN/canController.h>#include <CAN/canBoard.h>#ifdef INCLUDE_TOUCAN#include <CAN/toucan.h>#include <CAN/toucanOffsets.h>#include <drv/misc/uimb/ppcUimb.h>/*static variable to read free running timer Timer is read to unlock a channel, after it has been accessed.Static declaration is used to prevent optimization of timer read statement.*/static USHORT timerRead;extern UINT32 vxImemBaseGet(void);#define VECTOR_TABLE_OFFSET_FROM_LEVEL(n) (2*n + 1)const WNCAN_ChannelType g_TOUCANchnType[TOUCAN_MAX_MSG_OBJ] ={ WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE, WNCAN_CHN_TRANSMIT_RECEIVE };/******************************************************************************* TouCANSetHaltFrz - Sets up registers for debug mode * Set FRZ and HALT bits in MCR ** RETURNS: Error value*/static UCHAR TouCANSetHaltFrz( TouCAN pTouCanRegs){ /* * Request debug mode * Set FRZ and HALT */ pTouCanRegs->can_MCR = (TOUCAN_FRZ | TOUCAN_HALT); /* * Poll till FRZACK is set */ while(!(pTouCanRegs->can_MCR & TOUCAN_FRZACK)) { /* just spin */ } return OK;}/****************************************************************************** TouCANResetHaltFrz - Resets debug mode** RETURNS: Error value*/static void TouCANResetHaltFrz( TouCAN pTouCanRegs){ /*Clear FRZ bit in MCR*/ pTouCanRegs->can_MCR &= ~(TOUCAN_FRZ | TOUCAN_HALT); return; }/************************************************************************** TouCAN_Init - This function initializes 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. Unless user has changed these values before init is called, the* default bit timing values are set to a baud rate of 250K. TouCAN has a * separate field provided for setting the propgation delay in the bit time. * The default value of propseg is 7. A TouCAN controller specific function* TouCAN_SetPropseg is provided to change the propseg value stored in the * CAN controller structure in software. The new value will be written to * the hardware register when CAN_Init or CAN_SetBitTiming is called.* 4. Following reset both error counters reset to zero* 5. Sets local and global receive masks to don't care (accept all)* 6. Makes all channels inactive in hardware* 7. Set default values for timer sync = enabled, lbuf = lowest id first,* auto power save mode = disabled, * 8. 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 always** ERRNO: N/A**/static STATUS TouCAN_Init( struct WNCAN_Device *pDev ){ struct canAccess *pcanAccess; TouCAN pTouCanRegs; TouCANBuf pTouCanBufs; UCHAR value; STATUS retCode; UINT iflag; UCHAR i; UCHAR j; pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs; pTouCanBufs = (TouCANBuf)pcanAccess->pTouCanBufs; /* Put the controller into debug mode */ TouCANSetHaltFrz(pTouCanRegs); /* Clear channel interrupt sources */ iflag = pTouCanRegs->can_IFLAG; pTouCanRegs->can_IFLAG = 0; /* Turn off Bus Off interrupt and error interrupt */ pTouCanRegs->can_CR0 &= ~(TOUCAN_BOFF_MASK_ENABLE | TOUCAN_ERROR_MASK_ENABLE); /* Write default values for timeer sync enable and buffer transmission priority, unless user has changed these by callin TouCAN specific function TouCAN_SetTimerSync and TouCAN_SetLBuf */ pTouCanRegs->can_CR1 = pcanAccess->TouCANTimerSync | pcanAccess->TouCANLBuf; /*Set bit Timing values*/ pTouCanRegs->can_PRESDIV = pDev->pCtrl->brp; /*baud rate prescalar*/ value = (UCHAR)((pDev->pCtrl->sjw << 6) | (pDev->pCtrl->tseg1 << 3) | pDev->pCtrl->tseg2); pTouCanRegs->can_CR2 = (UCHAR)value; /*sjw, tseg1, tseg2*/ if(pDev->pCtrl->samples) /*propseg and samples*/ pTouCanRegs->can_CR1 |= (0x80 | pcanAccess->ToucanPropseg); else pTouCanRegs->can_CR1 |= pcanAccess->ToucanPropseg; /* reset receive and transmit error counters */ pTouCanRegs->can_RxECTR = 0; pTouCanRegs->can_TxECTR = 0; /*Set receive masks to dont care*/ /*0 -> is don't care and 1 -> match the corresponding id bit*/ pTouCanRegs->can_RxGlobalMask = 0; pTouCanRegs->can_RxBuff15Mask = 0; pTouCanRegs->can_RxBuff14Mask = 0; /* Make all 16 channels inactive */ for(i = 0 ; i < TOUCAN_MAX_MSG_OBJ; i++) { pDev->pCtrl->chnMode[i] = WNCAN_CHN_INVALID; pTouCanBufs->can_MSG[i].Control = TOUCAN_INACTIVE_BUFFER; pTouCanBufs->can_MSG[i].Id = 0; pTouCanBufs->can_MSG[i].Id2_OR_TimeStamp = 0; for(j = 0 ; j < 8 ; j++) pTouCanBufs->can_MSG[i].Data[j] = 0; } /* Clear the controller reset */ /* * Self wake, auto power save, low power stop mode are disabled by default * The user can set them by calling the api provided if required */ pTouCanRegs->can_MCR |= pcanAccess->TouCANAutoPowersSave; /* * Leave the HALT and FRZ bits asserted. The user will have to call * CAN_Start to negate these bits and enable CAN communication */ pTouCanRegs->can_MCR &= ~(TOUCAN_SFTRST | TOUCAN_SUPV); retCode = OK; return retCode;}/************************************************************************** TouCAN_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: N/A** ERRNO: N/A**/static void TouCAN_Start( struct WNCAN_Device *pDev ){ struct canAccess *pcanAccess; TouCAN pTouCanRegs; /* * Get pointer to TouCAN registers */ pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs; /* Start the TouCAN controller */ TouCANResetHaltFrz(pTouCanRegs); }/************************************************************************** TouCAN_Stop - Put CAN controller offline** Disables communication between CAN controller and the CAN bus** RETURNS: N/A* * ERRNO: N/A**/static void TouCAN_Stop( struct WNCAN_Device *pDev ){ struct canAccess *pcanAccess; TouCAN pTouCanRegs; /* * Get pointer to TouCAN registers */ pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs; /* enter debug mode */ TouCANSetHaltFrz(pTouCanRegs); }/************************************************************************** TouCAN_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 TouCAN_SetIntMask(struct WNCAN_Device *pDev, WNCAN_IntType intMask){ struct canAccess *pcanAccess; TouCAN pTouCANRegs; int oldLevel; USHORT value; STATUS retCode=OK; /* * Get pointer to TouCAN registers */ pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCANRegs = (TouCAN)pcanAccess->pTouCanRegs; /* 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 { /* Check if controller is in configuration change enable mode if not set HALT bit */ value = pTouCANRegs->can_MCR; if((value & TOUCAN_HALT) != TOUCAN_HALT) TouCANSetHaltFrz(pTouCANRegs); oldLevel = intLock(); if(intMask & WNCAN_INT_ERROR) pTouCANRegs->can_CR0 |= TOUCAN_ERROR_MASK_ENABLE; else pTouCANRegs->can_CR0 &= ~TOUCAN_ERROR_MASK_ENABLE; if(intMask & WNCAN_INT_WAKE_UP) pTouCANRegs->can_MCR |= TOUCAN_WAKEUPINT_ENABLE; else pTouCANRegs->can_MCR &= ~TOUCAN_WAKEUPINT_ENABLE; if(intMask & WNCAN_INT_BUS_OFF) pTouCANRegs->can_CR0 |= TOUCAN_BOFF_MASK_ENABLE; else pTouCANRegs->can_CR0 &= ~TOUCAN_BOFF_MASK_ENABLE; intUnlock(oldLevel); /* Restore original state of controller */ if((value & TOUCAN_HALT) != TOUCAN_HALT) TouCANResetHaltFrz(pTouCANRegs); } return retCode; }/************************************************************************** TouCAN_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 TouCAN_EnableInt( struct WNCAN_Device *pDev ){ struct canAccess *pcanAccess; TouCAN pTouCanRegs; UINT ppc5xxIlevel; UINT32 tblOffset = 0; int oldLevel; /* * Get pointer to TouCAN registers. */ pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs; ppc5xxIlevel = ((pTouCanRegs->can_ICR & 0x00c0) >> 3) | ((pTouCanRegs->can_ICR & 0x0700) >> 8); oldLevel = intLock(); tblOffset = VECTOR_TABLE_OFFSET_FROM_LEVEL(ppc5xxIlevel); /* activate IRQ at the board and CPU level */ intEnable(tblOffset); intUnlock(oldLevel); return;}/************************************************************************** TouCAN_DisableInt - CAN interrupts are disabled on the controller.** RETURNS: N/A* * ERRNO: **/static void TouCAN_DisableInt( struct WNCAN_Device *pDev ){ struct canAccess *pcanAccess; TouCAN pTouCanRegs; UINT ppc5xxIlevel; UINT32 tblOffset = 0; int oldLevel; /* * Get pointer to TouCAN registers. */ pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs; ppc5xxIlevel = ((pTouCanRegs->can_ICR & 0x00c0) >> 3) | ((pTouCanRegs->can_ICR & 0x0700) >> 8); oldLevel = intLock();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -