What is the fastest method for port output? PORTX?

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

Hi guys, I was wondering what is the quickest method for turning a port high and then low?

for example the following code:

#include 

void main()
{
	DDRB = 0XFF;
	
	while(1)
	{
		PORTB = 0x00;
		PORTB = 0XFF;
	}
return;
}

with the ATmega328p set at 20MHz I got the following reading on a logic analyzer:

http://www.tinkerjunkies.com/Sample1.html

you'll notice the port stays high for 0.8us and low for only about 0.2us.

I noticed when i reversed the order and had PORTB = 0xFF first and then 0x00 I had a slightly better response time.

Is there a better method that updates a bit quicker?

Thanks!

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

When this turns into assembler there is a jump back to the start of the loop. This is what cause the delay. If you want equal hi/lo time you need to add a small delay.

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

Quote:

with the ATmega328p set at 20MHz

Quote:

the port stays high for 0.8us and low for only about 0.2us.

I'll wager your AVR is not running at 20MHz. Unless perhaps you are running at -O0?

Yes, with a "conventional" AVR8 you can in fact toggle a pin at clk/2 with a timer and CTC. Whith Xmega there are probably more DMA modes that could be used.

Is this one of these "puzzles" to challenge us? What exactly are you trying to obtain? It certainly can't be "if I put an AVR into an infinite loop how often can I toggle an I/O pin"? We've addressed that before.

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

I have a 20MHz ceramic resonator and set the fuse bits accordingly. Unless I'm missing something? the microcontroller stalls if there is no resonator so it is set for external resonator.

So is PORTX the only way to toggle I/O?

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

Quote:

So is PORTX the only way to toggle I/O?

Are you reading the replies you get?
Lee wrote:

Yes, with a "conventional" AVR8 you can in fact toggle a pin at clk/2 with a timer and CTC.

If you are not content with that, eg you need to toggle a pin other than one of the timer output pins, then some (newish) AVRs have the capability to toggle (in the meaning "invert it's state") a single pin by writing to the PINx register. Your data sheet will tell more.

Apart from that, Lee's question still stands: What are you trying to accomplish. With knowledge about that, someone might give some Really Good Advice[tm]. Without that you will get these dry and terse answers.

The quality of the answers you get is correlated with the quality of the question you ask.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Quote:

So is PORTX the only way to toggle I/O?

Quote:

What exactly are you trying to obtain?

If you are trying to obtain a faster "soft toggle", perhaps you should switch toolchains. :twisted:

Yes, I can think of other ways to toggle an I/O pin. Define "toggle" for these purposes. [I >>hate<< trying to play the game when I don't know the rules, or the objective, or what I must do to "win".]

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

You can deliver CLK via CKOUT and XTAL2.
You can deliver CLK / 2 via certain pins.
Both these methods require no interrupts or CPU cycles.

You can also waste all your AVR power by trying to wiggle a PORT in software. But then you won't be able to do anything else.

David.

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

Forget CLK/2, I can get you CLK from an AVR Pin...

Just connect a wire to the XTal1 pin, and voila.. now you have a toggle speed equal to your clock speed!

.... hey, you didn't set any rules, so I claim victory over your challenge.

What is the prize?

Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

Quote:

Just connect a wire to the XTal1 pin, and voila.. now you have a toggle speed equal to your clock speed!

Well, often (see the current thread about crystal "swing") connecting a wire to XTAL1 will result in a >>dead<< signal--lol.

But anyway, I'll claim two better solutions than yours-- XTAL2, and CLKO. But we still don't know when we "win".

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

As stated in the Wikipedia entry on AVR's.

Quote:
Atmel's AVRs have a two stage, single level pipeline design. This means the next machine instruction is fetched as the current one is executing. Most instructions take just one or two clock cycles, making AVRs relatively fast among the eight-bit microcontrollers.

That may show the problem. And it a few tenths of a micro second that big of a deal?

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

theusch wrote:
[I >>hate<< trying to play the game when I don't know the rules, or the objective, or what I must do to "win".]

Lee

haha i agree it's annoying when a poster doesn't give enough information. Sorry guys, this was general question, so there wasn't any rules. I've been using PORTX the entire time and was wondering if I had alternatives, or a better way of doing it.

The current output (1us period so that would be 1MHz switching) should satisfy my project which is simulating a playstation controller. The playstation has a clock speed of 500KHz that the AVR has to send data out at. So I should be fine, with 20 MIPS and 1MHz I/O.

this question was a learning experience to do things better. :)

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

Why don't you look at the generated Asm and count the cycles (maybe even use the simulator to do this for you if it's a complex sequence?

I compiled your code above:

   while(1) 
   { 
      PORTB = 0x00; 
  70:	18 ba       	out	0x18, r1	; 24
      PORTB = 0XFF; 
  72:	88 bb       	out	0x18, r24	; 24
  74:	fd cf       	rjmp	.-6      	; 0x70 

That's built -Os. Each OUT takes one cycle and the RJMP takes two cycles. So the output will remain low for 1 cycle and high for 3 cycles.

If you build the code -O0 you'd get:

   while(1) 
   { 
      PORTB = 0x00; 
  7c:	e8 e3       	ldi	r30, 0x38	; 56
  7e:	f0 e0       	ldi	r31, 0x00	; 0
  80:	10 82       	st	Z, r1
      PORTB = 0XFF; 
  82:	e8 e3       	ldi	r30, 0x38	; 56
  84:	f0 e0       	ldi	r31, 0x00	; 0
  86:	8f ef       	ldi	r24, 0xFF	; 255
  88:	80 83       	st	Z, r24
  8a:	f8 cf       	rjmp	.-16     	; 0x7c 

The LDI's are one cycle each and the ST's and RJMP are two cycles. If you start counting just after a state change (where R1=0 is stored to the port address) the signal remains low for three LDIs and an ST - so 5 cycles. It is then high for an RJMP(2), two LDIs(2*1) and an ST(2) - so 6 cycles.

Personally I'd vote for the following built -Os:

   while(1) 
   { 
      PORTB ^= 0xFF; 
   } 

which will at least yield a symmetric pattern:

   while(1) 
   { 
      PORTB ^= 0xFF; 
  70:	88 b3       	in	r24, 0x18	; 24
  72:	80 95       	com	r24
  74:	88 bb       	out	0x18, r24	; 24
  76:	fc cf       	rjmp	.-8      	; 0x70 

(obviously this is doing a bit more than forcing 00/FF but will invert the bit pattern whatever it happens to be)

Cliff

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

Cliff:
You can toggle the pin by writing to the PINx register (see page 75).
This will be faster :-)

while (1)
{
   PINB |= 0xFF;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Indeed - I wasn't sure whether this was a "modern" AVR or not. I see it's a 328P so you are right. However your code as written yields:

   while(1) 
   { 
      PINB |= 0xFF; 
  70:	96 b3       	in	r25, 0x16	; 22
  72:	86 bb       	out	0x16, r24	; 22
  74:	fd cf       	rjmp	.-6      	; 0x70 

I guess you mean "PINB = 0xFF" rather than "PINB |= 0xFF" which yields the optimal:

   while(1) 
   { 
      PINB = 0xFF; 
  70:	86 bb       	out	0x16, r24	; 22
  72:	fe cf       	rjmp	.-4      	; 0x70 

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

Since this is apparently to generate a 500kHz clock, I would guess that you really do not want jitter.

So if you just let the timer hardware produce the clock, your AVR can get on with the rest of its life.

There will be other occasions when you want to produce a short pulse train when it is as easy to toggle the PORTx rather than set the hardware to produce # pulses.

David.

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

clawson wrote:
I compiled your code above:
... So the output will remain low for 1 cycle and high for 3 cycles.

If it remains low for 1 cycle, and that was 0.2us, does that mean my Atmega328p is only running at 5MHz and not 20MHz?

Quote:
I'll wager your AVR is not running at 20MHz.

Sorry i'm unfamiliar with "-0O" means, i'll have to Google it.

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

Quote:

Sorry i'm unfamiliar with "-0O" means

It means that compiler optimization of the code is shut off.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Well for one thing -O is a parameter passed to the compiler to select a level of optimisation to be applied. Most IDEs and Makefiles will default this to -Os but in some places it might be left to default to -O0 which means "don't optimise I'm happy to accept the most crap code you can possibly think of producing" - never a great strategy!

As for 20MHz==5MHz. I bet you did your sums wrong and the CPU is actually running at 2.5MHz.

While you may have attached a 20MHz crystal and you may have programmed the CKSEL fuses to enable its use I'll bet you forgot to change the state of the CKDIV8 fuse so you are actually running at 20MHz/8 = 2.5MHz

Try adding these lines to the top of your code:

	CLKPR = (1 << CLKPCE); // enable a change to CLKPR
	CLKPR = 0; // set the CLKDIV to 0 - was 0011b = div by 8 taking 20MHz to 2.5MHz

which will over-ride whatever the CKDIV8 fuse is set to.

Cliff

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

Quote:

The playstation has a clock speed of 500KHz that the AVR has to send data out at. So I should be fine, with 20 MIPS and 1MHz I/O.

Well, then why don't you generate a 500kHz clock? Instead of asking about the fastest method for port output, with is unrelated, or perhaps very loosely related.

And ??? -- I thought you needed to be an SPI slave, based on your previous thread. Thus, "generating" the clock is immaterial.
https://www.avrfreaks.net/index.p...

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

Quote:

The quality of the answers you get is correlated with the quality of the question you ask.

Johann, you should add this as a FAQ in your signature something like what Cliff has. I have seen it just too many times now. :)

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

Quote:

Johann, you should add this as a FAQ in your signature

Well, I kind of indulge in adding such "footers" when I think they are applicable. (And I see the risk of stepping on my own land-mine, so to speak, if it is in every post I drop here at 'freaks :wink: ).

You get this (with a big :wink: and a bigger :D to go with it):
My attitude towards you is correlated with your ability to spell my name correctly (I'm from Sweden, not from Austria, darn it!)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Quote:

not from Austria

You mean where the Kangaroos live? ;-)

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

Quote:
I'll bet you forgot to change the state of the CKDIV8 fuse so you are actually running at 20MHz/8 = 2.5MHz

I had set the CKDIV8 fuse bit to 1 (unprogrammed), I thought this would stop it from dividing. Is that incorrect? I have to use code to set it and not disable it from the fuse bits?

Quote:
Most IDEs and Makefiles will default this to -Os but in some places it might be left to default to -O0

I Googled this and found very little infromation. How can I determine what my compiler and or makefile are set to? I'm using WinAVR GCC, Programmer's Notepad, and AVRDUDE. (I also have CodeVisionAVR available but thought i should start off with Programmer's Notepad to get a hang of it first - more support available.)

Quote:
Well, then why don't you generate a 500kHz clock? Instead of asking about the fastest method for port output, with is unrelated, or perhaps very loosely related.

I mentioned earlier that this thread wasn't specifically based on my project, it was to help me learn more about the AVR :)

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

Quote:

I mentioned earlier that this thread wasn't specifically based on my project, it was to help me learn more about the AVR

Since it appears you have a 'scope or at least a logic analyzer, then why not set the CKOUT fuse to see what speed you are >>really<< running at?

From there it is all you--what firmware have >>you<< chosen to program; what toolchain >>you<< have chosen to use, what chip options (fuses) and toolchain options >>you<< have chosen to use.

If it wasn't dealing with your project, then why did you say

Quote:
The current output (1us period so that would be 1MHz switching) should satisfy my project which is simulating a playstation controller. The playstation has a clock speed of 500KHz that the AVR has to send data out at.
in this thread? And the SPI slave output speed doesn't have anything directly to do with how fast the AVR can toggle a port bit in a tight loop. As is in the datasheet and was noted in the other thread, SPI slave rates can be up to clk/4. Your speeds are modest.

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

Quote:
my project which is simulating a playstation controller.

The playstation protocol is basically just SPI, so I would use that instead of rolling my own.

Regards,
Steve A.

The Board helps those that help themselves.

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

Quote:

Quote:

not from Austria

You mean where the Kangaroos live? Wink


A dangerous place:
http://www.msnbc.msn.com/id/3410...

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

Quote:
Quote:
I'll bet you forgot to change the state of the CKDIV8 fuse so you are actually running at 20MHz/8 = 2.5MHz

I had set the CKDIV8 fuse bit to 1 (unprogrammed), I thought this would stop it from dividing. Is that incorrect? I have to use code to set it and not disable it from the fuse bits?

Quote:
Most IDEs and Makefiles will default this to -Os but in some places it might be left to default to -O0

I Googled this and found very little infromation. How can I determine what my compiler and or makefile are set to? I'm using WinAVR GCC, Programmer's Notepad, and AVRDUDE. (I also have CodeVisionAVR available but thought i should start off with Programmer's Notepad to get a hang of it first - more support available.)

^ hey guys I need to pick your brains about this

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

theusch wrote:
Quote:

Since it appears you have a 'scope or at least a logic analyzer, then why not set the CKOUT fuse to see what speed you are >>really<< running at?

My scope max is 8MHz, so I put on a 4MHz ceramic resonator and it ran at exactly 4MHz. I then put the 20MHz ceramic resonator back on and all the scope saw was a constant high level - which makes sense. So all we know is that the AVR is running at higher than 8MHz for sure.

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

Sorry Johan, I misspelled your name..Maybe you can add that as another FAQ..:)

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

Quote:

How can I determine what my compiler and or makefile are set to?

Attach the makefile to a post here.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl wrote:
Quote:

Attach the makefile to a post here.

# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
#
# Released to the Public Domain
#
# Additional material for this makefile was written by:
# Peter Fleury
# Tim Henigan
# Colin O'Flynn
# Reiner Patommel
# Markus Pfaff
# Sander Pool
# Frederik Rouleau
# Carlos Lamas
#
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
#                Please customize the avrdude settings below first!
#
# make debug = Start either simulavr or avarice as specified for debugging, 
#              with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
#                   bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------


# MCU name
MCU = atmega328p


# Processor frequency.
#     This will define a symbol, F_CPU, in all source code files equal to the 
#     processor frequency. You can then use this symbol in your source code to 
#     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
#     automatically to create a 32-bit value in your source code.
#     Typical values are:
#         F_CPU =  1000000
#         F_CPU =  1843200
#         F_CPU =  2000000
#         F_CPU =  3686400
#         F_CPU =  4000000
#         F_CPU =  7372800
#         F_CPU =  8000000
#         F_CPU = 11059200
#         F_CPU = 14745600
#         F_CPU = 16000000
#         F_CPU = 18432000
#         F_CPU = 20000000
F_CPU = 8000000


# Output format. (can be srec, ihex, binary)
FORMAT = ihex


# Target file name (without extension).
TARGET = twentymhz


# Object files directory
#     To put object files in current directory, use a dot (.), do NOT make
#     this an empty or blank macro!
OBJDIR = .


# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c


# List C++ source files here. (C dependencies are automatically generated.)
#CPPSRC = 


# List Assembler source files here.
#     Make them always end in a capital .S.  Files ending in a lowercase .s
#     will not be considered source files but generated files (assembler
#     output from the compiler), and will be deleted upon "make clean"!
#     Even though the DOS/Win* filesystem matches both .s and .S the same,
#     it will preserve the spelling of the filenames, and gcc itself does
#     care about how the name is spelled on its command-line.
ASRC =


# Optimization level, can be [0, 1, 2, 3, s]. 
#     0 = turn off optimization. s = optimize for size.
#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s


# Debugging format.
#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
#     AVR Studio 4.10 requires dwarf-2.
#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2


# List any extra directories to look for include files here.
#     Each directory must be seperated by a space.
#     Use forward slashes for directory separators.
#     For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS = 


# Compiler flag to set the C Standard level.
#     c89   = "ANSI" C
#     gnu89 = c89 plus GCC extensions
#     c99   = ISO C99 standard (not yet fully implemented)
#     gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99


# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL


# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)


# Place -D or -U options here for C++ sources
CPPDEFS = -DF_CPU=$(F_CPU)UL
#CPPDEFS += -D__STDC_LIMIT_MACROS
#CPPDEFS += -D__STDC_CONSTANT_MACROS



#---------------- Compiler Options C ----------------
#  -g*:          generate debugging information
#  -O*:          optimization level
#  -f...:        tuning, see GCC manual and avr-libc documentation
#  -Wall...:     warning level
#  -Wa,...:      tell GCC to pass this to the assembler.
#    -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char
CFLAGS += -funsigned-bitfields
CFLAGS += -fpack-struct
CFLAGS += -fshort-enums
CFLAGS += -Wall
CFLAGS += -Wstrict-prototypes
#CFLAGS += -mshort-calls
#CFLAGS += -fno-unit-at-a-time
#CFLAGS += -Wundef
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wsign-compare
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)


#---------------- Compiler Options C++ ----------------
#  -g*:          generate debugging information
#  -O*:          optimization level
#  -f...:        tuning, see GCC manual and avr-libc documentation
#  -Wall...:     warning level
#  -Wa,...:      tell GCC to pass this to the assembler.
#    -adhlns...: create assembler listing
CPPFLAGS = -g$(DEBUG)
CPPFLAGS += $(CPPDEFS)
CPPFLAGS += -O$(OPT)
CPPFLAGS += -funsigned-char
CPPFLAGS += -funsigned-bitfields
CPPFLAGS += -fpack-struct
CPPFLAGS += -fshort-enums
CPPFLAGS += -fno-exceptions
CPPFLAGS += -Wall
CPPFLAGS += -Wundef
#CPPFLAGS += -mshort-calls
#CPPFLAGS += -fno-unit-at-a-time
#CPPFLAGS += -Wstrict-prototypes
#CPPFLAGS += -Wunreachable-code
#CPPFLAGS += -Wsign-compare
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
#CPPFLAGS += $(CSTANDARD)


#---------------- Assembler Options ----------------
#  -Wa,...:   tell GCC to pass this to the assembler.
#  -adhlns:   create listing
#  -gstabs:   have the assembler create line number information; note that
#             for use in COFF files, additional information about filenames
#             and function names needs to be present in the assembler source
#             files -- see avr-libc docs [FIXME: not yet described there]
#  -listing-cont-lines: Sets the maximum number of continuation lines of hex 
#       dump that will be displayed for a given single line of source input.
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100


#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min

# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt

# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB = 
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)


# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min

# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt

# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB = 
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)


MATH_LIB = -lm


# List any extra directories to look for libraries here.
#     Each directory must be seperated by a space.
#     Use forward slashes for directory separators.
#     For a directory that has spaces, enclose it in quotes.
EXTRALIBDIRS = 



#---------------- External Memory Options ----------------

# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff

# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff

EXTMEMOPTS =



#---------------- Linker Options ----------------
#  -Wl,...:     tell GCC to pass this to linker.
#    -Map:      create map file
#    --cref:    add cross reference to  map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
#LDFLAGS += -T linker_script.x



#---------------- Programming Options (avrdude) ----------------

# Programming hardware
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = stk500v2

# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = com1    # programmer connected to serial device

AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep


# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y

# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V

# Increase verbosity level.  Please use this when submitting bug
# reports about avrdude. See  
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v

AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)



#---------------- Debugging Options ----------------

# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(F_CPU)

# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight

# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr

# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit

# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1

# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242

# Debugging host used to communicate between GDB / avarice / simulavr, normally
#     just set to localhost unless doing some sort of crazy debugging when 
#     avarice is running on a different computer.
DEBUG_HOST = localhost



#============================================================================


# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AR = avr-ar rcs
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
REMOVEDIR = rm -rf
COPY = cp
WINSHELL = cmd


# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = --------  end  --------
MSG_SIZE_BEFORE = Size before: 
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling C:
MSG_COMPILING_CPP = Compiling C++:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
MSG_CREATING_LIBRARY = Creating library:




# Define all object files.
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) 

# Define all listing files.
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) 


# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d


# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)





# Default target.
all: begin gccversion sizebefore build sizeafter end

# Change the build target to build a HEX file or a library.
build: elf hex eep lss sym
#build: lib


elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
LIBNAME=lib$(TARGET).a
lib: $(LIBNAME)



# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
	@echo
	@echo $(MSG_BEGIN)

end:
	@echo $(MSG_END)
	@echo


# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf

sizebefore:
	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
	2>/dev/null; echo; fi

sizeafter:
	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
	2>/dev/null; echo; fi



# Display compiler version information.
gccversion : 
	@$(CC) --version



# Program the device.  
program: $(TARGET).hex $(TARGET).eep
	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)


