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.

CAN Arbitration

Hi

I am running a 1MHz CAN network with 9 nodes consisting of 28335 and 2809 micros. The bus time usage is around 60%. All messages use std 11 bit identifiers and 8 byte data fields

The master node does not use any CAN interrupts

The slave nodes (3 of) each have an ECAN0INTA interrupt which immediately grabs and uses the data

The master node has to transmit very time sensitive data for reception by 3 nodes (sent at 1kHz rate). This uses the lowest active CAN ID 64 so it should always be the next one to transmit if the bus is busy when it needs it. This tx mail box also has the TPL set to the maximum value.

All bus packet lengths are around 125uS (depending on bit stuffing) so in theory the max delay for ID64 should be around 125uS

The master node (blue/green trace) sets/clears a port pin each time the data is sent

Each slave node (orange trace) sets/clears a port pin when the data is received

Most of the time it works correctly. However, every few minutes the ID64 message will be delayed by up to 500uS

The attached scope shots show normal behaviour

7510.Simple tx method - Ideal timing.TIF

1680.Ref tx method - Ideal timing.TIF

Also attached is another shot where ID64 is delayed

2804.Simple tx method - ID64 delayed.TIF

7411.Ref method - ID64 delayed.TIF

In this example ID 131 starts transmitting on the bus just before ID64 is sent to the peripheral

When ID131 finishes, ID65 and ID227 are sent before ID64 is sent. My understanding is that ID65 and ID227 should yield and let ID64 go first.

It seems clear that the master node is delaying sending the ID64 packet.

The slave is ISR is responding correctly

The bus physical layer seems to be working correctly, because if I stop most of the other nodes from transmitting the then system works perfectly with a correct delay for ID64 


#define CAN_PRIORITY_1				31
#define CAN_PRIORITY_2				30
#define CAN_PRIORITY_3				29
#define CAN_PRIORITY_4				28
#define CAN_PRIORITY_LO				0


#define BRAIN_INNER_VOL			64  //Lowest active CAN address
#define IAZ_BRAIN_ENC			65



void init_mailbox(void)
{
    mailboxCana(CAN_MAILBOX_4, CAN_DIR_RX, IAZ_BRAIN_ENC, CAN_8BYTE, CAN_NO_MASK, CAN_PRIORITY_LO);
	// And others
		
    mailboxCana(CAN_MAILBOX_21, CAN_DIR_TX, BRAIN_INNER_VOL, CAN_8BYTE, CAN_NO_MASK, CAN_PRIORITY_1);
	// And others

}





void init_cana(void)
{
	InitECanaGpio();							// Init IO for CAN_A module
	InitECana(); 								// Initialize eCAN-A module 
	
	ECanaRegs.CANRMP.all = 0xFFFFFFFF;			// Clear the received message pending bits
	ECanaRegs.CANTA.all = 0xFFFFFFFF;   		// Clear all transmit Ack (TAn) bits

	// DSP CAN port_a  MailBox and Bus Error Interrupt Initialisation 
	EALLOW;

	ECanaRegs.CANOPC.all = 0xFFFFFFFF;			// Set over write protect.

	ECanaRegs.CANGIM.all = 0x00000000;			// No interrupts enabled.

	ECanaRegs.CANMIM.all = 0x00000000;			// Disable Mailbox Interrupt for all 32 Mailboxes. 

	ECanaRegs.CANMIL.all = 0x00000000;			// Enable Mailbox interrupt on INT0 line when set to 0 
												// Enable Mailbox interrupt on INT1 line when set to 1 
	EDIS;
}




main()
{

	//extract from 1kHz loop
	ClearDebugOutput();							// port pin 

	cana_tx(BRAIN_INNER_VOL, &data);			

	SetDebugOutput();							// port pin 

}



void cana_tx(Uint16 message_id, CAN_DATA *tx_data)
{
	union CANTA_REG can_ta_shadow;
	union CANTRS_REG can_trs_shadow;

	switch(message_id)
	{

		// ******* Simple tx method version
		case BRAIN_INNER_VOL:
			if(ECanaRegs.CANTRS.bit.TRS21 == 0){	// Check mailbox is empty
				ECanaMboxes.MBOX21.MDL.all  = tx_data->can.longs.value1;		// Load first Long value
				ECanaMboxes.MBOX21.MDH.all  = tx_data->can.longs.value2;		// Load second Long value
				ECanaRegs.CANTRS.bit.TRS21 = 1;
			}
			break;


		// ******* Ref tx method as per TI examples
		case BRAIN_INNER_VOL:
			if(ECanaRegs.CANTRS.bit.TRS21 == 0){	// Check mailbox is empty
				ECanaMboxes.MBOX21.MDL.all  = tx_data->can.longs.value1;		// Load first Long value
				ECanaMboxes.MBOX21.MDH.all  = tx_data->can.longs.value2;		// Load second Long value

				can_trs_shadow.all = ECanaRegs.CANTRS.all;
				can_trs_shadow.bit.TRS21 = 1;
				ECanaRegs.CANTRS.all = can_trs_shadow.all;

			   do
				{
				   can_ta_shadow.all = ECanaRegs.CANTA.all;
				} while(can_ta_shadow.bit.TA21 == 0 );   // Wait for TAxx bit to be set..

			   can_ta_shadow.all = 0;
			   can_ta_shadow.bit.TA21 = 1;     	         // Clear TAxx
			   ECanaRegs.CANTA.all = can_ta_shadow.all;

			}
			break;

			
		default:
			if(ECanaRegs.CANTRS.bit.TRS31 == 0){	// Check mailbox is empty
				ECanaMboxes.MBOX31.MDL.all  = tx_data->can.longs.value1;			// Load first float value
				ECanaMboxes.MBOX31.MDH.all  = tx_data->can.longs.value2;			// Load second float value
				mailboxCana(CAN_MAILBOX_31, CAN_DIR_TX, message_id, CAN_8BYTE, CAN_NO_MASK, CAN_PRIORITY_LO);
				ECanaRegs.CANTRS.bit.TRS31 = 1;
			}
			break;
	}
}

			
			

Why is ID64 not always transmitted as soon as it is ready (following the end of the current packet)?

Thanks

Brent