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.

ECana1 interrupt is generated without Timer0 for scheduling CAN message transmission but not generated with Timer0

Other Parts Discussed in Thread: TMS320F2812, TMS320F28335

Hello All;

 

I am using TMS320F2812 for developing embedded application. My application has ECana1 interface communicating with remote system. I would like to schedule transmission of CAN message every 130 us. I am using Timer0 for scheduling CAN message transmission.

When i transmit CAN message without Timer0 (in Timer0 ISR), message is transmitted successfully on CAN bus, CAN Transmit Acknowledge flag (TA2) is set.

But, when i schedule my CAN message transmission with Timer0 (in Timer0 ISR), message is not transmitted on CAN bus, CAN Transmit Acknowledge flag (TA2) is not set.

I have set breakpoints in ECana1 ISR --> case 2 in application software under both conditions mentioned above (With Timer0 and Without Timer0). When Timer0 is not used for scheduling CAN message transmission, program halts at breakpoint, but when Timer0 is used for scheduling CAN message transmission, program does not halts at breakpoint.

What could be the reason for the program not halting at breakpoint when Timer0 is used for CAN message scheduling ?

Please suggest solutions to this problem.

 

Thank you,

Sunil Sawant

I have pasted my program code below:

/*---------------------- Application Main.c - Start ------------------------*/

#include "DSP281x_Device.h"
#include "DSP281x_Examples.h"

 

 

 

 

/* Global Variable Declarations */
struct ECAN_REGS ECanaShadow;
struct ECAN_REGS ECanbShadow;
//struct ECAN_MBOXES ECanaReadData;

t__TMS320F2812ECanaTransactionDataObject tTMS320F2812ECanaTransactionDataObject;
t__TMS320F2812ECanaTransactionStatusFlags tTMS320F2812ECanaTransactionStatusFlags;
t__TMS320F2812ECanaMailboxReceiveObject tTMS320F2812ECanaMailboxReceiveObject;
t__TMS320F2812ECanaMailboxTransmitObject tTMS320F2812ECanaMailboxTransmitObject;
t__TMS320F2812ECanaMessageObject tTMS320F2812ECanaMessageObject;


//Uint32 u32TransmitMDH = 0x08070605;
//Uint32 u32TransmitMDL = 0x04030201;
Uint32 u32TransmitMDH = 0x02010F0E;
Uint32 u32TransmitMDL = 0x0D0C0B0A;
Uint32 mdh = 0;
Uint32 mdl = 0;

 

 

 

void main(void)
{
 /* Step 1. Initialize System Control:          */
 /*   PLL, WatchDog, enable Peripheral Clocks       */
 /*   This example function is found in the DSP2833x_SysCtrl.c file. */
 InitSysCtrl();

 /* Step 2. Configure MCU pins to be used by eCANA */
 //InitECanGpio();

 /* Step 3. Initialize the eCAN module */
 InitECan();

 /* Step 4. Initialize the CPU Timers */
 InitCpuTimers();

 /* Step 5. Configure CPU Timers */
 /* 100MHz CPU Freq, 1 second Period (in uSeconds) */
 ConfigCpuTimer(&CpuTimer0, 150, 130);

 /* Step 6. Initialize the PIE vector table with pointers to the shell Interrupt */
 /*   Service Routines (ISR).             */
 /*   This will populate the entire table, even if the interrupt    */
 /*   is not used in this example.  This is useful for debug purposes.  */
 /*   The shell ISR routines are found in DSP2833x_DefaultIsr.c.    */
 /*   This function is found in DSP2833x_PieVect.c.       */
 InitPieVectTable();

 /* Step 7. Clear all interrupts and initialize PIE vector table.  */
 /*   Disable CPU interrupts and clear all CPU interrupt flags. */
 DINT;
 IER = 0x0000;
 IFR = 0x0000;

 /* Step 8. Initialize the PIE control registers to their default state. */
 /*   The default state is all PIE interrupts disabled and flags  */
 /*   are cleared.             */
 /*   This function is found in the DSP2833x_PieCtrl.c file.   */
 InitPieCtrl();

 /* Step 9. Disable interrupts again (for now) */
 DINT;

 /* Step 10. Interrupts that are used in this example are re-mapped to */
 /*      ISR functions found within this file.      */
 EnableInterrupts();

 /* Step 11. Initialize Mailbox Queues */
 //vInitializeMailboxQueues();

 /* Step 12. Now eCANA is ready to transmit/receive message on CAN bus */

 //vTransmitECanaMessage(&u32TransmitMDH, &u32TransmitMDL);
 vStartCpuTimer(&CpuTimer0);

 

 

 while(1)
 {
  asm(" NOP");
  asm(" NOP");
  asm(" NOP");

  //vTransmitECanaMessage(&u32TransmitMDH, &u32TransmitMDL);
  asm(" NOP");
  //vTransmitECanaMailbox1Message(&u32TransmitMDH, &u32TransmitMDL);
  asm(" NOP");
  //vTransmitECanaMailbox2Message(&u32TransmitMDH, &u32TransmitMDL);
  asm(" NOP");
  ///vTransmitECanaMailbox3Message(&u32TransmitMDH, &u32TransmitMDL);
  asm(" NOP");
  //vTransmitECanaMailbox4Message(&u32TransmitMDH, &u32TransmitMDL);
  asm(" NOP");
  //vTransmitECanaMailbox5Message(&u32TransmitMDH, &u32TransmitMDL);
  asm(" NOP");

  //vCommandTransmittingControlParameters();
  if(tTMS320F2812ECanaTransactionStatusFlags.Mailbox2.bit.b1CmdTxgCtrlParMsgTxd == 1)
  {
   //vStopCpuTimer(&CpuTimer0);
   tTMS320F2812ECanaTransactionStatusFlags.Mailbox2.bit.b1CmdTxgCtrlParMsgTxd = 0;
   vTransmitECanaMailbox2Message(&u32TransmitMDH, &u32TransmitMDL);

   asm(" NOP");
  }

  asm(" NOP");
  asm(" NOP");
  asm(" NOP");
 }
}

