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.

eCAN receive sample code

Other Parts Discussed in Thread: TMS320F28335

Hi,

I am wondering if there is any sample code setting up interrupts whenever the mailboxes receive new messages successfully.

I manage to have eCAN sending and receiving messages correctly, however, the receiving is currently done by pulling CANRMP

like,

while(ECanaRegs.CANRMP.all != 0xffff0000 ){}

ECanaRegs.CANRMP.all = 0xffff0000;

//copy data from the mailbox to somewhere in memory

 

As I read the manual, it is possible to set up an interrupt mechanism whenever CANRMP is set by the eCAN module. In addition to the old code, I added the interrupt register related code

EALLOW;

//    ECanaRegs.CANMIM.all = 0xFFFFFFFF;

ECanaShadow.CANMIM.all = ECanaRegs.CANMIM.all;

ECanaShadow.CANMIM.bit.MIM16=1;               //enable mailbox 16 

ECanaRegs.CANMIM.all = ECanaShadow.CANMIM.all;

//mailbox interrupt mask register, Alfred

EDIS;

EALLOW;

//configure receiving to trigger interrupt

//enable INT1 of MBox16

ECanaShadow.CANMIL.all = ECanaRegs.CANMIL.all;

ECanaShadow.CANMIL.bit.MIL16=1; //enable eCAN1INT

ECanaRegs.CANMIL.all = ECanaShadow.CANMIL.all;

/*

//enable interrupt for MBox16

ECanaShadow.CANMIM.bit.MIM16=1;

ECanaRegs.CANMIM.all = ECanaShadow.CANMIM.all;

*/

//enable eCan1INT on GIM

ECanaShadow.CANGIM.all = 0;

ECanaShadow.CANGIM.bit.GIL = 1; //level INT1, 

ECanaShadow.CANGIM.bit.I1EN = 1;

ECanaRegs.CANGIM.all = ECanaShadow.CANGIM.all;


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 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)

EDIS;

// Configure system interrupts 

IER |= 0x0100;

 

This is my ISR

interrupt void eCAN1INT_ISR(void)  // eCAN

{

received++;

//clean the receive acknowledge bit

ECanaShadow.CANRMP.all = ECanaRegs.CANRMP.all;

ECanaRegs.CANRMP.all = ECanaShadow.CANRMP.all;


PieCtrlRegs.PIEACK.bit.ACK9 = 1;    // Enables PIE to drive a pulse into the CPU

IER |= 0x0100; // Enable INT9 

EINT;

return;

}

 

received is a global variable I declared. And I noticed that it is alway 0, that means interrupt never happened. I check the mailbox 16, and looks it receives the message correctly. I am so confused that why interrupt doesn't get triggered. What else in the million registers do I need to set?

When writing this code, I referred to multint2.c from spra876a I googled and downloaded.

