Part Number: LAUNCHXL-F28379D
Other Parts Discussed in Thread: C2000WARE
Hi,
I am trying to implement two way CAN communication between 2 Launchpads F28379D using the can simple transmit and receive examples from C2000Ware.
I am able to transmit and receive data on both nodes.
However, the transmitting node's ISR is getting triggered after CAN_sendMessage function is executed.
Below is my Transmit side main code. Could you please check if I am enabling anything that is causing a CAN interrupt after transmission on Transmit side?
//
// Main
//
void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();
//
// Initialize GPIO and configure GPIO pins for CANTX/CANRX
// on module A
//
Device_initGPIO();
//
// Configure GPIO pins for CANTX/CANRX
//
GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXB);
GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXB);
//
// Initialize the CAN controllers
//
CAN_initModule(CANB_BASE);
//
// Set up the CAN bus bit rate to 500kHz for each module
// Refer to the Driver Library User Guide for information on how to set
// tighter timing control. Additionally, consult the device data sheet
// for more information about the CAN module clocking.
//
CAN_setBitRate(CANB_BASE, DEVICE_SYSCLK_FREQ, 500000, 16);
//******************************ADDED FOR INTERRUPTS********************************
//
// Enable interrupts on the CAN peripheral.
// Enables Interrupt line 0, Error & Status Change interrupts in CAN_CTL
// register.
//
CAN_enableInterrupt(CANB_BASE, CAN_INT_IE0 | CAN_INT_ERROR |
CAN_INT_STATUS);
//
// Initialize PIE and clear PIE registers. Disables CPU interrupts.
//
Interrupt_initModule();
//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
//
Interrupt_initVectorTable();
//
// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
//
EINT;
ERTM;
//
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
// This registers the interrupt handler in PIE vector table.
//
Interrupt_register(INT_CANB0, &canISR);
//
// Enable the CAN interrupt signal
//
Interrupt_enable(INT_CANB0);
CAN_enableGlobalInterrupt(CANB_BASE, CAN_GLOBAL_INT_CANINT0);
//
// Configure GPIO pins for initiating CAN Transmit
//
//PinMUX
GPIO_setPinConfig(GPIO_63_GPIO63);
GPIO_setDirectionMode(gpioButton01,GPIO_DIR_MODE_IN);
GPIO_setPadConfig(gpioButton01, GPIO_PIN_TYPE_PULLUP);
GPIO_setMasterCore(gpioButton01, GPIO_CORE_CPU1);
GPIO_setQualificationMode(gpioButton01,GPIO_QUAL_SYNC);
GPIO_SetupXINT1Gpio(gpioButton01);
GPIO_setInterruptType(GPIO_INT_XINT1, GPIO_INT_TYPE_FALLING_EDGE);
GPIO_setInterruptPin(gpioButton01, GPIO_INT_XINT1);
GPIO_enableInterrupt(GPIO_INT_XINT1);
Interrupt_register(INT_XINT1, &gpio63InterruptHandler);
Interrupt_enable(INT_XINT1);
//
// Enables CPU interrupts
//
Interrupt_enableMaster();
//******************************ADDED END********************************
//
// Initialize the transmit message object used for sending CAN messages.
// Message Object Parameters:
// CAN Module: A
// Message Object ID Number: 1
// Message Identifier: 0x95555555
// Message Frame: Extended
// Message Type: Transmit
// Message ID Mask: 0x0
// Message Object Flags: None
// Message Data Length: 4 Bytes
//
CAN_setupMessageObject(CANB_BASE, TX_MSG_OBJ_ID, 0x95555555,
CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_TX, 0,
CAN_MSG_OBJ_NO_FLAGS, MSG_DATA_LENGTH);
//
// Initialize the receive message object used for receiving CAN messages.
// Message Object Parameters:
// CAN Module: A
// Message Object ID Number: 1
// Message Identifier: 0x1
// Message Frame: Standard
// Message Type: Receive
// Message ID Mask: 0x0
// Message Object Flags: None
// Message Data Length: "Don't care" for a Receive mailbox
//
CAN_setupMessageObject(CANB_BASE, RX_MSG_OBJ_ID, 0x12345678,
CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0,
CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH);
//
// Initialize the transmit message object data buffer to be sent
//
txMsgData[0] = 0x01;
txMsgData[1] = 0x23;
txMsgData[2] = 0x45;
txMsgData[3] = 0x67;
txMsgData[4] = 0x89;
txMsgData[5] = 0xAB;
txMsgData[6] = 0xCD;
txMsgData[7] = 0xEF;
//
// Start CAN module A operations
//
CAN_startModule(CANB_BASE);
//
// Transmit messages from CAN-A
//
while(1)
{
//
// Check the error flag to see if errors occurred
//
if(errorFlag)
{
Example_Fail = 1;
asm(" ESTOP0");
}
}
//
// Stop application
//
asm(" ESTOP0");
}
and here is the CAN ISR
__interrupt void gpio63InterruptHandler(void)
{
CAN_sendMessage(CANB_BASE, TX_MSG_OBJ_ID, MSG_DATA_LENGTH, txMsgData);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}
//
// CAN B ISR - The interrupt service routine is called when an interrupt is
// triggered on CAN module B. It will be executed twice for every
// frame received.
// First time for status-change; second time for Mailbox receive.
//
__interrupt void canISR(void)
{
uint32_t status;
//
// Read the CAN-B interrupt status (in the CAN_INT register) to find the
// cause of the interrupt
//
status = CAN_getInterruptCause(CANB_BASE);
//
// If the cause is a controller status interrupt, then get the status.
// During first iteration of every ISR execution, status = 0x8000,
// which simply means CAN_ES != 0x07.
//
if(status == CAN_INT_INT0ID_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.
//
status = CAN_getStatus(CANB_BASE); // Return CAN_ES value.
//
// Now status = 0x00000010, indicating RxOK.
//
//
// Check to see if an error occurred.
//
if(((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK) &&
((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
{
//
// Set a flag to indicate some errors may have occurred.
//
errorFlag = 1;
}
}
//
// Check if the cause is the CAN-B receive message object 1. Will be skipped
// in the first iteration of every ISR execution
//
else if(status == RX_MSG_OBJ_ID)
{
//
// Get the received message
//
CAN_readMessage(CANB_BASE, RX_MSG_OBJ_ID, rxMsgData);
//
// Getting to this point means that the RX interrupt occurred on
// message object 1, and the message RX is complete. Clear the
// message object interrupt.
//
CAN_clearInterruptStatus(CANB_BASE, RX_MSG_OBJ_ID);
//
// Increment a counter to keep track of how many messages have been
// received. In a real application this could be used to set flags to
// indicate when a message is received.
//
rxMsgCount++;
//
// Since the message was received, clear any error flags.
//
errorFlag = 0;
}
//
// If something unexpected caused the interrupt, this would handle it.
//
else
{
//
// Spurious interrupt handling can go here.
//
}
//
// Clear the global interrupt flag for the CAN interrupt line
//
CAN_clearGlobalInterruptStatus(CANB_BASE, CAN_GLOBAL_INT_CANINT0);
//
// Acknowledge this interrupt located in group 9
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
Regards,
Rashmitha