Drexel University's Logo

Clayton McNeil

Texas Instruments F2808 DSP eCAN Guide


Home
About Me
Tutorials
Media Archive
Resources

Part 5: Transmitting and Receiving Messages

Transmitting Messages

The following code demonstrates the very basics of how to set up eCAN. Suggestions as to code for actually transmitting or receiving data will be covered in the sections to follow. Note that in this example, only the eCAN-A module is being used. To use the eCAN-B module instead of or in conjunction with eCAN-A, simply use the ECanbRegs structure as opposed to ECanaRegs. Also note that while both transmitting and receiving will be covered, the topics of message acceptances masks, extended message identifiers, Remote Transmission Request (RTR), and auto answer mode will not.

void SendCANMsg(int16 MBXnum,  Uint32 MBXDL,  Uint32 MBXDH)
{
    volatile struct MBOX *srcMBox;

    if (0 <= MBXnum && MBXnum <= 32)
    {
        Uint32 MBXflag = (0x00000001 << MBXnum);

        srcMBox = &ECanaMboxes.MBOX0 + MBXnum;
        srcMBox->MDL.all = MBXDL;
        srcMBox->MDH.all = MBXDH;

        ECanaRegs.CANTRS.all = MBXflag;
        while(ECanaRegs.CANTA.all != MBXflag) {}
        ECanaRegs.CANTA.all = MBXflag;
    }
}

The above is a simple function that can be used to transmit data over eCAN. The first line of the function body declares a structure pointer, srcMBox, of type MBOX. The volatile keyword tells the compiler that the pointer refers to an area of memory that can change on its own, as in not due to some programmed statement. The pointer needs this keyword because it is actually pointing to an area of physical memory that can also be changed by the eCAN module.

The next line of code sets a variable called MBXflag that is 32-bits in size. Many registers that will need to be accessed for transmitting and receiving messages are also 32-bits in size with each bit representing one of the 32 mailboxes. Therefore, it will help to have a variable which mirrors these registers in size and has the corresponding bit set already.

The next three lines of code point srcMBox to the mailbox of interest and load its Message Data registers. There are two: Message Data High (MDH) holds to the top 4 bytes and Message Data Low (MDL) holds to the bottom 4 bytes.

Finally, the message is ready to be sent. First, the bit in the Transmission Request Set (CANTRS) register corresponding to the mailbox of interest is set (using the MBXflag). Next, the corresponding bit in the Transmission Acknowledge (CANTA) register is monitored. When the message is successfully sent, this bit will be set. After this has occurred, this bit needs to be cleared. For this particular register, this is done by ‘setting’ the bit.

Receiving Messages
    for(;;) 
    {  
        if (ECanaRegs.CANRMP.all > 0 && ECanaRegs.CANGIF0.bit.MIV0 == 2)
        {
            ReceiveCANMsg (2);
        }
        
    }

Receiving a message over eCAN actually requires two steps – recognizing that a message has been received and recovering the data. The above is a snippet of code that might be used to monitor Mailbox 2. Whenever a message is received, the bit corresponding to its mailbox is set in the Received Message Pending (RMP) register. The actual number of the mailbox will also appear in the Mailbox Interrupt Vector (MIVx). Note that there are two MIVs; MIV0 in the Global Interrupt Flag 0 (CANGIF0) register and MIV1 in Global Interrupt Flag 0 (CANGIF0) register. Which MIV the mailbox number is sent to depends on which interrupt line/level has the mailbox’s interrupts mapped to it. Note that it is always necessary to check RMP first. If no message is pending, the value of MIV is undefined and thus unreliable.

void ReceiveCANMsg(int16 MBXnum)
{
    volatile struct MBOX *srcMBox;
    Uint32 raw_datah;
    Uint32 raw_datal;

    if (0 <= MBXnum && MBXnum <= 32)
    {
        // Get pointer to mailbox struct and grab data
        srcMBox = &ECanaMboxes.MBOX0 + MBXnum;
        raw_datah = srcMBox->MDH.all; 
        raw_datal = srcMBox->MDL.all; 
        ECanaRegs.CANRMP.all = (0x00000001 << MBXnum);

        /* Process Data */
    }
}

Once it has been determined that a message has been received, its data can be recovered. The above function is similar to the SendCANMsg() previously described. Essentially, a pointer to the mailbox containing the new message, specified via the MBXnum argument, is setup and used to retrieve the 32-bit data high and data low components of the message. Once this is done, the corresponding RMP bit is cleared by setting it. After that, the data can be processed as needed by the application. Although not shown in the example code above, it is also possible to retrieve the message’s ID via the pointer if that is needed.

Final Notes

Although the above sections should be enough to get the F2808 DSP sending and receiving messages over eCAN, they do not come close to covering all the features of eCAN or even the CAN standard itself. In the pursuit of simplification, many things were left out of the above examples. One of those things worth mentioning now is the importance of handling interrupts. For quick prototyping or testing, it is much easier to disable system interrupts and only handle the mailbox interrupts needed to recieve message. However, system interrupts indicate the occurrence of many critical events that should really be considered and handled in an appropriate fashion. Another suggestion to keep in mind is mailbox duplication. As described earlier, the OCP register can be used to control whether messages can be overwritten before they are recovered. The drawback of using this protection is that new messages could then be lost if they do not have a mailbox which will accept them. By duplicating mailboxes (that is, have multiple mailboxes that accept the same ID), the chances that a message will be either overwritten or lost can be reduced.


Home | About Me | Tutorials | Media Archive | Resources