Thanks!

  • Hi Alfred,

    After a quick glance at your code I'm wondering if the problem may be that you need to enable global interrupts with the command "EINT; " You have done this in your ISR, but you need to do this in your main code or you will never reach the ISR the first time. If you'll notice in the example code you refer to (multint.c from spra876a), "EINT;" is called right before entering the main while(1) loop, so I'd try adding that if you haven't already. Hope this helps!

    Regards,

    Katie

  • Hi Katie,

    Thanks a lot for the replay.

    Unfortunately, I did put EINT in the main function. However, it doesn't work. Do you have a working ECan receive interrupt example that I can look at. 

     

    Thanks,

    Alfred

  • Hi Alfred,

    If you use the example code from spra876a unmodified, does it work? I'd say that those examples are the best place to start, then start modifying to fit your application requirements.

    Regards,

    Katie

  • Hi Katie,

    spra876a examples are for F281x MCUs.

    However, I am using F28335, those header and source files are different. Therefore, I have no way to try those example without modifying it.

    Can I get an example for F28335?

    The only 2 examples I have are 

    ecan_a_to_b_xmit  and ecan_back2back from SPRC530.

    neither of them show how to enable interrupts upon receiving. 

     

    Thanks!

    Alfred

     

     

  • Hi Katie,

    I downloaded the TI teachingrom ssqc019, in lab11,

    Lab 11_4:

    Try to improve Lab11_2 and Lab11_3 by using the F2833x Interrupt System for the receiver part of the exercises. Instead of polling the “CANRMP-bit field” to wait for an incoming message your task is to use a mailbox interrupt request to read out the mailbox when necessary.

     

    However, the code for 11_4 is missing. It only contains Lab11_1.c and Lab11_2.c, I thing this Lab11_4.c is exactly what I will need. 

     

    Thanks a lot!

    Alfred

  • Alfred,

    as the author of the CD my intention was to provide the two basic exercises (11_1 and 11_2) also in form of solution-files. The task to develop these exercises in more advanced solutions as optional exercises was left to the students.

    Anyway, the attached file is a combined solution for simultaneous CAN transmit and receive with interrupt services. 

     

  • Thanks a lot, Frank and Katie, I checked my program, it is resemble to this example, and still doesn't work.

    Anyway, let me create a pjt for this source file and and code to run on the other side to test it.

     

    Alfred

  • Hi Frank and Katie,

    I tried the source code you posted here, and created 2 projects to run on 2 MCUs. It does magically work.

     

    However, I am confused about something.

    1.Notice it uses the watch dog. What is this for?

    2.Why does it has to wait for 500 ms? Is it able to send it as long as previous transmission's TAs are checked and cleaned I tried comment out everything inside while(1){...} and replaced by

    ECanaShadow.CANTRS.all = 0;

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

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

    while(ECanaRegs.CANTA.bit.TA15==0) {}

    ECanaRegs.CANTA.bit.TA15=1;

     

    and it doesn't work in that way.

     

    3. I tried commented out any thing inside while(1){...}, and PieCtrlRegs.PIEIER1.bit.INTx7 = 1 and nothing else; What I want is just to read received data in the interrupt service. Strangely, it receives twice and not any more. I don't want to wait to send messages in my application. Would you please tell me why?

     

    Or would you please just post the code of Lab11_4.c, I think that is exactly what I need according to the description. 

  • 1. The watchdog is a safety device to watch for a correct software flow. It is serviced in the Cpu-Timer ISR and in the while(1)-loop of main (in my example every 100ms).

    2. The 500ms intervall for transmission is just an example. You can easily reduce the interval to shorter periods. However, if you try to send as quick as possible (your code snipped tries to send the next frame as soon as the previous one has been acknowledged), you can have a situation, where your 2nd device, which sends the frame that you would like to receive, will never have a chance to transmit (depends on CAN priorities). Anyway, to repeatedly send as quick as possible is not realistic at all, it would produce a CAN - load of 100%. The CAN as a multi master system relies on the politeness of nodes, means transmit only if a message is actually worth to be transmitted.

    3. If you disable PIEIER.bit.INTx7 (CPU-Timer0), the watchdog will not be serviced and will cause a reset.  For such a test without the CPU-Timer0 ISR, you should disable the watchdog (remove the WDCR instruction at the beginning of main).

     

  • Thanks a lot, Frank, I think this totally makes sense. 

    I disabled the watch dog and CPU timer interrupt (INT7), and tried the send ASAP code, indeed, I saw it can hardly receive any message because the other side was busy all time receiving. I tried to use the DELAY_US() macro to give a little bit time in between sending rather than using the CPU timer counter.

    like 

    DELAY_US(2L);

    ECanaShadow.CANTRS.all = 0;

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

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

     

    I found for delay of 1 us, it doesn't work, it suppress the other side's sending. However, it works fine for as long as 2 us, amazing!

    Thanks a lot for you help! This is really helpful!

     

    Best,

    Alfred

  • Hi Alfred Zhong,

    Can you post your code here for reception of message using Interrupt without cpu timer and watchdog.

    It would be great help of me because I am getting some problem.

    Thanks in advance.

    Mehul

  • Hi Frank,

    If I use eCANB as receiver of same TMS320f28335 than what changes should i have to make in 
    Lab11_5_TX10_RX11.c (recieve with interrupt ) .

    please respond as soon as possible as my project deadline is coming.

    regards

    Mehul

  • 1.) make sure that CANB also has a CAN - transceiver

    2.) Intitialize CANB to the same parameters, data rate, sample point etc.

    3.) If you use interrupts, activate and use the PIE - interrupt lines for CANB.  If you use polling, poll the correct status bits from CANB.

      

  • Hi Frank,

    Thank a lot for answer.

    1) yes CANB has a CAN - transceiver 

    2) also initialized CANB

    3) I use interrupt and as I am using EcanA and EcanB, I set respective bit in MIL, MIM, GIF registers according to MB1 and MB5.

    here is some part of code :

    PieCtrlRegs.PIEIER9.bit.INTx6 = 1; // ECAN1INTA
    PieCtrlRegs.PIEIER9.bit.INTx8 = 1; // ECAN1INTB
    IER = 0x0101; // enable core line INT1

    interrupt void ecan1intB_isr(void)
    {
    unsigned int mailbox_nr;


    mailbox_nr = ECanbRegs.CANGIF1.bit.MIV1;
    if(mailbox_nr == 1) // mailbox #1 receive message
    {
    message[0]= ECanbMboxes.MBOX1.MDL.byte.BYTE0; // read message
    message[1]= ECanbMboxes.MBOX1.MDL.byte.BYTE1;
    message[2]= ECanbMboxes.MBOX1.MDL.byte.BYTE2;
    message[3]= ECanbMboxes.MBOX1.MDL.byte.BYTE3;
    message[4]= ECanbMboxes.MBOX1.MDH.byte.BYTE4;
    message[5]= ECanbMboxes.MBOX1.MDH.byte.BYTE5;
    message[6]= ECanbMboxes.MBOX1.MDH.byte.BYTE6;
    message[7]= ECanbMboxes.MBOX1.MDH.byte.BYTE7;
    ECanbRegs.CANRMP.bit.RMP1 = 1;
    }

    PieCtrlRegs.PIEACK.bit.ACK9 = 1;
    }

    interrupt void ecan1intA_isr(void)
    {
    unsigned int mailbox_nr;
    struct ECAN_REGS ECanaShadow;

    mailbox_nr = ECanaRegs.CANGIF1.bit.MIV1;
    if(mailbox_nr == 5) // mailbox #5 transmit-message
    {
    ECanaShadow.CANTA.all = 0;
    ECanaShadow.CANTA.bit.TA5 = 1;
    ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;
    CanMBox5Quit = 1;
    }
    PieCtrlRegs.PIEACK.bit.ACK9 = 1;
    }

    is this code correct ? or should i have to modify more?

    Regards

    Mehul

     

  • Hi Frank,

    In every exercise code LEDTOGGLE on GPIO34 is working with watchdog and timer0count.

    my question is : can it work without watchdog or timer because whenever i try to set LED without watchdog it never worked.

    Is there more LEDs other than GPIO34 that we can use as signal of message received. because GPIO30 port already used by CAN_Rx

    I want to use LED in above code (above post) for SET and RESET when I transmit 1 and 0 in byte0.

    is it possible ? how ?

    please respond 

    Thanx

    Mehul