I am working with an Atmel ATMEGA32U4 microcontroller - datasheet here with a 16 MHz crystal for system clock.
From my understanding, this chip has a 'Divide clock by 8' fuse programmed from the factory, effectively making my system clock 2 MHz. (Page 348 of datasheet. CKDIV8 (bit 7) default value is 0, programmed).
I would like to confirm my system clock speed, so I wrote some code to output a pin low, delay one clock cycle, and then put the pin high again. Measuring the time the pin is low should equal one clock cycle.
Here is the code I used to accomplish this:
//Set PORT E as output
DDRE = 0xFF;
asm volatile("nop\n\t"::);
PORTE |= 1<<2;
asm volatile("nop\n\t"::);
PORTE &=~ (1<<2);
asm volatile("nop\n\t"::);
PORTE |= 1<<2;
asm volatile("nop\n\t"::);
PORTE &=~ (1<<2);
A 'nop' is equal to one clock cycle, according to the AVR instruction set manual, page 108.
Based on this information, I would assume a 'nop' instruction to take 500 nanoseconds. Is this assumption correct? (16 MHz/8 = 2 MHz. \$\frac1{2MHz}\$ = 500ns)
Here is a scope plot of my findings:
It would appear a 'nop' execution time is only 200ns (5 MHz) I would expect there to be some additional overhead using C to set the port high/low, so 500ns is actually the minimum time I would expect the pin to be low. But as you can see from my measurement cursors 'a' and 'b', its not even close to 500ns.
Can anyone explain whats going on?
Is there an error in my method?
Am I missing something 'face-palming-ly' stupid? :p
Thanks for any help!
volatile
, GCC will still move those assembly statements around per gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html if you have optimization turned on (anything other than-O0
). \$\endgroup\$out DDRE, 0xFF; nop; sbi PORTB, 2; nop; cbi PORTB, 2; nop; sbi PORTB, 2; nop; cbi PORTB, 2;
since these are all 1-cycle instructions, the time between output changes should be 2 cycles (one for thenop
, one forsbi
/cbi
). however, your compiler might optimize thenop
s away or be not smart enough to usesbi
andcbi
\$\endgroup\$