Hello!
I use a F28377D DSP and want to handle both CAN interrupts (CANA0_INT and CANA1_INT). Status, error and receive interrupts on CANA0_INT and transmit interrupts on CANA1_INT. My problem is that CANA1_INT do not occur.
The basic programm is TI example 'can_loopback_interrupts' from 'controlSUITE\device_support\F2837xD\v190\F2837xD_examples_Cpu1\can_loopback_interrupts\cpu01'. I modify the example in two points. First, don't use CAN test mode with loopback, instead I send the receive CAN message by a external tool. This works perfect as long as I use only CANA0_INT for all interrupts.
The second modification is to handle the transmit messages by CANA1_INT (The reason is we want to transfer an older F28355 project on the F28377D. In this project CAN receive messages are handled by CANA0 and transmitted messages by CANA1. So we don't want to modify the complete source code). I add the interrupt assignment as described in https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/494481 and in chapter 22.16.2.22 (CAN_IP_MUX21 Register) of the TMS320F2837xD Dual-Core Delfino - Technical Reference Manual (spruhm8). For that see line 260 in my source code below (HWREGH(CANA_BASE + CAN_O_IP_MUX21) = .....).
But then I debug the program the transmit messages are handled in CANA0_INT. I see the LED flashing (CANA0_INT -> CANIntHandler) not toggling (CANA1_INT -> CANInt1Handler). Why? What I have additionally to do?
By the way. In the TI 'F2837xD CAN Initialization & Support Functions' (Files 'can.c' and 'can.h' in 'controlSUITE\device_support\F2837xD\v190\F2837xD_common\driverlib') I can't find any function to configure or handling 'CANA1_INT'.
I hope anyone could help me. Thanks!
Rudolf Richter
------------------------------------------------------------------------------
Modified TI example code
------------------------------------------------------------------------------
//###########################################################################
// FILE: can_loopback_interrupts.c
// TITLE: Example to demonstrate basic CAN setup and use.
//
//! This example uses the following interrupt handlers:\n
//! - INT_CANA0 - CANIntHandler
//!
//
//###########################################################################
// $TI Release: F2837xD Support Library v190 $
// $Release Date: Mon Feb 1 16:51:57 CST 2016 $
// $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################
#include "F28x_Project.h" // Device Headerfile and Examples Include File
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_can.h"
#include "driverlib/can.h"
#include "GPIO_pin_assignment.h"
//*****************************************************************************
// Defines
//*****************************************************************************
// CAN message ID of TX-RX-Test of CAN messages with same CAN ID
#define CAN_MSGID_TXRX_TEST 4
// Object ID of TX object in TX-RX-Test
#define OBJ_ID_TXRX_TEST_TX 1
// Object ID of RX object in TX-RX-Test
#define OBJ_ID_TXRX_TEST_RX 7
//*****************************************************************************
// A counter that keeps track of the number of times the TX interrupt has
// occurred, which should match the number of TX messages that were sent.
//*****************************************************************************
volatile unsigned long g_ulTxMsgCount = 0;
volatile unsigned long g_ulRxMsgCount = 0;
unsigned long u32CanAErrorStatus;
//*****************************************************************************
// A flag to indicate that some transmission error occurred.
//*****************************************************************************
volatile unsigned long g_bErrFlag = 0;
tCANMsgObject sTXCANMessage;
unsigned char ucTXMsgData[8] ={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
tCANMsgObject sRXCANMessage;
unsigned char ucRXMsgData[8];
unsigned long u32CntTXMsgData = 0x12345678;
//*****************************************************************************
// 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.
//*****************************************************************************
interrupt void CANIntHandler(void)
{
unsigned long ulStatus;
// Read the CAN interrupt status to find the cause of the interrupt
ulStatus = CANIntStatus(CANA_BASE, CAN_INT_STS_CAUSE);
// If the cause is a controller status interrupt, then get the status
if(ulStatus == CAN_INT_INT0ID_STATUS)
{
// Read the controller status.
ulStatus = CANStatusGet(CANA_BASE, CAN_STS_CONTROL);
//Check to see if an error occurred.
if(((ulStatus & ~(CAN_ES_TXOK | CAN_ES_RXOK)) != 7) && ((ulStatus & ~(CAN_ES_TXOK | CAN_ES_RXOK)) != 0)) {
}
}
// Check if the cause is message object OBJ_ID_TXRX_TEST_TX, which what we are using for
// sending messages.
else if(ulStatus == OBJ_ID_TXRX_TEST_TX)
{
// Getting to this point means that the TX interrupt occurred on message object 'OBJ_ID_TXRX_TEST_TX',
// and the message TX is complete. Clear the message object interrupt.
CANIntClear(CANA_BASE, OBJ_ID_TXRX_TEST_TX);
// Increment a counter to keep track of how many messages have been sent. In a real application this
// could be used to set flags to indicate when a message is sent.
g_ulTxMsgCount++;
// TX should handled by INT 1.
g_bErrFlag |= 0x02;
// Signal with DSP LED
GPIO_TogglePin(DSP_LED);
DELAY_US(1000*30);
GPIO_TogglePin(DSP_LED);
}
// Check if the cause is message object 'OBJ_ID_TXRX_TEST_RX', which what we are using for the
// receiving messages of the TX-RX-Test.
else if(ulStatus == OBJ_ID_TXRX_TEST_RX)
{
// Get the received message
CANMessageGet(CANA_BASE, OBJ_ID_TXRX_TEST_RX, &sRXCANMessage, true);
// Getting to this point means that the RX interrupt occurred on message object 'OBJ_ID_TXRX_TEST_RX',
// and the message RX is complete. Clear the message object interrupt.
CANIntClear(CANA_BASE, OBJ_ID_TXRX_TEST_RX);
// Increment a counter to keep track of how many messages have been sent. In a real application this
// could be used to set flags to indicate when a message is sent.
g_ulRxMsgCount++;
// Since the message was sent, clear error flags.
g_bErrFlag &= 0xFFF3;
// Toggle DSP LED
/// DISABLED GPIO_TogglePin(DSP_LED);
}
// Otherwise, something unexpected caused the interrupt. This should never happen.
else
{
// Spurious interrupt handling can go here.
}
CANGlobalIntClear(CANA_BASE, CAN_GLB_INT_CANINT0);
PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
}
//*****************************************************************************
// Handler of CAN A interrupt 1
//*****************************************************************************
interrupt void CANInt1Handler(void)
{
unsigned long ulStatus;
// Read the CAN interrupt status to find the cause of the interrupt
ulStatus = CANIntStatus(CANA_BASE, CAN_INT_STS_CAUSE);
// Check if the cause is message object OBJ_ID_TXRX_TEST_TX, which what we are using for
// sending messages.
if(ulStatus == OBJ_ID_TXRX_TEST_TX)
{
// Getting to this point means that the TX interrupt occurred on message object 'OBJ_ID_TXRX_TEST_TX',
// and the message TX is complete. Clear the message object interrupt.
CANIntClear(CANA_BASE, OBJ_ID_TXRX_TEST_TX);
// Increment a counter to keep track of how many messages have been sent. In a real application this
// could be used to set flags to indicate when a message is sent.
g_ulTxMsgCount++;
// Since the message was sent, clear any error flags.
g_bErrFlag = 0;
// Signal with DSP LED
GPIO_TogglePin(DSP_LED);
}
CANGlobalIntClear(CANA_BASE, CAN_GLB_INT_CANINT1);
PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
}
//*****************************************************************************
// Configure the CAN and enter a loop to transmit periodic CAN messages.
//*****************************************************************************
int main(void)
{
uint16_t i;
uint32_t DbgVal = 0;
// Step 1. Initialize System Control:
InitSysCtrl();
// Step 2. Initialize GPIO:
InitGpio();
//DSP LED
GPIO_SetupPinMux(DSP_LED, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(DSP_LED, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_WritePin(DSP_LED, 1);
for(i = 0; i < 10; i++) {
GPIO_TogglePin(DSP_LED);
DELAY_US(1000*250);
}
// Init the pins for the SCI-A port.
GPIO_SetupPinMux(COM1_RX, GPIO_MUX_CPU1, 6);
GPIO_SetupPinOptions(COM1_RX, GPIO_INPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(COM1_TX, GPIO_MUX_CPU1, 6);
GPIO_SetupPinOptions(COM1_TX, GPIO_OUTPUT, GPIO_ASYNC);
//GPIO30 - CANRXA
GPIO_SetupPinMux(CAN1_RXD, GPIO_MUX_CPU1, 6);
//GPIO31 - CANTXA
GPIO_SetupPinMux(CAN1_TXD, GPIO_MUX_CPU1, 6);
GPIO_SetupPinOptions(CAN1_RXD, GPIO_INPUT, GPIO_ASYNC);
GPIO_SetupPinOptions(CAN1_TXD, GPIO_OUTPUT, GPIO_PUSHPULL);
// Initialize the CAN controller
CANInit(CANA_BASE);
// Setup CAN to be clocked off the PLL output clock
CANClkSourceSelect(CANA_BASE, 0); // 500kHz CAN-Clock
// Set up the bit rate for the CAN bus
CANBitRateSet(CANA_BASE, 200000000, 500000);
// Enable interrupts on the CAN peripheral.
CANIntEnable(CANA_BASE, CAN_INT_IE0 | CAN_INT_IE1 | CAN_INT_ERROR | CAN_INT_STATUS);
// Step 3. Clear all interrupts and initialize PIE vector table: Disable CPU interrupts
DINT;
// Initialize the PIE control registers to their default state.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt Service Routines (ISR).
InitPieVectTable();
// Interrupts that are used in this example are re-mapped toISR functions found within this file.
// Register interrupt handler in RAM vector table
EALLOW;
PieVectTable.CANA0_INT = CANIntHandler;
PieVectTable.CANA1_INT = CANInt1Handler;
EDIS;
// Enable the CAN interrupt on the processor (PIE).
PieCtrlRegs.PIEIER9.bit.INTx5 = 1;
PieCtrlRegs.PIEIER9.bit.INTx6 = 1;
IER |= 0x0100; /* M_INT9 */
EINT;
// Enable the CAN for operation.
CANEnable(CANA_BASE);
CANGlobalIntEnable(CANA_BASE, CAN_GLB_INT_CANINT0);
CANGlobalIntEnable(CANA_BASE, CAN_GLB_INT_CANINT1);
// Initialize the message object that will be used for sending CAN messages. The message will be 4 bytes
// that will contain an incrementing value. Initially it will be set to 0x12345678.
ucTXMsgData[0] = (u32CntTXMsgData>>24) & 0xFF;
ucTXMsgData[1] = (u32CntTXMsgData>>16) & 0xFF;
ucTXMsgData[2] = (u32CntTXMsgData>>8) & 0xFF;
ucTXMsgData[3] = (u32CntTXMsgData) & 0xFF;
sTXCANMessage.ui32MsgID = CAN_MSGID_TXRX_TEST; // CAN message ID
sTXCANMessage.ui32MsgIDMask = 0; // no mask needed for TX
sTXCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE; // enable interrupt on TX
sTXCANMessage.ui32MsgLen = sizeof(ucTXMsgData); // size of message is 8
sTXCANMessage.pucMsgData = ucTXMsgData; // ptr to message content
// Map TX object on CANA1_INT by register 'CAN_O_IP_MUX21'
// See document: TMS320F2837xD Dual-Core Delfino - Technical Reference Manual (spruhm8)
// Chapter: 22.16.2.22 CAN_IP_MUX21 Register
// See URL: e2e.ti.com/.../494481
HWREGH(CANA_BASE + CAN_O_IP_MUX21) = (HWREGH(CANA_BASE + CAN_O_IP_MUX21) | ((1 << (OBJ_ID_TXRX_TEST_TX - 1)) | 0x0000U));
DbgVal = HWREGH(CANA_BASE + CAN_O_IP_MUX21);
// Initialize the message objects that will be used for receiving CAN messages.
*(unsigned long *)ucRXMsgData = 0;
sRXCANMessage.ui32MsgID = CAN_MSGID_TXRX_TEST; // CAN message ID
sRXCANMessage.ui32MsgIDMask = 0; // no mask needed for RX
sRXCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE; // enable interrupt on RX
sRXCANMessage.ui32MsgLen = sizeof(ucRXMsgData); // size of message is 8
sRXCANMessage.pucMsgData = ucRXMsgData; // ptr to message content
// Map RX object of TX-RX-Test on CANA0_INT by register 'CAN_O_IP_MUX21'
HWREGH(CANA_BASE + CAN_O_IP_MUX21) = (HWREGH(CANA_BASE + CAN_O_IP_MUX21) & (~(1 << (OBJ_ID_TXRX_TEST_RX - 1)) & CAN_REG_WORD_MASK));
DbgVal = HWREGH(CANA_BASE + CAN_O_IP_MUX21);
// Setup the message objects being used to receive messages
CANMessageSet(CANA_BASE, OBJ_ID_TXRX_TEST_RX, &sRXCANMessage, MSG_OBJ_TYPE_RX);
// Send the CAN message using object number 'OBJ_ID_TXRX_TEST_TX'.
// This function will cause the message to be transmitted right away.
ucTXMsgData[0] = (u32CntTXMsgData>>24) & 0xFF;
ucTXMsgData[1] = (u32CntTXMsgData>>16) & 0xFF;
ucTXMsgData[2] = (u32CntTXMsgData>>8) & 0xFF;
ucTXMsgData[3] = (u32CntTXMsgData) & 0xFF;
// Enter loop to send messages. A new message will be sent once per second. The 4 bytes of message content
// will be treated as an unsigned long and incremented by one each time.
for(;;)
{
// Get some informations
DbgVal = CANIntStatus(CANA_BASE, CAN_INT_STS_OBJECT);
DbgVal = HWREGH(CANA_BASE + CAN_O_IP_MUX21);
// Get status: objects with valid transmit requests
DbgVal = CANStatusGet(CANA_BASE, CAN_STS_TXREQUEST);
// All transmit requests handled?
if(0 == DbgVal) {
CANMessageSet(CANA_BASE, OBJ_ID_TXRX_TEST_TX, &sTXCANMessage, MSG_OBJ_TYPE_TX);
}
// Now wait 1 second before continuing
DELAY_US(1000*1000);
// Increment the value in the transmitted message data.
(*(unsigned long *)ucTXMsgData)++;
}
}