I wrote a simple code that does nothing but switch a pin on and off via port manipulations, with a one microsecond delay. I then hooked it up to an oscillator and noticed that between loops there seemed to be extra time being inserted.
#define VIDEO_ON PORTB|=B00000010
#define VIDEO_OFF PORTB&=B11111101
#define NOP asm("nop")
inline void one_us()
{
// 1us / 62.5ns = 16
NOP; NOP; NOP; NOP;
NOP; NOP; NOP; NOP;
NOP; NOP; NOP; NOP;
NOP; NOP;
//NOP; remove one to offset time for next instruction to complete
//NOP; remove one more due to switching time, but will
//result in slightly less than 1 us (but less than 62.5ns off)
//~.996ns vs 1.06us, slightly less drift
}
void loop()
{
VIDEO_ON;
one_us();
VIDEO_OFF;
NOP;
}
If my information is correct, 1 nop should take 62.5ns, however in between the pin going low and high there's more than 62.5ns. The time between high and low is about 1us, as planned.
I expect that there's going to be a jump back to the top, which takes a couple of instructions, but even then I'm measuring ~800ns between loop end and start.
What's going on between loops? Is there anyway to cut down this extra time?
Note that "call" and "ret" are both 4-clock instructions, while rjmp is 2 clocks, so you "at least 10 cycles" is awfully close. sbi and cbi are also among the 2-cycle instructions.
If you're going to do video, you probably are going to need a more extensive set of tools than those provided by the arduino environment. The above dissassembly was obtained with "avr-objdump -d", which is included in the tools packaged with arduino (.../hardware/tools/avr/bin/avr-objdump on my mac. YMMV.)
(you also haven't done anything about the periodic timer tick, which will come along and take much more time, every once in a while (approximately every millisecond.))
I've been doing cli(), does that actually disable interrupts?
Yes but note that that method disables all interrupts. This may be an issue if you have serial I/O occurring at the same time and interrupts are disabled for more than 10 to 15 bit times.