Warning: Atmega644, 644P and 324P and crystal settings

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

Warning: Atmega644, 644P and 324P and crystal settings

After spending lots of time tracking down erratic behavior, incl. finding bugs with the Jtagice mkII, I have found that the Atmega324p, Atmega644 and Atmega644p, when used with an external 20 Mhz crystal and lots of serial input interrupts, ALL REQUIRE THAT THE FUSE IS SET TO FULL SWING OSCILLATOR.

I've written a test program that stores incoming serial input in a large buffer using an ISR routine, then empties the buffer in a forever loop. The test program checks explicitly for conditions that can never happen (like identical pointer tests generating different results with all interrupts off). If the fuse is set to "Ext Crystal 8 Mhz-", the test program fails when sending it lots of serial input. When the fuse is set to "Full Swing Osc", the test program never fails. The test program shows clearly invalid values in the internal registers of the AVR.

The problem is particularly insidious because the AVR seems to run fine, until it receives a lot of interrupts (and maybe other conditions too)

I have run these tests at various baudrates (19200, 38400 and 115200) with identical results.

All tests were run with 5V regulated power. A scope shows NO voltage level variations when executing the tests.

The test program fails on the Atmega324p, Atmega644 and Atmega644p, all 40-pin DIP with the fuse set to "Ext Crystal 8Mhz-". However the test program passes on the Atmega328p with the same fuse settings.

The crystal I used is from Mouser, 815-ABL-20-B2, brand Abracom and the 2 caps are 22 pF each. I have used this combination on my Oscilloscope Clock kit for several years using an Atmega168 and Atmega328p. With over 1000 units sold, there never has been a problem.

I did try 2 other 20 Mhz crystals I had (unknown brand) and they showed identical behavior.

Voltage range (p/p) for the oscillator signal was about 800mV on the XTAL1 pin and 500mV on the XTAL2 pin when using the "Ext Crystal 8 Mhz-" fuse setting and 3.56V on XTAL1, 3.36V on XTAL2 (same for all tested AVRs). However I did notice significant distortions on the XTAL2 pins when the serial interrupts where occuring (I used BreyTerminal to send a batch of 50 characters or more, as well as sending text files).

I'll post the test program in another posting.

My conclusion: the Atmega324P, Atmega644 and Atmega644P (DIP versions) are more sensitive to the crystal used then previous AVRs, specifically the Atmega168 and Atmega328p, and require the "Full Swing Oscillator" fuse setting.

jrseattle

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

I am really skeptical of this conclusion, and await confirmation from other users. This does not mean that the conclusion IS faulty, it only means that there is no apparent good reason for it to be true.

Some important questions:
1. What sort of hardware (circuit board, etc) was this tested on?
2. How were the oscillator capacitors grounded?
3. What other circuit traces or wires ran close to the crystal?
4. How was the power supply bypassed?

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

Quote:
ALL REQUIRE THAT THE FUSE IS SET TO FULL SWING OSCILLATOR.
Sorry JR but this is OLD news. :) Anything that runs at 8MHz and above MUST run in full swing mode.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

It's not quite that cut and dried...

The low power "Vittoz" mode oscillator has been with us since at least the M128, and it is the default in the M128 (maybe all, I haven't checked)

It requires careful selection of the crystal to work properly, but it will "work" with most crystals, most of the time. I've seen this result in slightly slow baud rates, and glitchy problems in data manipulation that we were sure were software, or external hardware problems, till a new batch of M128s wouldn't even start up with our existing crystals.

Since then, I've contacted other people using the M128 in projects where they had wierd issues, and it's amazing how many cleared right up when the full-swing oscillator is selected.

There's more than that to a proper oscillator design, but that's another rant. :)

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

ka7ehk wrote:

2. How were the oscillator capacitors grounded?
3. What other circuit traces or wires ran close to the crystal?
4. How was the power supply bypassed?

Jim

Yup..
First off, select full swing mode always..
Second, what cap values did you use, and why?
Third, how are the traces routed, including the cap grounds. Dumping those into a plane is "ok", but routing them back to the chip on their own isolated track is better..

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

Hi, Jim.