# Generate avr-gdb config/init file which does the following:
#     define the reset signal, load the target file, connect to target, and set 
#     a breakpoint at main().
gdb-config: 
	@$(REMOVE) $(GDBINIT_FILE)
	@echo define reset >> $(GDBINIT_FILE)
	@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
	@echo end >> $(GDBINIT_FILE)
	@echo file $(TARGET).elf >> $(GDBINIT_FILE)
	@echo target remote $(DEBUG_HOST):$(DEBUG_PORT)  >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
	@echo load  >> $(GDBINIT_FILE)
endif
	@echo break main >> $(GDBINIT_FILE)

debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
	@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
	@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
	$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
	@$(WINSHELL) /c pause

else
	@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
	$(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
	@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)




# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT = $(OBJCOPY) --debugging
COFFCONVERT += --change-section-address .data-0x800000
COFFCONVERT += --change-section-address .bss-0x800000
COFFCONVERT += --change-section-address .noinit-0x800000
COFFCONVERT += --change-section-address .eeprom-0x810000



coff: $(TARGET).elf
	@echo
	@echo $(MSG_COFF) $(TARGET).cof
	$(COFFCONVERT) -O coff-avr $< $(TARGET).cof


extcoff: $(TARGET).elf
	@echo
	@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
	$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof



# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
	@echo
	@echo $(MSG_FLASH) $@
	$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature $< $@

%.eep: %.elf
	@echo
	@echo $(MSG_EEPROM) $@
	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
	--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0

# Create extended listing file from ELF output file.
%.lss: %.elf
	@echo
	@echo $(MSG_EXTENDED_LISTING) $@
	$(OBJDUMP) -h -S -z $< > $@

# Create a symbol table from ELF output file.
%.sym: %.elf
	@echo
	@echo $(MSG_SYMBOL_TABLE) $@
	$(NM) -n $< > $@



# Create library from object files.
.SECONDARY : $(TARGET).a
.PRECIOUS : $(OBJ)
%.a: $(OBJ)
	@echo
	@echo $(MSG_CREATING_LIBRARY) $@
	$(AR) $@ $(OBJ)


# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
	@echo
	@echo $(MSG_LINKING) $@
	$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)


# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c
	@echo
	@echo $(MSG_COMPILING) $<
	$(CC) -c $(ALL_CFLAGS) $< -o $@ 


# Compile: create object files from C++ source files.
$(OBJDIR)/%.o : %.cpp
	@echo
	@echo $(MSG_COMPILING_CPP) $<
	$(CC) -c $(ALL_CPPFLAGS) $< -o $@ 


# Compile: create assembler files from C source files.
%.s : %.c
	$(CC) -S $(ALL_CFLAGS) $< -o $@


# Compile: create assembler files from C++ source files.
%.s : %.cpp
	$(CC) -S $(ALL_CPPFLAGS) $< -o $@


# Assemble: create object files from assembler source files.
$(OBJDIR)/%.o : %.S
	@echo
	@echo $(MSG_ASSEMBLING) $<
	$(CC) -c $(ALL_ASFLAGS) $< -o $@


# Create preprocessed source for use in sending a bug report.
%.i : %.c
	$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 


# Target: clean project.
clean: begin clean_list end

clean_list :
	@echo
	@echo $(MSG_CLEANING)
	$(REMOVE) $(TARGET).hex
	$(REMOVE) $(TARGET).eep
	$(REMOVE) $(TARGET).cof
	$(REMOVE) $(TARGET).elf
	$(REMOVE) $(TARGET).map
	$(REMOVE) $(TARGET).sym
	$(REMOVE) $(TARGET).lss
	$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
	$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
	$(REMOVE) $(SRC:.c=.s)
	$(REMOVE) $(SRC:.c=.d)
	$(REMOVE) $(SRC:.c=.i)
	$(REMOVEDIR) .dep


# Create object files directory
$(shell mkdir $(OBJDIR) 2>/dev/null)


# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)


# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config

is it the "OPT = s" line? So this optimizes for size and therefore speed?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
# Optimization level, can be [0, 1, 2, 3, s]. 
#     0 = turn off optimization. s = optimize for size. 
#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)

But anyway - what happened on the CKOUT pin after you set the fuse that Lee (theusch) suggested? Does your scope show that the CPU really is running at 20MHz?

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

Mahhari wrote:
theusch wrote:
Quote:

Since it appears you have a 'scope or at least a logic analyzer, then why not set the CKOUT fuse to see what speed you are >>really<< running at?

My scope max is 8MHz, so I put on a 4MHz ceramic resonator and it ran at exactly 4MHz. I then put the 20MHz ceramic resonator back on and all the scope saw was a constant high level - which makes sense. So all we know is that the AVR is running at higher than 8MHz for sure.

^ I posted my findings a few posts up.

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

If Cliff had been a Nice Guy[tm] he would have made this quote from the makefile:

# Optimization level, can be [0, 1, 2, 3, s].
#     0 = turn off optimization. s = optimize for size.
#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s 

So you are running the compiler with -Os.

The makefile you are quoting is derived from the Mfile utilitys template makefile. If you are lucky you might even be able to open it in Mfile and manipulate it with relatively little knowledge about GNU Make and makefiles. (Just take a backup of the file before you try that, please.)

Mfile comes with WinAVR, so you already have it installed on your system.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

We've been going at this for several days now. Even the infinite-value compiler is not going to take 20 cycles/loop at Os.

You GCC gurus: tell OP how to obtain the generated code as Cliff did for his test program with the code. Or OP could load it up into the simulator and pose a screen-shot of the mixed view. Or ...?

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

Quote:

You GCC gurus: tell OP how to obtain the generated code as Cliff did for his test program with the code. Or OP could load it up into the simulator and pose a screen-shot of the mixed view. Or ...?

OK I took the program from the very first post of this thread and the Makefile posted just above here and simply used "make". One of the output files was twentymhz.lss and within that the main() consists of:

00000080 
: #include void main() { DDRB = 0XFF; 80: 8f ef ldi r24, 0xFF ; 255 82: 84 b9 out 0x04, r24 ; 4 while(1) { PORTB = 0x00; 84: 15 b8 out 0x05, r1 ; 5 PORTB = 0XFF; 86: 85 b9 out 0x05, r24 ; 5 88: fd cf rjmp .-6 ; 0x84

So, unless the OP has some other compiler installed (I'm using the 2009 one) he will have been running exactly this code when the picture in the first post was generated.

Just in case there's a different compiler being used all the OP needs to do is "make" and then edit the twentymhz.lss that was generated to see the exact code being used. Another view of the same thing is the twentymhz.lst in the same directory:

  16               	.global	main
  18               	main:
  19               	.LFB2:
  20               	.LM1:
  21               	/* prologue: function */
  22               	/* frame size = 0 */
  23               	.LM2:
  24 0000 8FEF      		ldi r24,lo8(-1)
  25 0002 84B9      		out 36-32,r24
  26               	.L2:
  27               	.LM3:
  28 0004 15B8      		out 37-32,__zero_reg__
  29               	.LM4:
  30 0006 85B9      		out 37-32,r24
  31 0008 00C0      		rjmp .L2

which is the listing file output by the assembler.

Cliff

EDIT: I went back to the picture in the first post and modified it to see how many of the "low period" would fit into one /div on the scope screen (set to 1us). It looks to me like about 8.5 so the low period looks like 1/8.5us. I wonder if it's really 1/10us perhaps? The cycle time of a 20MHz CPU is 1/20 us

Attachment(s): 

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

Quote:
Even the infinite-value compiler

That there is funny stuff every time, Lee. :)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Which certainly doesn't explain 20 cycles/1us per loop as shown in the timing diagram. So either the chip isn't running at 20MHz, or that code isn't really being run.

With OUT being 1 cycle and RJMP being 2 cycles, then a 1:3 ratio of high:low on the pin(s) makes sense.

Now, if I'm counting correctly 4 cycles <=> 1us, implying an AVR clock rate of 4MHz. (There were some other numbers like 5MHz kicked around, but the loop is indeed 4 cycles, isn't it?)

Hmmm--one of the test runs was

Quote:
My scope max is 8MHz, so I put on a 4MHz ceramic resonator and it ran at exactly 4MHz.

As it is a bit difficult to get 4 cycles in 1us at 20MHz, I think somewhere apples and oranges got mixed.

I still don't understand the rules and conditions of the contest posed in the thread title.

And for some reason there appears to be resistance by the OP to do a clean repeat of the test and post the relevant generated code fragments.

If the 'scope only goes up to 8MHz then the expected 5MHz output is outside Nyquist anyway...

Tell you what: Repeat the test with the same program adding a clock prescaler, and use a high CLKPR of say /64. Now your trace (and CLKO pin!) are within the limits of your measuring device. What do you get for the traces for CLKO pin and the output pins?

If the arithmetic works out, the use the next lower prescaler and repeat.

Continue on down to /1.

Are the results good through /4 and maybe /2, but you get the "bad" results for /1? Then we may need to take a trip to visit Mr. Nyquist.

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

Oh I missed this 8MHz scope thing along the line there somewhere. So how on earth did the OP expect to resolve a signal outside the range of his measuring device in the first place? But what's more odd is how has it managed to draw fairly accurately and consistently something looking like a 1/8th..1/10th us pulse? Normally when you get into "glitch" territory of a scope/LA it gets "messy", not ordered like this display?

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

Quote:

But what's more odd is how has it managed to draw fairly accurately and consistently something looking like a 1/8th..1/10th us pulse?

??? The link from the first post shows a perfectly uniform 1us cycle, with 1/4 of that low.

(Hmmm--makes my eyes hurt--it might be less than 250ns low, and that indeed is 1:4 (1/5) not 1:3 (1/4). So the "cycle time" is still 1us...)

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

Quote:

with 1/4 of that low

No Lee, it's not 1/4 - that was the purpose of the small picture I edited and attached above. I took the low period and duplicated it as many times as it would fit into a 1us division and it's about 8.5 - so the low period is more like a consistent 1/8.5us which an 8MHz device should not be able to render according to Nyquist.

For the myopic amongst us (me included) here's the key part of that picture again blown up a bit...

Attachment(s): 

Last Edited: Tue. Nov 24, 2009 - 03:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

LOL -- [referring to another current thread] Perhaps AVRs aren't "well optimized", and are not a good choice for a serial stream/simple waveform generation at modest rates.

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

Quote:
And for some reason there appears to be resistance by the OP to do a clean repeat of the test and post the relevant generated code fragments.

nope not at all! I would be glad too. Let me just make sure I know what it is you want me to repeat. The Nyquist Theorem defiantly applies here. With my 8MHz scope I will only be able to test the 4MHz clock. And I have tested that and found one clock period to be 0.25us which should equal 4MHz.

