📄 toucan.c
字号:
tblOffset = VECTOR_TABLE_OFFSET_FROM_LEVEL(ppc5xxIlevel); /* activate IRQ at the board and CPU level */ intDisable(tblOffset); intUnlock(oldLevel); return;}/************************************************************************** TouCAN_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 in software, 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 + (propseg + 1) + (tseg1 + 1) + (tseg2+1) time quanta ** tseg1 refers to the segment of bit time after the end of propseg * and upto the sample point. The TouCAN has a settable propseg, there* is a controller specific function provided to set it. There will be* a place holder for the propseg in the CAN controller struct as well,* with the other bit timing parameters. For TouCAN the default* value of propseg is 7.* ---------------------------------------------------------* | | | | | * sync <--propseg-> <---tseg1 -->^|^<---------tseg2 ------>* sample point ** RETURNS: ERROR if any of the input parameters have invalid values,* OK otherwise.* * ERRNO: S_can_invalid_parameter**/static STATUS TouCAN_SetBitTiming( struct WNCAN_Device *pDev, UCHAR tseg1, UCHAR tseg2, UCHAR brp, UCHAR sjw, BOOL samples ){ struct canAccess *pcanAccess; TouCAN pTouCANRegs; UCHAR value; STATUS retCode = ERROR; USHORT regMCR; /* qualify parameters */ if((sjw > 0x03) || (tseg1 > 7) || (tseg2 > 7)) { errnoSet(S_can_invalid_parameter); goto exit; } /* * Get pointer to TouCAN registers and channels. */ pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCANRegs = (TouCAN)pcanAccess->pTouCanRegs; /* Check if controller is in configuration change enable mode if not set HALT bit */ regMCR = pTouCANRegs->can_MCR; if((regMCR & TOUCAN_HALT) != TOUCAN_HALT) TouCANSetHaltFrz(pTouCANRegs); /*Save input bit timing values in software CAN controller structure*/ pDev->pCtrl->brp = brp; pDev->pCtrl->sjw = sjw; pDev->pCtrl->tseg1 = tseg1; pDev->pCtrl->tseg2 = tseg2; pDev->pCtrl->samples = samples; /*Set bit Timing values*/ /* btr0 and btr1 */ pTouCANRegs->can_PRESDIV = brp; /*Write values for rjw, tseg1, tseg2 in CR2*/ value = ((sjw << 6) | (tseg1 << 3) | tseg2); pTouCANRegs->can_CR2 = (UCHAR)value; /*Write value for propseg*/ /* * If the user does not want a hard coded value of 7 * the value can be changed by calling the api TouCAN_SetPropseg */ value = pTouCANRegs->can_CR1 & ~(TOUCAN_PROPSEG); if(samples) value |= (0x80 | pcanAccess->ToucanPropseg); else value |= pcanAccess->ToucanPropseg; pTouCANRegs->can_CR1 = value; /*restore controller state*/ if((regMCR & TOUCAN_HALT) != TOUCAN_HALT) TouCANResetHaltFrz(pTouCANRegs); retCode = OK; exit: return retCode;}/**************************************************************************** TouCAN_GetBaudRate: Returns baud rate by recalculating bit timing parameters* * RETURNS: baud rate in bps* * ERRNO: N/A*/static UINT TouCAN_GetBaudRate( struct WNCAN_Device *pDev, UINT *samplePoint ){ struct canAccess *pcanAccess; TouCAN pTouCanRegs; ULONG sys_clk_frequency; UINT32 base; volatile unsigned int uimbMcr; USHORT num_time_quanta; UCHAR brp, tseg1, tseg2, propseg; /* * Get pointer to TouCAN registers and channels. */ pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs; sys_clk_frequency = pDev->pBrd->xtalFreq; /*Get base of address space*/ base = vxImemBaseGet(); /*Check the Half speed bit setting in the UMCR*/ uimbMcr = *(PPCUIMB_MCR(base)); if(uimbMcr && UIMB_HSPEED) { /*The IMB frequency is one half that of the U bus*/ sys_clk_frequency = sys_clk_frequency / 2; } brp = (pTouCanRegs->can_PRESDIV) + 1; tseg1 = ((pTouCanRegs->can_CR2 & TOUCAN_PSEG) >> 3) + 1; tseg2 = (pTouCanRegs->can_CR2 & TOUCAN_PSEG2) + 1; propseg = (pTouCanRegs->can_CR1 & TOUCAN_PROPSEG) + 1; /*Calculate baud rate*/ num_time_quanta = 1 + propseg + tseg1 + tseg2; *samplePoint = ((1+propseg+tseg1) * 100)/num_time_quanta; return(sys_clk_frequency / (num_time_quanta * brp)); }/************************************************************************** TouCAN_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 TouCAN_GetBusStatus( struct WNCAN_Device *pDev ){ struct canAccess *pcanAccess; TouCAN pTouCanRegs; USHORT regStatus; WNCAN_BusStatus retStat=WNCAN_BUS_OFF; /* * Get pointer to TouCAN registers and channels. */ pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs; /* read the status register */ regStatus = pTouCanRegs->can_ESTAT; if((regStatus & TOUCAN_FCS) == TOUCAN_ERR_ACTIVE) retStat = WNCAN_BUS_OK; else if(regStatus & 0x0020) retStat = WNCAN_BUS_OFF; if((regStatus & TOUCAN_TXWARN) || (regStatus & TOUCAN_RXWARN)) retStat = WNCAN_BUS_WARN; return retStat;}/************************************************************************** TouCAN_GetBusError - get the bus error** This function returns an ORed bit mask of all the bus errors that have* occured during the last bus activity.* Bus errors returned by this function can have the following values:* WNCAN_ERR_NONE: No errors detected* WNCAN_ERR_BIT: Bit error. * WNCAN_ERR_ACK: Acknowledgement error. * WNCAN_ERR_CRC: CRC error* WNCAN_ERR_FORM: Form error* WNCAN_ERR_STUFF: Stuff error* WNCAN_ERR_UNKNOWN: this condition should not occur* The five errors are not mutually exclusive. * The occurence of an error will be indicated by an interrupt. Typically, * this function will be called from the error interrupt handling case in the* user's ISR callback function, to find out the kind of error that occured* on the bus.** RETURNS: the bus error** ERRNO: N/A**/static WNCAN_BusError TouCAN_GetBusError( struct WNCAN_Device *pDev ){ struct canAccess *pcanAccess; TouCAN pTouCanRegs; USHORT value; WNCAN_BusError error = WNCAN_ERR_NONE; pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs; /* read the error status capture register */ value = pTouCanRegs->can_ESTAT; if(value & TOUCAN_ACKERR) error |= WNCAN_ERR_ACK; if(value & TOUCAN_CRCERR) error |= WNCAN_ERR_CRC; if(value & TOUCAN_FORMERR) error |= WNCAN_ERR_FORM; if(value & TOUCAN_STUFFERR) error |= WNCAN_ERR_STUFF; if(value & (TOUCAN_TXDOM_RXREC | TOUCAN_TXREC_TXDOM)) error |= WNCAN_ERR_BIT; return error; }/************************************************************************** TouCAN_ReadID - read the CAN Id ** This function reads the CAN Id corresponding to the channel number on* the controller. The standard or extended flag is set by the function.* The mode of the channel cannot be WNCAN_CHN_INACTIVE or WNCAN_CHN_INVALID** RETURNS: LONG: the CAN Id; on error return -1** ERRNO: S_can_illegal_channel_no,* S_can_illegal_config* S_can_busy***/static long TouCAN_ReadID( struct WNCAN_Device *pDev, UCHAR channelNum, BOOL* ext ){ struct canAccess *pcanAccess; TouCAN pTouCanRegs; TouCANBuf pTouCanBufs; volatile TouCAN_StandardMsgType *buffer; unsigned short value; long msgID = -1; /* invalid msg id */ /* * Check if channel number is within range * or if it marked as inactive * or if the buffer is currently receiving and hence busy */ if (channelNum >= TOUCAN_MAX_MSG_OBJ) { errnoSet(S_can_illegal_channel_no); goto exit; } if((pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_INACTIVE) || (pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_INVALID)) { errnoSet(S_can_illegal_config); goto exit; } /* * Get pointer to TouCAN registers. */ pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs; pTouCanBufs = (TouCANBuf)pcanAccess->pTouCanBufs; buffer = &pTouCanBufs->can_MSG[channelNum]; /*next test busy bit only for Rx buffers*/ if((pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_RECEIVE) || (pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_RTR_RESPONDER)) { if(buffer->Control & TOUCAN_BUFFER_BUSY) { errnoSet(S_can_busy); goto exit; } } /* * Get the message ID from the buffer, and copy the ID */ if((buffer->Id & TOUCAN_IDE_EXT) == TOUCAN_IDE_EXT) { /*Copy ID of message */ value = (USHORT)((buffer->Id & (USHORT)TOUCAN_ID_BITS_28TO18) | ((buffer->Id & (USHORT)TOUCAN_ID_BITS_17TO15) << 2)); msgID = ((ULONG)value << 13) | ((ULONG)buffer->Id2_OR_TimeStamp>>1); *ext = TRUE; } else { msgID = (buffer->Id >> 5); *ext = FALSE; } /*Read the free running timer to unlock channel accessed*/ timerRead = pTouCanRegs->can_TIMER; exit: return msgID;} /************************************************************************** TouCAN_ReadData - reads 0 to 8 bytes of data from channel** This function reads "len" bytes of data from the channel and sets the value* of len to the number of bytes read. The range of "len" is zero (for zero * length data) to a maximum of eight. The mode of the channel must not be * WNCAN_CHN_INVALID or WNCAN_CHN_INACTIVE; however, the newData flag is valid * WNCAN_CHN_RECEIVE or WNCAN_CHN_REQUESTER channel mode.* For receive channels, if no new data has been received since the last* CAN_ReadData function call, the newData flag is set to FALSE; * otherwise, the flag is TRUE. In both cases, the data and length of the* data currently in the channel are read. ** RETURNS: OK, or ERROR** ERRNO: S_can_illegal_channel_no,* S_can_illegal_config,* S_can_buffer_overflow,* S_can_busy**/static STATUS TouCAN_ReadData ( struct WNCAN_Device *pDev, UCHAR channelNum, UCHAR *data, UCHAR *len, BOOL *newData ){ struct canAccess *pcanAccess; TouCAN pTouCanRegs; TouCANBuf pTouCanBufs; volatile TouCAN_StandardMsgType *buffer; UINT i; STATUS retCode = ERROR; /* pessimistic */ volatile USHORT regCtrl; volatile UCHAR hwLength; if (channelNum >= TOUCAN_MAX_MSG_OBJ) { errnoSet(S_can_illegal_channel_no); goto exit; } if((pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_INACTIVE) || (pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_INVALID)) { errnoSet(S_can_illegal_config); goto exit; } /* * Get pointer to TouCAN registers and channels. */ pcanAccess = (struct canAccess *)pDev->pCtrl->csData; pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs; pTouCanBufs = (TouCANBuf)pcanAccess->pTouCanBufs; buffer = &pTouCanBufs->can_MSG[channelNum]; /*next test busy bit only for Rx buffers*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -