Why is there a delay at the end of void Loop?

KE7GKP:

being 32x more precise.

Not really. Attempting to generate a "precise" (however you are defining it) frequency with Arduino is a classic example of using the wrong tool. It just isn't made for it. Arduino is good for a great many things, but being a precise frequency generator ain't one of them.

I think you misconstrued my intent. I was illustrating a way to minimize the error. I was not arguing fitness of the arduino as a precise square wave generator. I thought I was pretty clear on that. Especially since I agreed with the comment stating a timer, rtc, whatever, should be used rather than the arduino itself. And to be clear, "yes really." The error rate was diminished accordingly. Saying, "not really", doesn't really change that. I assume your, "not really", was more of a conflation of fitness and approach moreso than commentary of the results.

Err .. yes ... as the 'starter' of the thread I need to point at that I am just trying to determine what the 'somewhat theoretical' maximum speed is for Arduino to update 8 shiftregisters with eight bytes.

My tests are based on sending 8 bytes on SPI together with latching required. For those interested I achived 68KHz so far, or 4.3MHz at the bit level .. faster if you count the latches also.

I was not aware that adding code to functions and void loop{} added overhead and when I noticed these discrepancies I asked why, in this thread. I think the topic has been covered.

As stated I need to remove as much incidental overhead as possible from the measurement so as to closer approach the theoretical maximum. Thats all. No square wave generators and no goto vs no goto arguments intended. I believe the results speak for themselves in this regard.

Thank you all for your valued input, I find this all fascinating and learned a great deal in a very quick time. Special thanks to gerg who first got me started on this track with his inline compiling suggestions. :)

PS: IMHO goto is just another code statement, its all rock and roll to me :P

JBMetal: My tests are based on sending 8 bytes on SPI together with latching required. For those interested I achived 68KHz so far, or 4.3MHz at the bit level .. faster if you count the latches also.

In that case I would use the SPI hardware built into the chip. My measurements here:

http://www.gammon.com.au/spi

... showed that I could achieve around 4 MHz at the bit level (0.125 uS per pulse).

Using the hardware means you can let interrupts do the work for you (on the receiving end at least). I think for the base chip (the Atmega) which is clocked at 16 MHz, getting pulses out at 4 MHz (where a pulse is an off and on sequence) is about the best you can do.

Okay, with all the "goto is evil... from my books' point of view" nay-sayers in this thread, sort of "third-party bashing" goto with ye olde C teachings... I've got to come to its rescue.

There is not a DANG thing wrong with using goto, in my opinion. Personally, I've always avoided it because of all the negativity surrounding it, but I think that may be subject to change. Even with the most efficient C-style code blocks and structures, a goto would make the code much easier to follow and understand, and save thousands of compiled bytes at times. Sometimes you just need to "loop this if that plus that, always run this part of the loop, only do this part of the loop sometimes, and skip to the end of the loop if that", and a "break" just won't do. Often, the more complicated the loop's control, the more efficient the program can run - too many independent function calls and control statements, and you end up wasting lots of code and clock cycles. The "lowly goto" is an amazingly elegant way to "just GO TO" a part of the code, discarding all the conditions in the block... well, provided you do so within the construct of the language you use, like, don't "goto" outside the current function or something. There's LOTS of ways to abuse goto, which is probably what started the whole "evil goto" thing. I think the use of goto should be considered on the implementation, not the fact that it's present at all.

Because in the end, goto is indeed the single most absolutely efficient branching method possible: function calls push/pop registers to set up its environment; control statements perform validation. It's one instruction: jump to "here". :)

Because in the end, goto is indeed the single most absolutely efficient branching method possible:

I wonder if that's why compilers use it so much in "while", "do..while" and "for" loops?

Seriously, more often than not, if you have to use a goto, you haven't understood the structure of your problem correctly.

FalconFour:
Even with the most efficient C-style code blocks and structures, a goto would make the code much easier to follow and understand, and save thousands of compiled bytes at times.

I’m sorry to burst your bubble, but that simply isn’t true. Consider this sketch:

void setup () {}
void loop ()
{
 while (true) 
  {
  digitalWrite (5, HIGH);
  } 
}

That uses a “while” loop.

Sketch size:

Binary sketch size: 724 bytes (of a 30720 byte maximum)

Generated code:

00000102 <loop>:
void loop ()
{
 while (true) 
  {
  digitalWrite (5, HIGH);
 102:	85 e0       	ldi	r24, 0x05	; 5
 104:	61 e0       	ldi	r22, 0x01	; 1
 106:	0e 94 86 00 	call	0x10c	; 0x10c <digitalWrite>
 10a:	fb cf       	rjmp	.-10     	; 0x102 <loop>

0000010c <digitalWrite>:
	}
}

Now consider this:

void setup () {}

void loop ()
{
  foo:
  digitalWrite (5, HIGH);
  goto foo;
}

Sketch size:

Binary sketch size: 724 bytes (of a 30720 byte maximum)

Generated code:

00000102 <loop>:
void loop ()
{
  foo:
  digitalWrite (5, HIGH);
 102:	85 e0       	ldi	r24, 0x05	; 5
 104:	61 e0       	ldi	r22, 0x01	; 1
 106:	0e 94 86 00 	call	0x10c	; 0x10c <digitalWrite>
 10a:	fb cf       	rjmp	.-10     	; 0x102 <loop>

0000010c <digitalWrite>:
	}
}

The code sizes are identical! The generated code is identical!

There is no saving of “thousands of bytes” using goto. None. Not a byte.

There is no speed improvement. The compiler has generated, in both cases, "rjmp .-10 " - the same machine code instruction.

All the goto does is make the code harder to read. It possibly introduces subtle errors of logic, if you “goto” over stuff you shouldn’t.

It is not the panacea for saving memory, saving time. It does none of that.

In the OP’s code (and I am sure he realizes this) he could have changed:

void loop() {
  start:
  LATCH_ON();
  LATCH_OFF();
  LATCH_ON();
  LATCH_OFF();
 goto start;
} // with goto

to:

void loop() {
  while (true)
  {
  LATCH_ON();
  LATCH_OFF();
  LATCH_ON();
  LATCH_OFF();
  }
} // with goto

The goto didn’t save time. It was changing the code to omit the repeated function calls that saved time. But you can do that without using goto.

Because in the end, goto is indeed the single most absolutely efficient branching method possible: …

No, that simply is not true. You can achieve the same thing with “do” and “while”. Keep the code elegant and maintainable.

...and, as stated earlier in the thread... you can gain much efficiency by using Hardware SPI as built into the AVR chip.

http://softsolder.com/2009/07/18/arduino-hardware-assisted-spi-synchronous-serial-data-io/

Ed was able to get a "factor-of-15 speedup" with 595 latches.

As Nick points out, there is absolutely nothing magical about goto. I get the impression from some followup comments that people now believe goto should be commonly used. If I gave that impression, I apologize. Goto should absolutely not be commonly be used. It should be used very sparingly. Its easy to create rats nests of code which is extremely difficult to read and understand. This is a tale any old BASIC coder will be more than willing to share. It should not be viewed as a general purpose flow control mechanism. It should be viewed as one of many in a developer's optimization bag of tricks. And is widely known, the root of all evil is premature optimization. So that should tell you, if you're readily reaching for goto, you're using it wrong.

In my many, many years of coding, I've used goto in C/C++ code less than a half dozen times. Once or twice more I would have used it again except it was forbidden by the coding standards. In all cases where I've used it, it was in fairly complex code where goto was the only possibly means to obtain the optimizations required while ensuring some facet of readability. Generally speaking, if you find you're using goto more frequently than once every couple of years, while coding on a daily basis, chances are very high you're using it wrong.

Now then, as I originally stated, goto has been demonized and is frequently forbidden. Such a response is almost as inappropriate as daily use. But, just because the use of goto is a legitmate flow control technique doesn't mean it should be used without considerable thought. Generally speaking, it should only be used as a optimization technique of last resort, and then generally only by experienced coders.