I was worried about aliasing with the first post when I got 0.8us as a high and 0.2 for a low on the output port. But, it was consistent so I assumed the AVR was actually outputting at that frequency and there wasn't any aliasing.

Quote:
Tell you what: Repeat the test with the same program adding a clock prescaler, and use a high CLKPR of say /64. Now your trace (and CLKO pin!) are within the limits of your measuring device. What do you get for the traces for CLKO pin and the output pins?

So theusch, I should use the 20MHz resonator and set a prescaler which will bring the clocking frequency down to below 4MHz which I can read with the scope correct? Will a prescaler of /64 result in a clock frequency of clk/64 = 20/64 = 0.3125MHz = 312.5KHz?

If that's correct let me know and I’ll test it tonight when I get home.

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

Right - stick with your original program so we know the loop will be:

00000080 
: #include void main() { DDRB = 0XFF; 80: 8f ef ldi r24, 0xFF ; 255 82: 84 b9 out 0x04, r24 ; 4 while(1) { PORTB = 0x00; 84: 15 b8 out 0x05, r1 ; 5 PORTB = 0XFF; 86: 85 b9 out 0x05, r24 ; 5 88: fd cf rjmp .-6 ; 0x84

given the code and the Makefile settings but just make a small change:

#include  

void main() 
{ 
	CLKPR = (1 << CLKPCE);
	CLKPR = 6;  //this divides 20MHz by 64 = 0.3125Mhz, 1 cycle = 3.2us
    
   while(1) 
   { 
      PORTB = 0x00; 
      PORTB = 0XFF; 
   } 
return; 
}

The comment says it all really but this will run the CPU (assuming it started at 20MHz) at 0.3125MHz with a 3.2us cycle. So the low period should measure 3.2 divisions on your 1us/div scope.

Cliff

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

... and we >>still<< haven't seen generated code from the OP as Cliff has posted several times with the re-creation. sigh

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

Okay I redid the test with Cliff's code (copy pasted). you can see the results here:

www.tinkerjunkies.com/Sample1.html

As you can see, CLKPR 6 with 20MHz resonator does give a 3.2us cycle. Then I tested with CLKPR 3 with 20MHz resonator, and you can see clear aliasing or bad clock signal. This is only 2.5MHz. I then switched to the 4Mhz resonator and set CLKPR to 0, and you get a clean clock signal. I found this interesting.

Also here is the .lss file

00000080 
: void main() { //CLKPR = (1 << CLKPCE); //CLKPR = 0; //this divides 20MHz by 64 = 0.3125Mhz, 1 cycle = 3.2us DDRB = 0xFF; 80: 8f ef ldi r24, 0xFF ; 255 82: 84 b9 out 0x04, r24 ; 4 while(1) { PORTB = 0xff; 84: 85 b9 out 0x05, r24 ; 5 86: fe cf rjmp .-4 ; 0x84 00000088 <_exit>: 88: f8 94 cli 0000008a <__stop_program>: 8a: ff cf rjmp .-2 ; 0x8a <__stop_program>

Cliff I also noticed you didn't use DDRB, why is that? I'll have to redo this test with the outputs. I forgot this time, i was just looking at the clock :(

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

Oh no, it was meant to have DDRB (as your code) I think when I Ctrl-V'd the CLKPR lines I may have inadvertently had the DDRB line selected - so it was obliterated.

But I'm still confused by your result. It was the LOW PERIOD, not the CYCLE that was expected to be 3.2us. Also the pulse was expected to be non-symmetric - low for 1/4 of the cycle and high for 3/4 yet you have a 50:50 mark:space ?!?

And another thing. You say the code you actually used was:

   while(1)
   {
      PORTB = 0xff;
  84:   85 b9          out   0x05, r24   ; 5
  86:   fe cf          rjmp   .-4         ; 0x84 

but that code does nothing more than repeatedly write 0xFF to PORTB, jumping back to location 84 and then doing it again each time. This cannot possibly be the code that produced those graphs you posted. That never drives the output low.

Something here is very fishy so I'm out - I fear we're being trolled.

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

Quote:

This cannot possibly be the code that produced those graphs you posted.

Quote:

Something here is very fishy so I'm out - I fear we're being trolled.

Certain things didn't add up to me all along.

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

no no I said that those graphs are for the clock cycles and not the outputs for PORTB. I forgot to check the outputs, I just wanted to make sure the avr was at 20mhz.

anyways, I've learned a lot from this thread.