I understand your reaction. My experience only applies to 40-pin DIP AVRs:

    1. I used a small breadboard
    2. both capacitors are connected to the ground rail.
    3. no traces. the crystal is connected to pins 12,13. Pins 10 and 11 are VCC, GND. Pins 14 and 15 are RXD0 and TXD0, connected to a level converted using a wire.
    5. Power comes from the STK-600 and both a 100 uF c electrolytic cap and a .1 uF ceramic cap are used. I checked the power line with a scope.

I'm posting the test program here for other to verify. There are 2 files:
foo.c contains nothing but: void foo(void) {}
bug3.c is below.
Build using -Os, the proper frequency (20 Mhz) and the proper AVR selection.
Then program the AVR (Atmega324P, Atmega644, Atmega644P) using your preferred method, use a 20 Mhz external crystal, connect pin 29 (PC7) to a LED, connect pins 14 and 15 to an RS-232 level converter and send the test setup lots of data at 115,200 bps (I used brey's terminal). The serial output will report incorrect behavior (incl. spontaneous reboots)
In my case, when setting the SUT_CKSEL fuse to "Ext Crystal 8 Mhz -", the test program fails, setting it to "Full swing Oscillator" results in no failures.




#include 
#include 
#include 
#include 

//#define UART_19200	 	64				//at 20 Mhz
#define UART_19200	 	25				//at 8 Mhz
#define UART_115200 	10				//at 20 Mhz
#define UART_38400		32			//at 20 Mhz
//#define UART_38400		12				//at 8 Mhz
#define	UART_SPEED		UART_115200

typedef unsigned char  uint8;
typedef          char  int8;
typedef unsigned int   uint;
typedef unsigned long  ulong;

#define RXSIZE 512
#ifndef cbi
	#define cbi(reg,bit)	reg &= ~(_BV(bit))
#endif
#ifndef sbi
	#define sbi(reg,bit)	reg |= (_BV(bit))
#endif


#define DEBUG 1
uint8 RxBuffer[RXSIZE];		//Serial In Receive Buffer
#if 0
uint8 RxBufferZone[8];
uint8 pwrup_state;
uint8 RefreshLine;
uint8 PCL0;
uint8 PDATA;
uint8 BDATA;
uint8 PClusterBuffer[8];
uint8 Vx, Vy;
uint  Vpix;
#endif
uint8 GrStateMem, GrOldCmdMem, GrCmdMem;
volatile uint8 *TailPtr;
volatile uint8 *HeadPtr;


volatile uint8   UART_Ready;
#define PRG_RDB(p) (p)

void UART_SendByte(uint8 Data)
{   
    /* wait for UART to become available */
	while ((UART_Ready == 0) && ((UCSR0A & _BV(TXC0)) == 0)) ;
	UCSR0A |= _BV(TXC0);
    UART_Ready = 0;
    /* Send character */
    UDR0 = Data;
}

//
// Immediate version
//
void UART_PrintfProgStr_I(prog_char* pBuf)
{
	uint8 ch;
	while ((ch = pgm_read_byte(pBuf)) != 0) {
		UART_SendByte(ch);
		++pBuf;
		while ((UART_Ready == 0) && ((UCSR0A & _BV(TXC0)) == 0)) ;
		UART_Ready = 1;
		UCSR0A |= _BV(TXC0);
	}
}


void UART_PrintfU4(uint8 Data)
{
    /* Send 4-bit hex value */
    uint8 Character = Data&0x0f;
    if (Character>9)
    {
        Character+='A'-10;
    }
    else
    {
        Character+='0';
    }
    UART_SendByte(Character);
}

void UART_Printfuint8(uint8 Data)
{
    /* Send 8-bit hex value */
    UART_PrintfU4(Data>>4);
    UART_PrintfU4(Data);
}

void UART_Printfuint(uint Data)
{
    /* Send 16-bit hex value */
    UART_Printfuint8(Data>>8);
    UART_Printfuint8(Data);
}

void BlinkFast(void)
{
	for (int i = 0; i < 10; ++i) {
		sbi(PORTC,7);
		_delay_ms(100);
		cbi(PORTC,7);
		_delay_ms(100);
	}
}

void ShortBlinkFast(void)
{
	for (int i = 0; i < 3; ++i) {
		sbi(PORTC,7);
		_delay_ms(100);
		cbi(PORTC,7);
		_delay_ms(100);
	}
}

void BlinkSlow(void)
{
	for (int i = 0; i < 10; ++i) {
		sbi(PORTC,7);
		_delay_ms(250);
		cbi(PORTC,7);
		_delay_ms(250);
	}
}
//
// PC7, PB7 are debug leds
//
void InitDebug(void)
{
	cbi(PORTC,7);			//low
	sbi(DDRC,7);			//output
}

const char DiagStr1[] PROGMEM = "DebugL1\n\r";
const char DiagStr2[] PROGMEM = "DebugL2\n\r";
const char DiagStr3[] PROGMEM = "DebugL3\n\r";
const char DiagStr4[] PROGMEM = "DebugL4\n\r";
const char DiagStr5[] PROGMEM = "DebugL5\n\r";

void DebugL1(void)
{
	UART_PrintfProgStr_I((prog_char*)DiagStr1);
	BlinkSlow();
}

void DebugL2(void)
{
	UART_PrintfProgStr_I((prog_char*)DiagStr2);
	BlinkFast();
}

void DebugL3(void)
{
	UART_PrintfProgStr_I((prog_char*)DiagStr3);
	BlinkFast();
}

void DebugL4(void)
{
	UART_PrintfProgStr_I((prog_char*)DiagStr4);
	BlinkFast();
}

void DebugL5(void)
{
	UART_PrintfProgStr_I((prog_char*)DiagStr5);
	BlinkFast();
}

void foo(void);


void InitCtrl(void)
{
//
// UART0 init.
//
	UBRR0L = UART_SPEED;		//value depends on Clock speed
	UBRR0H = 0;
	UCSR0A = 0;
// Enable UART
    UCSR0B = _BV(RXEN0)|_BV(TXEN0);
	sbi(UCSR0B, RXCIE0);
// set default 8 bits, no parity, 1 stop
	UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
//
	InitDebug();
    UART_Ready        = 1;
//
// initialize Serial In buffer pointers
//
//	ParseIdx = 0;
	HeadPtr = TailPtr = &RxBuffer[0];
}


//
// RS232 RECEIVE EVENT HANDLER
//
// Serial Input Buffer pointers
//
ISR(USART0_RX_vect)
{
	uint8 ch;
//
// Get Data from RS232
//
	ch = UDR0;
	*HeadPtr++ = ch;
	if (HeadPtr >= &RxBuffer[RXSIZE]) {
		HeadPtr = RxBuffer;
	}
	if (HeadPtr == TailPtr) {	//overflow test
		--HeadPtr;
		if (HeadPtr < RxBuffer) {
			HeadPtr = &RxBuffer[RXSIZE-1];
		}
	}
}

void foo(void);
volatile uint8 state;
volatile uint8 *HP1;
volatile uint8 *TP1;
volatile uint8 *HP2;
volatile uint8 *TP2;
volatile uint8 *HP3;
volatile uint8 *TP3;
volatile uint8 *HP4;
volatile uint8 *TP4;
volatile uint8 *HP5;
volatile uint8 *TP5;
uint8 SavedR24;

//
// Command Processing
//
// Idea is to pull bytes from the Serial In buffer and process them.
//
// Since the buffer pointers are changed by the Serial In ISR,
// we need to disable interrupts when accessing them.
//
// For some reason, the buffer pointers are all messed up,
// even when disabling interrupts for most of the time.
//
void ProcessCommands()
{
	while (1) {
		cli();
		state = 10;
		HP1 = HeadPtr;
		TP1 = TailPtr;
		state++;		//11
		foo();
		if (HeadPtr == TailPtr) {
			break;
		} else {
			HP2 = HeadPtr;
			TP2 = TailPtr;
			foo();
			if (TailPtr == HeadPtr) {
				if (HeadPtr != HP2) {
					UART_Printfuint((uint)HeadPtr);
					UART_SendByte(' ');
					UART_Printfuint((uint)HP2);
					UART_SendByte(' ');
				}
				if (TailPtr != TP2) {
					UART_Printfuint((uint)TailPtr);
					UART_SendByte(' ');
					UART_Printfuint((uint)TP2);
					UART_SendByte(' ');
				}
				DebugL1();		// HOW CAN THIS HAPPEN?
				break;
			}
		}
		state++;		//12
		GrCmdMem = *TailPtr;
		state++;		//13
		HP3 = HeadPtr;
		TP3 = TailPtr;
		foo();
		if (HeadPtr == TailPtr) {
			DebugL2();		// HOW CAN THIS HAPPEN?
			break;
		}
		state++;		//14
		HP3 = HeadPtr;
		TP3 = TailPtr;
		foo();
		if (TailPtr > &RxBuffer[RXSIZE]) {
			DebugL3();		// HOW CAN THIS HAPPEN?
			TailPtr = HeadPtr;
			break;
		}
		state++;		//15
		HP4 = HeadPtr;
		TP4 = TailPtr;
		foo();
		if (HeadPtr > &RxBuffer[RXSIZE]) {
			DebugL4();		// HOW CAN THIS HAPPEN?
			HeadPtr = TailPtr;
			break;
		}
		state++;		//16

		if (++TailPtr >= &RxBuffer[RXSIZE]) {
			TailPtr = &RxBuffer[0];
		}
		sei();
		state = 0;
 	}
	sei();
}

const char DiagStr[] PROGMEM = "Program Start\n\r";

int main(void)
{
	unsigned int i = 0;
	InitCtrl();

	UART_PrintfProgStr_I((prog_char*)DiagStr);

	sei();							//start interrupts -> screen refresh, serial in


	do {
		//
		// process queued graphic commands from SerialIn
		//
		_delay_ms(1);

		ProcessCommands();

		if (++i == 0x1ff) {
			i = 0;
			UART_SendByte('.');
			ShortBlinkFast();
		}

	} while (1);
}



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

I for one am not surprised. Using the low power mode is BEGGING for trouble. Like walking through the bad part of Detroit in a suit made of money.

The worst thing about it, is that it frequently looks like it's working ok.

I don't know why they made it the default.. Most users are apparently clueless as to the implications, and the problems it causes are hard to pick up, unless you get lucky and it just fails to run.

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

I'm sorry for having reinvented the wheel :)

Since this setup works great with the 20 and 28 pins DIP AVRs, I was blindsided and was not aware of the risks involved when using the "Ext crystal 8 Mhz -" mode. I won't do that again.

jrseattle.

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

The problem is not "external crystal". It is external crystal in low power (not full swing) mode.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

You need to also look over the datasheet instead of counting on the Avr Studio fuse selection list to guide you. In Avr Studio, 'Ext. Crystal Osc 8.0-' means 'Low Power Crystal Oscillator' which in the datasheet lists 8-16mhz as an option in that mode. No 20mhz listed, except in the 'Full Swing Crystal Oscillator' and 'External Clock' sections. Which means the only options for 20mhz, is full swing crystal or external clock. I think one would still have problems at 8-16 unless in full swing mode (I can't run 14.7 reliably unless in full swing).

Figure out from the datasheet what fuses you want/need, then make sure that matches with what Studio is doing.

I'm not sure why they can't match the datasheet wording for the low power crystal settings.

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

Quote:

The problem is not "external crystal". It is external crystal in low power (not full swing) mode.

From the threads, I'd say the problem is not "external crystal in low power mode", but rather "driving too fast for conditions". You kids allus gotta go so fast.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Yea, but then some oldster do also.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

theusch wrote:
Quote:

The problem is not "external crystal". It is external crystal in low power (not full swing) mode.

From the threads, I'd say the problem is not "external crystal in low power mode", but rather "driving too fast for conditions". You kids allus gotta go so fast.

Lee

Well, "overclocking" is another thing, and IMHO always a bad idea..

But I have seen wonderous and fearfully bizarre things happen with the "low power" mode, even at low speeds. The oscillator amplitude can apparently be low enough that either clocking itself is unreliable, or parts of the chip don't get clocked reliably. Hard to tell from the outside.

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

jrseattle wrote:

The crystal I used is from Mouser, 815-ABL-20-B2, brand Abracom and the 2 caps are 22 pF each. I have used this combination on my Oscilloscope Clock kit for several years using an Atmega168 and Atmega328p. With over 1000 units sold, there never has been a problem.

I did try 2 other 20 Mhz crystals I had (unknown brand) and they showed identical behavior.

Voltage range (p/p) for the oscillator signal was about 800mV on the XTAL1 pin and 500mV on the XTAL2 pin when using the "Ext Crystal 8 Mhz-" fuse setting and 3.56V on XTAL1, 3.36V on XTAL2 (same for all tested AVRs). However I did notice significant distortions on the XTAL2 pins when the serial interrupts where occuring (I used BreyTerminal to send a batch of 50 characters or more, as well as sending text files).

jrseattle

Hmm.. Despite how many have been built in the past, this doesn't seem right.
http://www.abracon.com/Resonator...
So for the 20 MHz part, we have 40 ohms ESR, 18pF, and 100uW drive.

Fox has probably the clearest writeup:
http://www.foxonline.com/pdfs/os...

Given the specs, I'd expect around 27-33pF for cap values. I'd also want to do the negative resistance measurement, and assure that the crystal isn't being overdriven.

But I do agree, the low power mode is a far more serious problem. Scoping the drive level is even problematic, a typical scope probe will contribute about 10pF. An active FET probe would be better, but I don't have one handy, and most people won't either.

And: So you're the oscilliscope clock guy! :) I like it. Very nice.

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

dbvanhorn wrote:

Given the specs, I'd expect around 27-33pF for cap values. I'd also want to do the negative resistance measurement, and assure that the crystal isn't being overdriven.

My experience tells me that that is way too high. I'm going to say you need to be in the 12-15pF range for a 20MHz crystal oscillator.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

glitch wrote:
dbvanhorn wrote:

Given the specs, I'd expect around 27-33pF for cap values. I'd also want to do the negative resistance measurement, and assure that the crystal isn't being overdriven.

My experience tells me that that is way too high. I'm going to say you need to be in the 12-15pF range for a 20MHz crystal oscillator.

Exactly. Read the fox app note. The two caps are in series, as far as the crystal is concerned, so you need a bit less than twice the Cl value, plus parasitics.

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

Quote:

Well, "overclocking" is another thing,

I wasn't referring to overclocking, and the comments were somewhat tongue-in-cheek:

-- While I usually have full-swing set on my non-battery-powered apps (why not?), I've tried it both ways.

-- When I tested the power draw on a battery app, full-swing versus not, there was only a minute difference in power draw. [This became moot as the app needed fast wakeup so internal oscillator was used which also takes less power than a crystal.]

-- Re the need for speed: I've only got one (actually a pair of related) app in well over 100 production AVR apps over the years that are clocked faster than 7.3728MHz. I don't know what kind of apps y'all have that need all those MHz (and power usage and EMI radiation) but I don't run into them much.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:

-- While I usually have full-swing set on my non-battery-powered apps (why not?), I've tried it both ways.

Yeah, the Low power oscillator could be a good thing, but it takes a lot more work to select a crystal that will work RELIABLY with it.
One of the articles I read on the Vittoz oscillators back when I was researching this, said that these oscillators are so sensitive that a fingerprint on the PCB could be enough to cause problems.

They were developed for ultra-low power applications like digital watches.

theusch wrote:

-- Re the need for speed: I've only got one (actually a pair of related) app in well over 100 production AVR apps over the years that are clocked faster than 7.3728MHz. I don't know what kind of apps y'all have that need all those MHz (and power usage and EMI radiation) but I don't run into them much.
Lee

Yeah.. Normally I'm developing with the fastest I can get, but in production, I peel it back to what it needs. The current app uses only two timers, and one ADC input, or two I/O pins, and the uart, but it uses ALL the sram, and needs some serious crunch. I'm only about halfway there. I'm doing some fun sensor processing. The link gives some idea where I'm headed.

http://www.cs.cmu.edu/~jch1/rese...

Not bad for my second project in C after "Hello World" eh? :)

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

curtvm wrote:
You need to also look over the datasheet instead of counting on the Avr Studio fuse selection list to guide you. In Avr Studio, 'Ext. Crystal Osc 8.0-' means 'Low Power Crystal Oscillator' which in the datasheet lists 8-16mhz as an option in that mode. No 20mhz listed, except in the 'Full Swing Crystal Oscillator' and 'External Clock' sections.

Figure out from the datasheet what fuses you want/need, then make sure that matches with what Studio is doing.

I'm not sure why they can't match the datasheet wording for the low power crystal settings.

>insert long, creative, and unprintable cursing which wouldn't be acceptable for a public forum<

Dammit! I've been bit by that @!@##!$ CKOPT fuse again! I didn't read the options closely enough.. It seems that they've decided to stop calling it CKOPT, and rolled it in with the rest of the bits.

My low fuses were 0xDF, which selected that damnable low power mode!.. I should have been using, and AM NOW USING 0xD7, which is the full swing mode.
Verified on scope, it was about 1/2VCC amplitude.