AT90CAN RTR response

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi everybody again.
I have a question about the CAN module in AT90CAN devices.
I want to answer to a RTR request which is sent by a AT91SAM7X (ARM7 from atmel). That uP seems to work alright.
I want to choose the data to send once when the RTR arrives, so I don't want the automatic reply mode. is this possible?

I'm having a problem here. I first wait for an incomming message by polling RXOK (later I will use interrupts). Then, I use the same mailbox to transmit the message with the same ID, and it works.
However, when I re-enable reception on that mailbox, I experience a problem, and it is that the CAN bus is showing as completely busy.
That doesn't happen if I wait about a millisecond before re-enabling reception.

I suppose there is an issue with the CAN module getting the same message it outputted a little while ago. is this possible?

oh, I wait for TXOK before enabling reception again.

thanks!
Carlos

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The benefit of a Remote Frame is entirely in its automatic response. If you do not want an automatic response, use a zero byte Data Frame (no RTR bit set) instead and use your software to respond to that Data Frame RXOK (what you are trying to do requires software intervention anyway).

I have never used a Remote Frame without the CANCDMOB register RPLV bit already set. The normal automatic reply with the Remote Frame RTR bit set completes with a TXOK after the automatic reply is sent by the AVR. As far as I know, there is no RXOK set in CANSTMOB when you Rx with RTRTAG set. Maybe there is a RXOK if RPLV is cleared, but I have no reason to expect this to be true. Try it an see what you get!

As a work around you could create a normal AVR Rx with RTRTAG cleared in the CANIDT4 register and the RTRMSK bit cleared in the CANIDM4 register (i.e. Rx a Remote Frame without setting the RTRTAG bit to get a RXOK). Then when you get the MOb RXOK, read the CANIDT4 register RTRTAG which will give you the actual Rx value of the RTR bit sent by the ARM (the CAN Rx updates the AVR MOb registers with actual Rx data). This would allow you to Rx a Remote Frame from the ARM. Then your software would do its data return CAN Tx to answer the ARM Remote Frame request.

The only possible advantage to using a Remote Frame instead of a Data Frame is two different CAN nodes are able to use what is otherwise an identical Message Identifier CAN frame (except for the RTR bit difference). As you know two or more Tx CAN nodes that send totally identical Message Identifiers might collide in arbitration, which would allow more than one single CAN node to pass through arbitration together and screw up the entire CAN bus with a later CANSTMOB register BERR error response. The only way to prevent screwing up the CAN bus would be if all the colliding CAN frames were absolutely identical for every bit in the entire CAN Frame, which multiple identical Remote Frames from different CAN nodes could do in theory.

If you do multiple CAN Data Frames in different CAN nodes with identical Message Identifiers (completely identical arbitration fields) and get BERR error responses, the CAN automatic retry mechanism would keep repeating the same BERR again on every retry, eventually forcing colliding nodes into a BUS OFF shutdown. Then they would wait for 128 occurrences of 11 consecutive recessive bits, automatically re-enable and start the same BERR show all over again eating up CAN bus bandwidth while blocking any lower priority CAN frames. The important thing to keep in mind is this type of BERR behavior is not a CAN bus problem, its a problem created by the person that improperly programed the CAN.

cbecker wrote:
However, when I re-enable reception on that mailbox, I experience a problem, and it is that the CAN bus is showing as completely busy.
The important question I have for you is how are you determining the CAN bus is completely busy? Also, are there any Remote Frames involved or are these only Data Frames?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the quick reply!

Mike B wrote:

I have never used a Remote Frame without the CANCDMOB register RPLV bit already set. The normal automatic reply with the Remote Frame RTR bit set completes with a TXOK after the automatic reply is sent by the AVR. As far as I know, there is no RXOK set in CANSTMOB when you Rx with RTRTAG set. Maybe there is a RXOK if RPLV is cleared, but I have no reason to expect this to be true. Try it an see what you get!

I can see that the RXOK flag gets set when receiving with RTRTAG, just as if it was any other frame. In fact, if I don't send the message after the RTR frame, everything is just fine. It goes right if I send the message with any another ID, but it does not if I use the same ID which caused the RTR frame (except if I wait like 1-2 msecs as I said before).

Mike B wrote:

As a work around you could create a normal AVR Rx with RTRTAG cleared in the CANIDT4 register and the RTRMSK bit cleared in the CANIDM4 register (i.e. Rx a Remote Frame without setting the RTRTAG bit to get a RXOK). Then when you get the MOb RXOK, read the CANIDT4 register RTRTAG which will give you the actual Rx value of the RTR bit sent by the ARM (the CAN Rx updates the AVR MOb registers with actual Rx data). This would allow you to Rx a Remote Frame from the ARM. Then your software would do its data return CAN Tx to answer the ARM Remote Frame request.

I have to try that. However, a good thing about the arm is that one of its mailboxes can be put in 'consumer mode', so it sends the RTR frame and automatically receives the incoming data (quite lazy huh!)

Mike B wrote:

The only possible advantage to using a Remote Frame instead of a Data Frame is two different CAN nodes are able to use what is otherwise an identical Message Identifier CAN frame (except for the RTR bit difference). As you know two or more Tx CAN nodes that send totally identical Message Identifiers might collide in arbitration, which would allow more than one single CAN node to pass through arbitration together and screw up the entire CAN bus with a later CANSTMOB register BERR error response. The only way to prevent screwing up the CAN bus would be if all the colliding CAN frames were absolutely identical for every bit in the entire CAN Frame, which multiple identical Remote Frames from different CAN nodes could do in theory.

If you do multiple CAN Data Frames in different CAN nodes with identical Message Identifiers (completely identical arbitration fields) and get BERR error responses, the CAN automatic retry mechanism would keep repeating the same BERR again on every retry, eventually forcing colliding nodes into a BUS OFF shutdown. Then they would wait for 128 occurrences of 11 consecutive recessive bits, automatically re-enable and start the same BERR show all over again eating up CAN bus bandwidth while blocking any lower priority CAN frames. The important thing to keep in mind is this type of BERR behavior is not a CAN bus problem, its a problem created by the person that improperly programed the CAN.

cbecker wrote:
However, when I re-enable reception on that mailbox, I experience a problem, and it is that the CAN bus is showing as completely busy.
The important question I have for you is how are you determining the CAN is completely busy? Also, are there any Remote Frames involved or are these only Data Frames?

yes that's right.
I see the CAN is busy because there are LEDs at TX/RX from the AT90CAN (AT90DVK board). If I add the millisecond delay then I LEDs light up only when I send a remote frame request and on reply (which is quite fast), so they turn off when I'm not requesting anything from the at90can. I only have the ARM and the 90can connected to the bus, and even disabling the CAN transceiver on the ARM side, the LEDs will look busy forever once I started the first RTR. The message arrives alright at the ARM, no errors.

I will keep experimenting, thanks for the information!

Carlos

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AT90CAN128 data sheet wrote:
19.5.2.4 Automatic Reply
2. When a remote frame matches, automatically the RTRTAG and the reply valid bit (RPLV) are reset. No flag (or interrupt) is set at this time. Since the CAN data buffer has not been used by the incoming remote frame, the MOb is then ready to be in transmit mode without any more setting. The IDT, the IDE, the other tags and the DLC of the received remote frame are used for the reply.
3. When the transmission of the reply is completed the TXOK flag is set (interrupt).
Your finding say that when RTRTAG is set and RPLV is not set, then the RXOK is generated. Even though the configuration with RPLV not set is show in Table 19-1 MOb Configuration, I didn't find any specific interrupt response description for this setup. My expectation was wrong. With this there is no need for using the mask to Rx the Remote Frame (except you might experiment with it too see if the eternal busy problem goes away or not).

Since the RXOK should disable the MOb (the CANEN1/CANEN2 register bit for the MOb should be cleared), just setting the RPLV after the RXOK shouldn't do anything at all. Maybe this is not working the way I expect?

There is a side effect when using the RPLV bit. The Data Length Code (DLC) is copied from the ARM into the AVR. Then the automatic reply uses this DLC when sending the Data Frame. If the AVR DLC is changed by the Rx from what you initialized the auto-reply MOb with, then the CANSTMOB register DLCW bit should be set, but its too late to stop the auto-reply. This means you could send uninitialized CANMSG bytes from the AVR in the auto-reply if the ARM Rx DLC was larger than the AVR setup DLC. The ARM will get the DLC it sent back from the AVR, so only the AVR knows the problem occurred through the DLCW bit. It is potentially a messy error to clean up. Not using RPLV means you may deal with this problem and prevent any possibility of passing along a bad auto-reply.

Check your chip marking on the AT90DVK board. The early ones use the original A or B revisions of the AT90CAN128. This original AT90CAN128 data sheet has the errata if you have an old -EL part.
https://www.avrfreaks.net/index.p...

About the eternally busy LEDs. After you get the CANSTMOB register RXOK, the appropriate read only CANEN1/CANEN2 register bit for the MOb should be cleared. Since you are experiencing strange behavior you might want to double check this. Since you just received a Remote Frame and this is not an auto-reply, make sure to clear the RTRTAG bit in the AVR before reusing the MOb to Tx your manual-reply. For debugging try checking the CANIDT and CANCDMOB register values after the Data Frame RXOK, just to make sure they are what you expect before reusing the MOb. There is nothing I am aware of that would require any MOb setup delay after the RXOK and CANEN1/2 disable. Although, as I said I have never tried auto-reply without RPLV set, so you are venturing into new territory for me.

The LEDs are interesting. They show the dominant state on the AT90CAN128 interface, but since the ATA6660 loops pin 1 Tx back to pin 4 Rx (through the CAN bus interface) both LEDs act like single LED when the AT90CAN128 sends CAN dominant serial data. The CAN Rx LED will act as a single LED when only receiving dominant data from the CAN bus. You should be able to get some extra information based on one or both LEDs lighting at once. It would be very interesting to put a logic analyzer or CAN analyzer on these pins and see what is really happening during this eternal busy state.

BTW, if you use some standards like CANopen you will find they do not allow Remote Frames because they also support old CAN chips that did not implement this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

well that's quite a lot of interesting info! thanks Mike!

I am doing some tests right know. I will let you know what happens.

Oh, the data code on the 90can says 0644, which is sort of confusing when reading the datasheet (the >= or < ). I guess that's week 44, year 06 so it would be REV D, but I can't get it clear actually, since the datasheet also mentions datecode '4006', what's that? It looks as if RevC devices came with a mistaken date code.

I will let you know if I find something out.

oh, btw, the critical delay up to which it starts working is 140uS approx. (if it really helps).

Oh, as I said, both leds are on when I say the 'CAN busy' thing.

Apart from that, I'm clearing the RTR bits in both mask and ID before sending data, and also setting them properly before activating reception again.

Here I post the code I use for testing.

thanks again!
Carlos

can.c:

#include "can.h"

#include "globals.h"

/** FCLK = 16MHz, CAN brate = 500Kbps (hoja de datos)     */

#define	CAN_B_BT1	0x02
#define	CAN_B_BT2	0x0C
#define	CAN_B_BT3	0x37


static void	CAN_setIDT( u32 can_id );

static void	CAN_setIDT( u32 can_id )
{
	// shift for comfortability
	can_id <<= (32-29);

	// don't touch not used bits
	CANIDT4 &= ~( (1U<<0) | (1U<<1) | (1U<<2) );	// no tocamos los 3 lsb
	CANIDT4	|= can_id & 0xFF;

	CANIDT3	= (can_id >> 8) & 0xFF;
	CANIDT2	= (can_id >> 16) & 0xFF;
	CANIDT1	= (can_id >> 24 ) & 0xFF;
}

// idem to setIDT()
static void	CAN_setIDM( u32 can_id )
{
	
	can_id <<= (32-29);

	
	CANIDM4 &= ~( (1U<<0) | (1U<<1) | (1U<<2) );	// no tocamos los 3 lsb
	CANIDM4	|= can_id & 0xFF;

	CANIDM3	= (can_id >> 8) & 0xFF;
	CANIDM2	= (can_id >> 16) & 0xFF;
	CANIDM1	= (can_id >> 24 ) & 0xFF;
}


void	CAN_init(void)
{
	//reset
	CANGCON |= 1;
	CANGCON = 0 ;	//off

	/* in/out setup	*/
	setbit( DDRD, 5 );
	clrbit( DDRD, 4 );
	setbit( PORTD, 5 );

	//config timing
	CANBT1	= CAN_B_BT1;
	CANBT2	= CAN_B_BT2;
	CANBT3	= CAN_B_BT3;



	//mobs to 0
	CANEN2 = CANEN1 = 0;

	//disable all mobs
	u08 i;
	for( i=0; i < 15; i++ )
	{
		CANPAGE 	= (i<<4);	//select
		CANSTMOB = 0;
		CANCDMOB 	= 0;		//disable
	}


	//not used however
	CANGIE	= (1<<ENIT) | (1<<ENRX) ;


	//enable & wait
	CANGCON	= (1<<ENASTB);

	while( ! testbit(CANGSTA, ENFG) )
		;

}


int	CAN_setReply( u08 mob, u32 can_id, u08 *d, u08 length)
{
	u08 i;
	
	{
		//selecc mob
		CANPAGE		= (mob<<4);
	
		//clear flags..
		clrbit( CANSTMOB, TXOK );
		clrbit( CANSTMOB, RXOK );
		clrbit( CANSTMOB, BERR );
		clrbit( CANSTMOB, CERR );
		clrbit( CANSTMOB, FERR );
		clrbit( CANSTMOB, AERR );

		CANIDT4 = 0;	//reset
		CAN_setIDT( can_id );
		CANIDT4 |= (1<<RTRMSK);

		CANIDM4 = 0;	//reset
		CAN_setIDM( 0xFFFFFFFF );	//exact match
		setbit( CANIDM4, IDEMSK );
		CANIDM4 |= (1<<RTRTAG);
	}

	//set data..

	for( i=0; i < length ; i++ )
		CANMSG = d[i];

	CANCDMOB 	= length | (1<<IDE);
	CANCDMOB |= (2<<6);		//enable rx


	//'wait till finished
	while( ! testbit(CANSTMOB, RXOK ) )
	{
		if ( testbit( CANSTMOB, BERR) )
			return -1;
		else if ( testbit( CANSTMOB, BERR) )
			return -2;
		else if ( testbit( CANSTMOB, CERR) )
			return -3;
		else if ( testbit( CANSTMOB, FERR) )
			return -4;
		else if ( testbit( CANSTMOB, AERR) )
			return -5;
	}

	CAN_tx( mob, can_id, d, length );

	return 0;
}

int	CAN_tx( u08 mob, u32 can_id, u08 *d, u08 length)
{
	u08 i;

	//selecc mob
	CANPAGE		= (mob<<4);

	//clear flags..
	clrbit( CANSTMOB, TXOK );
	clrbit( CANSTMOB, BERR );
	clrbit( CANSTMOB, CERR );
	clrbit( CANSTMOB, FERR );
	clrbit( CANSTMOB, AERR );

	CANIDT4 = 0;	//reset
	CAN_setIDT( can_id );

	CANIDM4 = 0;	//reset
	CAN_setIDM( 0xFFFFFFFF );	//not used here
	setbit( CANIDM4, IDEMSK );

	for( i=0; i < length ; i++ )
		CANMSG = d[i];

	CANCDMOB 	= length | (1<<IDE);	//length data byte

	
	CANCDMOB |= (1<<6);


	//wait till finish
	while( ! testbit(CANSTMOB, TXOK ) )
	{
		if ( testbit( CANSTMOB, BERR) )
			return -1;
		else if ( testbit( CANSTMOB, BERR) )
			return -2;
		else if ( testbit( CANSTMOB, CERR) )
			return -3;
		else if ( testbit( CANSTMOB, FERR) )
			return -4;
		else if ( testbit( CANSTMOB, AERR) )
			return -5;
	}

	return 0;
}

main.c

#include "globals.h"

#include "can.h"

int main(void)
{
	u08	a = 1;
	u08 n = 0;

	//Change System CLK-Prescaler to 1
	CLKPR = 0x80;
	CLKPR = 0x00; 

	CAN_init();

	sei();

	DDRA = 0xFF;	//todos salida
	PORTA = 0;		//apagados


	//sensado PORTE
	DDRE = 0;
	PORTE	= 0xFF;	//input & pullup

	CAN_setupDataMBox( 0x11 );

	u08 sensor[2];

	while( 1 )
	{
		sensor[0] = PINE;

		//int ret = -CAN_tx( sensor );
		int ret = -CAN_setReply( 1, 0x11, sensor, 2 );

        a = 1<<ret;
		PORTA = a;


		if ( n ) 
		{
			setbit(PORTA,7);

			//PING!

		}
		else
			clrbit(PORTA,7 );

		n = !n;
		_delay_us(10);_delay_us(10);_delay_us(10);_delay_us(10);_delay_us(10);_delay_us(10);_delay_us(10);_delay_us(10);_delay_us(10);
		_delay_us(10);_delay_us(10);_delay_us(10);_delay_us(10);
	}
}


  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
	//mobs to 0
	CANEN2 = CANEN1 = 0;

This doesn't work. In the AT90CAN32/64/128 data sheet version 7679F–CAN–11/07, all the CANEN1 register bits are R for read only (except for bit 7) and all the CANEN2 register bits are R for read only. Writing to these registers has no effect at all. To understand how the CANEN1/2 registers work, look at the CANCDMOB register description • Bit 7:6 – CONMOB1:0: Configuration of Message Object (this is what sets a CANEN1/2 register bit). The various ways these bits get reset is described in this data sheet section 19.10.5 CAN Enable MOb Registers CANEN2 and CANEN1.

I also learned the hard way, to always carefully check the data sheet for R read only bits. Sometimes its only one bit, other timers it might be all the bits in a register. The CAN module has more than a few R read only bits hiding in various registers, so be vigilant.

	/* in/out setup */
	setbit( DDRD, 5 );
	clrbit( DDRD, 4 );
	setbit( PORTD, 5 );

This code should not be needed since there is an internal pull-up resistor built into the ATA6660 Tx pin. When the CAN is disabled, the AVR pins become normal I/O pins (unless timer1 XCK1 or T1 is enabled) and having both AVR pins TXCAN and RXCAN as default high impedance (no internal pull-up) inputs does not bother the ATA6660 (nothing bad will happen on the CAN bus). When the CAN is enabled, it automatically sets the TXCAN pin to an output port and the RXCAN pin as an input port.

Page 80 of the data sheet:
• TXCAN/XCK1 – Port D, Bit 5
TXCAN, CAN Transmit Data (Data output pin for the CAN). When the CAN is enabled, this pin is configured as an output regardless of the value of DDD5.

Page 80 of the data sheet:
• RXCAN/T1 – Port D, Bit 6
RXCAN, CAN Receive Data (Data input pin for the CAN). When the CAN controller is enabled this pin is configured as an input regardless of the value of DDD6. When the CAN forces this pin to be an input, the pull-up can still be controlled by the PORTD6 bit.

BTW, the ATA6660 does not need any AVR internal pull-up for the Rx pin.

