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.

Writing to CAN results in setting CANAA

Other Parts Discussed in Thread: TMS320F28069

Hi,

I am having some issues using a transmit mailbox to write to CAN. I followed the instructions on the technical guide for my microcontroller (TMS320F28069) on "how to configure a mailbox for transmit" and "how to transmit a message".

My main issue is that when I set the transmit request register (TRS.0) for the mailbox, I am stuck waiting for the the transmit acknowledge register to be set (TA.0). 

As a result, when i halt the code and check the eCAN registers, CANAA for mailbox 0 is set. What can be the cause of this?

Here is my code:

void main() 
{
	
	

	InitSysCtrl();	// Defined in F2806x_SysCtrl.c

	// Initialize CAN GPIO pins
	canA_gpio_init();

	EDIS;

	// Disable CPU interrupts
	DINT;

	EALLOW;
	InitPieCtrl();	// Defined in F2806x_PieCtrl.c
	EDIS;
	// Disable CPU interrupts and clear all interrupt flags
	IER = 0x0000;
	IFR = 0x0000;

	EALLOW;
	InitECana();
	EDIS;
	
	EALLOW;
	InitPieVectTable(); // Defined in F2806x_PieVect.c
	EDIS;
	//canA_init(19);

	
	// TEST
	/* mailbox interrupt mask */
	/* 1 = interrupt enabled */
	ECanaRegs.CANMIM.all = 0xFFFFFFFF;

	
	/* mailbox interrupt level */
	/* mailbox inerrupt is generated on interrupt line 1. */
	ECanaRegs.CANMIL.all = 0xFFFFFFFF;

	
	/* Global Interrupt Mask Register */
	ECanaShadow.CANGIM.all = ECanaRegs.CANGIM.all;
	ECanaShadow.CANGIM.all = 0;
	ECanaShadow.CANGIM.bit.AAIM = 1; /* Abort acknowledge */
	ECanaShadow.CANGIM.bit.WDIM = 1; /* Write denied */
	ECanaShadow.CANGIM.bit.WUIM = 1; /* Wake up */
	ECanaShadow.CANGIM.bit.BOIM = 1; /* Bus-off */
	ECanaShadow.CANGIM.bit.EPIM = 1; /* Error-passive */
	ECanaShadow.CANGIM.bit.WLIM = 1; /* Warning level */
	ECanaShadow.CANGIM.bit.I1EN = 1; /* Interrupt 1 enable */
	ECanaShadow.CANGIM.bit.GIL  = 1; /* Global Interrup Level. */
	// ECanaShadow.CANGIM.bit.I0EN = 1; /* Interrupt 0 enable */
	// ECanaShadow.CANGIM.bit.GIL  = 0; /* Global Interrup Level. */
	ECanaShadow.CANGIM.bit.RMLIM = 1; /* Received Message Lost */
	ECanaRegs.CANGIM.all = ECanaShadow.CANGIM.all;

        EDIS;

        for(;;)
	{
		
		EALLOW;
		writeCan();
		EDIS;
		
         }



}


