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.

TMS320F28075: CAN mailbox initialization problem

Part Number: TMS320F28075
Other Parts Discussed in Thread: C2000WARE


Hi,
I'm trying to develop a CANopen library on my embedded system but I ran into some issues with CAN controller.
I'm using CCS 6.1.1.00022 with C compiler TI v15.12.4.LTS.

I built up the project "can_external_transmit_cpu01" starting from C2000Ware_1_00_01_00 example project (C2000Ware_1_00_01_00\driverlib\f2807x\examples\cpu1\can\can_ex3_external_transmit.c) and driver (C2000Ware_1_00_01_00\driverlib\f2807x\driverlib\can.c and can.h).

I slightly modified the main function to initialize my hardware and to both receive and transmit messages through CAN B module (CAN A module is not used). You can see my code at the bottom of this post. I didn't changed CAN driver functions and canbISR interrupt routine.

I used mailbox 2 to receive messages (RX mailbox) and mailbox 1 to transmit messages (TX mailbox).

I connected my system to a CANopen master with baud rate 500kHz and I inserted a CAN analyzer to sniff messages.

When the program runs I see two problems.


PROBLEM 1 - Mailbox configuration problem
If I pause the program after initialization steps (for example at line CycleCounter++;) I find the following value

CAN_MVAL_21 = 0x80000003

This means that mailbox 1, 2 and 32 are enabled.

However I never enabled mailbox 32.

Moreover if I watch RAM area beginning at address 0x4B000 I see that words in range 0x4B000-0x4B01F (RAM message object 32) and the words in range 0x4B040-0x4B05F (RAM message object 2) have the same configuration.
This means that mailbox 2 and mailbox 32 have the same configuration.

But I never initialized mailbox 32.


PROBLEM 2 - Sending messages
Each time I send one message through CAN_sendMessage the CAN analyzer detects two messages:

- a message with ID 0x581 and data 0x11223344 (correct);
- a RTR message with ID 0x345 (not correct);

The RTR message should not be sent.
It seems like the sending command to TX mailbox 1 triggers also a transmission on mailbox 2 or 32. Because they are both RX mailboxes a RTR message is sent, instead of a data message.

However I never triggered a transmission on mailbox 2 or 32.


