[SOLVED] Dynamic Clock Switch don't seems to work

Go To Last Post
67 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Part: ATtiny167

Referring to its datasheet, I've tried the code on page 36 but seems to have problem => clock don't seems to be switching.

1. I think there is a typo-error under the watchdog section. There is no "WDTCSR". I've changed it to WDTCR.

2. Should I added

asm("sei"); 

right after

SREG = temp;

to re-enable the interrupts?

Thanks.

Once an engineer, forever an engineer

Last Edited: Wed. Jun 19, 2013 - 12:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MacTuxLin wrote:
Referring to its datasheet, I've tried the code on page 36 but seems to have problem => clock don't seems to be switching.
What clock sources are you switching between? What clock is active on reset?
Quote:
I think there is a typo-error under the watchdog section. There is no "WDTCSR". I've changed it to WDTCR.
There's a few typos like that scattered throughout AVR datasheets. Probably a copy-and-paste error on the part of the technical writers.
Quote:
Should I added
asm("sei"); 

right after

SREG = temp;

to re-enable the interrupts?

No. If interrupts were enabled before, then:
temp = SREG;

... will capture that, and:

SREG = temp;

... will restore it. Adding and SEI will simply force interrupts to be enabled, even if they weren't before.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Thanks JJ.

I've placed the code inside a ClockSwitching.c & reference from the main.c. I've burnt the fuse to get from external crystal. Have I erred?

So when I called

	//Switching Clock
	ClockSwitching(0x02, 0x02);

my blinking LED doesn't blink anymore.

Attachment(s): 

Once an engineer, forever an engineer

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

You should uncheck the CKDIV8 fuse. And always a good idea to turn BOD on.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

That's right. Thanks John.

Still, the ClockSwitching() isn't working though.

void ClockSwitching(unsigned char clk_number, unsigned char sut )
{
	#define	CLOCK_RECOVER	0x05
	#define CLOCK_ENABLE	0x02
	#define CLOCK_SWITCH	0X04
	#define CLOCK_DISABLE	0x01
	#define WD_ARL_ENABLE	0x06
	
	#define WD_2048CYCLES	0x07
	
	unsigned char previous_clk, temp;
	
	//Disable interrupts
	//temp = SREG; asm("cli");
	temp = SREG; // asm("cli");
	
	//Save the current system clock source
	CLKSELR = 1 << CLKCCE;
	CLKCSR = CLOCK_RECOVER;
	previous_clk = CLKSELR & 0x0F;
	//Enable the new clock source
	CLKSELR = ((sut << 4) & 0x30) | (clk_number & 0x0F);
	CLKCSR = 1 << CLKCCE;
	CLKCSR = CLOCK_ENABLE;
	//Wait for clock validity
	while ((CLKCSR & (1 << CLKRDY)) == 0);
	//Enable the watchdog in automatic reload mode
	WDTCR = (1 << WDCE) | (1 << WDE);
	WDTCR = (1 << WDE) | WD_2048CYCLES;
	CLKCSR = 1 << CLKCCE;
	CLKCSR = WD_ARL_ENABLE;
	//Switch clock source
	CLKCSR = 1 << CLKCCE;
	CLKCSR = CLOCK_SWITCH;
	//Wait for effective switching
	while(1)
	{
		CLKCSR = 1 << CLKCCE;
		CLKCSR = CLOCK_RECOVER;
		if((CLKSELR & 0x0F) == (clk_number & 0x0F)) break;
	}
	//Shutdown unneeded clock source
	if(previous_clk != (clk_number & 0x0F))
	{
		CLKSELR = previous_clk;
		CLKCSR = 1 << CLKCCE;
		CLKCSR = CLOCK_DISABLE;
	}
	SREG = temp;
	//asm("sei");
}

Once an engineer, forever an engineer

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

Are you using optimisation? If not some of that stuff may not work as it may need the correct ammount of clock cycles or the operation will fail.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Thanks John. Do you mean the watchdog's wait cycles? Just noticed that the value assigned to the WD_2048CYCLES in the datasheet seems wrong as the value should seems to be referring to 256K cycles instead. But, even if I increased that to 8.0s, the result remains the same.

As for optimisation, do you mean I should add parameters to avr-gcc? My test code, main.c, is very simple, just:

#define F_CPU	4000000

#include 
#include 

void ClockSwitching(unsigned char clk_number, unsigned char sut );

int main(void)
{
	
	//Switching Clock
	ClockSwitching(0x0C, 0x02);
		
	DDRA |= (1 << PORTA0);	//Output for LED
	
    while(1)
    {
		PORTA ^= (1 << PORTA0);
		_delay_ms(1000);
    }
}

I've placed a 4MHz crystal at XTAL1 & 2 with 22pF each. Have I erred anywhere? If I comment out ClockSwitching(), code worked as it should.

Thanks.

Once an engineer, forever an engineer

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

Quote:

As for optimisation, do you mean I should add parameters to avr-gcc?

Make sure the optimisation is set to anything from -O1 upwards (usually -Os). Do not use -O0 as that is what will cause real problems with any timed sequences as the compiler output will be so dire it almost certainly will not meet the deadlines.

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

Thanks Clawson. I've tried -O1 to -O3 & -Os. Result remains the same. The LED will not blink. Should I try debugging & step through to see where it actually seems to have gone wrong?

Attachment(s): 

Once an engineer, forever an engineer

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

I'm a little lost with AS6 but I think you need to set the optimisation both for the release and debug version of the code.

With another brand IDE I simply set both to -Os as I can't be bothered.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I've switched to debugWIRE & noticed that the instructions just hangs (loop) within:

while ((CLKCSR & (1 << CLKRDY)) == 0);

From datasheet (page 40), it states that after writing CLKCCE to CLKCSR, the desired value (I presume its Enable clock source in the datasheet's code) be written to CLKCSR within 4 clock cycles. From one instruction to the next, wouldn't that be less than 4 cycles?

CLKCSR = 1 << CLKCCE;
CLKCSR = CLOCK_ENABLE;

Once I start the debug, I did a "Run to Cursor" where my cursor was right after the loop

WDTCR = (1 << WDCE) | (1 << WDE);

So that gave me my assumptions that the CLKRDY bit was never set. Meaning, the clock is not available & not stable? Where am I doing it wrong? :?

Once an engineer, forever an engineer

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

Quote:
wouldn't that be less than 4 cycles?
Only if optimisation is enabled otherwise it can be anything.

An easy way to find out is to look at the .lss file and it will show you.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Thanks John. I noticed quite a number of instructions had the words <_bad_interrupt>... What does that mean?

	//Disable interrupts
	//temp = SREG; asm("cli");
	temp = SREG;
   0:	0c 94 28 00 	jmp	0x50	; 0x50 <__ctors_end>
	
	//Save the current system clock source
	CLKSELR = 1 << CLKCCE;
   4:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
	CLKCSR = CLOCK_RECOVER;
   8:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
   c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
	previous_clk = CLKSELR & 0x0F;
  10:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
	//Enable the new clock source
	CLKSELR = ((sut << 4) & 0x30) | (clk_number & 0x0F);
  14:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  18:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  1c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  20:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  24:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  28:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  2c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
	//CLKCSR = 1 << CLKCCE;
	CLKCSR = 1 << CLKCCE & 0xFF;
  30:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
	CLKCSR = CLOCK_ENABLE;
  34:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
	//Wait for clock validity
	while ((CLKCSR & (1 << CLKRDY)) == 0);
  38:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  3c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
	//Enable the watchdog in automatic reload mode
	WDTCR = (1 << WDCE) | (1 << WDE);
  40:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  44:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
	//WDTCR = (1 << WDE) | WD_2048CYCLES;
	//WDTCR = (1 << WDE) | WD_4096CYCLES;
	//WDTCR = (1 << WDE) | WD_32KCYCLES;
	//WDTCR = (1 << WDE) | WD_256KCYCLES;
	WDTCR = (1 << WDE) | WD_MAXCYCLES;
  48:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
	
	CLKCSR = 1 << CLKCCE;
  4c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>

Once an engineer, forever an engineer

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

Something is SERIOUSLY WRONG! Your code is doing nothing but jumping to the __bad_interrupt.

You need to post some REAL code which is compilable by others, the above is utter nonsense. :-)

edit alao are you supposed to put definitions inside functions? I don't really know but I have never done it.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Well, that seems to tell me that I ought to trash the codes from the datasheet as that is where I've gotten them from.

Once an engineer, forever an engineer

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

Or set up the code properly with all defintions in .h files or at least at the top of the main file rather than within the function. But I could be wrong again. :-)

Also I don't thing that you don't need to do anything with SREG.

I don't have AS6 on this computer so I can't do any testing.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Ok so AS4.18 supports the chip. This seems to produce sensible code, can't test for functionality as I don't have a chip.

#define F_CPU   4000000 

#include  
#include  

#define CLOCK_RECOVER   0x05 
#define CLOCK_ENABLE   0x02 
#define CLOCK_SWITCH   0X04 
#define CLOCK_DISABLE   0x01 
#define WD_ARL_ENABLE   0x06 
    
#define WD_2048CYCLES   0x07 

//void ClockSwitching(unsigned char clk_number, unsigned char sut ); 
void ClockSwitching(unsigned char clk_number, unsigned char sut ) 
{ 

   unsigned char previous_clk;	//, temp; 
    
//Disable interrupts 
//temp = SREG; asm("cli"); 
//temp = SREG; // asm("cli"); 
    
   //Save the current system clock source 
   CLKSELR = 1 << CLKCCE; 
   CLKCSR = CLOCK_RECOVER; 
   previous_clk = CLKSELR & 0x0F; 
   //Enable the new clock source 
   CLKSELR = ((sut << 4) & 0x30) | (clk_number & 0x0F); 
   CLKCSR = 1 << CLKCCE; 
   CLKCSR = CLOCK_ENABLE; 
   //Wait for clock validity 
   while ((CLKCSR & (1 << CLKRDY)) == 0); 
   //Enable the watchdog in automatic reload mode 
   WDTCR = (1 << WDCE) | (1 << WDE); 
   WDTCR = (1 << WDE) | WD_2048CYCLES; 
   CLKCSR = 1 << CLKCCE; 
   CLKCSR = WD_ARL_ENABLE; 
   //Switch clock source 
   CLKCSR = 1 << CLKCCE; 
   CLKCSR = CLOCK_SWITCH; 
   //Wait for effective switching 
   while(1) 
   { 
      CLKCSR = 1 << CLKCCE; 
      CLKCSR = CLOCK_RECOVER; 
      if((CLKSELR & 0x0F) == (clk_number & 0x0F)) break; 
   } 
   //Shutdown unneeded clock source 
   if(previous_clk != (clk_number & 0x0F)) 
   { 
      CLKSELR = previous_clk; 
      CLKCSR = 1 << CLKCCE; 
      CLKCSR = CLOCK_DISABLE; 
   } 

//SREG = temp; 
//asm("sei"); 
} 