/*---------------------- Application Main.c - End -------------------------*/

 

*---------------------- DSP28xx_PieCtrl.c - Start -------------------------*/

void EnableInterrupts(void)
{
/*
    // Enable the PIE
    PieCtrlRegs.PIECRTL.bit.ENPIE = 1;
      
 // Enables PIE to drive a pulse into the CPU
 PieCtrlRegs.PIEACK.all = 0xFFFF; 

 // Enable Interrupts at the CPU level
    EINT;
*/

 /* ---------- eCANA Peripheral Mailboxes Enable - Start ----------- */
    /* Enable the PIE */
 PieCtrlRegs.PIECRTL.bit.ENPIE = 1;

 /* Enables PIE to drive a pulse into the CPU */
 PieCtrlRegs.PIEACK.all = 0xFFFF;

 /* Configure CAN interrupts */
 ECanaShadow.CANMIL.all = ECanaRegs.CANMIL.all;
 ECanaShadow.CANMIL.all = 0xFFFFFFFF; // Interrupts asserted on eCAN0INT and eCAN1INT
 ECanaRegs.CANMIL.all = ECanaShadow.CANMIL.all;

 /* Disable register-write protection, since CANGIM and CANMIM registers are EALLOW protected */
 EALLOW;

 ECanaShadow.CANMIM.all = ECanaRegs.CANMIM.all;
 //ECanaShadow.CANMIM.all = 0x00000006; // Enable interrupts for mailboxes 1 and 2
 ECanaShadow.CANMIM.all = 0xFFFFFFFF; // Enable interrupts for all mailboxes
 ECanaRegs.CANMIM.all = ECanaShadow.CANMIM.all;

 ECanaShadow.CANGIM.all = ECanaRegs.CANGIM.all;
 ECanaShadow.CANGIM.all = 0;
 ECanaShadow.CANGIM.bit.AAIM = 1;  // Enable Abort Interrupt
 ECanaShadow.CANGIM.bit.WDIM = 1;  // Enable Watchdog Timer Interrupt
 ECanaShadow.CANGIM.bit.WUIM = 1;  // Enable
 ECanaShadow.CANGIM.bit.BOIM = 1;  // Enable
 ECanaShadow.CANGIM.bit.EPIM = 1;  // Enable
 ECanaShadow.CANGIM.bit.WLIM = 1;  // Enable
 ECanaShadow.CANGIM.bit.I0EN = 1;  // Enable eCAN1INT or eCAN0INT
 ECanaShadow.CANGIM.bit.I1EN = 1;
 ECanaRegs.CANGIM.all = ECanaShadow.CANGIM.all;
 /* ---------- eCANA Peripheral Mailboxes Enable - End ------------ */

 /* ---------- eCANA Peripheral ISR Assignment - Start ----------- */
 /* 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 = &ECAN0INTA_ISR;
 PieVectTable.ECAN1INTA = &ECAN1INTA_ISR;
 /* ---------- eCANA Peripheral ISR Assignment - End ------------- */

 /* ---------- CPU Timer0 Peripheral Interrupt Lines - Start ---------- */
 PieVectTable.TINT0 = &TINT0_ISR;
 /* ---------- CPU Timer0 Peripheral Interrupt Lines - End ------------ */

 /* Enable register-write protection */
 EDIS;

 /* ---------- eCANA Peripheral Interrupt Lines - Start ---------- */
 /* Configure PIE interrupts */
 //PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable vector fetching from PIE block
 PieCtrlRegs.PIECRTL.bit.ENPIE = 1;
 PieCtrlRegs.PIEACK.bit.ACK9 = 1; // Enables PIE to drive a pulse into the CPU
 // The interrupt can be asserted in either of the eCAN interrupt lines
 // Comment out the unwanted line...
 PieCtrlRegs.PIEIER9.bit.INTx5 = 0; // Enable INTx.5 of INT9 (eCAN0INT)
 PieCtrlRegs.PIEIER9.bit.INTx6 = 1; // Enable INTx.6 of INT9 (eCAN1INT)

 /* Configure system interrupts */
 IER |= 0x0100;      // Enable INT9 of CPU
 /* ---------- eCANA Peripheral Interrupt Lines - End ------------ */

 /* ---------- Timer0 Peripheral Interrupt Lines - Start ---------- */
 /* Enable CPU INT1 which is connected to CPU TIMER0 INT: */
 //IER |= M_INT10; //M_INT1;
 PieCtrlRegs.PIECRTL.bit.ENPIE = 1;
 PieCtrlRegs.PIEACK.bit.ACK10 = 1;

 /* Enable Timer0 INTn in the PIE: Group 3 interrupt 1-6 */
 //PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
 PieCtrlRegs.PIEIER10.bit.INTx7 = 1;

 IER |= M_INT10; //M_INT1;  // Enable INT10 of CPU
 /* ---------- Timer0 Peripheral Interrupt Lines - End ------------ */

 /* Enable Interrupts at the CPU level */
    EINT;

    /* Enable Global realtime interrupt DBGM */
    ERTM;
}