WORKAROUND (MAYBE...)
I noted that C2000Ware can driver uses both 32-bit and 16-bit access to CAN controller registers, however in this issue (e2e.ti.com/.../2133415 Hareesh reported the following note:
"The CAN module uses a special addressing scheme to support byte accesses. It is recommended to only use 32-bit accesses to the CAN registers using the HWREG_BP() macro which uses the __byte_peripheral_32() intrinsic. If 16-bit accesses are to be used, the lower 16 bits should be written to the register's address, and the upper 16 bits should be written to the register's address plus 2." (another related issue is the following e2e.ti.com/.../2141528

So I modified driver function CAN_setupMessageObject by replacing these lines

  //
  // Write out the registers to program the message object.
  //
  HWREG_BP(base + CAN_O_IF1CMD) = cmdMaskReg;
  HWREG_BP(base + CAN_O_IF1MSK) = maskReg;
  HWREG_BP(base + CAN_O_IF1ARB) = arbReg;
  HWREG_BP(base + CAN_O_IF1MCTL) = msgCtrl;

  //
  // Transfer data to message object RAM
  //
  HWREGH(base + CAN_O_IF1CMD) = objID & CAN_IF1CMD_MSG_NUM_M;

with these lines        
        
    //
    // Write out the registers to program the message object.
    //
    HWREG_BP(base + CAN_O_IF1MSK) = maskReg;
    HWREG_BP(base + CAN_O_IF1ARB) = arbReg;
    HWREG_BP(base + CAN_O_IF1MCTL) = msgCtrl;

    //
    // Transfer data to message object RAM
    //
    HWREG_BP(base + CAN_O_IF1CMD) = cmdMaskReg | (objID & CAN_IF1CMD_MSG_NUM_M);

and I found that both the problems disappeared.

In other words I've replaced two 16-bit writing accesses to IF1CMD register with a single 32-bit writing access and all seems to work properly: mailbox 32 si disabled, its RAM area is blank (all zeroes) and only data message with ID=0x581 is sent.

So I ask: is this workaround the right solution to the issues?

Should I replace any 16-bit access to IF register with 32-bit access in C2000Ware can driver files?

Is there any other way to fix these problems?

Thank you,

Demis




------------------------------------------------------------------------------------
MY CODE

// constant
#define MSG_DATA_LENGTH    8
#define TX_MSG_OBJ_ID    1
#define RX_MSG_OBJ_ID    2


// main function
void main(void)
{

    /* HW initialization */
    BootInit(TRUE);

    /* CAN B clock enable */
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CANB);

    //
    // Initialize GPIO and configure GPIO pins for CANTX/CANRX
    // on module B
    //
    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXB);
    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXB);

    //
    // Initialize the CAN controller B
    //
    CAN_initModule(CANB_BASE);

    //
    // Set up the CAN bus bit rate to 500kHz
    //
    CAN_setBitRate(CANB_BASE, SYSTEM_CLOCK, 500000, 16);

    //
    // Enable interrupts on receiving message on the CAN B peripheral.
    //
    CAN_enableInterrupt(CANB_BASE, CAN_INT_IE0);

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;

    //
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    // This registers the interrupt handler in PIE vector table.
    //
    Interrupt_register(INT_CANB_1, &canbISR);

    //
    // Enable the CAN-B interrupt signal
    //
    Interrupt_enable(INT_CANB_1);
    CAN_enableGlobalInterrupt(CANB_BASE, CAN_GLOBAL_INT_CANINT0);

    //
    // Initialize the receive message object used for receiving CAN messages.
    // Message Object Parameters:
    //      CAN Module: B
    //      Message Object ID Number: 2
    //      Message Identifier: 0x345
    //      Message Frame: Standard
    //      Message Type: Receive
    //      Message ID Mask: 0x0
    //      Message Object Flags: Receive Interrupt and Use ID Filter
    //      Message Data Length: 8 Bytes
    //
    CAN_setupMessageObject(CANB_BASE, RX_MSG_OBJ_ID, 0x345,
                         CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0,
                         CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER, MSG_DATA_LENGTH);


    //
    // Initialize the transmit message object used for sending CAN messages.
    // Message Object Parameters:
    //      CAN Module: A
    //      Message Object ID Number: 1
    //      Message Identifier: 0x581
    //      Message Frame: Standard
    //      Message Type: Transmit
    //      Message ID Mask: 0x0
    //      Message Object Flags: None
    //      Message Data Length: 8 Bytes
    //
    CAN_setupMessageObject(CANB_BASE, TX_MSG_OBJ_ID, 0x581,
                         CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0,
                         CAN_MSG_OBJ_NO_FLAGS, MSG_DATA_LENGTH);

    //
    // Initialize the transmit message object data buffer to be sent
    //
    txMsgData[0] = 0x43;
    txMsgData[1] = 0x00;
    txMsgData[2] = 0x10;
    txMsgData[3] = 0x00;
    txMsgData[4] = 0x44;
    txMsgData[5] = 0x33;
    txMsgData[6] = 0x22;
    txMsgData[7] = 0x11;

    //
    // Start CAN module B operations
    //
    CAN_startModule(CANB_BASE);

    while(1)
    {
        //
        // Counter for debug purpose
        //
        CycleCounter++;
    
        //
        // Delay 1 second before continuing
        //
    DEVICE_DELAY_US(1000000);

        //
        // Send message
        //
        CAN_sendMessage(CANB_BASE, TX_MSG_OBJ_ID, MSG_DATA_LENGTH, txMsgData);
    }

}    /* end main */

  • Demis

    Yes, your workaround is correct. The HWREG_BP is actually 32-bits and HWREGH is 16-bits. This is already a noted bug internally and will be fixed. Sorry for the trouble.

    Best regards
    Chris
  • Thank you Chris,
    would it not be better if you notify internally confirmed bugs to your customers too?

    Ok, we all know it isn't such a great thing to admit something you do doesn't work properly, but we are programmers and we are all aware that we create new bugs (almost) every day, isn't it? ;-)

    So, I think it would be a very useful thing for us to be informed about kwnown issues.

    It could be an error list extracted from your internal bug tracker or something similar. A kind of database that someone can consult when something seems not to work as it should.
    That's my two cents.

    Anyway thank you for your assistance.

    Best regards,

    Demis
  • Demis

    Thank you for our feedback. We will try to improve our communications in that area.

    Best regards
    Chris