Other Parts Discussed in Thread: LAUNCHXL-F28379D, C2000WARE
Title: how to correctly setup both CAN lines to work with interrupt
Part: TMS320F28379DZWTT
Question:
I’ve been working with the launchpad LAUNCHXL-F28379D and I am trying to work with both CAN lines on my project.
CANB is correctly setup with GPIO 17 and 12, CANA is connected to an external transceiver.
I followed the C2000Ware example to setup a ISR to go off whenever a CAN message is received.
CANB works perfectly.
The issue with CANA is that I am able to correctly send messagges but it doesn’t recevie.
With a CAN sniffer I am able to send messages to the F28379D but my guess is that the ISR never start.
I think there is something wrong with the interrupt lines, but I cant figure out what.
Below is my code:
<code snippet>
#include "can_management.h"
void canSetup()
{
//
// Configure GPIO pins for CANTX/CANRX
//
GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXB);
GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXB);
GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);
//
// Initialize the CAN controller
//
CAN_initModule(CANB_BASE);
CAN_initModule(CANA_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, 1000000, 10);
CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 1000000, 10);
//
//FROM can_ex2_loopback_interrupts.c example ---------------------------------------------
//
//
//
// 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);
CAN_enableInterrupt(CANA_BASE, CAN_INT_IE1 | CAN_INT_ERROR |
CAN_INT_STATUS);
//
// 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_B);
Interrupt_register(INT_CANA1, &canISR_A);
//
// Enable the CAN interrupt signal
//
Interrupt_enable(INT_CANB0);
CAN_enableGlobalInterrupt(CANB_BASE, CAN_GLOBAL_INT_CANINT0);
Interrupt_enable(INT_CANA1);
CAN_enableGlobalInterrupt(CANA_BASE, CAN_GLOBAL_INT_CANINT1);
//
// Initialize the receive message object used for receiving CAN messages.
int i;
for (i = 0; i<4; i++)
{
CAN_setupMessageObject(CANB_BASE, OBJ_ID_FROM_AMK, AMK_VAL_1_IDS[i], //AMK actual values 1
CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x1FFFFFF0,
CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER, MSG_DATA_LENGTH);
CAN_setupMessageObject(CANB_BASE, OBJ_ID_FROM_AMK, AMK_VAL_2_IDS[i], //AMK actual values 2
CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x1FFFFFF0,
CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER, MSG_DATA_LENGTH);
CAN_setupMessageObject(CANB_BASE, (14 + i), AMK_SETPOINTS_IDS[i], //AMK setpoints
CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0,
CAN_MSG_OBJ_NO_FLAGS, sizeof(CAN_AMK_SET_POINT[i]));
}
CAN_setupMessageObject(CANB_BASE, OBJ_ID_FROM_SENDYNE, SENDYNE_ID, //SENDYNE
CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x0,
CAN_MSG_OBJ_RX_INT_ENABLE , MSG_DATA_LENGTH);
CAN_setupMessageObject(CANA_BASE, 1, 0x120,
CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x0,
CAN_MSG_OBJ_RX_INT_ENABLE , MSG_DATA_LENGTH);
CAN_setupMessageObject(CANA_BASE, 2, 0x100,
CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0,
CAN_MSG_OBJ_NO_FLAGS, 8);
//
// Start CAN module operations
//
CAN_startModule(CANB_BASE);
CAN_startModule(CANA_BASE);
}
//
// CAN ISR - The interrupt service routine called when a CAN interrupt is
// triggered. It checks for the cause of the interrupt, and
// maintains a count of all messages that have been transmitted.
//
__interrupt void
canISR_B(void)
{
uint32_t status;
//
// Read the CAN interrupt status to find the cause of the interrupt
//
status = CAN_getInterruptCause(CANB_BASE);
//
// If the cause is a controller status interrupt, then get the status
//
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);
//
// Check to see if an error occurred.
//
if(((status & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 7) &&
((status & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 0))
{
//
// Set a flag to indicate some errors may have occurred.
//
errorFlag = 1;
}
}
//
// Check if the cause is the receive message object 2
//
else if(status == OBJ_ID_FROM_AMK)
{
//
// Get the received message
//
CAN_readMessage(CANB_BASE, OBJ_ID_FROM_AMK, AMK_Values_temp);
id = getMessageID(CANB_BASE,OBJ_ID_FROM_AMK);
if (getAMKValNumber(id) == 1)
{
GPIO_togglePin(DEVICE_GPIO_PIN_LED2);
rxBMsgCount++;
read_AMK_Values1(AMK_Values_temp, getMotorIndex(id));
}
else if (getAMKValNumber(id) == 2)
{
GPIO_togglePin(DEVICE_GPIO_PIN_LED2);
rxBMsgCount++;
read_AMK_Values2(AMK_Values_temp, getMotorIndex(id));
}
//
// Getting to this point means that the RX interrupt occurred on
// message object 2, and the message RX is complete. Clear the
// message object interrupt.
//
CAN_clearInterruptStatus(CANB_BASE, OBJ_ID_FROM_AMK);
//
// 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.
//
//
// Since the message was received, clear any error flags.
//
errorFlag = 0;
} else if (status == OBJ_ID_FROM_SENDYNE)
{
//
// Get the received message
//
CAN_readMessage(CANB_BASE, OBJ_ID_FROM_SENDYNE, (uint16_t *) CAN_SENDYNE_ACT_VALUES);
id = getMessageID(CANB_BASE, OBJ_ID_FROM_SENDYNE);
read_SENDYNE_Message(CAN_SENDYNE_ACT_VALUES);
GPIO_togglePin(DEVICE_GPIO_PIN_LED2);
rxBMsgCount++;
CAN_clearInterruptStatus(CANB_BASE, OBJ_ID_FROM_SENDYNE);
}
//
// 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);
}
__interrupt void
canISR_A(void)
{
uint32_t status;
//
// Read the CAN interrupt status to find the cause of the interrupt
//
status = CAN_getInterruptCause(CANA_BASE);
//
// If the cause is a controller status interrupt, then get the status
//
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(CANA_BASE);
//
// Check to see if an error occurred.
//
if(((status & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 7) &&
((status & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 0))
{
//
// Set a flag to indicate some errors may have occurred.
//
errorFlag = 1;
}
}
//
// Check if the cause is the receive message object 2
//
else if(status == 1)
{
//
// Get the received message
//
CAN_readMessage(CANA_BASE, 1, RX_A_temp);
GPIO_togglePin(DEVICE_GPIO_PIN_LED2);
//
// Getting to this point means that the RX interrupt occurred on
// message object 2, and the message RX is complete. Clear the
// message object interrupt.
//
CAN_clearInterruptStatus(CANA_BASE, 1);
//
// 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.
//
rxAMsgCount++;
//
// 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(CANA_BASE, CAN_GLOBAL_INT_CANINT1);
//
// Acknowledge this interrupt located in group 9
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
uint32_t getMessageID(uint32_t base, uint32_t objID)
{
uint32_t msgID = 0;
CAN_transferMessage(base, 2, objID, false);
msgID = HWREG(base + CAN_O_IF2ARB);
msgID &= CAN_IF2ARB_STD_ID_M;
msgID = msgID >> CAN_IF2ARB_STD_ID_S;
return msgID;
}
Note that in my project I am also using CPU timer interrupt 0, 1 and 2.
Any help is appreciated.
Alessandro Fano