However, if you feel the ATA6660 Tx pin pull-up may not be enough when the CAN is disabled, change the AVR TXCAN pin in a way that will never allow a zero value to be output between the PORT and DDR changes.

	/* in/out setup */
	setbit( PORTD, 5 );
	setbit( DDRD, 5 );
	clrbit( DDRD, 4 );

This will avoid ever sending a temporary false dominant CAN bus state while initializing the AVR CAN. The DDRD4 is not really needed, except you do want to make sure it is never an output because an AVR output would try and drive the ATA6660 Rx output pin (redundantly setting it as in input does no harm).

	//not used however
	CANGIE = (1<<ENIT) | (1<<ENRX);

Since you have a SEI in main(), this is a potential bomb. The only thing that saved you is no CANIE1, CANIE2 or CANGIT register bits were enabled. If you want to do polling, you may set the CANGIE bits and CANIE1/2 bits, but never set the CANGIE register ENIT bit. When ENIT is set an interrupt will be generated to the AVR, which will cause a crash if no interrupt hander vector code is present. When polling with ENIT cleared, the CANGIT register CANIT bit becomes a composite value for all enabled CANGIE and CANIE1/2 enabled MOb. Your polling code still has to drill down to the individual CAN CANGIT or CANSTMOB register bits, but it is more efficient to have one single composite bit to check first for any pending activity. Actually, AVR CAN polling and interrupt setups are the same, except for the CANGIE register ENIT bit only being set for interrupt usage and there are no interrupt handlers when only polling.

//'wait till finished
while( ! testbit(CANSTMOB, RXOK ) )
{
	if ( testbit( CANSTMOB, BERR) )
		return -1;
	else if ( testbit( CANSTMOB, BERR) )
		return -2;
	else if ( testbit( CANSTMOB, CERR) )
		return -3;
	else if ( testbit( CANSTMOB, FERR) )
		return -4;
	else if ( testbit( CANSTMOB, AERR) )
		return -5;
}

If you return from this code with an error value, the Rx MOb is still active (the CANEN1/2 register ENMOBn bit is still set) and this MOb is still in use. You might want to set your PORTA (error?) output pin inside the RXOK wait loop and not return here. You could have a RXOK wait loop timeout, then disable the Rx MOb (check the CANEN1/2 bit to verify its disabled) on a timeout error and return. Any CANSTMOB errors do not disable the MOb. The TXOK or RXOK is the only MOb disable the CANSTMOB register has and the CANSTMOB interrupt error flags are all cleared upon a TXOK or RXOK. The BERR cannot happen during in a Rx MOb, BERR is a CAN Tx only error.

It would be a good idea to always check the CANEN1 and CANEN2 register ENMOBn bit and make sure it is disabled before using/setting CANCDMOB.

int ret = -CAN_setReply( 1, 0x11, sensor, 2 );

Is the above -CAN_setReply dash before the C a typo?

You never cleared the RXOK bit before or after the CAN_tx() call. Whenever you are starting with a fresh MOb setup (meaning the CANEN1/2 register ENMOBn bit is cleared), it is best to just set the entire CANSTMOB = 0 and not clear each individual CANSTMOB bit. With your simple polling you do not need to do much with the CANSTMOB bits, but with interrupts you will have to clear all the enabled CANSTMOB bits before you may return from the interrupt.

Also by ignoring the CANGIT error flags you are missing any errors that are not part of an acceptance filter matched MOb. From the beginning of the DLC in the control field to after the 6th bit of the EOF end of frame field is where an active "matched" Rx MOb will divert Rx errors to the CANSTMOB register. All the rest of the CAN serial data frame sends all errors to the CANGIT register. If no acceptance "match" if found for a MOb, the CANGIT is the only place Rx errors are sent. Since an AVR CAN Tx requires a MOb to send anything at all, all local Tx errors always go to CANSTMOB until after the TXOK where the Tx is finished.

You do not need to set CANIDM in the CAN_tx() code. You are redundantly setting the sensor[2] values into CANMSG in both CAN_setReply() and CAN_tx(). You have two tests for BERR in CAN_tx().

I see there are no delays between CAN the CAN_setReply() RXOK and CAN_tx() TXOK (and these work). The delay is between the last CAN_tx() TXOK and the next CAN_setReply() setup. I can't see why this would be a problem. Try checking CANTEC and CANREC values before the delay. Then if you get back into an unending LED activity loop, try checking CANTEC and CANREC again. You might have some kind of AVR error process causing the unending CAN activity?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The ints were enabled because I used an interrupt-driven at first, and then passed on to a polling method to test it outside ISR handlers. I actually put a ISR handler for the CAN, but I forgot to paste it here, sorry.
You're right about the read only bits/registers. I noticed that but forgot to remove it from my code, even though it is harmless here.
The reason that the values are redundantly set is that it was from old code and again, I forgot to delete it.

As you say, the error happens if I don't allow that delay between TXOK and enabling new reception.
I will check CANTEC and CANREC to see what happens, together with CANGIT in both funcs to catch errors. However, I'm getting successful transmission always, even with the 'can bus busy' condition.

The minus sign in

int ret = -CAN_setReply(xxxx,xxx);

is to get a positive value to then shift the bit to show the error on the ATDVK leds (could be done another way too).

I will let you know if I find out something else.
Now I am thinking it could be the SAM7X ARM cpu, but as I said before, even disabling the CAN transceiver and CAN module on the SAM the leds keep on. To clarify, what I do is a single RTR to 0x11 and then disable everything related to CAN on the SAM... and the leds on the 90DVK won't turn off. However, I will try to get more that from this.

thanks!

Carlos

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well..here it is the conclusion => ARM incorrect programming!

I've seen that the ARM was not requesting only one frame with RTR, but several consecutive ones! There was a register which had to be set to 0 in order to avoid that (my misunderstanding with the datasheet!).
It seems to be that the delay there would cause an error so the ARM would stop sending RTR, thus appearing as if the AVR was doing nasty things..

Thanks Mike, and sorry for this long post, it was such a simple thing at last!

So, in the end, it is possible to receive a RTR frame to then send it with the same MOB as the RTR response. It seems to work alright so far!

thanks a lot!

Carlos

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I forgot to mention this:
while( ! testbit(CANSTMOB, TXOK ) )

loop has almost the same exit on error problem where the Tx MOb will still be enabled until the TXOK happens. If the ARM is not hooked up then you will get non-stop CANSTMOB register AERR flags, which would cause you to exit CAN_tx() with a return error, except the AVR CAN automatic retries would keep firing off new CAN Tx frames looking for an acknowledge. CAN_tx() returns an error value to CAN_setReply(), which it ignores and returns a zero back to main(). Your code will never show any return error from CAN_tx().

Whenever main calls CAN_setReply() again, it will overwrite the still active Tx MOb (clearing the CANSTMOB bits in CAN_setReply() will not make any difference since the still active Tx MOb might write to them again at anytime). Then it will try and force a Rx MOb CANCDMOB state on the active Tx MOb. This might contribute to strange behavior.

At your baud rate (2 us per CAN bit) with PART B CAN frames and 2 CANMSG bytes makes 80 CAN bits per Tx data frame plus 3 intermission bits for 83 (84 with the CAN errata). This makes about 166 us (83 * 2 us) between setting another AERR flag. I don't think this timing has anything to do with the unending Tx 140 us delay fix, but I just threw it out for consideration anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oops, I didn't see your latest post until just now after posting again. Its always good news when you kill the bug :wink: BTW, if you want to process errors in your interrupt code there are some special considerations to avoid loosing a RXOK or TXOK interrupt. If you want to send me a PM with an e-mail address I will e-mail my AVR CAN article PDF (about 118 kb) with the details.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

just forgot to close the thread.
Thanks mike for the tips.
So, in the end, yes, it is possible to answer a RTR 'by hand' with 90CAN AVRs.

Carlos