void CANIntHandler(void) { unsigned long status_flags; status_flags = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); if (status_flags == CAN_INT_INTID_STATUS) { status_flags = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL); // TODO: process the error? } else if (status_flags == 1) { // Wheel A sCANMessage.pui8MsgData = (uint8_t *)&wheel_a_data; CANMessageGet(CAN0_BASE, 1, &sCANMessage, 1); } else if (status_flags == 2) { // Wheel B sCANMessage.pui8MsgData = (uint8_t *)&wheel_b_data; CANMessageGet(CAN0_BASE, 2, &sCANMessage, 1); } else if (status_flags == 3) { // Engine sCANMessage.pui8MsgData = (uint8_t *)&engine_data; CANMessageGet(CAN0_BASE, 3, &sCANMessage, 1); } else if (status_flags == 4) { // Fuel sCANMessage.pui8MsgData = (uint8_t *)&fuel_data; CANMessageGet(CAN0_BASE, 4, &sCANMessage, 1); } else { // // Spurious interrupt handling can go here. // } }
int getFormMachine(char* id) { int value = -999; // error code int rc = 0; g_MsgObjectRx.ulMsgID = (0x400); g_MsgObjectRx.ulMsgIDMask = 0x7f8; g_MsgObjectRx.ulFlags = MSG_OBJ_USE_ID_FILTER; g_MsgObjectRx.ulMsgLen = snprintf(ucBufferIn, BUFFER_LEN, "%s", id, value); g_MsgObjectRx.pucMsgData = ucBufferIn; CANMessageSet(CAN0_BASE, 1, &g_MsgObjectRx, MSG_OBJ_TYPE_RX); printf("getFormMachine Message: %s\n", g_MsgObjectRx.pucMsgData); while((CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT)) & 1 == 0) { } CANMessageGet(CAN0_BASE, 1, &g_MsgObjectRx, true); value = atoi(strstr(g_MsgObjectRx.pucMsgData) + 1); printf("getFromMachine GetMessage: %s\n", g_MsgObjectRx.pucMsgData); return rc; return value; }
int can_recv(can_msg_t *msg) { tCANMsgObject MsgObjectRx; int i; unsigned long MsgObjNr,temp; MsgObjNr = CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT); if(MsgObjNr == 0) return 1; //find which msg object receives the can frame for (i = 0; i < 31; i++) { temp = 1 << i; if (MsgObjNr & temp) break; } MsgObjectRx.pucMsgData = (unsigned char *)msg->data; CANMessageGet(CAN0_BASE, i + 1, &MsgObjectRx, 1); msg->dlc = MsgObjectRx.ulMsgLen; if (MsgObjectRx.ulFlags & MSG_OBJ_EXTENDED_ID) { msg->flag = 1; msg->id = (MsgObjectRx.ulMsgID & 0x1FFFFFFF); } else { msg->flag = 0; msg->id = (MsgObjectRx.ulMsgID & 0x000007FF); } return 0; }
//***************************************************************************** // // The CAN controller interrupt handler. // //***************************************************************************** void CAN0_Handler(void){ uint8_t data[8]; uint32_t ulIntStatus, ulIDStatus; int i; tCANMsgObject xTempMsgObject; xTempMsgObject.pucMsgData = data; ulIntStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); // cause? if(ulIntStatus & CAN_INT_INTID_STATUS){ // receive? ulIDStatus = CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT); for(i = 0; i < 64; i++){ //test every bit of the mask if( (0x1 << i) & ulIDStatus){ // if active, get data CANMessageGet(CAN0_BASE, (i+1), &xTempMsgObject, true); if(xTempMsgObject.ulMsgID == RCV_ID){ if(CAN0_Fifo_Put(data[0])==0||CAN0_Fifo_Put(data[1])==0|| CAN0_Fifo_Put(data[2])==0||CAN0_Fifo_Put(data[3])==0|| CAN0_Fifo_Put(data[4])==0||CAN0_Fifo_Put(data[5])==0|| CAN0_Fifo_Put(data[6])==0||CAN0_Fifo_Put(data[7])==0){ PacketLost++;//increment the packet lost } MailFlag = true; // new mail } } } } CANIntClear(CAN0_BASE, ulIntStatus); // acknowledge }
//***************************************************************************** // // The CAN controller interrupt handler. // //***************************************************************************** void CANIntHandler(void) { unsigned long ulStatus; // // Find the cause of the interrupt, if it is a status interrupt then just // acknowledge the interrupt by reading the status register. // ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); // // The first eight message objects make up the Transmit message FIFO. // if(ulStatus <= 8) { // // Increment the number of bytes transmitted. // g_sCAN.ulBytesTransmitted += 8; } // // The second eight message objects make up the Receive message FIFO. // else if((ulStatus > 8) && (ulStatus <= 16)) { // // Read the data out and acknowledge that it was read. // CANMessageGet(CAN0_BASE, ulStatus, &g_sCAN.MsgObjectRx, 1); // // Advance the read pointer. // g_sCAN.MsgObjectRx.pucMsgData += 8; // // Decrement the expected bytes remaining. // g_sCAN.ulBytesRemaining -= 8; } else { // // This was a status interrupt so read the current status to // clear the interrupt and return. // CANStatusGet(CAN0_BASE, CAN_STS_CONTROL); } // // Acknowledge the CAN controller interrupt has been handled. // CANIntClear(CAN0_BASE, ulStatus); }
void setup(){ Serial.begin(9600); Serial.println("DEBUG1"); SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); SysCtlPeripheralEnable(GPIO_PORTE_BASE); GPIOPinTypeCAN(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5); GPIOPinConfigure(GPIO_PE4_CAN0RX); GPIOPinConfigure(GPIO_PE5_CAN0TX); tCANMsgObject sCANMessage; uint8_t ucMsgData[8]; Serial.println("DEBUG2"); uint8_t pui8BufferIn[8]; uint8_t pui8BufferOut[8]; Serial.println("DEBUG3"); CANInit(CAN0_BASE); CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); CANEnable(CAN0_BASE); sCANMessage.ui32MsgID = 0; // CAN msg ID - 0 for any sCANMessage.ui32MsgIDMask = 0; // mask is 0 for any ID sCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; sCANMessage.ui32MsgLen = 8; // allow up to 8 bytes // // Now load the message object into the CAN peripheral. Once loaded the // CAN will receive any message on the bus, and an interrupt will occur. // Use message object 1 for receiving messages (this is not the same as // the CAN ID which can be any value in this example). // CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX); Serial.println("DEBUG5"); while((CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT) & 1) == 0) { // // Read the message out of the message object. // CANMessageGet(CAN0_BASE, 1, &sCANMessage, true); Serial.println(sCANMessage.ui32MsgLen); } Serial.println(sCANMessage.ui32MsgLen); Serial.println(sCANMessage.ui32MsgID); }
void CAN_ISR(void) { unsigned long ulStatus; ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); switch(ulStatus) { case MSG_NUM_RX: // message received CANMessageGet(CAN0_BASE, MSG_NUM_RX, &g_MsgRx, /*clear int*/ 1); NetworkRxCallback(g_ulRxData); // call user function upon receiving a message break; default: // status or other interrupt: clear it without further action CANStatusGet(CAN0_BASE, CAN_STS_CONTROL); CANIntClear(CAN0_BASE, ulStatus); } }
//***************************************************************************** // // This function handles connection with the other CAN device and also // handles incoming commands. // // /return None. // //***************************************************************************** void CANMain(void) { unsigned char pucData[8]; // // The data has been received. // if((g_ulFlags & FLAG_DATA_RECV) == 0) { return; } // // Read the data from the message object. // g_MsgObjectRx.pucMsgData = pucData; g_MsgObjectRx.ulMsgLen = 8; CANMessageGet(CAN0_BASE, MSGOBJ_NUM_DATA_RX, &g_MsgObjectRx, 1); // // Indicate that the data has been read. // g_ulFlags &= (~FLAG_DATA_RECV); switch(g_MsgObjectRx.pucMsgData[0]) { case CMD_GET_VERSION: { // // Send the Version. // g_ulFlags |= FLAG_DATA_TX_PEND; g_MsgObjectTx.pucMsgData = (unsigned char *)&g_ulVersion; g_MsgObjectTx.ulMsgLen = 4; CANMessageSet(CAN0_BASE, MSGOBJ_NUM_DATA_TX, &g_MsgObjectTx, MSG_OBJ_TYPE_TX); } } // // Clear the flag. // g_ulFlags &= ~(FLAG_DATA_RECV); }
int platform_can_recv( unsigned id, u32 *canid, u8 *idtype, u8 *len, u8 *data ) { // wait for a message if( can_rx_flag != 0 ) { can_msg_rx.pucMsgData = data; CANMessageGet(CAN0_BASE, 1, &can_msg_rx, 0); can_rx_flag = 0; *canid = ( u32 )can_msg_rx.ulMsgID; *idtype = ( can_msg_rx.ulFlags & MSG_OBJ_EXTENDED_ID )? ELUA_CAN_ID_EXT : ELUA_CAN_ID_STD; *len = can_msg_rx.ulMsgLen; return PLATFORM_OK; } else return PLATFORM_UNDERFLOW; }
//***************************************************************************** // // This function handles incoming commands. // //***************************************************************************** void ProcessCmd(void) { unsigned char pucData[8]; // // If no data has been received, then there is nothing to do. // if((g_ulFlags & FLAG_DATA_RECV) == 0) { return; } // // Receive the command. // g_MsgObjectRx.pucMsgData = pucData; g_MsgObjectRx.ulMsgLen = 8; CANMessageGet(CAN0_BASE, MSGOBJ_NUM_DATA_RX, &g_MsgObjectRx, 1); // // Clear the flag to indicate that the data has been read. // g_ulFlags &= (~FLAG_DATA_RECV); switch(g_MsgObjectRx.pucMsgData[0]) { // // This is a request for the firmware version for this application. // case CMD_GET_VERSION: { // // Send the Version. // g_ulFlags |= FLAG_DATA_TX_PEND; g_MsgObjectTx.pucMsgData = (unsigned char *)&g_ulVersion; g_MsgObjectTx.ulMsgLen = 4; CANMessageSet(CAN0_BASE, MSGOBJ_NUM_DATA_TX, &g_MsgObjectTx, MSG_OBJ_TYPE_TX); break; } } }
//***************************************************************************** // // This function sends a message to retrieve the firmware version from the // target board. // //***************************************************************************** int CANGetTargetVersion(unsigned long *pulVersion) { static unsigned char ucVerCmd = CMD_GET_VERSION; // // If there was already a previous message being transmitted then just // return. // if(g_ulFlags & FLAG_DATA_TX_PEND) { return(-1); } // // A transmit request is about to be pending. // g_ulFlags |= FLAG_DATA_TX_PEND; // // Send the button update request. // g_MsgObjectTx.pucMsgData = &ucVerCmd; g_MsgObjectTx.ulMsgLen = 1; CANMessageSet(CAN0_BASE, MSGOBJ_NUM_DATA_TX, &g_MsgObjectTx, MSG_OBJ_TYPE_TX); // // Wait for some data back from the target. // while ((g_ulFlags & FLAG_DATA_RECV) == 0) { } // // Read the data from the message object. // g_MsgObjectRx.pucMsgData = (unsigned char *)pulVersion; g_MsgObjectRx.ulMsgLen = 4; CANMessageGet(CAN0_BASE, MSGOBJ_NUM_DATA_RX, &g_MsgObjectRx, 1); return(0); }
int sendToMachine(char* id, int value) { int rc = 0; g_MsgObjectRx.ulMsgID = (0x400); g_MsgObjectRx.ulMsgIDMask = 0x7f8; g_MsgObjectRx.ulFlags = MSG_OBJ_USE_ID_FILTER; g_MsgObjectRx.ulMsgLen = snprintf(ucBufferIn, BUFFER_LEN, "%s:%d", id, value); g_MsgObjectRx.pucMsgData = ucBufferIn; CANMessageSet(CAN0_BASE, 1, &g_MsgObjectRx, MSG_OBJ_TYPE_RX); printf("setToMachine SetMessage: %s\n", g_MsgObjectRx.pucMsgData); while((CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT)) & 1 == 0) {} CANMessageGet(CAN0_BASE, 1, &g_MsgObjectRx, true); printf("setToMachine Message: %s\n", g_MsgObjectRx.pucMsgData); return rc; }
//***************************************************************************** // // The CAN controller interrupt handler. // //***************************************************************************** void CAN0_Handler(void){ uint8_t data[4]; uint32_t ulIntStatus, ulIDStatus; unsigned long temp; int i; tCANMsgObject xTempMsgObject; xTempMsgObject.pucMsgData = data; ulIntStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); // cause? if(ulIntStatus & CAN_INT_INTID_STATUS){ // receive? ulIDStatus = CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT); for(i = 0; i < 32; i++){ //test every bit of the mask if( (0x1 << i) & ulIDStatus){ // if active, get data CANMessageGet(CAN0_BASE, (i+1), &xTempMsgObject, true); if(xTempMsgObject.ulMsgID == Ping1_ID){ //temp = (data[0]<<24)&0xFF000000 + (data[1]<<16)&0x00FF0000 + (data[2]<<8)&0x0000FF00 + data[3]&0x000000FF; temp = (data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3]; Mailbox = temp; }else if(xTempMsgObject.ulMsgID == Ping2_ID){ temp = (data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3]; Mailbox2 = temp; }else if(xTempMsgObject.ulMsgID == Ping3_ID){ temp = (data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3]; Mailbox3 = temp; }else if(xTempMsgObject.ulMsgID == Ping4_ID){ temp = (data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3]; Mailbox4 = temp; }else if(xTempMsgObject.ulMsgID == Button1_ID){ button1Pressed = 1; //add thread that compensates for wall hit }else if(xTempMsgObject.ulMsgID == Button2_ID){ button2Pressed = 1; //add thread that compensates for wall hit }else if(xTempMsgObject.ulMsgID == IR_ID){ temp = (data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3]; Mailbox5 = temp; } } } } CANIntClear(CAN0_BASE, ulIntStatus); // acknowledge }
void CAN0_Handler(void) { unsigned char data[8]; unsigned long ulIntStatus, ulIDStatus; CANmsgType rxMsg; int i; tCANMsgObject xTempMsgObject; xTempMsgObject.pucMsgData = data; // rxMsg.timestamp = OS_getTime(); //timestamp the CAN message ulIntStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); if(ulIntStatus & CAN_INT_INTID_STATUS) { // receive? ulIDStatus = CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT); for(i = 0; i < 32; i++) { //test every bit of the mask if( (0x1 << i) & ulIDStatus) { // if active, get data CANMessageGet(CAN0_BASE, (i+1), &xTempMsgObject, true); rxMsg.byte0 = data[0]; rxMsg.byte1 = data[1]; rxMsg.byte2 = data[2]; rxMsg.byte3 = data[3]; rxMsg.byte4 = data[4]; rxMsg.byte5 = data[5]; rxMsg.byte6 = data[6]; rxMsg.byte7 = data[7]; rxMsg.length = xTempMsgObject.ulMsgLen; rxMsg.ID = xTempMsgObject.ulMsgID; if(CAN_RX_FIFOFifo_Put(rxMsg) == CANFIFOFAIL); CAN_Data_lost++; OS_Signal(&CANmessagesReceived); break; } } } CANIntClear(CAN0_BASE, ulIntStatus); // acknowledge }
//***************************************************************************** // // The CAN controller interrupt handler. // //***************************************************************************** void CAN0_Handler(void){ unsigned char data[4]; unsigned long ulIntStatus, ulIDStatus; int i; tCANMsgObject xTempMsgObject; xTempMsgObject.pucMsgData = data; ulIntStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); // cause? if(ulIntStatus & CAN_INT_INTID_STATUS){ // receive? ulIDStatus = CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT); for(i = 0; i < 32; i++){ //test every bit of the mask if( (0x1 << i) & ulIDStatus){ // if active, get data CANMessageGet(CAN0_BASE, (i+1), &xTempMsgObject, true); if(xTempMsgObject.ulMsgID == RCV_ID){ RCVData[0] = data[0]; RCVData[1] = data[1]; RCVData[2] = data[2]; RCVData[3] = data[3]; MailFlag = true; // new mail } } } } CANIntClear(CAN0_BASE, ulIntStatus); // acknowledge }
//***************************************************************************** // // Configure the CAN and enter a loop to receive CAN messages. // //***************************************************************************** int main(void) { tCANMsgObject sCANMessage; uint8_t pui8MsgData[8]; // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal used on your board. // SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for CAN operation. // InitConsole(); // // For this example CAN0 is used with RX and TX pins on port B4 and B5. // The actual port and pins used may be different on your part, consult // the data sheet for more information. // GPIO port B needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Configure the GPIO pin muxing to select CAN0 functions for these pins. // This step selects which alternate function is available for these pins. // This is necessary if your part supports GPIO pin function muxing. // Consult the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using // GPIOPinConfigure(GPIO_PB4_CAN0RX); GPIOPinConfigure(GPIO_PB5_CAN0TX); // // Enable the alternate function on the GPIO pins. The above step selects // which alternate function is available. This step actually enables the // alternate function instead of GPIO for these pins. // TODO: change this to match the port/pin you are using // GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5); // // The GPIO port and pins have been set up for CAN. The CAN peripheral // must be enabled. // SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // // Initialize the CAN controller // CANInit(CAN0_BASE); // // Set up the bit rate for the CAN bus. This function sets up the CAN // bus timing for a nominal configuration. You can achieve more control // over the CAN bus timing by using the function CANBitTimingSet() instead // of this one, if needed. // In this example, the CAN bus is set to 500 kHz. In the function below, // the call to SysCtlClockGet() is used to determine the clock rate that // is used for clocking the CAN peripheral. This can be replaced with a // fixed value if you know the value of the system clock, saving the extra // function call. For some parts, the CAN peripheral is clocked by a fixed // 8 MHz regardless of the system clock in which case the call to // SysCtlClockGet() should be replaced with 8000000. Consult the data // sheet for more information about CAN peripheral clocking. // CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); // // Enable interrupts on the CAN peripheral. This example uses static // allocation of interrupt handlers which means the name of the handler // is in the vector table of startup code. If you want to use dynamic // allocation of the vector table, then you must also call CANIntRegister() // here. // // CANIntRegister(CAN0_BASE, CAN0_IRQHandler); // if using dynamic vectors // CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // // Enable the CAN interrupt on the processor (NVIC). // IntEnable(INT_CAN0); // // Enable the CAN for operation. // CANEnable(CAN0_BASE); // // Initialize a message object to receive CAN messages with ID 0x1001. // The expected ID must be set along with the mask to indicate that all // bits in the ID must match. // sCANMessage.ui32MsgID = 0x1001; sCANMessage.ui32MsgIDMask = 0xfffff; sCANMessage.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER | MSG_OBJ_EXTENDED_ID); sCANMessage.ui32MsgLen = 8; // // Now load the message object into the CAN peripheral message object 1. // Once loaded the CAN will receive any messages with this CAN ID into // this message object, and an interrupt will occur. // CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX); // // Change the ID to 0x2001, and load into message object 2 which will be // used for receiving any CAN messages with this ID. Since only the CAN // ID field changes, we don't need to reload all the other fields. // sCANMessage.ui32MsgID = 0x2001; CANMessageSet(CAN0_BASE, 2, &sCANMessage, MSG_OBJ_TYPE_RX); // // Change the ID to 0x3001, and load into message object 3 which will be // used for receiving any CAN messages with this ID. Since only the CAN // ID field changes, we don't need to reload all the other fields. // sCANMessage.ui32MsgID = 0x3001; CANMessageSet(CAN0_BASE, 3, &sCANMessage, MSG_OBJ_TYPE_RX); // // Enter loop to process received messages. This loop just checks flags // for each of the 3 expected messages. The flags are set by the interrupt // handler, and if set this loop reads out the message and displays the // contents to the console. This is not a robust method for processing // incoming CAN data and can only handle one messages at a time per message // object. If many messages are being received close together using the // same message object, then some messages may be dropped. In a real // application, some other method should be used for queuing received // messages in a way to ensure they are not lost. You can also make use // of CAN FIFO mode which will allow messages to be buffered before they // are processed. // for(;;) { // // If the flag for message object 1 is set, that means that the RX // interrupt occurred and there is a message ready to be read from // this CAN message object. // if(g_bRXFlag1) { // // Reuse the same message object that was used earlier to configure // the CAN for receiving messages. A buffer for storing the // received data must also be provided, so set the buffer pointer // within the message object. This same buffer is used for all // messages in this example, but your application could set a // different buffer each time a message is read in order to store // different messages in different buffers. // sCANMessage.pui8MsgData = pui8MsgData; // // Read the message from the CAN. Message object number 1 is used // (which is not the same thing as CAN ID). The interrupt clearing // flag is not set because this interrupt was already cleared in // the interrupt handler. // CANMessageGet(CAN0_BASE, 1, &sCANMessage, 0); // // Clear the pending message flag so that the interrupt handler can // set it again when the next message arrives. // g_bRXFlag1 = 0; // // Print information about the message just received. // PrintCANMessageInfo(&sCANMessage, 1); } // // Check for message received on message object 2. If so then // read message and print information. // if(g_bRXFlag2) { sCANMessage.pui8MsgData = pui8MsgData; CANMessageGet(CAN0_BASE, 2, &sCANMessage, 0); g_bRXFlag2 = 0; PrintCANMessageInfo(&sCANMessage, 2); } // // Check for message received on message object 3. If so then // read message and print information. // if(g_bRXFlag3) { sCANMessage.pui8MsgData = pui8MsgData; CANMessageGet(CAN0_BASE, 3, &sCANMessage, 0); g_bRXFlag3 = 0; PrintCANMessageInfo(&sCANMessage, 3); } } // // Return no errors // return(0); }
//***************************************************************************** // // Set up the system, initialize the UART, Graphics, and CAN. Then poll the // UART for data. If there is any data send it, if there is any thing received // print it out to the UART. If there are errors call the error handling // function. // //***************************************************************************** int main(void) { // // Enable lazy stacking for interrupt handlers. This allows floating-point // instructions to be used within interrupt handlers, but at the expense of // extra stack usage. // ROM_FPULazyStackingEnable(); // // Set the clocking to run directly from the crystal. // ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); // // Initialize the UART // ConfigureUART(); // // Initialize the graphical display // InitGraphics(); // // Initialize CAN0 // InitCAN0(); // // Print welcome message // UARTprintf("\nCAN Example App\n"); UARTprintf("Type something to see it show up on the other terminal: \n\n"); // // Poll UART for data, transmit across CAN when something is entered // while(1) { // // If the flag is set, that means that the RX interrupt occurred and // there is a message ready to be read from the CAN // if(g_bRXFlag) { // // Reuse the same message object that was used earlier to configure // the CAN for receiving messages. A buffer for storing the // received data must also be provided, so set the buffer pointer // within the message object. // g_sCAN0RxMessage.pui8MsgData = (uint8_t *) &g_ui8RXMsgData; // // Read the message from the CAN. Message object RXOBJECT is used // (which is not the same thing as CAN ID). The interrupt clearing // flag is not set because this interrupt was already cleared in // the interrupt handler. // CANMessageGet(CAN0_BASE, RXOBJECT, &g_sCAN0RxMessage, 0); // // Clear the pending message flag so that the interrupt handler can // set it again when the next message arrives. // g_bRXFlag = 0; // // Check to see if there is an indication that some messages were // lost. // if(g_sCAN0RxMessage.ui32Flags & MSG_OBJ_DATA_LOST) { UARTprintf("\nCAN message loss detected\n"); } // // Print the received character to the UART terminal // UARTprintf("%c", g_ui8RXMsgData); // // Print the received character to the display, // clear line with spaces // GrStringDrawCentered(&g_sContext, "RX Data", -1, GrContextDpyWidthGet(&g_sContext) / 2, SCREENLINE2, 0); GrStringDrawCentered(&g_sContext, (const char *) &g_ui8RXMsgData, 1, GrContextDpyWidthGet(&g_sContext) / 2, SCREENLINE3, true); GrFlush(&g_sContext); } else { // // Error Handling // if(g_ui32ErrFlag != 0) { CANErrorHandler(); } // // See if there is something new to transmit // while(ROM_UARTCharsAvail(UART0_BASE)) { // // Read the next character from the UART terminal // g_ui8TXMsgData = ROM_UARTCharGetNonBlocking(UART0_BASE); // // Write the character to the display // clear line with spaces // GrStringDrawCentered(&g_sContext, "TX Data", -1, GrContextDpyWidthGet(&g_sContext) / 2, SCREENLINE4, true); GrStringDrawCentered(&g_sContext, (const char *)&g_ui8TXMsgData, 1, GrContextDpyWidthGet(&g_sContext) / 2, SCREENLINE5, true); GrFlush(&g_sContext); // // Send the CAN message using object number TXOBJECT (not the // same thing as CAN ID, which is also TXOBJECT in this // example). This function will cause the message to be // transmitted right away. // CANMessageSet(CAN0_BASE, TXOBJECT, &g_sCAN0TxMessage, MSG_OBJ_TYPE_TX); } } } }
//***************************************************************************** // // This function is the interrupt handler for the CAN peripheral. It checks // for the cause of the interrupt, and maintains a count of all messages that // have been transmitted. // //***************************************************************************** extern "C" void CAN0IntHandler(void) { unsigned long ulStatus; // Read the CAN interrupt status to find the cause of the interrupt ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); // // If the cause is a controller status interrupt, then get the status // if (ulStatus == CAN_INT_INTID_STATUS) { // // Read the controller status. This will return a field of status // error bits that can indicate various errors. Error processing // is not done in this example for simplicity. Refer to the // API documentation for details about the error status bits. // The act of reading this status will clear the interrupt. If the // CAN peripheral is not connected to a CAN bus with other CAN devices // present, then errors will occur and will be indicated in the // controller status. // ulStatus = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL); if (ulStatus == CAN_STATUS_TXOK) { } else if (ulStatus == CAN_STATUS_RXOK) { } else /* CAN_STS_CONTROL - the main controller status CAN_STS_TXREQUEST - bit mask of objects pending transmissio CAN_STS_NEWDAT - bit mask of objects with new data CAN_STS_MSGVAL - bit mask of objects with valid configuration CAN_STATUS_BUS_OFF - controller is in bus-off condition CAN_STATUS_EWARN - an error counter has reached a limit of at least 96 CAN_STATUS_EPASS - CAN controller is in the error passive state CAN_STATUS_RXOK - a message was received successfully (independent of any mes-sage filtering). CAN_STATUS_TXOK - a message was successfully transmitted CAN_STATUS_LEC_MSK - mask of last error code bits (3 bits) CAN_STATUS_LEC_NONE - no error CAN_STATUS_LEC_STUFF - stuffing error detected CAN_STATUS_LEC_FORM - a format error occurred in the fixed format part of amessage CAN_STATUS_LEC_ACK - a transmitted message was not acknowledged CAN_STATUS_LEC_BIT1 - dominant level detected when trying to send in recessive mode CAN_STATUS_LEC_BIT0 - recessive level detected when trying to send in dominant mode CAN_STATUS_LEC_CRC - CRC error in received message */ can0._countErr++; } // // Check if the cause is message object 1, which what we are using for // sending messages. // else if (ulStatus < can0._tableIdx + 1 && ulStatus > 0) { uint32_t idx = ulStatus - 1; if (can0._table[idx].mode == CAN::RECV) { tCANMsgObject* msgObj = (can0._table[idx].msgObject); CANIntClear(CAN0_BASE, idx + 1); CANMessageGet(CAN0_BASE, idx + 1, msgObj, true); can0._countRxd++; CANListener* listener = can0._table[idx].listener; listener->recv(msgObj->ulMsgID, msgObj->ulMsgLen, msgObj->pucMsgData); CANMessageSet(CAN0_BASE, ulStatus, msgObj, MSG_OBJ_TYPE_RX); // CANMessageSet(CAN0_BASE, ulStatus, msgObj, MSG_OBJ_TYPE_TX); // reload } else if (can0._table[idx].mode == CAN::SEND) { CANListener* listener = can0._table[idx].listener; tCANMsgObject* msgObj = (can0._table[idx].msgObject); CANIntClear(CAN0_BASE, idx + 1); can0._countTxd++; listener->sendDone(msgObj->ulMsgID, E_OK); } } else { // // Spurious interrupt handling can go here. // CANIntClear(CAN0_BASE, ulStatus); } }
//***************************************************************************** // // The CAN controller Interrupt handler. // //***************************************************************************** void CANHandler(void) { unsigned long ulStatus; // // Find the cause of the interrupt, if it is a status interrupt then just // acknowledge the interrupt by reading the status register. // ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); switch(ulStatus) { // // Let the forground loop handle sending this, just set a flag to // indicate that the data should be sent. // case MSGOBJ_NUM_BUTTON: { // // Read the Button Message. // CANMessageGet(CAN0_BASE, MSGOBJ_NUM_BUTTON, &g_MsgObjectButton, 1); // // Only respond to buttons being release. // if(g_MsgObjectButton.pucMsgData[0] == EVENT_BUTTON_RELEASED) { // // Check if the up button was released. // if(g_MsgObjectButton.pucMsgData[1] == TARGET_BUTTON_UP) { // // Adjust the volume up by 10. // AudioVolumeUp(10); } // // Check if the down button was released. // if(g_MsgObjectButton.pucMsgData[1] == TARGET_BUTTON_DN) { // // Adjust the volume down by 10. // AudioVolumeDown(10); } } break; } // // When the LED message object interrupts, just clear the flag so that // more LED messages are allowed to transfer. // case MSGOBJ_NUM_LED: { g_ulFlags &= (~FLAG_LED_TX_PEND); break; } // // When the transmit data message object interrupts, clear the // flag so that more data can be trasferred. // case MSGOBJ_NUM_DATA_TX: { g_ulFlags &= (~FLAG_DATA_TX_PEND); break; } // // When a receive data message object interrupts, set the flag to // indicate that new data is ready. // case MSGOBJ_NUM_DATA_RX: { g_ulFlags |= FLAG_DATA_RECV; break; } // // This was a status interrupt so read the current status to // clear the interrupt and return. // default: { // // Read the controller status to acknowledge this interrupt. // CANStatusGet(CAN0_BASE, CAN_STS_CONTROL); // // If there was a LED transmission pending, then stop it and // clear the flag. // if(g_ulFlags & FLAG_LED_TX_PEND) { // // Disable this message object until we retry it later. // CANMessageClear(CAN0_BASE, MSGOBJ_NUM_LED); // // Clear the transmit pending flag. // g_ulFlags &= (~FLAG_LED_TX_PEND); } // // If there was a Data transmission pending, then stop it and // clear the flag. // if(g_ulFlags & FLAG_DATA_TX_PEND) { // // Disable this message object until we retry it later. // CANMessageClear(CAN0_BASE, MSGOBJ_NUM_DATA_TX); // // Clear the transmit pending flag. // g_ulFlags &= (~FLAG_DATA_TX_PEND); } return; } } // // Acknowledge the CAN controller interrupt has been handled. // CANIntClear(CAN0_BASE, ulStatus); }
//***************************************************************************** // // Configure the CAN and enter a loop to receive CAN messages. // //***************************************************************************** int main(void) { #if defined(TARGET_IS_TM4C129_RA0) || \ defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) uint32_t ui32SysClock; #endif tCANMsgObject sCANMessage; uint8_t pui8MsgData[8]; // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal used on your board. // #if defined(TARGET_IS_TM4C129_RA0) || \ defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_OSC) 25000000); #else SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); #endif // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for CAN operation. // InitConsole(); // // For this example CAN0 is used with RX and TX pins on port B4 and B5. // The actual port and pins used may be different on your part, consult // the data sheet for more information. // GPIO port B needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Configure the GPIO pin muxing to select CAN0 functions for these pins. // This step selects which alternate function is available for these pins. // This is necessary if your part supports GPIO pin function muxing. // Consult the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using // GPIOPinConfigure(GPIO_PB4_CAN0RX); GPIOPinConfigure(GPIO_PB5_CAN0TX); // // Enable the alternate function on the GPIO pins. The above step selects // which alternate function is available. This step actually enables the // alternate function instead of GPIO for these pins. // TODO: change this to match the port/pin you are using // GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5); // // The GPIO port and pins have been set up for CAN. The CAN peripheral // must be enabled. // SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // // Initialize the CAN controller // CANInit(CAN0_BASE); // // Set up the bit rate for the CAN bus. This function sets up the CAN // bus timing for a nominal configuration. You can achieve more control // over the CAN bus timing by using the function CANBitTimingSet() instead // of this one, if needed. // In this example, the CAN bus is set to 500 kHz. In the function below, // the call to SysCtlClockGet() or ui32SysClock is used to determine the // clock rate that is used for clocking the CAN peripheral. This can be // replaced with a fixed value if you know the value of the system clock, // saving the extra function call. For some parts, the CAN peripheral is // clocked by a fixed 8 MHz regardless of the system clock in which case // the call to SysCtlClockGet() or ui32SysClock should be replaced with // 8000000. Consult the data sheet for more information about CAN // peripheral clocking. // #if defined(TARGET_IS_TM4C129_RA0) || \ defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) CANBitRateSet(CAN0_BASE, ui32SysClock, 500000); #else CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); #endif // // Enable interrupts on the CAN peripheral. This example uses static // allocation of interrupt handlers which means the name of the handler // is in the vector table of startup code. If you want to use dynamic // allocation of the vector table, then you must also call CANIntRegister() // here. // // CANIntRegister(CAN0_BASE, CANIntHandler); // if using dynamic vectors // CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // // Enable the CAN interrupt on the processor (NVIC). // IntEnable(INT_CAN0); // // Enable the CAN for operation. // CANEnable(CAN0_BASE); // // Initialize a message object to be used for receiving CAN messages with // any CAN ID. In order to receive any CAN ID, the ID and mask must both // be set to 0, and the ID filter enabled. // sCANMessage.ui32MsgID = 0; sCANMessage.ui32MsgIDMask = 0; sCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; sCANMessage.ui32MsgLen = 8; // // Now load the message object into the CAN peripheral. Once loaded the // CAN will receive any message on the bus, and an interrupt will occur. // Use message object 1 for receiving messages (this is not the same as // the CAN ID which can be any value in this example). // CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX); // // Enter loop to process received messages. This loop just checks a flag // that is set by the interrupt handler, and if set it reads out the // message and displays the contents. This is not a robust method for // processing incoming CAN data and can only handle one messages at a time. // If many messages are being received close together, then some messages // may be dropped. In a real application, some other method should be used // for queuing received messages in a way to ensure they are not lost. You // can also make use of CAN FIFO mode which will allow messages to be // buffered before they are processed. // for(;;) { unsigned int uIdx; // // If the flag is set, that means that the RX interrupt occurred and // there is a message ready to be read from the CAN // if(g_bRXFlag) { // // Reuse the same message object that was used earlier to configure // the CAN for receiving messages. A buffer for storing the // received data must also be provided, so set the buffer pointer // within the message object. // sCANMessage.pui8MsgData = pui8MsgData; // // Read the message from the CAN. Message object number 1 is used // (which is not the same thing as CAN ID). The interrupt clearing // flag is not set because this interrupt was already cleared in // the interrupt handler. // CANMessageGet(CAN0_BASE, 1, &sCANMessage, 0); // // Clear the pending message flag so that the interrupt handler can // set it again when the next message arrives. // g_bRXFlag = 0; // // Check to see if there is an indication that some messages were // lost. // if(sCANMessage.ui32Flags & MSG_OBJ_DATA_LOST) { UARTprintf("CAN message loss detected\n"); } // // Print out the contents of the message that was received. // UARTprintf("Msg ID=0x%08X len=%u data=0x", sCANMessage.ui32MsgID, sCANMessage.ui32MsgLen); for(uIdx = 0; uIdx < sCANMessage.ui32MsgLen; uIdx++) { UARTprintf("%02X ", pui8MsgData[uIdx]); } UARTprintf("total count=%u\n", g_ui32MsgCount); } } // // Return no errors // return(0); }
//***************************************************************************** // // The CAN controller interrupt handler. // // /return None. // //***************************************************************************** void CANHandler(void) { unsigned long ulStatus; // // Find the cause of the interrupt, if it is a status interrupt then just // acknowledge the interrupt by reading the status register. // ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); switch(ulStatus) { // // Let the forground loop handle sending this, just set a flag to // indicate that the data should be sent. // case MSGOBJ_NUM_BUTTON: { // // Indicate a pending button transmission is complete. // g_ulFlags &= (~FLAG_BUTTON_PEND); break; } case MSGOBJ_NUM_LED: { // // Read the new LED level and let the foreground handle it. // CANMessageGet(CAN0_BASE, MSGOBJ_NUM_LED, &g_MsgObjectLED, 1); // // Limit the LED Level to MAX_LED_BRIGHTNESS. // if((g_ucLEDLevel & LED_FLASH_VALUE_MASK) > MAX_LED_BRIGHTNESS) { g_ucLEDLevel = MAX_LED_BRIGHTNESS | (g_ucLEDLevel & LED_FLASH_ONCE); } // // Indicate that the LED needs to be updated. // g_ulFlags |= FLAG_UPDATE_LED; break; } // // The data transmit message object has been sent successfully. // case MSGOBJ_NUM_DATA_TX: { // // Clear the data transmit pending flag. // g_ulFlags &= (~FLAG_DATA_TX_PEND); break; } // // The data receive message object has received some data. // case MSGOBJ_NUM_DATA_RX: { // // Indicate that the data message object has new data. // g_ulFlags |= FLAG_DATA_RECV; break; } // // This was a status interrupt so read the current status to // clear the interrupt and return. // default: { CANStatusGet(CAN0_BASE, CAN_STS_CONTROL); return; } } // // Acknowledge the CAN controller interrupt has been handled. // CANIntClear(CAN0_BASE, ulStatus); }