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 */