void writeCan()
{
	/*
	To transmit a message, the following steps need to be performed (in this example, for mailbox 1):
	1. Clear the appropriate bit in the CANTRS register to 0:
	Clear CANTRS.1 = 0 (Writing a 0 to TRS has no effect; instead, set TRR.1 and wait until TRS.1
	clears.) If the RTR bit is set, the TRS bit can send a remote frame. Once the remote frame is sent, the
	TRS bit of the mailbox is cleared by the CAN module. The same node can be used to request a data
	frame from another node.
	*/
	EALLOW;
	ECanaShadow.CANTRS.all = ECanaRegs.CANTRS.all;
	ECanaShadow.CANTRR.all = ECanaRegs.CANTRR.all;

	ECanaShadow.CANTRR.bit.TRR0 = 1;
	while (ECanaShadow.CANTRS.bit.TRS0 != 0) {};

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

	/*
	2. Disable the mailbox by clearing the corresponding bit in the mailbox enable (CANME) register.
	Clear CANME.filter1 = 0
	*/

	ECanaShadow.CANME.all = ECanaRegs.CANME.all;
	ECanaShadow.CANME.bit.ME0 = 0;
	ECanaRegs.CANME.all = ECanaShadow.CANME.all;


	/*
	3. Load the message identifier (MSGID) register of the mailbox. Clear the AME (MSGID.30) and AAM
	(MSGID.29) bits for a normal send mailbox (MSGID.30 = 0 and MSGID.29 = 0). This register is usually
	not modified during operation. It can only be modified when the mailbox is disabled. For example:
	(a) Write MSGID(1) = 0x15AC0000
	(b) Write the data length into the DLC field of the message control field register (MSGCTRL.3:0). The
	RTR flag is usually cleared (MSGCTRL.4 = 0).
	(c) Set the mailbox direction by clearing the corresponding bit in the CANMD register.
	(d) Clear CANMD.1 = 0
	*/

	/* Mailbox 0 */
	// ID: 0x5A584B
	// AAM: 0
	// AME: 0
	// IDE: 1
	ECanaMboxes.MBOX0.MSGID.all = 0x805A584B;

	// Specify that 8 bits will be sent/received
	ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8;

	ECanaShadow.CANMD.all = ECanaRegs.CANMD.all;
	ECanaShadow.CANMD.bit.MD0 = 0;
	ECanaRegs.CANMD.all = ECanaShadow.CANMD.all;


	/*
	4. Set the mailbox enable by setting the corresponding bit in the CANME register
	Set CANME.1 = 1
	This configures mailbox 1 for transmit mode.
	16.11.2 Transmitting a Message
	*/

	ECanaShadow.CANME.all = ECanaRegs.CANME.all;
	ECanaShadow.CANME.bit.ME0 = 1;
	ECanaRegs.CANME.all = ECanaShadow.CANME.all;

	/*
	To start a transmission (in this example, for mailbox:
	1. Write the message data into the mailbox data field.
	(a) Since DBO (MC.10) is set to zero in the configuration section and MSGCTRL(1) is set to 2, the
	data are stored in the 2 MSBytes of CANMDL(1).
	(b) Write CANMDL(1) = xxxx0000h
	*/
	EALLOW;
	ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
	ECanaShadow.CANMC.bit.DBO = 0;
	// 1 = self-test mode
	ECanaShadow.CANMC.bit.STM = 0;
	// 1 = FREE mode (peripheral continues to run normally in SUSPEND)
	ECanaShadow.CANMC.bit.SUSP = 1;
	ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
	EDIS;

	// Write to the mailbox RAM field of MBOX0
	ECanaMboxes.MBOX0.MDL.all = 0x9555AAA0;
	ECanaMboxes.MBOX0.MDH.all = 0x89ABCDEF;

	/*
	2. Set the corresponding flag in the transmit request register (CANTRS.1 = 1) to start the transmission of
	the message. The CAN module now handles the complete transmission of the CAN message.
	*/

	ECanaShadow.CANTRS.all = ECanaRegs.CANTRS.all;
	ECanaShadow.CANTRS.bit.TRS0 = 1;
	ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;

	/*
	3. Wait until the transmit-acknowledge flag of the corresponding mailbox is set (TA.1 = 1). After a
	successful transmission, this flag is set by the CAN module.
	*/
     
	ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;
	while (ECanaShadow.CANTA.bit.TA0 != 1) {};        // THIS IS WHERE THE CODE GETS STUCK
	ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;

	/*
	4. The TRS flag is reset to 0 by the module after a successful or aborted transmission (TRS.1 = 0).
	*/

	ECanaShadow.CANTRS.all = ECanaRegs.CANTRS.all;
	while (ECanaShadow.CANTRS.bit.TRS0 != 0) {};
	ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;

	/*
	5. The transmit acknowledge must be cleared for the next transmission (from the same mailbox).
	(a) Set TA.1 = 1
	(b) Wait until read TA.1 is 0
	*/

	ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;
	ECanaShadow.CANTA.bit.TA0 = 1;
	while (ECanaShadow.CANTA.bit.TA0 != 0) {};
	ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;

	/*
	6. To transmit another message in the same mailbox, the mailbox RAM data must be updated. Setting
	the TRS.1 flag starts the next transmission. Writing to the mailbox RAM can be half-word (16 bits) or
	full word (32 bits) but the module always returns 32-bit from even boundary. The CPU must accept all
	the 32 bits or part of it.
	*/
	MessageReceivedCount++;

	EDIS;
}

  • Adam,

    Please make sure that the CANTX and CANRX pins are connected to a transceiver and there is at least one other node on the bus. If you don't have another node, tie CANTX and CANRX together and set the CANMC.STM bit to enable self-test mode.
  • Thanks for the response Adam.

    I double checked that the CANTX and CANRX pins were connected to a transceiver and that there was another node.

    After lots of debugging, it turns out my problem was a timing issue.

    I needed to change the BRPREG,TSEG1 and TSEG2 bits to get a more accurate bit rate of 500 kb/s. Also, introducing some delay into between my transmission request to write and transmission acknowledge allowed the bits to set and clear correctly.