void CAN1RxMsgProcess(void) { CANRxMessageBuffer *message; if(isCAN1MsgReceived == FALSE) { return; } isCAN1MsgReceived = FALSE; message = CANGetRxMessage(CAN1, CAN_CHANNEL1); lcdInstruction("0;0H"); unsigned int sid = message->msgSID.SID; unsigned int data = message->data[0] << 8; unsigned int data2 = message->data[1]; float temp = (data + data2) * 0.1; sprintf(buffer, "%u", sid); lcdString(buffer); sprintf(buffer, "%2.2fF", temp); lcdInstruction("1;0H"); lcdString("ET: "); lcdString(buffer); CANUpdateChannel(CAN1, CAN_CHANNEL1); CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); }
void __attribute__((vector(47), interrupt(ipl4), nomips16)) CAN2InterruptHandler(void) { /* This is the CAN2 Interrupt Handler. Note that there * are many events in the CAN2 module that can cause * this interrupt. These events are enabled by the * CANEnableModuleEvent() function. In this example, * only the RX_EVENT is enabled. */ /* Check if the source of the interrupt is RX_EVENT. * This is redundant since only this event is enabled * in this example but this shows one scheme for handling * interrupts. */ if((CANGetModuleEvent(CAN2) & CAN_RX_EVENT) != 0) { /* Within this, you can check which event caused the * interrupt by using the CANGetPendingEventCode() function * to get a code representing the highest priority active * event.*/ if(CANGetPendingEventCode(CAN2) == CAN_CHANNEL1_EVENT) { /* This means that channel 1 caused the event. * The CAN_RX_CHANNEL_NOT_EMPTY event is persistent. You * could either read the channel in the ISR * to clear the event condition or as done * here, disable the event source, and set * an application flag to indicate that a message * has been received. The event can be * enabled by the application when it has processed * one message. * * Note that leaving the event enabled would * cause the CPU to keep executing the ISR since * the CAN_RX_CHANNEL_NOT_EMPTY event is persistent (unless * the not empty condition is cleared.) * */ CANEnableChannelEvent(CAN2, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE); isCAN2MsgReceived = TRUE; } } /* The CAN2 Interrupt flag is cleared at the end of the * interrupt routine. This is because the event * that could have caused this interrupt to occur * (CAN_RX_CHANNEL_NOT_EMPTY) is disabled. Attempting to * clear the CAN2 interrupt flag when the the CAN_RX_CHANNEL_NOT_EMPTY * interrupt is enabled will not have any effect because the * base event is still present. */ INTClearFlag(INT_CAN2); }
CAN1InterruptHandler(void) { if ((CANGetModuleEvent(CAN1) & CAN_RX_EVENT) != 0) { if(CANGetPendingEventCode(CAN1) == CAN_CHANNEL1_EVENT) { CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE); isCAN1MsgReceived = TRUE; } } INTClearFlag(INT_CAN1); }
void CAN1Init(void) { CAN_BIT_CONFIG canBitConfig; UINT baudPrescalar; CANEnableModule(CAN1, TRUE); CANSetOperatingMode(CAN1, CAN_CONFIGURATION); while(CANGetOperatingMode(CAN1) != CAN_CONFIGURATION); // Standard Values canBitConfig.phaseSeg2Tq = CAN_BIT_3TQ; canBitConfig.phaseSeg1Tq = CAN_BIT_5TQ; canBitConfig.propagationSegTq = CAN_BIT_1TQ; canBitConfig.phaseSeg2TimeSelect = TRUE; canBitConfig.sample3Time = TRUE; canBitConfig.syncJumpWidth = CAN_BIT_1TQ; // Set speed to 1Mbit/s CANSetSpeed(CAN1, &canBitConfig, SYSTEM_FREQ, CAN_BUS_SPEED); // 256 bytes of storage space CANAssignMemoryBuffer(CAN1, CAN1MessageFifoArea, (2*8*16)); CANConfigureChannelForTx(CAN1, CAN_CHANNEL0, 8, CAN_TX_RTR_DISABLED, CAN_LOW_MEDIUM_PRIORITY); CANConfigureChannelForRx(CAN1, CAN_CHANNEL1, 8, CAN_RX_FULL_RECEIVE); CANConfigureFilter(CAN1, CAN_FILTER0, 0x5F1, CAN_SID); CANConfigureFilterMask(CAN1, CAN_FILTER_MASK0, 0x7FF, CAN_SID, CAN_FILTER_MASK_IDE_TYPE); CANLinkFilterToChannel(CAN1, CAN_FILTER0, CAN_FILTER_MASK0, CAN_CHANNEL1); CANEnableFilter(CAN1, CAN_FILTER0, TRUE); CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); CANEnableModuleEvent(CAN1, CAN_RX_EVENT, TRUE); INTSetVectorPriority(INT_CAN_1_VECTOR, INT_PRIORITY_LEVEL_4); INTSetVectorSubPriority(INT_CAN_1_VECTOR, INT_SUB_PRIORITY_LEVEL_0); INTEnable(INT_CAN1, INT_ENABLED); CANSetOperatingMode(CAN1, CAN_NORMAL_OPERATION); while(CANGetOperatingMode(CAN1) != CAN_NORMAL_OPERATION); }
CANRxMessageBuffer* CAN1RxMsgProcess(void) { /* This function will check if a CAN * message is available in CAN1 channel 1. * If so , the message is read. Byte 0 of * the received message will indicate if * LED6 should be switched ON or OFF. */ CANRxMessageBuffer * message; if(isCAN1MsgReceived == FALSE) { /* CAN1 did not receive any message so * exit the function. Note that the * isCAN1MsgReceived flag is updated * by the CAN1 ISR. */ return 0; } /* Message was received. Reset message received flag to catch * the next message and read the message. Note that * you could also check the CANGetRxMessage function * return value for null to check if a message has * been received. */ isCAN1MsgReceived = FALSE; message = CANGetRxMessage(CAN1,CAN_CHANNEL1); /* Call the CANUpdateChannel() function to let * CAN 1 module know that the message processing * is done. Enable the receive channale not empty event * so that the CAN module generates an interrupt when * the event occurs the next time.*/ CANUpdateChannel(CAN1, CAN_CHANNEL1); CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); return message; }
s32 nu__Can__add_channel_tx(const struct nu__Can *c, CAN_CHANNEL channel, u32 channel_msg_size, CAN_TX_RTR rtr_enabled, CAN_TXCHANNEL_PRIORITY tx_priority, CAN_CHANNEL_EVENT interrupt_events) { s32 err; if ((err = go_config_mode(c)) < 0) { go_normal_mode(c); return err; } CANConfigureChannelForTx(c->module, channel, channel_msg_size, rtr_enabled, tx_priority); CANEnableChannelEvent(c->module, channel, interrupt_events, TRUE); if ((err = go_normal_mode(c)) < 0) return err; return 0; }
s32 nu__Can__add_channel_rx(const struct nu__Can *c, CAN_CHANNEL chn, u32 channel_msg_size, CAN_RX_DATA_MODE data_only, CAN_CHANNEL_EVENT interrupt_events) { s32 err; if ((err = go_config_mode(c)) < 0) { go_normal_mode(c); return err; } CANConfigureChannelForRx(c->module, chn, channel_msg_size, data_only); CANConfigureFilter(c->module, CAN_FILTER0, 0, CAN_SID); CANConfigureFilterMask(c->module, CAN_FILTER_MASK0, 0, CAN_SID, CAN_FILTER_MASK_ANY_TYPE); CANLinkFilterToChannel(c->module, CAN_FILTER0, CAN_FILTER_MASK0, CAN_CHANNEL1); CANEnableFilter(c->module, CAN_FILTER0, TRUE); CANEnableChannelEvent(c->module, chn, interrupt_events, TRUE); if ((err = go_normal_mode(c)) < 0) return err; return 0; }
CANRxMessageBuffer* CAN2RxMsgProcess(void) { /* This function will check if CAN 2 received * a message from CAN1. If so it will then read * CAN2 Channel 1. * Byte 0 of the received message will indicate * if the LED5 should be switched ON or OFF. */ CANRxMessageBuffer * message; if(isCAN2MsgReceived == FALSE) { /* CAN2 did not receive any message * so exit the function. Note that the * isCAN2MsgReceived flag is updated * by the CAN2 ISR. */ return 0; } /* Message was received. Reset isCAN2MsgReceived flag * to catch the next message. */ isCAN2MsgReceived = FALSE; message = CANGetRxMessage(CAN2,CAN_CHANNEL1); /* Call the CANUpdateChannel() function to let * the CAN module know that the message processing * is done. Enable the event so that the CAN module * generates an interrupt when the event occurs.*/ CANUpdateChannel(CAN2, CAN_CHANNEL1); CANEnableChannelEvent(CAN2, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); return message; }
void CAN1Init(void) { CAN_BIT_CONFIG canBitConfig; /* This function will intialize * CAN1 module. */ /* Step 1: Switch the CAN module * ON and switch it to Configuration * mode. Wait till the switch is * complete */ CANEnableModule(CAN1,TRUE); CANSetOperatingMode(CAN1, CAN_CONFIGURATION); while(CANGetOperatingMode(CAN1) != CAN_CONFIGURATION); /* Step 2: Configure the CAN Module Clock. The * CAN_BIT_CONFIG data structure is used * for this purpose. The propagation segment, * phase segment 1 and phase segment 2 * are configured to have 3TQ. The * CANSetSpeed function sets the baud.*/ canBitConfig.phaseSeg2Tq = CAN_BIT_3TQ; canBitConfig.phaseSeg1Tq = CAN_BIT_3TQ; canBitConfig.propagationSegTq = CAN_BIT_3TQ; canBitConfig.phaseSeg2TimeSelect = TRUE; canBitConfig.sample3Time = TRUE; canBitConfig.syncJumpWidth = CAN_BIT_2TQ; CANSetSpeed(CAN1,&canBitConfig,SYSTEM_FREQ,CAN_BUS_SPEED); /* Step 3: Assign the buffer area to the * CAN module. */ CANAssignMemoryBuffer(CAN1,CAN1MessageFifoArea,(2 * 8 * 16)); /* Step 4: Configure channel 0 for TX and size of * 8 message buffers with RTR disabled and low medium * priority. Configure channel 1 for RX and size * of 8 message buffers and receive the full message. */ CANConfigureChannelForTx(CAN1, CAN_CHANNEL0, 8, CAN_TX_RTR_DISABLED, CAN_LOW_MEDIUM_PRIORITY); CANConfigureChannelForRx(CAN1, CAN_CHANNEL1, 8, CAN_RX_FULL_RECEIVE); /* Step 5: Configure filters and mask. Configure * filter 0 to accept EID messages with ID 0x0. * Configure filter mask 0 to compare none of the ID * bits and to filter by the ID type specified in * the filter configuration. Messages accepted by * filter 0 should be stored in channel 1. */ //CANConfigureFilter (CAN1, CAN_FILTER0, 0x201, CAN_SID); CANConfigureFilter(CAN1, CAN_FILTER0, 0x0, CAN_EID); //The following Filter mask allows the program to listen for all CAN_EIDs change 0x0 //(the third parameter in CANConfigureFilterMask) to compare bits to mask CANConfigureFilterMask (CAN1, CAN_FILTER_MASK0, 0x0, CAN_EID, CAN_FILTER_MASK_IDE_TYPE); CANLinkFilterToChannel (CAN1, CAN_FILTER0, CAN_FILTER_MASK0, CAN_CHANNEL1); CANEnableFilter (CAN1, CAN_FILTER0, TRUE); /* Step 6: Enable interrupt and events. Enable the receive * channel not empty event (channel event) and the receive * channel event (module event). * The interrrupt peripheral library is used to enable * the CAN interrupt to the CPU. */ CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); CANEnableModuleEvent (CAN1, CAN_RX_EVENT, TRUE); /* These functions are from interrupt peripheral * library. */ INTSetVectorPriority(INT_CAN_1_VECTOR, INT_PRIORITY_LEVEL_4); INTSetVectorSubPriority(INT_CAN_1_VECTOR, INT_SUB_PRIORITY_LEVEL_0); INTEnable(INT_CAN1, INT_ENABLED); /* Step 7: Switch the CAN mode * to normal mode. */ CANSetOperatingMode(CAN1, CAN_NORMAL_OPERATION); while(CANGetOperatingMode(CAN1) != CAN_NORMAL_OPERATION); }
//================================================ // Configure the CAN1 interrupt handler //================================================ void __ISR(_CAN_1_VECTOR, CAN1_INT_PRIORITY) Can1InterruptHandler(void) { // Check if the source of the interrupt is RX_EVENT. This is redundant since // only this event is enabled in this example but this shows one scheme for // handling events if ((CANGetModuleEvent(CAN1) & CAN_RX_EVENT) != 0) { LED_CAN_TOGGLE; CANRxMessageBuffer *message; /* * CHANNEL 1 = SWITCHES STATES */ if (CANGetPendingEventCode(CAN1) == CAN_CHANNEL1_EVENT) { CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE); message = CANGetRxMessage(CAN1, CAN_CHANNEL1); CanSwitches_t switches; switches.bytes.low = message->data[0]; switches.bytes.high = message->data[1]; if (buttons.buttons.bits.steerWheelSw1 != switches.bits.sw1 ) { buttons.buttons.bits.steerWheelSw1 = switches.bits.sw1; buttons.chng.bits.steerWheelSw1 = 1; } if (buttons.buttons.bits.steerWheelSw4 != switches.bits.sw4 ) { buttons.buttons.bits.steerWheelSw4 = switches.bits.sw4; buttons.chng.bits.steerWheelSw4 = 1; } if (buttons.buttons.bits.steerWheelSw10 != switches.bits.sw10) { buttons.buttons.bits.steerWheelSw10 = switches.bits.sw10; buttons.chng.bits.steerWheelSw10 = 1; } LED_CAN_TOGGLE; CANUpdateChannel(CAN1, CAN_CHANNEL1); CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); } /* * CHANNEL 2 = WIND ANGLE */ if (CANGetPendingEventCode(CAN1) == CAN_CHANNEL2_EVENT) { CANEnableChannelEvent(CAN1, CAN_CHANNEL2, CAN_RX_CHANNEL_NOT_EMPTY, FALSE); message = CANGetRxMessage(CAN1, CAN_CHANNEL2); memcpy((void *) &rxWindAngle, &message->data[0], 4); oNewWindAngle = 1; CANUpdateChannel(CAN1, CAN_CHANNEL2); CANEnableChannelEvent(CAN1, CAN_CHANNEL2, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); } } // The CAN1 Interrupt flag is cleared at the end of the interrupt routine. // This is because the event source that could have caused this interrupt to // occur (CAN_RX_CHANNEL_NOT_EMPTY) is disabled. Attempting to clear the // CAN1 interrupt flag when the the CAN_RX_CHANNEL_NOT_EMPTY interrupt is // enabled will not have any effect because the base event is still present. INTClearFlag(INT_CAN1); }
/********************************************************************* * Function: void CAN2TCPBridgeTask(void) * * PreCondition: Stack is initialized() * * Input: None * * Output: None * * Side Effects: None * * Overview: None * * Note: None ********************************************************************/ void CAN2TCPBridgeTask(void) { static enum _BridgeState { SM_HOME = 0, SM_SOCKET_OBTAINED } BridgeState = SM_HOME; static TCP_SOCKET MySocket = INVALID_SOCKET; WORD wMaxPut, wMaxGet, w; BYTE *RXHeadPtrShadow, *RXTailPtrShadow; BYTE *TXHeadPtrShadow, *TXTailPtrShadow; switch(BridgeState) { case SM_HOME: #if defined(USE_REMOTE_TCP_SERVER) // Connect a socket to the remote TCP server MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, CAN2TCPBRIDGE_PORT, TCP_PURPOSE_CAN_2_TCP_BRIDGE); #else MySocket = TCPOpen(0, TCP_OPEN_SERVER, CAN2TCPBRIDGE_PORT, TCP_PURPOSE_CAN_2_TCP_BRIDGE); #endif // Abort operation if no TCP socket of type TCP_PURPOSE_CAN_2_TCP_BRIDGE is available // If this ever happens, you need to go add one to TCPIPConfig.h if(MySocket == INVALID_SOCKET) break; // Eat the first TCPWasReset() response so we don't // infinitely create and reset/destroy client mode sockets TCPWasReset(MySocket); // We have a socket now, advance to the next state BridgeState = SM_SOCKET_OBTAINED; break; case SM_SOCKET_OBTAINED: // Reset all buffers if the connection was lost if(TCPWasReset(MySocket)) { // Optionally discard anything in the CAN FIFOs RXHeadPtr = vCANRXFIFO; RXTailPtr = vCANRXFIFO; TXHeadPtr = vCANTXFIFO; TXTailPtr = vCANTXFIFO; // If we were a client socket, close the socket and attempt to reconnect #if defined(USE_REMOTE_TCP_SERVER) TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; BridgeState = SM_HOME; break; #endif } // Don't do anything if nobody is connected to us if(!TCPIsConnected(MySocket)) break; // Read FIFO pointers into a local shadow copy. Some pointers are volatile // (modified in the ISR), so we must do this safely by disabling interrupts RXTailPtrShadow = (BYTE*)RXTailPtr; TXHeadPtrShadow = (BYTE*)TXHeadPtr; CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE); CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, FALSE); RXHeadPtrShadow = (BYTE*)RXHeadPtr; TXTailPtrShadow = (BYTE*)TXTailPtr; CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); if(TXHeadPtrShadow != TXTailPtrShadow) CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, TRUE); // // Transmit pending data that has been placed into the CAN RX FIFO (in the ISR) // wMaxPut = TCPIsPutReady(MySocket); // Get TCP TX FIFO space wMaxGet = RXHeadPtrShadow - RXTailPtrShadow; // Get CAN RX FIFO byte count if(RXHeadPtrShadow < RXTailPtrShadow) wMaxGet += sizeof(vCANRXFIFO); if(wMaxPut > wMaxGet) // Calculate the lesser of the two wMaxPut = wMaxGet; if(wMaxPut) // See if we can transfer anything { // Transfer the data over. Note that a two part put // may be needed if the data spans the vCANRXFIFO // end to start address. w = vCANRXFIFO + sizeof(vCANRXFIFO) - RXTailPtrShadow; if(wMaxPut >= w) { TCPPutArray(MySocket, RXTailPtrShadow, w); RXTailPtrShadow = vCANRXFIFO; wMaxPut -= w; } TCPPutArray(MySocket, RXTailPtrShadow, wMaxPut); RXTailPtrShadow += wMaxPut; // No flush. The stack will automatically flush and do // transmit coallescing to minimize the number of TCP // packets that get sent. If you explicitly call TCPFlush() // here, latency will go down, but so will max throughput // and bandwidth efficiency. } // // Transfer received TCP data into the CAN TX FIFO for future transmission (in the ISR) // wMaxGet = TCPIsGetReady(MySocket); // Get TCP RX FIFO byte count wMaxPut = TXTailPtrShadow - TXHeadPtrShadow - 1;// Get CAN TX FIFO free space if(TXHeadPtrShadow >= TXTailPtrShadow) wMaxPut += sizeof(vCANTXFIFO); if(wMaxPut > wMaxGet) // Calculate the lesser of the two wMaxPut = wMaxGet; if(wMaxPut) // See if we can transfer anything { // Transfer the data over. Note that a two part put // may be needed if the data spans the vCANTXFIFO // end to start address. w = vCANTXFIFO + sizeof(vCANTXFIFO) - TXHeadPtrShadow; if(wMaxPut >= w) { TCPGetArray(MySocket, TXHeadPtrShadow, w); TXHeadPtrShadow = vCANTXFIFO; wMaxPut -= w; } TCPGetArray(MySocket, TXHeadPtrShadow, wMaxPut); TXHeadPtrShadow += wMaxPut; } // Write local shadowed FIFO pointers into the volatile FIFO pointers. CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE); CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, FALSE); RXTailPtr = (volatile BYTE*)RXTailPtrShadow; TXHeadPtr = (volatile BYTE*)TXHeadPtrShadow; CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE); if(TXHeadPtrShadow != TXTailPtrShadow) CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, TRUE); break; } }