Again, as Nick pointed out, the simple use of goto, in of itself, doesn't magically imbue optimizations. And by far, it can be easily used for evil. Which is exactly why it has such a bad reputation.

[quote author=Nick Gammon link=topic=65014.msg476136#msg476136 date=1309251055]Consider this sketch[/quote] I've never seen anyone post something SO distorted, so misinterpreted, and so blown out of proportion than the absolute CRAP you just posted in there. Dude, get your head outta your rear - do you even recognize that I actually know what I'm talking about and may actually have the slightest semblance of understanding more than your little 8-byte "demo"?

I said it COULD save thousands of bytes. Did you write ANY sort of complicated loop structure there? No, you jumped to the same g*ddamn location as the loop. Did you have nested if/else/while/select statements in there? Would you be able to imagine a reason to? No? OK, then you can't test it. Did you even understand what I was referring to by "saving thousands of bytes"? Apparently not. I don't mean using goto in place of a loop is somehow going to magically save a bunch of code. Far the hell from it.

I'm just f'ing dumbfounded how you pulled out such a far-fetched, WAY freaking overblown reply to such an outlandish misreading of the very specific and accurate wording I used in my post. And then to have other members actually reading that long drawn-out BS of a reply and running with it like gospel as well.

I'm just leaving it at that right now, as there's nothing I could really reply to say other than reposting the exact thing I already wrote and hoping someone actually reads it this time. Good god, never thought I'd be so pissed off at some crapshoot reply by an Arduino board member. :stuck_out_tongue_closed_eyes:

edit: Hmm, so I skimmed a few replies above and see just the piggy-backing on Nick's reply and "using that reply to read my post", so let me make this much bigger for your reading ability: I don't mean using goto in place of a loop is somehow going to magically save a bunch of code. Far the hell from it.

There, now would you mind going back and reading what I actually wrote?

FalconFour: Okay, with all the "goto is evil... from my books' point of view" nay-sayers in this thread, sort of "third-party bashing" goto with ye olde C teachings... I've got to come to its rescue.

There is not a DANG thing wrong with using goto, in my opinion. Personally, I've always avoided it because of all the negativity surrounding it, but I think that may be subject to change. Even with the most efficient C-style code blocks and structures, a goto would make the code much easier to follow and understand, and save thousands of compiled bytes at times. Sometimes you just need to "loop this if that plus that, always run this part of the loop, only do this part of the loop sometimes, and skip to the end of the loop if that", and a "break" just won't do. Often, the more complicated the loop's control, the more efficient the program can run - too many independent function calls and control statements, and you end up wasting lots of code and clock cycles. The "lowly goto" is an amazingly elegant way to "just GO TO" a part of the code, discarding all the conditions in the block... well, provided you do so within the construct of the language you use, like, don't "goto" outside the current function or something. There's LOTS of ways to abuse goto, which is probably what started the whole "evil goto" thing. I think the use of goto should be considered on the implementation, not the fact that it's present at all.

Because in the end, goto is indeed the single most absolutely efficient branching method possible: function calls push/pop registers to set up its environment; control statements perform validation. It's one instruction: jump to "here". :)

FalconFour: [quote author=Nick Gammon link=topic=65014.msg476136#msg476136 date=1309251055]Consider this sketch

I've never seen anyone post something SO distorted, so misinterpreted, and so blown out of proportion than the absolute CRAP you just posted in there. Dude, get your head outta your rear - do you even recognize that I actually know what I'm talking about and may actually have the slightest semblance of understanding more than your little 8-byte "demo"?

I said it COULD save thousands of bytes. Did you write ANY sort of complicated loop structure there? No, you jumped to the same g*ddamn location as the loop. Did you have nested if/else/while/select statements in there? Would you be able to imagine a reason to? No? OK, then you can't test it. Did you even understand what I was referring to by "saving thousands of bytes"? Apparently not. I don't mean using goto in place of a loop is somehow going to magically save a bunch of code. Far the hell from it.

I'm just f'ing dumbfounded how you pulled out such a far-fetched, WAY freaking overblown reply to such an outlandish misreading of the very specific and accurate wording I used in my post. And then to have other members actually reading that long drawn-out BS of a reply and running with it like gospel as well.

I'm just leaving it at that right now, as there's nothing I could really reply to say other than reposting the exact thing I already wrote and hoping someone actually reads it this time. Good god, never thought I'd be so pissed off at some crapshoot reply by an Arduino board member. :stuck_out_tongue_closed_eyes: [/quote]

Dude, settle down. No need for personal attacks.

FalconFour: There, now would you mind going back and reading what I actually wrote?

Well, I re-read it. Now instead of screaming at me if you would be kind enough to post an actual counter example I would be interested to see it. Code that compiles. Code that proves your point.

FalconFour:
edit: Hmm, so I skimmed a few replies above and see just the piggy-backing on Nick’s reply and “using that reply to read my post”, so let me make this much bigger for your reading ability:
I don’t mean using goto in place of a loop is somehow going to magically save a bunch of code. Far the hell from it.

If in fact, you’re saying that, in part, to my reply, as I think I’m reading it, I strongly encourage you to re-read what I said. Your tone implies you didn’t understand what you read - or I expressed myself very poorly. I just re-read my post and to me, it hints of the former rather than the later. You also need to keep in mind, there is a highly diverse skill set present on these forums. Some started coding today. Some have decades of experience. Many times a post is used as a soap box to share a cautionary tale so as to ensure others are not unknowingly led astray; even with the best of intentions to the contrary.

It is … interesting(?) … to notice that

[b]goto[/b]

still has not lost it’s magic - to get gentle and intelligent people into strong and heated debates. :slight_smile:

You'll notice that I did not say to never use goto:

[quote author=Nick Gammon link=topic=65014.msg475281#msg475281 date=1309167446] ... it's simply a case of using the right tool for the job. The goto statement has its uses, in possibly 0.01% of cases. [/quote]

If you look at Wikipedia:

http://en.wikipedia.org/wiki/Goto

To quote in part:

Probably the most famous criticism of GOTO is a 1968 letter by Edsger Dijkstra called Go To Statement Considered Harmful.

Then:

Some programmers, such as Linux Kernel designer and coder Linus Torvalds or software engineer and book author Steve McConnell also object to Dijkstra's point of view, stating that GOTOs can be a useful language feature, improving program speed, size and code clearness, but only when used in a sensible way by a comparably sensible programmer.

So, respected programmers agree that goto is useful under certain conditions: "when used in a sensible way by a comparably sensible programmer". I would not disagree with that.

My test case was intended to illustrate that, using the case of the original post in this thread, that the goto achieved nothing that a while loop would not have achieved. That was my point. For that case, I correctly showed that the goto did not speed it up, it was omitting the function call/return sequence, which the while loop also did exactly as efficiently.

To be fair, I believe he was referring to optimizations which are possible because of default flow-throughs and jumps, whereby its possible to avoid the expense of some comparisons. And/or a combination of jump tables. Obviously practical gains there would be CPU/architecture dependent based on the costs of jumps vs jump comparisons, branch prediction, and cache/pipeline availability. And in complex cases where multiple comparisons are required, its frequently possible to avoid multiple comparisons whereby progressive defaults can be assumed, saving some here and there. Typically a case a real rat's nest of logic is required and a goto can help alleviate, but even then, actual savings may not be there.

In the cases above which I eluded, they were typically some from column a and some from column b. Sometimes, adding a goto can actually improve readability when the conditionals are plentiful and complex. Providing for a small optimization and easing readability, IMOHO, can be a big win. I personally believe the vast, vast majority of those types of logical rat's nests stem from poor coding and/or poor design and thusly, the number of legitimate cases will be extremely rare and hard to come by unless you live 24/7 in hardcore optimization land. Very few coders do. Thusly my off the wall statement of likely applicability.

I think the vilified goto statement inherited most of it's bad reputation for it's use as a primary means of program flow control in the early versions of the BASIC language. A 'large' program written in early versions of BASIC (before they too added better structures) could be very difficult to follow and debug because of the need to trace through every goto command to tell what a program was actually doing.

Later better structured languages (including BASIC) showed far superior methods to break up large programs into functions, etc. So in my opinion the goto became more of a alias target for the legitimate criticism of the early BASIC programming language. While I have haven't yet found the need to use the goto in any of my arduino sketches, I'm certainly open minded enough to suspect that there could be valid uses of a goto in a C/C++ program.

Discussions of politics, religion, and the use of goto seems to always bring out the worst in people. ;)

Lefty

If speed is all there is to it .... why not overclock the chip by "upgradeing" the oscillator to a faster version?

-Fletcher

gerg: To be fair, I believe he was referring to optimizations which are possible because of default flow-throughs and jumps, whereby its possible to avoid the expense of some comparisons. And/or a combination of jump tables. Obviously practical gains there would be CPU/architecture dependent based on the costs of jumps vs jump comparisons, branch prediction, and cache/pipeline availability. And in complex cases where multiple comparisons are required, its frequently possible to avoid multiple comparisons whereby progressive defaults can be assumed, saving some here and there. Typically a case a real rat's nest of logic is required and a goto can help alleviate, but even then, actual savings may not be there.

Pretty much this. Sometimes, in certain logic constructs where the data doesn't very well self-modify to break/start a loop, for example, a "goto" not only makes the program more readable, but could be used to remove countless lines of nested loops and repetitive conditionals that would otherwise be necessary to mimic the useful "goto".

Personally, I haven't yet actually written "goto" into my programs. I only recently learned that it was even possible, by reading over a highly optimized compression algorithm (FastLZ) and seeing that it uses goto to break traditional C limitations and "conditionally jump" instead of "conditionally loop", which is the only construct that's really familiar to C coders. Sometimes, it may be necessary to conditionally jump to a previous part of the program, but that whole block would be pretty unreadable (or require unnecessary use of counter/status variables) if it were all placed into a "do { ... } while()" block.

That's what I meant about the use of goto. Not that it be used in place of loops at free will, but that it not entirely be shunned. That its use be frowned upon or admired in its context, not just the fact that the letters "goto" appear in someone's program. Sometimes it may be sloppy, but with limited use of "goto", I find it makes the code much easier to understand - I can just look for that label and pick it up right there, unconditionally, as I don't have to think about the setup and incrementing of a "for (x; y; z)" structure to see where variables will begin and end, what gets passed to it, etc.

And in terms of efficiency, a "goto" is one "jump" command in assembly. That's what I meant by being the most efficient branching method in C. No conditionals, just "jump". It's just as elegant as the command says it is :)

And finally, sorry if I was a bit abrasive in my reply there, but I really was upset when one guy mis-interpreted what I was trying to say (perhaps I didn't say it as clearly as I thought I did), then everyone kinda ran with it and gave me the stampede treatment. Kinda like a snowball of miscommunication landing on me. XD

@everyone who mentioned it, I do use SPI for this

@Nick Gammon: Sir, you are confusing the readers of this thread, I believe, and drawing attention away from the results presented.

You've gone and translated my test code to:

start:
  LATCH_ON();
  LATCH_OFF();
  LATCH_ON();
  LATCH_OFF();
 goto start;

Then only stating on a single line -

The goto didn't save time. It was changing the code to omit the repeated function calls that saved time. But you can do that without using goto.

[u]This was the whole point of the exercise[/u]! And the result: goto is faster than using a function call, end of story.

If you would like to argue the merits of goto vs while please start a new thread. Nobody said replacing while is slower than goto I believe? I may be incorrect on this as I only skimmed the heated responses ...

I would however like to know what options there are, in my test code example, for me to branch code without using a function or goto as in the quote above?

And the result: goto is faster than using a function call, end of story.

You missed the point too; there was no need for a goto.