int main(void) 
{ 
    
   //Switching Clock 
   ClockSwitching(0x0C, 0x02); 
       
   DDRA |= (1 << PORTA0);   //Output for LED 
    
    while(1) 
    { 
      PORTA ^= (1 << PORTA0); 
      _delay_ms(1000); 
    } 
} 

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:
Something is SERIOUSLY WRONG! Your code is doing nothing but jumping to the __bad_interrupt.
Something is indeed seriously wrong, but I don't believe it is merely jumping to the __bad_interrupt.
MacTuxLin wrote:
Well, that seems to tell me that I ought to trash the codes from the datasheet as that is where I've gotten them from.
I don't think that's the conclusion either. The code example in the datasheet is sound. It looks like your (AS6's) build process is broken on your machine.

Have a look at the .lss posted above again. We're seeing the interrupt vectors interspersed with source from the code in ClockSwitching(). The vector table is what I'd expect to see at the beginning of the .lss, and it is located at the correct address, but that's all we get. The reset vector at 0x0000 correctly points to <__ctors_end> at 0x0050, but that and everything else after it has been omitted.

Is this in fact the complete .lss?

I don't use AS6 so I can't advise you, unfortunately. I assume you're up-to-date with the latest 6.1? I've heard of trouble with earlier 6.0 releases.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Thanks for your patience, John. Not sure why then the datasheet placed the stop interrupts but I'll dig deeper. I'm still quite new to AVR but I'm gonna make more effort in getting it to work. I'm basically trying out different features before properly writing our my final code. Headers in .h, codes & such. I'm trying out USART right after sorting this out.

JJ, I think you're right. I'm have some frustrating time with AS6.1. Normally, pressing Ctrl+Alt+F5 should build & load to device. However, it is not always properly loaded. Only by selecting the Tools/Device Programming & performing a Program under Memories will ensure the device gets the correct .elf loaded. I'm reinstalling AS6.1 (uninstall/ccclean registers/install AS6.1). Anyway, I've added this problem to Atmel's bugzilla site. Not sure if it has anything to do with my installation but I reckon it should not have a inconsistent loading of firmware to the device, though.

Attached is the latest .lss file I get from John's code.


TryingClockingATtiny167_R2.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000000  00800100  00000120  00000194  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         00000120  00000000  00000000  00000074  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .stab         000006cc  00000000  00000000  00000194  2**2
                  CONTENTS, READONLY, DEBUGGING
  3 .stabstr      00000097  00000000  00000000  00000860  2**0
                  CONTENTS, READONLY, DEBUGGING
  4 .comment      0000002f  00000000  00000000  000008f7  2**0
                  CONTENTS, READONLY
  5 .debug_aranges 00000028  00000000  00000000  00000926  2**0
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_info   00000189  00000000  00000000  0000094e  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_abbrev 00000130  00000000  00000000  00000ad7  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_line   000001c0  00000000  00000000  00000c07  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_frame  00000034  00000000  00000000  00000dc8  2**2
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_str    00000153  00000000  00000000  00000dfc  2**0
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_loc    00000042  00000000  00000000  00000f4f  2**0
                  CONTENTS, READONLY, DEBUGGING
 12 .debug_ranges 00000018  00000000  00000000  00000f91  2**0
                  CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 28 00 	jmp	0x50	; 0x50 <__ctors_end>
   4:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
   8:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
   c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  10:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  14:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  18:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  1c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  20:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  24:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  28:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  2c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  30:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  34:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  38:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  3c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  40:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  44:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  48:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  4c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>

00000050 <__ctors_end>:
  50:	11 24       	eor	r1, r1
  52:	1f be       	out	0x3f, r1	; 63
  54:	ce ef       	ldi	r28, 0xFE	; 254
  56:	d2 e0       	ldi	r29, 0x02	; 2
  58:	de bf       	out	0x3e, r29	; 62
  5a:	cd bf       	out	0x3d, r28	; 61
  5c:	0e 94 7b 00 	call	0xf6	; 0xf6 
60: 0c 94 8e 00 jmp 0x11c ; 0x11c <_exit> 00000064 <__bad_interrupt>: 64: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 00000068 : //Disable interrupts //temp = SREG; asm("cli"); //temp = SREG; // asm("cli"); //Save the current system clock source CLKSELR = 1 << CLKCCE; 68: 90 e8 ldi r25, 0x80 ; 128 6a: 90 93 63 00 sts 0x0063, r25 CLKCSR = CLOCK_RECOVER; 6e: 25 e0 ldi r18, 0x05 ; 5 70: 20 93 62 00 sts 0x0062, r18 previous_clk = CLKSELR & 0x0F; 74: 40 91 63 00 lds r20, 0x0063 78: 4f 70 andi r20, 0x0F ; 15 //Enable the new clock source CLKSELR = ((sut << 4) & 0x30) | (clk_number & 0x0F); 7a: 58 2f mov r21, r24 7c: 5f 70 andi r21, 0x0F ; 15 7e: 70 e0 ldi r23, 0x00 ; 0 80: 62 95 swap r22 82: 72 95 swap r23 84: 70 7f andi r23, 0xF0 ; 240 86: 76 27 eor r23, r22 88: 60 7f andi r22, 0xF0 ; 240 8a: 76 27 eor r23, r22 8c: 60 73 andi r22, 0x30 ; 48 8e: 77 27 eor r23, r23 90: 65 2b or r22, r21 92: 60 93 63 00 sts 0x0063, r22 CLKCSR = 1 << CLKCCE; 96: 90 93 62 00 sts 0x0062, r25 CLKCSR = CLOCK_ENABLE; 9a: 92 e0 ldi r25, 0x02 ; 2 9c: 90 93 62 00 sts 0x0062, r25 //Wait for clock validity while ((CLKCSR & (1 << CLKRDY)) == 0); a0: 90 91 62 00 lds r25, 0x0062 a4: 94 ff sbrs r25, 4 a6: fc cf rjmp .-8 ; 0xa0 //Enable the watchdog in automatic reload mode WDTCR = (1 << WDCE) | (1 << WDE); a8: 98 e1 ldi r25, 0x18 ; 24 aa: 90 93 60 00 sts 0x0060, r25 WDTCR = (1 << WDE) | WD_2048CYCLES; ae: 9f e0 ldi r25, 0x0F ; 15 b0: 90 93 60 00 sts 0x0060, r25 CLKCSR = 1 << CLKCCE; b4: 90 e8 ldi r25, 0x80 ; 128 b6: 90 93 62 00 sts 0x0062, r25 CLKCSR = WD_ARL_ENABLE; ba: 26 e0 ldi r18, 0x06 ; 6 bc: 20 93 62 00 sts 0x0062, r18 //Switch clock source CLKCSR = 1 << CLKCCE; c0: 90 93 62 00 sts 0x0062, r25 CLKCSR = CLOCK_SWITCH; c4: 94 e0 ldi r25, 0x04 ; 4 c6: 90 93 62 00 sts 0x0062, r25 //Wait for effective switching while(1) { CLKCSR = 1 << CLKCCE; ca: 30 e8 ldi r19, 0x80 ; 128 CLKCSR = CLOCK_RECOVER; cc: 25 e0 ldi r18, 0x05 ; 5 CLKCSR = 1 << CLKCCE; CLKCSR = CLOCK_SWITCH; //Wait for effective switching while(1) { CLKCSR = 1 << CLKCCE; ce: 30 93 62 00 sts 0x0062, r19 CLKCSR = CLOCK_RECOVER; d2: 20 93 62 00 sts 0x0062, r18 if((CLKSELR & 0x0F) == (clk_number & 0x0F)) break; d6: 90 91 63 00 lds r25, 0x0063 da: 98 27 eor r25, r24 dc: 9f 70 andi r25, 0x0F ; 15 de: b9 f7 brne .-18 ; 0xce } //Shutdown unneeded clock source if(previous_clk != (clk_number & 0x0F)) e0: 45 17 cp r20, r21 e2: 41 f0 breq .+16 ; 0xf4 { CLKSELR = previous_clk; e4: 40 93 63 00 sts 0x0063, r20 CLKCSR = 1 << CLKCCE; e8: 80 e8 ldi r24, 0x80 ; 128 ea: 80 93 62 00 sts 0x0062, r24 CLKCSR = CLOCK_DISABLE; ee: 81 e0 ldi r24, 0x01 ; 1 f0: 80 93 62 00 sts 0x0062, r24 f4: 08 95 ret 000000f6
: int main(void) { //Switching Clock ClockSwitching(0x0C, 0x02); f6: 62 e0 ldi r22, 0x02 ; 2 f8: 8c e0 ldi r24, 0x0C ; 12 fa: 0e 94 34 00 call 0x68 ; 0x68 DDRA |= (1 << PORTA0); //Output for LED fe: 08 9a sbi 0x01, 0 ; 1 while(1) { PORTA ^= (1 << PORTA0); 100: 91 e0 ldi r25, 0x01 ; 1 102: 82 b1 in r24, 0x02 ; 2 104: 89 27 eor r24, r25 106: 82 b9 out 0x02, r24 ; 2 #else //round up by default __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); #endif __builtin_avr_delay_cycles(__ticks_dc); 108: 2f ef ldi r18, 0xFF ; 255 10a: 34 e3 ldi r19, 0x34 ; 52 10c: 8c e0 ldi r24, 0x0C ; 12 10e: 21 50 subi r18, 0x01 ; 1 110: 30 40 sbci r19, 0x00 ; 0 112: 80 40 sbci r24, 0x00 ; 0 114: e1 f7 brne .-8 ; 0x10e 116: 00 c0 rjmp .+0 ; 0x118 118: 00 00 nop 11a: f3 cf rjmp .-26 ; 0x102 0000011c <_exit>: 11c: f8 94 cli 0000011e <__stop_program>: 11e: ff cf rjmp .-2 ; 0x11e <__stop_program>

Once an engineer, forever an engineer

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

Quote:
Not sure why then the datasheet placed the stop interrupts but I'll dig deeper
If interrupts are being use in the final code then you MUST stop them otherwise, if an interrupt happens, the 4 clock cycles requirements for some operation will fail.

Does the above code work now with the chip or is it still hanging somewhere?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

No, it was still hanging somewhere. Anyway, I'm now reinstalling AS6.1 & will test it again.

As for the interrupt, understood.

Once an engineer, forever an engineer

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

Just moved the code to AS6.1 and added interrupts bits, unfortunately the simulator in AS6 doesn't support the chip. :(

#define F_CPU   4000000 

#include  
#include  
#include 

#define CLOCK_RECOVER   0x05 
#define CLOCK_ENABLE   0x02 
#define CLOCK_SWITCH   0X04 
#define CLOCK_DISABLE   0x01 
#define WD_ARL_ENABLE   0x06 
    
#define WD_2048CYCLES   0x07 

//void ClockSwitching(unsigned char clk_number, unsigned char sut ); 
void ClockSwitching(unsigned char clk_number, unsigned char sut ) 
{ 

   unsigned char previous_clk;	//, temp; 
    
//Disable interrupts 
//temp = SREG; asm("cli"); 
//temp = SREG; // asm("cli"); 
 
    cli ();
	
   //Save the current system clock source 
   CLKSELR = 1 << CLKCCE; 
   CLKCSR = CLOCK_RECOVER; 
   previous_clk = CLKSELR & 0x0F; 
   //Enable the new clock source 
   CLKSELR = ((sut << 4) & 0x30) | (clk_number & 0x0F); 
   CLKCSR = 1 << CLKCCE; 
   CLKCSR = CLOCK_ENABLE; 
   //Wait for clock validity 
   while ((CLKCSR & (1 << CLKRDY)) == 0); 
   //Enable the watchdog in automatic reload mode 
   WDTCR = (1 << WDCE) | (1 << WDE); 
   WDTCR = (1 << WDE) | WD_2048CYCLES; 
   CLKCSR = 1 << CLKCCE; 
   CLKCSR = WD_ARL_ENABLE; 
   //Switch clock source 
   CLKCSR = 1 << CLKCCE; 
   CLKCSR = CLOCK_SWITCH; 
   //Wait for effective switching 
   while(1) 
   { 
      CLKCSR = 1 << CLKCCE; 
      CLKCSR = CLOCK_RECOVER; 
      if((CLKSELR & 0x0F) == (clk_number & 0x0F)) break; 
   } 
   //Shutdown unneeded clock source 
   if(previous_clk != (clk_number & 0x0F)) 
   { 
      CLKSELR = previous_clk; 
      CLKCSR = 1 << CLKCCE; 
      CLKCSR = CLOCK_DISABLE; 
   } 

	sei ();
	
//SREG = temp; 
//asm("sei"); 
} 

int main(void) 
{ 
    
   //Switching Clock 
   ClockSwitching(0x0C, 0x02); 
       
   DDRA |= (1 << PORTA0);   //Output for LED 
    
    while(1) 
    { 
      PORTA ^= (1 << PORTA0); 
      _delay_ms(1000); 
    } 
} 

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Still the same. I've create a new project with only the above code. I've went into debugWIRE & is it still looping within this statement. I'm really pulling my hair now....

If I comment this out, the LED blinks ...

ClockSwitching(0x0C, 0x02);

Attachment(s): 

Once an engineer, forever an engineer

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

The .lss file:


TryingClockingATtiny167_R3.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000000  00800100  0000011a  0000018e  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         0000011a  00000000  00000000  00000074  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .stab         000006cc  00000000  00000000  00000190  2**2
                  CONTENTS, READONLY, DEBUGGING
  3 .stabstr      00000097  00000000  00000000  0000085c  2**0
                  CONTENTS, READONLY, DEBUGGING
  4 .comment      0000002f  00000000  00000000  000008f3  2**0
                  CONTENTS, READONLY
  5 .debug_aranges 00000028  00000000  00000000  00000922  2**0
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_info   00000187  00000000  00000000  0000094a  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_abbrev 00000130  00000000  00000000  00000ad1  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_line   000001c1  00000000  00000000  00000c01  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_frame  00000034  00000000  00000000  00000dc4  2**2
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_str    00000153  00000000  00000000  00000df8  2**0
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_loc    00000021  00000000  00000000  00000f4b  2**0
                  CONTENTS, READONLY, DEBUGGING
 12 .debug_ranges 00000018  00000000  00000000  00000f6c  2**0
                  CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 28 00 	jmp	0x50	; 0x50 <__ctors_end>
   4:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
   8:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
   c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  10:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  14:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  18:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  1c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  20:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  24:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  28:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  2c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  30:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  34:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  38:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  3c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  40:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  44:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  48:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  4c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>

00000050 <__ctors_end>:
  50:	11 24       	eor	r1, r1
  52:	1f be       	out	0x3f, r1	; 63
  54:	ce ef       	ldi	r28, 0xFE	; 254
  56:	d2 e0       	ldi	r29, 0x02	; 2
  58:	de bf       	out	0x3e, r29	; 62
  5a:	cd bf       	out	0x3d, r28	; 61
  5c:	0e 94 78 00 	call	0xf0	; 0xf0 
60: 0c 94 8b 00 jmp 0x116 ; 0x116 <_exit> 00000064 <__bad_interrupt>: 64: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 00000068 : //Disable interrupts //temp = SREG; asm("cli"); //temp = SREG; // asm("cli"); cli (); 68: f8 94 cli //Save the current system clock source CLKSELR = 1 << CLKCCE; 6a: a3 e6 ldi r26, 0x63 ; 99 6c: b0 e0 ldi r27, 0x00 ; 0 6e: 90 e8 ldi r25, 0x80 ; 128 70: 9c 93 st X, r25 CLKCSR = CLOCK_RECOVER; 72: e2 e6 ldi r30, 0x62 ; 98 74: f0 e0 ldi r31, 0x00 ; 0 76: 25 e0 ldi r18, 0x05 ; 5 78: 20 83 st Z, r18 previous_clk = CLKSELR & 0x0F; 7a: 5c 91 ld r21, X 7c: 5f 70 andi r21, 0x0F ; 15 //Enable the new clock source CLKSELR = ((sut << 4) & 0x30) | (clk_number & 0x0F); 7e: 48 2f mov r20, r24 80: 4f 70 andi r20, 0x0F ; 15 82: 26 2f mov r18, r22 84: 30 e0 ldi r19, 0x00 ; 0 86: 22 95 swap r18 88: 32 95 swap r19 8a: 30 7f andi r19, 0xF0 ; 240 8c: 32 27 eor r19, r18 8e: 20 7f andi r18, 0xF0 ; 240 90: 32 27 eor r19, r18 92: 20 73 andi r18, 0x30 ; 48 94: 33 27 eor r19, r19 96: 24 2b or r18, r20 98: 2c 93 st X, r18 CLKCSR = 1 << CLKCCE; 9a: 90 83 st Z, r25 CLKCSR = CLOCK_ENABLE; 9c: 92 e0 ldi r25, 0x02 ; 2 9e: 90 83 st Z, r25 //Wait for clock validity while ((CLKCSR & (1 << CLKRDY)) == 0); a0: 90 81 ld r25, Z a2: 94 ff sbrs r25, 4 a4: fd cf rjmp .-6 ; 0xa0 //Enable the watchdog in automatic reload mode WDTCR = (1 << WDCE) | (1 << WDE); a6: e0 e6 ldi r30, 0x60 ; 96 a8: f0 e0 ldi r31, 0x00 ; 0 aa: 98 e1 ldi r25, 0x18 ; 24 ac: 90 83 st Z, r25 WDTCR = (1 << WDE) | WD_2048CYCLES; ae: 9f e0 ldi r25, 0x0F ; 15 b0: 90 83 st Z, r25 CLKCSR = 1 << CLKCCE; b2: e2 e6 ldi r30, 0x62 ; 98 b4: f0 e0 ldi r31, 0x00 ; 0 b6: 90 e8 ldi r25, 0x80 ; 128 b8: 90 83 st Z, r25 CLKCSR = WD_ARL_ENABLE; ba: 26 e0 ldi r18, 0x06 ; 6 bc: 20 83 st Z, r18 //Switch clock source CLKCSR = 1 << CLKCCE; be: 90 83 st Z, r25 CLKCSR = CLOCK_SWITCH; c0: 94 e0 ldi r25, 0x04 ; 4 c2: 90 83 st Z, r25 //Wait for effective switching while(1) { CLKCSR = 1 << CLKCCE; c4: 30 e8 ldi r19, 0x80 ; 128 CLKCSR = CLOCK_RECOVER; c6: 25 e0 ldi r18, 0x05 ; 5 if((CLKSELR & 0x0F) == (clk_number & 0x0F)) break; c8: a3 e6 ldi r26, 0x63 ; 99 ca: b0 e0 ldi r27, 0x00 ; 0 CLKCSR = 1 << CLKCCE; CLKCSR = CLOCK_SWITCH; //Wait for effective switching while(1) { CLKCSR = 1 << CLKCCE; cc: 30 83 st Z, r19 CLKCSR = CLOCK_RECOVER; ce: 20 83 st Z, r18 if((CLKSELR & 0x0F) == (clk_number & 0x0F)) break; d0: 9c 91 ld r25, X d2: 98 27 eor r25, r24 d4: 9f 70 andi r25, 0x0F ; 15 d6: d1 f7 brne .-12 ; 0xcc } //Shutdown unneeded clock source if(previous_clk != (clk_number & 0x0F)) d8: 54 17 cp r21, r20 da: 41 f0 breq .+16 ; 0xec { CLKSELR = previous_clk; dc: 50 93 63 00 sts 0x0063, r21 CLKCSR = 1 << CLKCCE; e0: e2 e6 ldi r30, 0x62 ; 98 e2: f0 e0 ldi r31, 0x00 ; 0 e4: 80 e8 ldi r24, 0x80 ; 128 e6: 80 83 st Z, r24 CLKCSR = CLOCK_DISABLE; e8: 81 e0 ldi r24, 0x01 ; 1 ea: 80 83 st Z, r24 } sei (); ec: 78 94 sei ee: 08 95 ret 000000f0
: int main(void) { //Switching Clock ClockSwitching(0x0C, 0x02); f0: 62 e0 ldi r22, 0x02 ; 2 f2: 8c e0 ldi r24, 0x0C ; 12 f4: 0e 94 34 00 call 0x68 ; 0x68 DDRA |= (1 << PORTA0); //Output for LED f8: 08 9a sbi 0x01, 0 ; 1 while(1) { PORTA ^= (1 << PORTA0); fa: 91 e0 ldi r25, 0x01 ; 1 fc: 82 b1 in r24, 0x02 ; 2 fe: 89 27 eor r24, r25 100: 82 b9 out 0x02, r24 ; 2 #else //round up by default __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); #endif __builtin_avr_delay_cycles(__ticks_dc); 102: 2f ef ldi r18, 0xFF ; 255 104: 34 e3 ldi r19, 0x34 ; 52 106: 8c e0 ldi r24, 0x0C ; 12 108: 21 50 subi r18, 0x01 ; 1 10a: 30 40 sbci r19, 0x00 ; 0 10c: 80 40 sbci r24, 0x00 ; 0 10e: e1 f7 brne .-8 ; 0x108 110: 00 c0 rjmp .+0 ; 0x112 112: 00 00 nop 114: f3 cf rjmp .-26 ; 0xfc 00000116 <_exit>: 116: f8 94 cli 00000118 <__stop_program>: 118: ff cf rjmp .-2 ; 0x118 <__stop_program>

Once an engineer, forever an engineer

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

I have a spare ATtiny167. Regardless if we could or could not solve this mystery & if you like, I could mail it to you.

Once an engineer, forever an engineer

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   //Save the current system clock source
   CLKSELR = 1 << CLKCCE;
  6a:   a3 e6          ldi   r26, 0x63   ; 99
  6c:   b0 e0          ldi   r27, 0x00   ; 0
  6e:   90 e8          ldi   r25, 0x80   ; 128
  70:   9c 93          st   X, r25

That is -O0 code! If I build that single line for 167 with various optimisation levels I get:

// -O0
	CLKSELR = 1 << CLKCCE;
  6a:	83 e6       	ldi	r24, 0x63	; 99
  6c:	90 e0       	ldi	r25, 0x00	; 0
  6e:	20 e8       	ldi	r18, 0x80	; 128
  70:	fc 01       	movw	r30, r24
  72:	20 83       	st	Z, r18
// -O1
	CLKSELR = 1 << CLKCCE;
  62:	80 e8       	ldi	r24, 0x80	; 128
  64:	80 93 63 00 	sts	0x0063, r24
// -O2
	CLKSELR = 1 << CLKCCE;
  62:	80 e8       	ldi	r24, 0x80	; 128
  64:	80 93 63 00 	sts	0x0063, r24
// -O3
	CLKSELR = 1 << CLKCCE;
  62:	80 e8       	ldi	r24, 0x80	; 128
  64:	80 93 63 00 	sts	0x0063, r24
// -Os
	CLKSELR = 1 << CLKCCE;
  62:	80 e8       	ldi	r24, 0x80	; 128
  64:	80 93 63 00 	sts	0x0063, r24

As you can see only -O0 outputs that horrendous code - all the rest output exactly what you might hope for (and within 4 cycle limit).

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

But I don't get it. As you can see, I've set it -O3 in AS6.1....

Attachment(s): 

Once an engineer, forever an engineer

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

This is part of the code generated with -Os and AS4.18, quite a bit shorter

 68:	28 2f       	mov	r18, r24
//Disable interrupts 
//temp = SREG; asm("cli"); 
//temp = SREG; // asm("cli"); 
    
   //Save the current system clock source 
   CLKSELR = 1 << CLKCCE; 
  6a:	90 e8       	ldi	r25, 0x80	; 128
  6c:	90 93 63 00 	sts	0x0063, r25
   CLKCSR = CLOCK_RECOVER; 
  70:	85 e0       	ldi	r24, 0x05	; 5
  72:	80 93 62 00 	sts	0x0062, r24
   previous_clk = CLKSELR & 0x0F; 
  76:	40 91 63 00 	lds	r20, 0x0063
  7a:	4f 70       	andi	r20, 0x0F	; 15

Attaching also the related hex file (as above without the interrupts disable bit), may want to try this out.

Attachment(s): 

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Thanks John but still, it hanged, which I believe still looping at the

while ((CLKCSR & (1 << CLKRDY)) == 0);

In fact, I tried on another Win7 notebook with AS6.1 & the result was the same. Then, I installed AS6.1 on my WinXP box & tried. Result was still the same. debugWIRE still shows looping there. I was so fed-up I comment out the above statement just to let the code pass. Anyway, that means the clock didn't switch? Don't know why. I'm putting this aside as I've wasted everyone's time and I needed to move on to USART now.

Thanks again.
Ken

Once an engineer, forever an engineer

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

Could dW be interfering with this?

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

So I went back to the start of the thread and I don't understand WHY you need to switch the clock, yes I'm a little sloooowwww.

You have a crystal on Xtal1 and Xtal2 and have set the fuses accordingly therefore the chip will run at 4MHz.

What is the reason to change clock source on the fly? I have never done anything like this, it's just a crystal or internal oscillator and set the fuse accordingly.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Being a glutton for punishment I searched for the same clock features and it seems that only the Tiny87/167 have this???

All other chips I have here don't seem to have it.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:
Being a glutton for punishment I searched for the same clock features and it seems that only the Tiny87/167 have this???

All other chips I have here don't seem to have it.

The ATtiny4/5/9/10 can do on-the-fly clock switching as well, but they don't support an external crystal oscillator, only the calibrated internal 8 MHz RC, the 128 kHz internal RC, and an external clock. The clock switching procedure isn't as complicated, however neither does it support clock monitoring as does the 87/167.

Of course I can't answer for the OP, and truthfully I have never played with an 87/167, but I believe the intent is to have clock redundancy. A scenario would be to fuse the mcu to start up under one of the internal oscillators, and then fire up the external one. A failure of the external clock or oscillator would spell disaster for an application based on a normal AVR, but with clock monitoring the 87/167 can recover via a WDT reset and continue to function on the somewhat less vulnerable (if slower and less accurate) internal oscillator, perhaps providing 'failsafe' functionality in the application. All of this behaviour would of course have to be directed by carefully designed software.

There is of course always the engineer's go-to answer: "Because we can!" :)

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Quote:
The ATtiny4/5/9/10 can do on-the-fly
Except that a fly is bigger then the chip......

I have done something similar with the Xmega of course but the code is completely different.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Quote:

As you can see, I've set it -O3

Do a rebuild and post the text of the Output window here. It may say -O3 but I'm in no doubt you have -O0 code being generated.

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

joeymorin wrote:
Could dW be interfering with this?

JJ

Not sure but it wasn't working in ISP mode either.

Once an engineer, forever an engineer

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

js wrote:
What is the reason to change clock source on the fly? I have never done anything like this, it's just a crystal or internal oscillator and set the fuse accordingly.

I'm currently working on a project & I'm checking out this feature as I would like to give an option of not having a crystal onboard for the users if the Internal RC 8MHz for a particular application would suffice by with a jumper. At least this provides some flexibility to the users in the fields without the need to reflash the firmware. I've been designing PCB for a number of years but just not with AVR chips so these newbie queries :)

Once an engineer, forever an engineer

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

clawson wrote:
Quote:

As you can see, I've set it -O3

Do a rebuild and post the text of the Output window here. It may say -O3 but I'm in no doubt you have -O0 code being generated.

I sure hope I mess up somewhere as it is an easier fix. OK, I'll try again but on my WinXP PC now. I'll post the Output window shortly.

Once an engineer, forever an engineer

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

Done with -O3. Tried attaching ClockSwitching2.lss file but doesn't seems to work so pasting it instead. The results in output window is attached.

Thanks


ClockSwitching2.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000000  00800100  00000124  00000198  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         00000124  00000000  00000000  00000074  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .stab         000006cc  00000000  00000000  00000198  2**2
                  CONTENTS, READONLY, DEBUGGING
  3 .stabstr      00000097  00000000  00000000  00000864  2**0
                  CONTENTS, READONLY, DEBUGGING
  4 .comment      0000002f  00000000  00000000  000008fb  2**0
                  CONTENTS, READONLY
  5 .debug_aranges 00000028  00000000  00000000  0000092a  2**0
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_info   00000189  00000000  00000000  00000952  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_abbrev 00000130  00000000  00000000  00000adb  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_line   000001a9  00000000  00000000  00000c0b  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_frame  00000034  00000000  00000000  00000db4  2**2
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_str    00000151  00000000  00000000  00000de8  2**0
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_loc    00000042  00000000  00000000  00000f39  2**0
                  CONTENTS, READONLY, DEBUGGING
 12 .debug_ranges 00000018  00000000  00000000  00000f7b  2**0
                  CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 28 00 	jmp	0x50	; 0x50 <__ctors_end>
   4:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
   8:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
   c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  10:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  14:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  18:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  1c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  20:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  24:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  28:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  2c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  30:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  34:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  38:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  3c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  40:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  44:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  48:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  4c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>

00000050 <__ctors_end>:
  50:	11 24       	eor	r1, r1
  52:	1f be       	out	0x3f, r1	; 63
  54:	ce ef       	ldi	r28, 0xFE	; 254
  56:	d2 e0       	ldi	r29, 0x02	; 2
  58:	de bf       	out	0x3e, r29	; 62
  5a:	cd bf       	out	0x3d, r28	; 61
  5c:	0e 94 7d 00 	call	0xfa	; 0xfa 
60: 0c 94 90 00 jmp 0x120 ; 0x120 <_exit> 00000064 <__bad_interrupt>: 64: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 00000068 : //Disable interrupts //temp = SREG; asm("cli"); //temp = SREG; // asm("cli"); cli (); 68: f8 94 cli //Save the current system clock source CLKSELR = 1 << CLKCCE; 6a: 90 e8 ldi r25, 0x80 ; 128 6c: 90 93 63 00 sts 0x0063, r25 CLKCSR = CLOCK_RECOVER; 70: 25 e0 ldi r18, 0x05 ; 5 72: 20 93 62 00 sts 0x0062, r18 previous_clk = CLKSELR & 0x0F; 76: 40 91 63 00 lds r20, 0x0063 7a: 4f 70 andi r20, 0x0F ; 15 //Enable the new clock source CLKSELR = ((sut << 4) & 0x30) | (clk_number & 0x0F); 7c: 58 2f mov r21, r24 7e: 5f 70 andi r21, 0x0F ; 15 80: 70 e0 ldi r23, 0x00 ; 0 82: 62 95 swap r22 84: 72 95 swap r23 86: 70 7f andi r23, 0xF0 ; 240 88: 76 27 eor r23, r22 8a: 60 7f andi r22, 0xF0 ; 240 8c: 76 27 eor r23, r22 8e: 60 73 andi r22, 0x30 ; 48 90: 77 27 eor r23, r23 92: 65 2b or r22, r21 94: 60 93 63 00 sts 0x0063, r22 CLKCSR = 1 << CLKCCE; 98: 90 93 62 00 sts 0x0062, r25 CLKCSR = CLOCK_ENABLE; 9c: 92 e0 ldi r25, 0x02 ; 2 9e: 90 93 62 00 sts 0x0062, r25 //Wait for clock validity while ((CLKCSR & (1 << CLKRDY)) == 0); a2: 90 91 62 00 lds r25, 0x0062 a6: 94 ff sbrs r25, 4 a8: fc cf rjmp .-8 ; 0xa2 //Enable the watchdog in automatic reload mode WDTCR = (1 << WDCE) | (1 << WDE); aa: 98 e1 ldi r25, 0x18 ; 24 ac: 90 93 60 00 sts 0x0060, r25 WDTCR = (1 << WDE) | WD_2048CYCLES; b0: 9f e0 ldi r25, 0x0F ; 15 b2: 90 93 60 00 sts 0x0060, r25 CLKCSR = 1 << CLKCCE; b6: 90 e8 ldi r25, 0x80 ; 128 b8: 90 93 62 00 sts 0x0062, r25 CLKCSR = WD_ARL_ENABLE; bc: 26 e0 ldi r18, 0x06 ; 6 be: 20 93 62 00 sts 0x0062, r18 //Switch clock source CLKCSR = 1 << CLKCCE; c2: 90 93 62 00 sts 0x0062, r25 CLKCSR = CLOCK_SWITCH; c6: 94 e0 ldi r25, 0x04 ; 4 c8: 90 93 62 00 sts 0x0062, r25 //Wait for effective switching while(1) { CLKCSR = 1 << CLKCCE; cc: 30 e8 ldi r19, 0x80 ; 128 CLKCSR = CLOCK_RECOVER; ce: 25 e0 ldi r18, 0x05 ; 5 CLKCSR = 1 << CLKCCE; CLKCSR = CLOCK_SWITCH; //Wait for effective switching while(1) { CLKCSR = 1 << CLKCCE; d0: 30 93 62 00 sts 0x0062, r19 CLKCSR = CLOCK_RECOVER; d4: 20 93 62 00 sts 0x0062, r18 if((CLKSELR & 0x0F) == (clk_number & 0x0F)) break; d8: 90 91 63 00 lds r25, 0x0063 dc: 98 27 eor r25, r24 de: 9f 70 andi r25, 0x0F ; 15 e0: b9 f7 brne .-18 ; 0xd0 } //Shutdown unneeded clock source if(previous_clk != (clk_number & 0x0F)) e2: 45 17 cp r20, r21 e4: 41 f0 breq .+16 ; 0xf6 { CLKSELR = previous_clk; e6: 40 93 63 00 sts 0x0063, r20 CLKCSR = 1 << CLKCCE; ea: 80 e8 ldi r24, 0x80 ; 128 ec: 80 93 62 00 sts 0x0062, r24 CLKCSR = CLOCK_DISABLE; f0: 81 e0 ldi r24, 0x01 ; 1 f2: 80 93 62 00 sts 0x0062, r24 } sei (); f6: 78 94 sei f8: 08 95 ret 000000fa
: //asm("sei"); } int main(void) { DDRA |= (1 << PORTA0); //Output for LED fa: 08 9a sbi 0x01, 0 ; 1 //Switching Clock ClockSwitching(0x0C, 0x02); fc: 62 e0 ldi r22, 0x02 ; 2 fe: 8c e0 ldi r24, 0x0C ; 12 100: 0e 94 34 00 call 0x68 ; 0x68 while(1) { PORTA ^= (1 << PORTA0); 104: 91 e0 ldi r25, 0x01 ; 1 106: 82 b1 in r24, 0x02 ; 2 108: 89 27 eor r24, r25 10a: 82 b9 out 0x02, r24 ; 2 #else //round up by default __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); #endif __builtin_avr_delay_cycles(__ticks_dc); 10c: 2f ef ldi r18, 0xFF ; 255 10e: 34 e3 ldi r19, 0x34 ; 52 110: 8c e0 ldi r24, 0x0C ; 12 112: 21 50 subi r18, 0x01 ; 1 114: 30 40 sbci r19, 0x00 ; 0 116: 80 40 sbci r24, 0x00 ; 0 118: e1 f7 brne .-8 ; 0x112 11a: 00 c0 rjmp .+0 ; 0x11c 11c: 00 00 nop 11e: f3 cf rjmp .-26 ; 0x106 00000120 <_exit>: 120: f8 94 cli 00000122 <__stop_program>: 122: ff cf rjmp .-2 ; 0x122 <__stop_program>

Attachment(s): 

Once an engineer, forever an engineer

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

I can't be bothered to read the datasheet so I'm not sure exactly where the clock requirement actually is but that second write to CLKSELR with all those swap's and eor's is going to break the timing if that's where it is. So I'd precalculate the new value and make that a simple assignment. Also read previous_clk before you start not in the middle of the new assignment.

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

If I reading the datasheet right, its right after CLKCSR's CLKCCE bit is set that the timing of 4 cycles starts.

  CLKCSR = 1 << CLKCCE; 
  98:   90 93 62 00    sts   0x0062, r25 
   CLKCSR = CLOCK_ENABLE; 
  9c:   92 e0          ldi   r25, 0x02   ; 2 
  9e:   90 93 62 00    sts   0x0062, r25 

Looks to me its 3 clocks but then again, I might be wrong.

Thanks.

Once an engineer, forever an engineer

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

js wrote:
Quote:
The ATtiny4/5/9/10 can do on-the-fly
Except that a fly is bigger then the chip......
You've hit on one of the selling points!

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

You have made a typo:

	//Save the current system clock source
	CLKSELR = 1 << CLKCCE;
	CLKCSR = CLOCK_RECOVER;
	previous_clk = CLKSELR & 0x0F;

... should be:

	//Save the current system clock source
	CLKCSR = 1 << CLKCCE;
	CLKCSR = CLOCK_RECOVER;
	previous_clk = CLKSELR & 0x0F;

With your typo, the change sequence is never initiated, so the new clock source is never started, therefore the CLKRDY bit will never be set, therefore you will hang on:

	//Wait for clock validity
	while ((CLKCSR & (1 << CLKRDY)) == 0);

Why didn't you just copy/paste from the datasheet? Apart from the datasheet's own typo (WDTCSR instead of WDTCR), you could have avoided this whole thread... assuming this will work for you now ;)

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Holy mooly crap, I knew there has got to be an easier explanation for this! I did "cut&paste", albeit "read&type". Sigh... I'll try this when I get back. Thank you JJ, John & the rest for keeping up with my boo-boo.

Once an engineer, forever an engineer

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

It didn't work either. Re-copied (select) & pasted from datasheet to new project file. Tried -O1, -O2, -O3 & -Os, all failed. CLKRDY bit in CLKCSR was never set. Anyway, loved to hear from anyone who successfully got this working in the future.

Thanks.

Once an engineer, forever an engineer

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

Just for kicks, post the .lss for your latest attempt.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

What package is the chip in? How is it mounted on the board?

I don't think I have anything where the chip can be easily mounted on even if SOIC as it will also need the crystal, I'm getting more curious with each post. :roll:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

joeymorin wrote:
Just for kicks, post the .lss for your latest attempt.

JJ

OK. I've just re-compiled again & below is the .lss file.


TryingClockingATtiny167_R4.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000000  00800100  00000126  0000019a  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         00000126  00000000  00000000  00000074  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .stab         000006cc  00000000  00000000  0000019c  2**2
                  CONTENTS, READONLY, DEBUGGING
  3 .stabstr      00000097  00000000  00000000  00000868  2**0
                  CONTENTS, READONLY, DEBUGGING
  4 .comment      0000002f  00000000  00000000  000008ff  2**0
                  CONTENTS, READONLY
  5 .debug_aranges 00000028  00000000  00000000  0000092e  2**0
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_info   00000196  00000000  00000000  00000956  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_abbrev 00000130  00000000  00000000  00000aec  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_line   000001bd  00000000  00000000  00000c1c  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_frame  00000034  00000000  00000000  00000ddc  2**2
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_str    00000158  00000000  00000000  00000e10  2**0
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_loc    00000042  00000000  00000000  00000f68  2**0
                  CONTENTS, READONLY, DEBUGGING
 12 .debug_ranges 00000018  00000000  00000000  00000faa  2**0
                  CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 28 00 	jmp	0x50	; 0x50 <__ctors_end>
   4:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
   8:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
   c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  10:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  14:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  18:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  1c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  20:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  24:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  28:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  2c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  30:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  34:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  38:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  3c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  40:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  44:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  48:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>
  4c:	0c 94 32 00 	jmp	0x64	; 0x64 <__bad_interrupt>

00000050 <__ctors_end>:
  50:	11 24       	eor	r1, r1
  52:	1f be       	out	0x3f, r1	; 63
  54:	ce ef       	ldi	r28, 0xFE	; 254
  56:	d2 e0       	ldi	r29, 0x02	; 2
  58:	de bf       	out	0x3e, r29	; 62
  5a:	cd bf       	out	0x3d, r28	; 61
  5c:	0e 94 7d 00 	call	0xfa	; 0xfa 
60: 0c 94 91 00 jmp 0x122 ; 0x122 <_exit> 00000064 <__bad_interrupt>: 64: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 00000068 : void ClockSwitching(unsigned char clk_number, unsigned char sut) { unsigned char previous_clk, temp; // Disable interrupts temp = SREG; asm ("cli"); 68: 4f b7 in r20, 0x3f ; 63 6a: f8 94 cli // Save the current system clock source CLKCSR = 1 << CLKCCE; 6c: 90 e8 ldi r25, 0x80 ; 128 6e: 90 93 62 00 sts 0x0062, r25 CLKCSR = CLOCK_RECOVER; 72: 25 e0 ldi r18, 0x05 ; 5 74: 20 93 62 00 sts 0x0062, r18 previous_clk = CLKSELR & 0x0F; 78: 20 91 63 00 lds r18, 0x0063 7c: 2f 70 andi r18, 0x0F ; 15 // Enable the new clock source CLKSELR = ((sut << 4 ) & 0x30) | (clk_number & 0x0F); 7e: 38 2f mov r19, r24 80: 3f 70 andi r19, 0x0F ; 15 82: 70 e0 ldi r23, 0x00 ; 0 84: 54 e0 ldi r21, 0x04 ; 4 86: 66 0f add r22, r22 88: 77 1f adc r23, r23 8a: 5a 95 dec r21 8c: e1 f7 brne .-8 ; 0x86 8e: 60 73 andi r22, 0x30 ; 48 90: 77 27 eor r23, r23 92: 63 2b or r22, r19 94: 60 93 63 00 sts 0x0063, r22 CLKCSR = 1 << CLKCCE; 98: 90 93 62 00 sts 0x0062, r25 CLKCSR = CLOCK_ENABLE; 9c: 92 e0 ldi r25, 0x02 ; 2 9e: 90 93 62 00 sts 0x0062, r25 // Wait for clock validity if((CLKCSR & 0x10) == 0) a2: 90 91 62 00 lds r25, 0x0062 a6: 94 ff sbrs r25, 4 a8: fc cf rjmp .-8 ; 0xa2 { while ((CLKCSR & (1 << CLKRDY)) == 0); } // Enable the watchdog in automatic reload mode WDTCR = (1 << WDCE) | (1 << WDE); aa: 98 e1 ldi r25, 0x18 ; 24 ac: 90 93 60 00 sts 0x0060, r25 WDTCR = (1 << WDE ) | WD_2048CYCLES; b0: 9f e0 ldi r25, 0x0F ; 15 b2: 90 93 60 00 sts 0x0060, r25 CLKCSR = 1 << CLKCCE; b6: 90 e8 ldi r25, 0x80 ; 128 b8: 90 93 62 00 sts 0x0062, r25 CLKCSR = WD_ARL_ENABLE; bc: 56 e0 ldi r21, 0x06 ; 6 be: 50 93 62 00 sts 0x0062, r21 // Switch clock source CLKCSR = 1 << CLKCCE; c2: 90 93 62 00 sts 0x0062, r25 CLKCSR = CLOCK_SWITCH; c6: 94 e0 ldi r25, 0x04 ; 4 c8: 90 93 62 00 sts 0x0062, r25 // Wait for effective switching while (1){ CLKCSR = 1 << CLKCCE; cc: 60 e8 ldi r22, 0x80 ; 128 CLKCSR = CLOCK_RECOVER; ce: 55 e0 ldi r21, 0x05 ; 5 // Switch clock source CLKCSR = 1 << CLKCCE; CLKCSR = CLOCK_SWITCH; // Wait for effective switching while (1){ CLKCSR = 1 << CLKCCE; d0: 60 93 62 00 sts 0x0062, r22 CLKCSR = CLOCK_RECOVER; d4: 50 93 62 00 sts 0x0062, r21 if ((CLKSELR & 0x0F) == (clk_number & 0x0F)) break; d8: 90 91 63 00 lds r25, 0x0063 dc: 98 27 eor r25, r24 de: 9f 70 andi r25, 0x0F ; 15 e0: b9 f7 brne .-18 ; 0xd0 } // Shut down unneeded clock source if (previous_clk != (clk_number & 0x0F)) { e2: 23 17 cp r18, r19 e4: 41 f0 breq .+16 ; 0xf6 CLKSELR = previous_clk; e6: 20 93 63 00 sts 0x0063, r18 CLKCSR = 1 << CLKCCE; ea: 80 e8 ldi r24, 0x80 ; 128 ec: 80 93 62 00 sts 0x0062, r24 CLKCSR = CLOCK_DISABLE; f0: 81 e0 ldi r24, 0x01 ; 1 f2: 80 93 62 00 sts 0x0062, r24 } // Re-enable interrupts SREG = temp; f6: 4f bf out 0x3f, r20 ; 63 f8: 08 95 ret 000000fa
: } int main(void) { DDRA |= (1 << PORTA0); fa: 08 9a sbi 0x01, 0 ; 1 PORTA &= ~(1 << PORTA0); fc: 10 98 cbi 0x02, 0 ; 2 ClockSwitching(0x02, 0x02); fe: 62 e0 ldi r22, 0x02 ; 2 100: 82 e0 ldi r24, 0x02 ; 2 102: 0e 94 34 00 call 0x68 ; 0x68 while(1) { PORTA ^= (1 << PORTA0); 106: 91 e0 ldi r25, 0x01 ; 1 108: 82 b1 in r24, 0x02 ; 2 10a: 89 27 eor r24, r25 10c: 82 b9 out 0x02, r24 ; 2 #else //round up by default __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); #endif __builtin_avr_delay_cycles(__ticks_dc); 10e: 2f e7 ldi r18, 0x7F ; 127 110: 39 ea ldi r19, 0xA9 ; 169 112: 83 e0 ldi r24, 0x03 ; 3 114: 21 50 subi r18, 0x01 ; 1 116: 30 40 sbci r19, 0x00 ; 0 118: 80 40 sbci r24, 0x00 ; 0 11a: e1 f7 brne .-8 ; 0x114 11c: 00 c0 rjmp .+0 ; 0x11e 11e: 00 00 nop 120: f3 cf rjmp .-26 ; 0x108 00000122 <_exit>: 122: f8 94 cli 00000124 <__stop_program>: 124: ff cf rjmp .-2 ; 0x124 <__stop_program>

Thanks.

Once an engineer, forever an engineer

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

js wrote:
What package is the chip in? How is it mounted on the board?

I don't think I have anything where the chip can be easily mounted on even if SOIC as it will also need the crystal, I'm getting more curious with each post. :roll:

Its a TSSOP mounted on a breakout board.

Thanks.

Attachment(s): 

Once an engineer, forever an engineer

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

I can only see 1 cap going to the crystal instead of 2, is the other one hidden behind the crystal? If so I still don't see another ground pin for it going anywhere behind the crystal.

Also it would still be nice to have another bypass cap on 15 and 16 like the one you have on 5 and 6. And finally I hope that the crystal is in fact 4MHz. :-)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Yes, there is one behind the crystal. I'm attaching another photo from another angle.

Yes, there is another bypass cap on pin 15 & 16 but was place a distance away as I was running out of space. I've now changed the routing a little so it is placed nearer to the pins. (Gnd & Reset pull-up underneath the board).

As for crystal, that's what was stated on the package. Hope I wasn't cheated... Anyway, I've also tried 5MHz & 6MHz but result was the same.

Thanks.

Attachment(s): 

Once an engineer, forever an engineer

Pages