This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28335: ECAN: Strange issues with Mailbox Timeout Interrupt.

Guru 20045 points
Part Number: TMS320F28335


Hello,

I am having difficulty in implementing CAN mailbox timeout interrupts.  The timeout interrupt is occurring, but it is not occurring on the correct CAN Interrupt line (As specified by CANGIM).  It is supposed to be occurring on CAN Interrupt Line 0, but it is occurring on Interrupt Line 1. Also, when the Timeout occurs, it only happens for a number of times (40 to 70) and then it stops happening altogether.

Furthermore, I am not able to clear the Timeout flags.

For my test, I don't have anything connected to the CAN bus. 

Below is a table showing the debugger output after ECanb is initialize.  

What am I missing?

Does anyone have any example code that shows how to implement CAN Mailbox Timeouts Interrupts?

Stephen

CANME 0xFFC00000 eCAN Mailbox Enable [Memory Mapped] Mailboxes 22 through 31 are enabled
CANMD 0xFE000000 eCAN Mailbox Direction [Memory Mapped] Mailboxes 25 through 31 are Rx, Mailboxes 22 through 24 are Tx
CANTRS  0x00000000 eCAN Transmission Request Set [Memory Mapped]  
CANTRR 0x00000000 eCAN Transmission Request Reset [Memory Mapped]  
CANTA 0x00000000 eCAN Transmission Acknowledge [Memory Mapped]  
CANAA 0x00000000 eCAN Abort Acknowledge [Memory Mapped]  
CANRMP 0x00000000 eCAN Received Message Pending [Memory Mapped]  
CANRML 0x00000000 eCAN Received Message Lost [Memory Mapped]  
CANRFP 0x00000000 eCAN Received Frame Pending [Memory Mapped]  
CANGAM 0x80000000 eCAN Global Acceptance Mask [Memory Mapped]  
CANMC 0x00002080 eCAN Master Control [Memory Mapped] Auto bus on,The MSB of the time stamp counter is reset to 0
CANBTC 0x000900CB eCAN Bit-Timing Configuration [Memory Mapped] 500k Baud
CANES 0x00000020 eCAN Error and Status [Memory Mapped] Suspend mode acknowledge (because of debugger)
CANTEC 0x00000000 eCAN Transmit Error Counter [Memory Mapped]  
CANREC 0x00000000 eCAN Receive Error Counter [Memory Mapped]  
CANGIF0 0x00000000 eCAN Global Interrupt Flag 0 [Memory Mapped]  
CANGIM 0x00020003 eCAN Global Interrupt Mask [Memory Mapped] Both Interrupt Line 1 and 2 are used for interrupts,  All global interrupts are mapped to the ECAN0INT interrupt line and Timeout Interrupt Enabled
CANGIF1 0x00000000 eCAN Global Interrupt Flag 1 [Memory Mapped]  
CANMIM 0xFE000000 eCAN Mailbox Interrupt Mask [Memory Mapped] Mailbox Interrupt Enabled for all Rx Mailboxes
CANMIL 0xFE000000 eCAN Mailbox Interrupt Level [Memory Mapped] Rx Mailbox interrupts on CAN interrupt Line 1
CANOPC 0x00000000 eCAN Overwrite Protection Control [Memory Mapped]  
CANTIOC 0x00000009 eCAN TX I/O Control [Memory Mapped] CAN Transmit Pin Enabled
CANRIOC 0x00000009 eCAN RX I/O Control [Memory Mapped] CAN Receive Pin Enabled
CANTSC 0x00000022 eCAN Time Stamp Counter [Memory Mapped]  
CANTOC 0x02000000 eCAN Time-Out Control [Memory Mapped] Timeout Mailbox Interrupt Enabled for Mailbox 25
  • Please refer to the timeout example in my app.note SPRA876

  • Hello,

    I examined the CAN_MOTO_A project from the examples and found the following comment shown below.  I assumed that the timeout flag could be reset by software, but doesn't seem to be the case. 

    Is that correct?  If so,this seems to be a major issue.  For my situation, I am more interested in a receive timeout.  What if the message never arrives?  How do I reset the timeout flag?

    No interrupts occur when I tried the example; however, it may be because I made a mistake when I changed ECana to ECanb  and the GPIO ports from GPIO8/10 to GPIO16/17.  I also, had to change all the main.c references of ECana to ECanb.  I attached the files that I changed.

    Stephen

    // TI Release: 28xx eCAN programming example
    // Release Date: Fri Aug 4 2017
    // Copyright:
    // Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // 
    
    /*********************************************************************
    * Filename: MOTO.c                                                
    *                                                                    
    * Description: This example illustrates the "MOTO" feature.
    * (MOTO - Message Object Time-Out)
    * Deliberately let a transmit mailbox timeout and check whether the
    * corresponding interrupt flag (MTOFn) and TOSn is set.
    * Mailbox 0 is used in this example
    *
    **********************************************************************/
    
    //
    // Included Files
    //
    #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    
    // Variable declarations
    
    long      i;
    int int0count = 0;		// Counter to track the # of level 0 interrupts
    int int1count = 0;	    // Counter to track the # of level 1 interrupts
    
    // Prototype statements for functions found within this file.
    
    interrupt void eCAN0INT_ISR(void);
    interrupt void eCAN1INT_ISR(void);
    
    /* Create a shadow register structure for the CAN control registers. This is
     needed, since, only 32-bit access is allowed to these registers. 16-bit access
     to these registers could potentially corrupt the register contents. This is
     especially true while writing to a bit (or group of bits) among bits 16 - 31 */
    
    struct ECAN_REGS ECanbShadow;
    
    void InitECan(void);
    
    main() 
    {
    
    /* Kill Watchdog, Init PLL, Enable peripheral clocks */
    
            InitSysCtrl();
    
    /* Initialize the CAN module */
    
            InitECan();
            InitECanGpio();
    
            EALLOW;
    
    /* Initialize PIE vector table To a Known State: */
    	// The PIE vector table is initialized with pointers to shell "Interrupt 
        // Service Routines (ISR)".  The shell routines are found in DSP28_DefaultIsr.c.
    	// Insert user specific ISR code in the appropriate shell ISR routine in 
        // the DSP28_DefaultIsr.c file.
        
        // InitPieVectTable();	 // uncomment this line if the shell ISR routines are needed
        
        // This function is found in DSP28_PieVect.c. It populates the PIE vector table
        // with pointers to the shell ISR functions found in DSP28_DefaultIsr.c. This 
        // function is not useful in this code because the user-specific ISR is present
        // in this file itself. The shell ISR routine in the DSP28_DefaultIsr.c file is
        // not used. If the shell ISR routines are needed, uncomment this line and add 
        // DSP28_PieVect.c & DSP28_DefaultIsr.c files to the project
    
    /* Disable and clear all CPU interrupts: */
    
    	DINT;
    	IER = 0x0000;
    	IFR = 0x0000;
    
    /* Initialize Pie Control Registers To Default State */
            
    	InitPieCtrl(); // This function is found in the DSP28_PieCtrl.c file. 
    
     /* Write to the MSGID field */
        
        ECanbMboxes.MBOX0.MSGID.all  = 0x9555AA00;
         
     /* Configure Mailbox under test as Tx */
    
    	ECanbRegs.CANMD.all = 0; 		// All mailboxes are made transmit..
    	
    /* Enable Mailbox under test */
    	
    	ECanbShadow.CANME.all = ECanbRegs.CANME.all;
    	ECanbShadow.CANME.bit.ME0 = 1;
    	ECanbRegs.CANME.all = ECanbShadow.CANME.all;
    	
    /* Write to Master Control field */
     
        ECanbMboxes.MBOX0.MSGCTRL.bit.DLC = 8;
            
    /* Write to the mailbox RAM field */
        
         ECanbMboxes.MBOX0.MDL.all = 0x9555AAA0;
    	 ECanbMboxes.MBOX0.MDH.all = 0x89ABCDEF;
    		           
    /* Configure CAN interrupts */ 
    
    	ECanbShadow.CANMIL.all = ECanbRegs.CANMIL.all;
    	//ECanbShadow.CANMIL.bit.MIL0 = 0 ; // MBOX0 asserts MTOF0 (eCAN0INT)
    	ECanbShadow.CANMIL.bit.MIL0 = 1 ;  // MBOX0 asserts MTOF1 (eCAN1INT)
    	ECanbRegs.CANMIL.all = ECanbShadow.CANMIL.all;
    	
    	ECanbShadow.CANGIM.all = 0;
        ECanbShadow.CANGIM.bit.I0EN = 1;     // Enable eCAN0INT
        ECanbShadow.CANGIM.bit.I1EN = 1;	 // Enable eCAN1INT
        ECanbShadow.CANGIM.bit.MTOM = 1;	 // Enable MBX Timeout interrupt
        ECanbRegs.CANGIM.all = ECanbShadow.CANGIM.all;
        
    /* Reassign ISRs. i.e. reassign the PIE vector for ECAN0INTA_ISR and ECAN0INTA_ISR 
       to point to a different ISR than the shell routine found in DSP28_DefaultIsr.c.
       This is done if the user does not want to use the shell ISR routine but instead
       wants to embed the ISR in this file itself. */
    	
    	PieVectTable.ECAN0INTA = &eCAN0INT_ISR;
    	PieVectTable.ECAN1INTA = &eCAN1INT_ISR;	
        
    /* Configure PIE interrupts */    
      
    	PieCtrlRegs.PIECTRL.bit.ENPIE = 1;  // Enable vector fetching from PIE block
    	
    	PieCtrlRegs.PIEACK.bit.ACK9 = 1;    // Enables PIE to drive a pulse into the CPU
    
    // The 'MOTO' interrupt can be asserted in either of the eCAN interrupt lines
    // Comment out the unwanted line...
    
    	PieCtrlRegs.PIEIER9.bit.INTx7 = 1;  // Enable INTx.5 of INT9 (eCAN0INT)
    	PieCtrlRegs.PIEIER9.bit.INTx8 = 1;  // Enable INTx.6 of INT9 (eCAN1INT)
    	
    /* Configure system interrupts */
    	
    	IER |= 0x0100;					// Enable INT9 of CPU
    	EINT;							// Global enable of interrupts   
    	
    /* Write to MOTO reg of Mailbox under test */
    
    	ECanbMOTORegs.MOTO0 = 0x80; // It was experimentally determined that
    						// this value would let MBX0 to timeout...MOTS0 contains
    						// 8Eh after transmission is complete..See Note 1
    						// This value may have to tweaked a bit based on the clock frequency etc..
    
    /* Enable time-out function for the mailbox */
        	 	
        ECanbShadow.CANTOC.all = 0;
    	ECanbShadow.CANTOC.bit.TOC0 = 1;
    	ECanbRegs.CANTOC.all = ECanbShadow.CANTOC.all;
    	
    /* Clear the "Time Stamp Counter"  */
    
    	ECanbRegs.CANTSC = 0;
    
    /* Begin transmitting */       
         		 	
         ECanbShadow.CANTRS.all = 0;
         ECanbShadow.CANTRS.bit.TRS0 = 1;     // Set TRS for mailbox under test
         ECanbRegs.CANTRS.all = ECanbShadow.CANTRS.all;
         
         for(i=0; i<111999999; i++) 	// A very long loop. Code loops here when CAN module transmits
    	 	{ asm(" NOP"); }        // the data and executes the ISR
    	 
    	 asm(" ESTOP0");									 // Code stops here after transmission
    
    }
    
    /* --------------------------------------------------- */
    /* ISR for PIE INT9.5                                  */
    /* Connected to HECC0-INTA  eCAN                       */
    /* ----------------------------------------------------*/
    
    interrupt void eCAN0INT_ISR(void)  // eCAN
    {
       ECanbShadow.CANTOS.all = ECanbRegs.CANTOS.all ;  // Copy TOS reg for inspection
       ECanbShadow.CANGIF0.all = ECanbRegs.CANGIF0.all; // Copy GIF0 reg for inspection
         
       ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;
          do {ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;}   // Wait for TA0 bit to be set..
           while(ECanbShadow.CANTA.bit.TA0 == 0 );
    
    // Clear TAn  
       ECanbShadow.CANTA.all = 0; 			// Initialize TA to zero before setting any
       ECanbShadow.CANTA.bit.TA0 = 1 ;		// bit in order to clear it. Otherwise, some
       							// other TAn bit that is set could be inadvertently cleared
       ECanbRegs.CANTA.all =  ECanbShadow.CANTA.all ;   // Clear TAn bit
    
    // Clear MTOF0   
       // MTOF0 cannot be manually cleared. It is automatically cleared when TOSn is cleared, 
       // which is automatically cleared when the message is successfully transmitted.
       
    
    // Re-enable PIE and Core interrupts   
       PieCtrlRegs.PIEACK.bit.ACK9 = 1;    	// Enables PIE to drive a pulse into the CPU
       IER |= 0x0100;					 	// These 2 lines allow for nested interrupts 
       EINT;								// Strictly not needed for this example.
       int0count++;
       return;
    }
    
    /* --------------------------------------------------- */
    /* ISR for PIE INT9.6                                  */
    /* Connected to HECC1-INTA  eCAN                       */
    /* ----------------------------------------------------*/
    
    interrupt void eCAN1INT_ISR(void)  // eCAN
    {
       ECanbShadow.CANTOS.all = ECanbRegs.CANTOS.all ;  // Copy TOS reg for inspection
       ECanbShadow.CANGIF1.all = ECanbRegs.CANGIF1.all; // Copy GIF1 reg for inspection
      
       ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;
          do {ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;}   // Wait for TA0 bit to be set..
           while(ECanbShadow.CANTA.bit.TA0 == 0 );
       
    // Clear TAn  
       ECanbShadow.CANTA.all = 0; 			// Initialize TA to zero before setting any
       ECanbShadow.CANTA.bit.TA0 = 1 ;		// bit in order to clear it. Otherwise, some
       							// other TAn bit that is set could be inadvertently cleared
       ECanbRegs.CANTA.all =  ECanbShadow.CANTA.all ;   // Clear TAn bit
    
    // Clear MTOF1   
       // MTOF1 cannot be manually cleared. It is automatically cleared when TOSn is cleared, 
       // which is automatically cleared when the message is successfully transmitted.
       
    // Re-enable PIE and Core interrupts   
       PieCtrlRegs.PIEACK.bit.ACK9 = 1;    // Enables PIE to drive a pulse into the CPU
       IER |= 0x0100;					 // Enable INT9 
       EINT;
       int1count++;
       return;
    }
    
    /* Notes:
    
    The TOS.n bit will be cleared upon (eventual) successful transmission.
    The only way to ascertain if a time-out occurred is to copy TOS and GIFn
    registers in the ISR to check if the relevant bits were set when the 
    ISR was just entered. 
    
    It can be verified that whether the MTOF bit gets set in GIF0 or GIF1 
    depends on the value of MILn. 
    
    This example is useful to check that MTOFn gets cleared if TOSn is cleared. 
    
    Note 1: TSC does not start running until the bit timing registers
    are configured. After configuration, it is a free running timer clocked by the 
    bit rate clock of the CAN module. The delay between the last instruction 
    that configures the bit timing to the instruction that initiates transmission will
    therefore affect this "experimentally determined" value. Since the counter runs at
    the bit clock rate, the fastest bit clock rate is 1 uS, which equates to 150 CPU
    clock cycles (@ 150 MHz SYSCLKOUT). Therefore adding/deleting a few instructions 
    will not make a significant change. A delay loop would.
    
    */
    
    
    // TI File $Revision: /main/8 $
    // Checkin $Date: June 25, 2008   15:19:07 $
    //###########################################################################
    //
    // FILE:	DSP2833x_ECan.c
    //
    // TITLE:	DSP2833x Enhanced CAN Initialization & Support Functions.
    //
    //###########################################################################
    // $TI Release: F2833x Support Library v2.00.00.00 $
    // $Release Date: Sun Sep 29 07:33:44 CDT 2019 $
    // $Copyright:
    // Copyright (C) 2009-2019 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
    #include "DSP2833x_Examples.h"   // DSP2833x Examples Include File
    
    //
    // InitECan - This function initializes the eCAN module to a known state.
    //
    void 
    InitECan(void)
    {
        InitECanb();
    }
    
    //
    // InitECana - Initialize eCAN-A module
    //
    void 
    InitECana(void)
    {
        //
        // Create a shadow register structure for the CAN control registers. This 
        // is needed, since only 32-bit access is allowed to these registers. 
        // 16-bit access to these registers could potentially corrupt the register
        // contents or return false data. This is especially true while writing 
        // to/reading from a bit (or group of bits) among bits 16 - 31
        //
        struct ECAN_REGS ECanaShadow;
    
        EALLOW;		// EALLOW enables access to protected bits
    
        //
        // Configure eCAN RX and TX pins for CAN operation using eCAN regs
        //
        ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all;
        ECanaShadow.CANTIOC.bit.TXFUNC = 1;
        ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all;
    
        ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all;
        ECanaShadow.CANRIOC.bit.RXFUNC = 1;
        ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all;
    
        //
        // Configure eCAN for HECC mode - (reqd to access mailboxes 16 thru 31)
        // HECC mode also enables time-stamping feature
        //
        ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
        ECanaShadow.CANMC.bit.SCB = 1;
        ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
    
        //
        // Initialize all bits of 'Master Control Field' to zero
        // Some bits of MSGCTRL register come up in an unknown state. For proper 
        // operation, all bits (including reserved bits) of MSGCTRL must be 
        // initialized to zero
        //
        ECanaMboxes.MBOX0.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX1.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX2.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX3.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX4.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX5.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX6.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX7.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX8.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX9.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX10.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX11.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX12.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX13.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX14.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX15.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX16.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX17.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX18.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX19.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX20.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX21.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX22.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX23.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX24.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX25.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX26.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX27.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX28.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX29.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX30.MSGCTRL.all = 0x00000000;
        ECanaMboxes.MBOX31.MSGCTRL.all = 0x00000000;
    
        //
        // TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
        // as a matter of precaution.
        //
        ECanaRegs.CANTA.all	= 0xFFFFFFFF;       // Clear all TAn bits
    
        ECanaRegs.CANRMP.all = 0xFFFFFFFF;      // Clear all RMPn bits
    
        ECanaRegs.CANGIF0.all = 0xFFFFFFFF;     // Clear all interrupt flag bits
        ECanaRegs.CANGIF1.all = 0xFFFFFFFF;
    
        //
        // Configure bit timing parameters for eCANA
        //
        ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
        ECanaShadow.CANMC.bit.CCR = 1 ;            // Set CCR = 1
        ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
    
        ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    
        do
        {
            ECanaShadow.CANES.all = ECanaRegs.CANES.all;
        } while(ECanaShadow.CANES.bit.CCE != 1 );  	// Wait for CCE bit to be set
    
        ECanaShadow.CANBTC.all = 0;
    
        //
        // CPU_FRQ_150MHz is defined in DSP2833x_Examples.h
        //
        #if (CPU_FRQ_150MHZ)
        //
        // The following block for all 150 MHz SYSCLKOUT 
        // (75 MHz CAN clock) - default. Bit rate = 1 Mbps See Note at End of File
        //
        ECanaShadow.CANBTC.bit.BRPREG = 4;
        ECanaShadow.CANBTC.bit.TSEG2REG = 2;
        ECanaShadow.CANBTC.bit.TSEG1REG = 10;
        #endif
        
        //
        // CPU_FRQ_100MHz is defined in DSP2833x_Examples.h
        //
        #if (CPU_FRQ_100MHZ)
        //
        // The following block is only for 100 MHz SYSCLKOUT (50 MHz CAN clock). 
        // Bit rate = 1 Mbps See Note at End of File
        //
        ECanaShadow.CANBTC.bit.BRPREG = 4;
        ECanaShadow.CANBTC.bit.TSEG2REG = 1;
        ECanaShadow.CANBTC.bit.TSEG1REG = 6;
        #endif
    
        ECanaShadow.CANBTC.bit.SAM = 1;
        ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;
    
        ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
        ECanaShadow.CANMC.bit.CCR = 0 ;            // Set CCR = 0
        ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
    
        ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    
        do
        {
            ECanaShadow.CANES.all = ECanaRegs.CANES.all;
        } while(ECanaShadow.CANES.bit.CCE != 0 );// Wait for CCE bit to be  cleared
    
        //
        // Disable all Mailboxes
        //
        ECanaRegs.CANME.all = 0;		// Required before writing the MSGIDs
    
        EDIS;
    }
    
    #if (DSP28_ECANB)
    //
    // Initialize eCAN-B module
    //
    void 
    InitECanb(void)
    {
        //
        // Create a shadow register structure for the CAN control registers. This 
        // is needed, since only 32-bit access is allowed to these registers. 
        // 16-bit access to these registers could potentially corrupt the register 
        // contents or return false data. This is especially true while writing 
        // to/reading from a bit (or group of bits) among bits 16 - 31
        //
        struct ECAN_REGS ECanbShadow;
    
        EALLOW;		// EALLOW enables access to protected bits
    
        //
        // Configure eCAN RX and TX pins for CAN operation using eCAN regs
        //
        ECanbShadow.CANTIOC.all = ECanbRegs.CANTIOC.all;
        ECanbShadow.CANTIOC.bit.TXFUNC = 1;
        ECanbRegs.CANTIOC.all = ECanbShadow.CANTIOC.all;
    
        ECanbShadow.CANRIOC.all = ECanbRegs.CANRIOC.all;
        ECanbShadow.CANRIOC.bit.RXFUNC = 1;
        ECanbRegs.CANRIOC.all = ECanbShadow.CANRIOC.all;
    
        //
        // Configure eCAN for HECC mode - (read to access mailboxes 16 thru 31)
        //
        ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
        ECanbShadow.CANMC.bit.SCB = 1;
        ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    
        //
        // Initialize all bits of 'Master Control Field' to zero
        // Some bits of MSGCTRL register come up in an unknown state. For proper 
        // operation, all bits (including reserved bits) of MSGCTRL must be 
        // initialized to zero
        //
        ECanbMboxes.MBOX0.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX1.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX2.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX3.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX4.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX5.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX6.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX7.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX8.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX9.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX10.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX11.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX12.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX13.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX14.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX15.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX16.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX17.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX18.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX19.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX20.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX21.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX22.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX23.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX24.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX25.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX26.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX27.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX28.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX29.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX30.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX31.MSGCTRL.all = 0x00000000;
    
        //
        // TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
        // as a matter of precaution.
        //
        ECanbRegs.CANTA.all	= 0xFFFFFFFF;	// Clear all TAn bits
    
        ECanbRegs.CANRMP.all = 0xFFFFFFFF;	// Clear all RMPn bits
    
        ECanbRegs.CANGIF0.all = 0xFFFFFFFF;	// Clear all interrupt flag bits
        ECanbRegs.CANGIF1.all = 0xFFFFFFFF;
    
        //
        // Configure bit timing parameters for eCANB
        //
        ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
        ECanbShadow.CANMC.bit.CCR = 1 ;            // Set CCR = 1
        ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    
        ECanbShadow.CANES.all = ECanbRegs.CANES.all;
    
        do
        {
            ECanbShadow.CANES.all = ECanbRegs.CANES.all;
        } while(ECanbShadow.CANES.bit.CCE != 1); // Wait for CCE bit to be  cleared
    
        ECanbShadow.CANBTC.all = 0;
    
        //
        // CPU_FRQ_150MHz is defined in DSP2833x_Examples.h
        //
        #if (CPU_FRQ_150MHZ)
        //
        // The following block for all 150 MHz SYSCLKOUT 
        // (75 MHz CAN clock) - default. Bit rate = 1 Mbps See Note at end of file
        //
        ECanbShadow.CANBTC.bit.BRPREG = 4;
        ECanbShadow.CANBTC.bit.TSEG2REG = 2;
        ECanbShadow.CANBTC.bit.TSEG1REG = 10;
        #endif
        
        //
        // CPU_FRQ_100MHz is defined in DSP2833x_Examples.h
        //
        #if (CPU_FRQ_100MHZ)
        //
        // The following block is only for 100 MHz SYSCLKOUT (50 MHz CAN clock).
        // Bit rate = 1 Mbps  See Note at end of file
        //
        ECanbShadow.CANBTC.bit.BRPREG = 4;
        ECanbShadow.CANBTC.bit.TSEG2REG = 1;
        ECanbShadow.CANBTC.bit.TSEG1REG = 6;
        #endif
    
        ECanbShadow.CANBTC.bit.SAM = 1;
        ECanbRegs.CANBTC.all = ECanbShadow.CANBTC.all;
    
        ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
        ECanbShadow.CANMC.bit.CCR = 0 ;            // Set CCR = 0
        ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    
        ECanbShadow.CANES.all = ECanbRegs.CANES.all;
    
        do
        {
            ECanbShadow.CANES.all = ECanbRegs.CANES.all;
        } while(ECanbShadow.CANES.bit.CCE != 0 );// Wait for CCE bit to be  cleared
    
        //
        // Disable all Mailboxes
        //
        ECanbRegs.CANME.all = 0;		// Required before writing the MSGIDs
    
        EDIS;
    }
    #endif // if DSP28_ECANB
    
    //
    // InitECanGpio - This function initializes GPIO pins to function as eCAN pins
    //
    // Each GPIO pin can be configured as a GPIO pin or up to 3 different
    // peripheral functional pins. By default all pins come up as GPIO
    // inputs after reset.
    //
    // Caution:
    // Only one GPIO pin should be enabled for CANTXA/B operation.
    // Only one GPIO pin shoudl be enabled for CANRXA/B operation.
    // Comment out other unwanted lines.
    //
    void 
    InitECanGpio(void)
    {
        InitECanbGpio();
    }
    
    //
    // InitECanaGpio - This function initializes GPIO pins to function as eCAN- A
    //
    void 
    InitECanaGpio(void)
    {
        EALLOW;
    
        //
        // Enable internal pull-up for the selected CAN pins
        // Pull-ups can be enabled or disabled by the user.
        // This will enable the pullups for the specified pins.
        // Comment out other unwanted lines.
        //
        //GpioCtrlRegs.GPAPUD.bit.GPIO30 = 0; // Enable pull-up for GPIO30 (CANRXA)
        GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0; // Enable pull-up for GPIO18 (CANRXA)
    
        //GpioCtrlRegs.GPAPUD.bit.GPIO31 = 0;  //Enable pull-up for GPIO31 (CANTXA)
        GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0;  //Enable pull-up for GPIO19 (CANTXA)
    
        //
        // Set qualification for selected CAN pins to asynch only
        // Inputs are synchronized to SYSCLKOUT by default.
        // This will select asynch (no qualification) for the selected pins.
        //
        //GpioCtrlRegs.GPAQSEL2.bit.GPIO30 = 3;   // Asynch qual for GPIO30 (CANRXA)
        GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3;  // Asynch qual for GPIO18 (CANRXA)
    
        //
        // Configure eCAN-A pins using GPIO regs
        // This specifies which of the possible GPIO pins will be eCAN functional 
        // pins.
        //
        //GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1;	// Configure GPIO30 for CANRXA
        GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 3;	// Configure GPIO18 for CANRXA
        //GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1;	// Configure GPIO31 for CANTXA
        GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 3;	// Configure GPIO19 for CANTXA
    
        EDIS;
    }
    
    #if (DSP28_ECANB)
    //
    // InitECanbGpio - This function initializes GPIO pins to function as eCAN-B
    //
    void 
    InitECanbGpio(void)
    {
        EALLOW;
    
        //
        // Enable internal pull-up for the selected CAN pins
        // Pull-ups can be enabled or disabled by the user.
        // This will enable the pullups for the specified pins.
        // Comment out other unwanted lines.
        //
        //GpioCtrlRegs.GPAPUD.bit.GPIO8 = 0;	  //Enable pull-up for GPIO8 (CANTXB)
        //GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0;   //Enable pull-up for GPIO12(CANTXB)
        GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0;   //Enable pull-up for GPIO16(CANTXB)
        //GpioCtrlRegs.GPAPUD.bit.GPIO20 = 0;   //Enable pull-up for GPIO20(CANTXB)
    
        //GpioCtrlRegs.GPAPUD.bit.GPIO10 = 0;	  // Enable pull-up for GPIO10(CANRXB)
        //GpioCtrlRegs.GPAPUD.bit.GPIO13 = 0;  // Enable pull-up for GPIO13(CANRXB)
        GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;  // Enable pull-up for GPIO17(CANRXB)
        //GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0;  // Enable pull-up for GPIO21(CANRXB)
    
        //
        // Set qualification for selected CAN pins to asynch only
        // Inputs are synchronized to SYSCLKOUT by default.
        // This will select asynch (no qualification) for the selected pins.
        // Comment out other unwanted lines.
        //
        //GpioCtrlRegs.GPAQSEL1.bit.GPIO10 = 3; // Asynch qual for GPIO10 (CANRXB)
        //GpioCtrlRegs.GPAQSEL1.bit.GPIO13 = 3; // Asynch qual for GPIO13 (CANRXB)
        GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3; // Asynch qual for GPIO17 (CANRXB)
        //GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 3; // Asynch qual for GPIO21 (CANRXB)
    
        //
        // Configure eCAN-B pins using GPIO regs
        // This specifies which of the possible GPIO pins will be eCAN functional 
        // pins.
        //
        //GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 2;   // Configure GPIO8 for CANTXB
        //GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 2;  // Configure GPIO12 for CANTXB 
        GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 2;  // Configure GPIO16 for CANTXB
        //GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 3;  // Configure GPIO20 for CANTXB 
    
        //GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 2;  // Configure GPIO10 for CANRXB
        //GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 2;  // Configure GPIO13 for CANRXB
        GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 2;  // Configure GPIO17 for CANRXB
        //GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 3;  // Configure GPIO21 for CANRXB
    
        EDIS;
    }
    #endif // if DSP28_ECANB
    
    //
    // Note: Bit timing parameters must be chosen based on the network parameters 
    // such as the sampling point desired and the propagation delay of the network.
    // The propagation delay is a function of length of the cable, delay introduced
    // by the transceivers and opto/galvanic-isolators (if any).
    //
    // The parameters used in this file must be changed taking into account the 
    // above mentioned factors in order to arrive at the bit-timing parameters 
    // suitable for a network.
    //
    
    //
    // End of File
    //
    
    

    // Clear MTOF0
    // MTOF0 cannot be manually cleared. It is automatically cleared when TOSn is cleared,
    // which is automatically cleared when the message is successfully transmitted.

  • Is that correct?

    Correct. 

    That is a tested example. Please run it “as is” and then do a file compare with your source. 

    Remember that the interrupt mapping for CAN-B module is different from that of CAN-A, so you need to modify the interrupt related lines. Check if these 2 lines need to be modified for CAN-B: 

    PieVectTable.ECAN0INTA = &eCAN0INT_ISR;
    
    PieVectTable.ECAN1INTA = &eCAN1INT_ISR;      

        

  • Thanks.  The interrupt happens after I made the following change

    //Change PieVectTable.ECAN0INTA to PieVectTable.ECAN0INTB and PieVectTable.ECAN1INTA to PieVectTable.ECAN1INTB
    PieVectTable.ECAN0INTB = &eCAN0INT_ISR;
    PieVectTable.ECAN1INTB = &eCAN1INT_ISR;

    However, eCAN1INT_ISR is called instead of eCAN0INT_ISR.

    Line 140 through 144 in the CAN_MOTO_A Example code sets up the Mailbox Timeout interrupt for interrupt line 0 and not interrupt line 1, so  why is Mailbox timeout occurring for interrupt line1?

    //This essentially sets ECanbShadow.CANGIM.bit.GIL = 0
    ECanbShadow.CANGIM.all = 0; 
    ECanbShadow.CANGIM.bit.I0EN = 1; // Enable eCAN0INT 
    ECanbShadow.CANGIM.bit.I1EN = 1; // Enable eCAN1INT 
    ECanbShadow.CANGIM.bit.MTOM = 1; // Enable MBX Timeout interrupt 
    ECanbRegs.CANGIM.all = ECanbShadow.CANGIM.all;

    Ok, if the software can not clear the Mailbox receive timeout interrupt, what does the software do if the message is never received? 

    I currently have one of the received mailboxes to time out in 4ms. After, 4ms one of two things may happen based on the the state of the code:

    1. Transmit a message.

    2. Wait for another message to be received with same timeout.

    Stephen

  • Line 140 through 144 in the CAN_MOTO_A Example code sets up the Mailbox Timeout interrupt for interrupt line 0 and not interrupt line 1, so why is Mailbox timeout occurring for interrupt line1?

     

    Those lines *enable* the interrupt lines, but does not choose the specific interrupt line. The specific interrupt selection is done by the following lines: 

    ECanaShadow.CANMIL.bit.MIL0 = 0 ; // MBOX0 asserts MTOF0 (eCAN0INT)
    ECanaShadow.CANMIL.bit.MIL0 = 1 ;  // MBOX0 asserts MTOF1 (eCAN1INT)
    

     

    Ok, if the software can not clear the Mailbox receive timeout interrupt, what does the software do if the message is never received?

    Please refer to section 2.18.3 in SPRUEU1:

    Time-out condition occurs. Both MTOF0/1 bit and TOS.n bits are set. Communication is never successful; i.e., the frame was never transmitted (or received). An interrupt is asserted. Application handles the issue and eventually clears both MTOF0/1 bit and TOS.n bit. 

    Although I haven’t tried this specific condition (message is never transmitted or received), it appears the application is able to clear the MTOF.n and TOS.n bit. You should be able to clear the TOS.n by clearing TOC.n

  • Hello Hareesh,

    I was able to clear the timeout flag with the code shown below.  That piece of code also sets the timeout to 4ms (=0.004*1Mbit/sec).

    I also changed the mailbox from a transmit to a receive mailbox and removed the transmit pieces of code (please see all changes in attached MOTO_A.c file).

    The receive timeout is now occurring every 4ms (which I was able to see by toggling GPIO8). 

    Thanks for all your help.

    Stephen

    ECanbShadow.CANTOC.all = 0;
    ECanbShadow.CANTOC.bit.TOC0 = 0;
    ECanbRegs.CANTOC.all = ECanbShadow.CANTOC.all;
    
    ECanbMOTORegs.MOTO0 = 4000;
    
    ECanbShadow.CANTOC.all = 0;
    ECanbShadow.CANTOC.bit.TOC0 = 1;
    ECanbRegs.CANTOC.all = ECanbShadow.CANTOC.all;
    
    ECanbRegs.CANTSC = 0;

    // TI Release: 28xx eCAN programming example
    // Release Date: Fri Aug 4 2017
    // Copyright:
    // Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // 
    
    /*********************************************************************
    * Filename: MOTO.c                                                
    *                                                                    
    * Description: This example illustrates the "MOTO" feature.
    * (MOTO - Message Object Time-Out)
    * Deliberately let a transmit mailbox timeout and check whether the
    * corresponding interrupt flag (MTOFn) and TOSn is set.
    * Mailbox 0 is used in this example
    *
    **********************************************************************/
    
    //
    // Included Files
    //
    #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    
    // Variable declarations
    
    long      i;
    int int0count = 0;		// Counter to track the # of level 0 interrupts
    int int1count = 0;	    // Counter to track the # of level 1 interrupts
    
    // Prototype statements for functions found within this file.
    
    interrupt void eCAN0INT_ISR(void);
    interrupt void eCAN1INT_ISR(void);
    
    /* Create a shadow register structure for the CAN control registers. This is
     needed, since, only 32-bit access is allowed to these registers. 16-bit access
     to these registers could potentially corrupt the register contents. This is
     especially true while writing to a bit (or group of bits) among bits 16 - 31 */
    
    struct ECAN_REGS ECanbShadow;
    
    void InitECan(void);
    
    main() 
    {
    
    /* Kill Watchdog, Init PLL, Enable peripheral clocks */
    
            InitSysCtrl();
    
    /* Initialize the CAN module */
    
            InitECan();
            InitECanGpio();
    
            //TestPointsInit();
            EALLOW;
            GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 0;
            GpioCtrlRegs.GPADIR.bit.GPIO8 = 1;
            GpioDataRegs.GPACLEAR.bit.GPIO8 = 1;
    
    
    
    /* Initialize PIE vector table To a Known State: */
    	// The PIE vector table is initialized with pointers to shell "Interrupt 
        // Service Routines (ISR)".  The shell routines are found in DSP28_DefaultIsr.c.
    	// Insert user specific ISR code in the appropriate shell ISR routine in 
        // the DSP28_DefaultIsr.c file.
        
        // InitPieVectTable();	 // uncomment this line if the shell ISR routines are needed
        
        // This function is found in DSP28_PieVect.c. It populates the PIE vector table
        // with pointers to the shell ISR functions found in DSP28_DefaultIsr.c. This 
        // function is not useful in this code because the user-specific ISR is present
        // in this file itself. The shell ISR routine in the DSP28_DefaultIsr.c file is
        // not used. If the shell ISR routines are needed, uncomment this line and add 
        // DSP28_PieVect.c & DSP28_DefaultIsr.c files to the project
    
    /* Disable and clear all CPU interrupts: */
    
    	DINT;
    	IER = 0x0000;
    	IFR = 0x0000;
    
    /* Initialize Pie Control Registers To Default State */
            
    	InitPieCtrl(); // This function is found in the DSP28_PieCtrl.c file. 
    
     /* Write to the MSGID field */
        
        ECanbMboxes.MBOX0.MSGID.all  = 0x9555AA00;
         
     /* Configure Mailbox under test as Tx */
    
    	ECanbRegs.CANMD.all = 1; 		// Mailbox 0 is a rx mailbox..
    	
    /* Enable Mailbox under test */
    	
    	ECanbShadow.CANME.all = ECanbRegs.CANME.all;
    	ECanbShadow.CANME.bit.ME0 = 1;
    	ECanbRegs.CANME.all = ECanbShadow.CANME.all;
    	
    /* Write to Master Control field */
     
        ECanbMboxes.MBOX0.MSGCTRL.bit.DLC = 8;
            
    /* Write to the mailbox RAM field */
        
         //ECanbMboxes.MBOX0.MDL.all = 0x9555AAA0;
    	 //ECanbMboxes.MBOX0.MDH.all = 0x89ABCDEF;
    		           
    /* Configure CAN interrupts */ 
    
    	ECanbShadow.CANMIL.all = ECanbRegs.CANMIL.all;
    	//ECanbShadow.CANMIL.bit.MIL0 = 0 ; // MBOX0 asserts MTOF0 (eCAN0INT)
    	ECanbShadow.CANMIL.bit.MIL0 = 1 ;  // MBOX0 asserts MTOF1 (eCAN1INT)
    	ECanbRegs.CANMIL.all = ECanbShadow.CANMIL.all;
    	
    	ECanbShadow.CANGIM.all = 0;
        ECanbShadow.CANGIM.bit.I0EN = 1;     // Enable eCAN0INT
        ECanbShadow.CANGIM.bit.I1EN = 1;	 // Enable eCAN1INT
        ECanbShadow.CANGIM.bit.MTOM = 1;	 // Enable MBX Timeout interrupt
        ECanbRegs.CANGIM.all = ECanbShadow.CANGIM.all;
        
    /* Reassign ISRs. i.e. reassign the PIE vector for ECAN0INTA_ISR and ECAN0INTA_ISR 
       to point to a different ISR than the shell routine found in DSP28_DefaultIsr.c.
       This is done if the user does not want to use the shell ISR routine but instead
       wants to embed the ISR in this file itself. */
    	
    	PieVectTable.ECAN0INTB = &eCAN0INT_ISR;
    	PieVectTable.ECAN1INTB = &eCAN1INT_ISR;
        
    /* Configure PIE interrupts */    
      
    	PieCtrlRegs.PIECTRL.bit.ENPIE = 1;  // Enable vector fetching from PIE block
    	
    	PieCtrlRegs.PIEACK.bit.ACK9 = 1;    // Enables PIE to drive a pulse into the CPU
    
    // The 'MOTO' interrupt can be asserted in either of the eCAN interrupt lines
    // Comment out the unwanted line...
    
    	PieCtrlRegs.PIEIER9.bit.INTx7 = 1;  // Enable INTx.5 of INT9 (eCAN0INT)
    	PieCtrlRegs.PIEIER9.bit.INTx8 = 1;  // Enable INTx.6 of INT9 (eCAN1INT)
    	
    /* Configure system interrupts */
    	
    	IER |= 0x0100;					// Enable INT9 of CPU
    	EINT;							// Global enable of interrupts   
    	
    /* Write to MOTO reg of Mailbox under test */
    
    	ECanbMOTORegs.MOTO0 = 4000; // It was experimentally determined that
    						// this value would let MBX0 to timeout...MOTS0 contains
    						// 8Eh after transmission is complete..See Note 1
    						// This value may have to tweaked a bit based on the clock frequency etc..
    
    /* Enable time-out function for the mailbox */
        	 	
        ECanbShadow.CANTOC.all = 0;
    	ECanbShadow.CANTOC.bit.TOC0 = 1;
    	ECanbRegs.CANTOC.all = ECanbShadow.CANTOC.all;
    	
    /* Clear the "Time Stamp Counter"  */
    
    	ECanbRegs.CANTSC = 0;
    
    /* Begin transmitting */       
    #if 0
         ECanbShadow.CANTRS.all = 0;
         ECanbShadow.CANTRS.bit.TRS0 = 1;     // Set TRS for mailbox under test
         ECanbRegs.CANTRS.all = ECanbShadow.CANTRS.all;
    #endif
    
         while(1){ asm(" NOP"); };
         for(i=0; i<111999999; i++) 	// A very long loop. Code loops here when CAN module transmits
    	 	{ asm(" NOP"); }        // the data and executes the ISR
    	 
    	 asm(" ESTOP0");									 // Code stops here after transmission
    
    }
    
    /* --------------------------------------------------- */
    /* ISR for PIE INT9.5                                  */
    /* Connected to HECC0-INTA  eCAN                       */
    /* ----------------------------------------------------*/
    
    interrupt void eCAN0INT_ISR(void)  // eCAN
    {
       ECanbShadow.CANTOS.all = ECanbRegs.CANTOS.all ;  // Copy TOS reg for inspection
       ECanbShadow.CANGIF0.all = ECanbRegs.CANGIF0.all; // Copy GIF0 reg for inspection
    
       ECanbShadow.CANTOC.all = 0;
    	ECanbShadow.CANTOC.bit.TOC0 = 1;
    	ECanbRegs.CANTOC.all = ECanbShadow.CANTOC.all;
         
       ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;
          do {ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;}   // Wait for TA0 bit to be set..
           while(ECanbShadow.CANTA.bit.TA0 == 0 );
    
    // Clear TAn  
       ECanbShadow.CANTA.all = 0; 			// Initialize TA to zero before setting any
       ECanbShadow.CANTA.bit.TA0 = 1 ;		// bit in order to clear it. Otherwise, some
       							// other TAn bit that is set could be inadvertently cleared
       ECanbRegs.CANTA.all =  ECanbShadow.CANTA.all ;   // Clear TAn bit
    
    // Clear MTOF0   
       // MTOF0 cannot be manually cleared. It is automatically cleared when TOSn is cleared, 
       // which is automatically cleared when the message is successfully transmitted.
       
    
    // Re-enable PIE and Core interrupts   
       PieCtrlRegs.PIEACK.bit.ACK9 = 1;    	// Enables PIE to drive a pulse into the CPU
       IER |= 0x0100;					 	// These 2 lines allow for nested interrupts 
       EINT;								// Strictly not needed for this example.
       int0count++;
       return;
    }
    
    /* --------------------------------------------------- */
    /* ISR for PIE INT9.6                                  */
    /* Connected to HECC1-INTA  eCAN                       */
    /* ----------------------------------------------------*/
    
    interrupt void eCAN1INT_ISR(void)  // eCAN
    {
    	EALLOW;
       GpioDataRegs.GPASET.bit.GPIO8 = 1;
    
       ECanbShadow.CANTOS.all = ECanbRegs.CANTOS.all ;  // Copy TOS reg for inspection
       ECanbShadow.CANGIF1.all = ECanbRegs.CANGIF1.all; // Copy GIF1 reg for inspection
    
       ECanbShadow.CANTOC.all = 0;
       ECanbShadow.CANTOC.bit.TOC0 = 0;
       ECanbRegs.CANTOC.all = ECanbShadow.CANTOC.all;
    
       ECanbMOTORegs.MOTO0 = 4000;
    
       ECanbShadow.CANTOC.all = 0;
       ECanbShadow.CANTOC.bit.TOC0 = 1;
       ECanbRegs.CANTOC.all = ECanbShadow.CANTOC.all;
    
       ECanbRegs.CANTSC = 0;
       
    #if 0
       ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;
          do {ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;}   // Wait for TA0 bit to be set..
            while(ECanbShadow.CANTA.bit.TA0 == 0 );
    
     //Clear TAn
    
       ECanbShadow.CANTA.all = 0; 			// Initialize TA to zero before setting any
       ECanbShadow.CANTA.bit.TA0 = 1 ;		// bit in order to clear it. Otherwise, some
       							// other TAn bit that is set could be inadvertently cleared
       ECanbRegs.CANTA.all =  ECanbShadow.CANTA.all ;   // Clear TAn bit
    #endif
    // Clear MTOF1   
       // MTOF1 cannot be manually cleared. It is automatically cleared when TOSn is cleared, 
       // which is automatically cleared when the message is successfully transmitted.
       
    // Re-enable PIE and Core interrupts   
       PieCtrlRegs.PIEACK.bit.ACK9 = 1;    // Enables PIE to drive a pulse into the CPU
       IER |= 0x0100;					 // Enable INT9 
       EINT;
       int1count++;
    
       GpioDataRegs.GPACLEAR.bit.GPIO8 = 1;
       EDIS;
       return;
    }
    
    /* Notes:
    
    The TOS.n bit will be cleared upon (eventual) successful transmission.
    The only way to ascertain if a time-out occurred is to copy TOS and GIFn
    registers in the ISR to check if the relevant bits were set when the 
    ISR was just entered. 
    
    It can be verified that whether the MTOF bit gets set in GIF0 or GIF1 
    depends on the value of MILn. 
    
    This example is useful to check that MTOFn gets cleared if TOSn is cleared. 
    
    Note 1: TSC does not start running until the bit timing registers
    are configured. After configuration, it is a free running timer clocked by the 
    bit rate clock of the CAN module. The delay between the last instruction 
    that configures the bit timing to the instruction that initiates transmission will
    therefore affect this "experimentally determined" value. Since the counter runs at
    the bit clock rate, the fastest bit clock rate is 1 uS, which equates to 150 CPU
    clock cycles (@ 150 MHz SYSCLKOUT). Therefore adding/deleting a few instructions 
    will not make a significant change. A delay loop would.
    
    */
    
    

      

  • Hareesh J said:

    Those lines *enable* the interrupt lines, but does not choose the specific interrupt line. The specific interrupt selection is done by the following lines: 

    1
    2
    ECanaShadow.CANMIL.bit.MIL0 = 0 ; // MBOX0 asserts MTOF0 (eCAN0INT)
    ECanaShadow.CANMIL.bit.MIL0 = 1 ;  // MBOX0 asserts MTOF1 (eCAN1INT)

    So, the Rx mailbox interrupt and the Mailbox Timeout interrupt will occur on the same interrupt line?

    I had thought the Mailbox Timeout interrupt was part of the global interrupts.

  • Ok, I found the answer on page 46 of the ECan documentation (sprueu1.pdf) (see below).

  • Did you attempt to clear TOS.n directly (either by writing a 1 or a 0) first? Just curious.

  • Yes, that is what I initially tried to do yesterday.  I tried writing both, a 1 and 0.

    Thanks,

    Stephen

  • While reading the material in the Reference Guide, I saw how it can be confusing to the user. I am thinking of changing the wordings as follows: (I have highlighted the sentences I modified) 

    1. Time-out condition occurs: Both MTOF.n and TOS.n bits are set. Communication is never successful; that is, the frame was never transmitted (or received). An interrupt is asserted. Application handles the issue and clears TOC.n bit which clears TOS.n bit which in turn clears the MTOF.n bit.

    2. Time-out condition occurs. Both MTOF.n and TOS.n bits are set. However, communication is eventually successful; that is, the frame gets transmitted (or received). Both MTOF.n and TOS.n bits are cleared automatically by the CPK. An interrupt is still asserted because, the interrupt occurrence was recorded in the PIE module. When the ISR scans the GIF register, it doesn't see the MTOF0/1 bit set. This is the phantom interrupt scenario. This is handled per the application requirements.

    Please let me know what you feel about the new wordings, from a user perspective.

  • Stephen,

      Any thoughts?

  • That sounds good to me.  I also set TSC = 0 before I clear TOC, but I am not sure if that is necessary.

    Thanks.

  • TSC is a free-running counter that is clocked at the rate of the CAN bit-clock. At 1 Mbps, the counter would overflow every 4295 seconds. Clearing the counter before that is application dependent (whether there are other mailboxes that are configured for time-out etc). 

    Thank you for your feedback. I’ll close this post.