*---------------------- DSP28xx_PieCtrl.c - End -------------------------*/

 

/*---------------------- DSP28xx_DefaultISR.c - Start -------------------------*/

interrupt void ECAN1INTA_ISR(void)  // eCAN-A
{
  // Insert ISR Code here
 switch(ECanaRegs.CANGIF1.bit.MIV1)
 {

case 2 : // Mailbox 2 - Command Transmitting Control Parameters
   ECanaShadow.CANTA.all = 0;
   ECanaShadow.CANTA.bit.TA2 = 1;
   ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;

   asm(" NOP");

/*   ECanaShadow.CANRMP.all = 0;  // Clear RMP2 interrupt on eCAN1
   ECanaShadow.CANRMP.bit.RMP2 = 1;
   ECanaRegs.CANRMP.all = ECanaShadow.CANRMP.all;
*/  break;

case default :

break;

}

/*---------------------- DSP28xx_DefaultISR.c - End -------------------------*/

 

*---------------------- DSP28xx_DefaultISR.c - Start -------------------------*/

interrupt void  TINT0_ISR(void)      // CPU-Timer 0
{
 // Insert ISR Code here
 tTMS320F2812ECanaTransactionStatusFlags.Mailbox2.bit.b1CmdTxgCtrlParMsgTxd = 1;

 asm(" NOP");

 // To receive more interrupts from this PIE group, acknowledge this interrupt
 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

 // Next two lines for debug only to halt the processor here
 // Remove after inserting ISR Code
    //asm ("      ESTOP0");
    //for(;;);
}

*---------------------- DSP28xx_DefaultISR.c - End --------------------------*/

  • How fast did you initialize the CAN? Please keep in mind that at 1MBPS a single bit time is 1 microseconds. If your run CAN at that speed, a complete CAN - message ( 64 Data bit, 29 Bit ID, stuff bits and the rest of the frame) is in the region of your repetition rate of 130 microseconds.
    I'd recommend to experiment with slower datarates first, e.g. 100 kBPS to see, if the problem persists.

    Frank
  • Dear Frank,


    Thank you for your reply to my post.
    My program ia working in Self-Test Mode at 1 Mbps.
    When i disable Self-Test Mode, program does not works as expected.

    Also, i have few observations:
    During message transmission, after setting TRS bit, i poll for setting of TA bit. But no success.
    Datasheet says, unless TA bit is set, message transmission is not complete.
    I understand TA bit not setting is not directly related to subject of this post.
    But i have a hunch that setting of TA bit may resolve the problem mentioned in this post.


    Thank you,

    Sunil Sawant
  • As you said, your last reply is a different question. Anyway, let me try to explain this 2nd topic again (if you search the E2E for "CAN TA" you will find a lot of threads...):

    1.) CAN-TA is set by the CAN-Engine, if a message has been transmitted succesfully (ACK) - YOU cannot set TA.  What you do is you clear TA (after it has been set by the CAN-CC), by writing a 1 into the TA-bitfield. Again, you cannot set TA! Ta is a sort of handshake between you and the CAN - CC (CC = Communication Controller).

    2.) If you disable Self-Test - you will need a real 2nd node on CAN to produce the ACK, so that your CAN-CC is able to set TA.  If there is no 2nd node - no ACK!

    3.) Most CAN monitoring devices, such as Vectors CAN-cards and the cheap USB to CAN device operate by default in "silent mode" - they will NOT generate ACK.

  • Dear Frank,



    Thank you for your reply.

    I have followed the steps for data transmission on CAN interface as mentioned in Section 3.2.1 of TMS320F2833x, 2823x
    Enhanced Controller Area Network (eCAN) Reference Guide (sprueu1.pdf).
    In the said section of the document, Step 1 suggests the programmer to set TRR.n bit of the mailbox to purge earlier transmissions. Is this really needed ? Usually TRR.n bit is used to cancel transmissions from a mailbox.

    One latest observation is Abort Acknowledge (AA) flag is set for the mailbox from where data is to be transmitted.
    The reason for AA.n flag being set could be the setting of TRR.n bit for the mailbox from where data is to be transmitted.
    And since AA.n flag is set, so TA.n flag is also not set. Hence data transmission from mailbox is unsuccessful.
    Is my analysis correct based on the observation of eCAN registers ?

    In my development set-up, i am using TMS320F2812 as one of the CAN node and TMS320F28335 as other CAN node. Data transfer is in both directions.

    I am not using CAN bus analyzer for debugging of CAN messages.



    Thank you,

    Sunil Sawant
  • HI Frank/Sunil

    My reply to this post is one of my doubt and not at all as an answer to the query.

    I just wanted to know what is the benefit of using the interrupt with CAN.As it will take its required time to transmit and generate acknowledgement and even if we use interrupts they have to be timed in  such  a way that it allows transmission of the data (i.e. minimum possible time).Then how does it improves transmission?

    Kindly help me understand this.

    Frank as you already know from earlier posts,I am still struggling to get a minimum transmission time.The transmission time of 140 us is too huge for my application.Say I have two systems and I need to send a critical data from 1 to 2.System 2 should react before system1 fails.So,say I set a threshold below which  a warning message is transmitted but it will reach system 2 only after 140 us.This time is too huge for my system.Can there be a way I can first send this warning message at a faster rate and then keep transmitting the rest at the usual rate.

    Thanks & Regards

    Sneha

  • Dear Sneha,


    Answer 1: Benefit of using interrupt for CAN transmission.

    After message is transmitted on CAN bus by setting TRS.n bit, TA.n flag is set to indicate successful transmission.
    After this TA.n flag should be cleared for next transmission to begin. But how will the CPU know that transmission has completed successfully ? This is done by either polling TA.n flag or generating an interrupt (ECana1INTA_ISR).
    If CPU polls TA.n flag, the CPU will be busy waiting for TA.n flag to set. Polling would increase CPU utilization for handling CAN activities and would allot less time for handling other important tasks. Moreover, handling of data transfer should not be done by CPU, but by peripheral (if exists).
    In case of interrupt, CPU is not kept busy waiting for TA.n flag. CPU is now free to execute other important tasks till TA.n flag is set. When TA.n flag sets, CPU is alerted by generating an interrupt (ECana1INTA_ISR). The CPU after detecting an interrupt, jumps to ISR, clears the TA.n flag and resumes its usual important function.



    Answer 2: How to reduce data transmission time on CAN bus.

    Assume:
    CAN Bit Rate = 1 Mbps
    Time needed to transmit 1-bit of data on CAN bus = 1 / 1 x 10^6 = 1 microseconds.
    One CAN frame with standard identifier contains 108-bits.
    Hence to transmit 108-bits of data on CAN bus, 1 microseconds x 108 = 108 microseconds are needed.

    An additional buffer time of 20 microseconds - 30 microseconds should be allotted to account for bus delays.
    Total time required for transmission of 1 CAN message = 108 + 30 = 140 microseconds.

    If you want to transmit critical information on CAN bus, search for more information about Time Triggered CAN (TTCAN) on google. Also, you have to develop your own protocol to transmit time critical data on CAN bus.




    Thank you,

    Sunil Sawant
  • HI Sunil

    Thank you so much for the elaborate answer.

    1. From what I understand we can use either
    a. CANTA:

    ECanaShadow.CANTRS.all = 0;
    ECanaShadow.CANTRS.bit.TRS1 = 1; // Set TRS for mailbox under test
    ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;

     do
     {
     ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;
     } while(ECanaShadow.CANTA.bit.TA1 == 0 ); // Wait for TA5 bit to be set..

    ECanaShadow.CANTA.all = 0;
    ECanaShadow.CANTA.bit.TA1 = 1; // Clear TA5
    ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;
    }

     or

    b. CAN interrupt.

    ECanaShadow.CANTRS.all = 0;
    ECanaShadow.CANTRS.bit.TRS1 = 1; // Set TRS for mailbox under test
    ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;

    Calling CAN ISR and then processing the following.

    ECanaShadow.CANTA.all = 0;
    ECanaShadow.CANTA.bit.TA1 = 1; // Clear TA5
    ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;

    2. I will read about TTCAN.

    Thanks & Regards

    Sneha

  • Dear Sneha,

    You will have to check TA.n bit after setting TRS.n bit, in case of interrupt based CAN transmission.

    This will ensure data transmission is complete and will not result in incorrect results at receiver.

    I have highlighted the code to be appended in red color text.

    Thank you,

    Sunil Sawant

    b. CAN interrupt.

    ECanaShadow.CANTRS.all = 0;

    ECanaShadow.CANTRS.bit.TRS1 = 1; // Set TRS for mailbox under test

    ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;

    do

    {

    ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;

    } while(ECanaShadow.CANTA.bit.TA1 == 0 ); // Wait for TA5 bit to be set..

     

    Calling CAN ISR and then processing the following.

    ECanaShadow.CANTA.all = 0;

    ECanaShadow.CANTA.bit.TA1 = 1; // Clear TA5

    ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;

  • Hi Sunil

    Thanks for your Input.

    I tried implementng CAN_ISR  interrupt routinue for transmitting adc value using MBOX1.

    Yes,it is more effective and my transmission time has drastically reduced down to ns from us.But as per your previous explanation us time is correct.What am i missing or not understanding.

    should  Cpu timer interrupt be also used with CAN ISR and if yes why?

    Thanks & Reagrds

    Sneha 

  • CpuTimer interrupt could be used for scheduling CAN message transmissions at fixed time intervals. This way application becomes more deterministic with reference to time. You can analyze/debug/trace program easily without depending on uncertainties of while(1) super-loop. You can also predict application behavior based on timing calculations. i.e., you can decide when to transmit which CAN message well in advance on paper and then try to get same results.
    Summarizing, application development becomes simpler with CpuTimer interrupts.
    However, it is not necessary to use CpuTimer interrupts, if you are able to analyze/debug/trace your application in while(1) super-loop.
    Read about "Time-Triggered Embedded Systems" on www.google.co.in to learn more about this method of embedded software development.
  • Hi Sunil

    Thanks for your replies.

    I have read certain papers on TTCAN and I am now getting the crux of it.

    Once again thanks for your inputs.They were really useful.

    Regards

    Sneha

  • SUNIL SAWANT said:

     PieCtrlRegs.PIEACK.bit.ACK10 = 1;

     /* Enable Timer0 INTn in the PIE: Group 3 interrupt 1-6 */
     //PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
     PieCtrlRegs.PIEIER10.bit.INTx7 = 1;

     IER |= M_INT10; //M_INT1;  // Enable INT10 of CPU

    Hello Sunil,

    Isn't Timer0 Interrupt in Group 1? Why these lines are using Group 10?

    SUNIL SAWANT said:
     PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

    And in your Timer interrupt, you acknowledge Group1 which is not match with Group10.

    Best regards,

    Maria

  • Hi Maria,


    Thank you for your suggestions. I will implement your suggestions.



    Regards,

    Sunil Sawant