Delay_ms() with arggument [SOLVED ): ]

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

Hello

I work on a litlle program.

This one use delay_ms().

If i put a numeric value (50) , when the prog is compiled it is 120 bytes long.

If i put a variable in delay_ms(),like this

delay_ms(tps)

with tps modified in an interrupt function then
the compiled size explosed to 3000 bytes, out of value for attiny2313....

Why can't i put variable to delay_ms?

Thanks.

computer : GNU Linux / e6750
ship : Attiny 2313 / ATmega8
compiler : avr-gcc 1:4.3.2-1

Last Edited: Tue. Feb 5, 2013 - 07:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

http://www.nongnu.org/avr-libc/u...

Quote:
Note:
In order for these functions to work as intended, compiler optimizations must be enabled, and the delay time must be an expression that is a known constant at compile-time. If these requirements are not met, the resulting delay will be much longer (and basically unpredictable), and applications that otherwise do not use floating-point calculations will experience severe code bloat by the floating-point library routines linked into the application.

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:

Why can't i put variable to delay_ms?

Because that's what the user manual tells you. The reason is that it uses floating point to work out how many time to run round a loop. If optimisation is switched on and the value passed is known at compile time then the compiler is smart enough to do the entire calculation and end up with a simple "for (i=0; i

The solution is (almost as your thread title suggests in fact) to implement your own loop. Something like:

void Delay_ms(int n) {
  while (n--) {
   _delay_ms(1);
 }
}

The _delay_ms(1) in this satisfies the condition that the constant is known at compile time so no floating point is involved. You can now happily call:

Delay_ms(tps);

for your variable delay. It's true the while(n--) loop "costs" a few cycles but only probably 0.003ms or something which compared to the _delay_ms(1) is insignificant.

By the way the fact you said this adds 3000 rather than just 700 when you do it suggests your build environment is not set up correctly. Your linker command should end eith "-lm" (that is "Lima" "Mike" in case you cannot read the font). That ensures that an optimised floating point library that adds just 700 bytes is used instead of the default that is terrible and adds 3000.

As Lee says the user manual is here:

http://www.nongnu.org/avr-libc/u...

Suggest you read that for any library function you call so you are aware of any implementation restrictions.

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

Ok, thanks.

I'll go on your link, and i never do this again :)

Have a good day, ciao.

computer : GNU Linux / e6750
ship : Attiny 2313 / ATmega8
compiler : avr-gcc 1:4.3.2-1

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

CodeVision has a specific function for milliseconds:

delay_ms(tps) 

The function can take a variable argument, and even kicks the Watchdog for you!

CodeVision uses a macro for delay_us(). These macros require a NUMBER as an argument. i.e. a compile-time constant value.

avr-gcc uses the same sort of macro for _delay_us() and for _delay_ms() and consequently precludes using a variable.

However the solution is simple. Write your own function:

void delay_ms(int ms)
{
    while (ms--) {
        _delay_us(1000);  // one millisecond
    }
}

David.

p.s. a 'feature' of avr-gcc's _delay_ms() macro is that it will introduce floating-point maths to totally screw any accurate timing if you use a variable.

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

This should not be any news to you, zettaman..

https://www.avrfreaks.net/index.p...

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:
CodeVision has a specific function for milliseconds:
But note that it takes an integer, so you can get 4ms or 5ms, but not 4.8ms. The avr-gcc _delay_ms() takes a float and therefore much finer granularity (at the expense of requiring a compile time constant).

Regards,
Steve A.

The Board helps those that help themselves.

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

This forum is really reactive...
Do somebody give you money for your stuff, or is it "passion"?

computer : GNU Linux / e6750
ship : Attiny 2313 / ATmega8
compiler : avr-gcc 1:4.3.2-1

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

Quote:

or is it "passion"

+1

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

Koshchi wrote:
Quote:
CodeVision has a specific function for milliseconds:
But note that it takes an integer, so you can get 4ms or 5ms, but not 4.8ms. The avr-gcc _delay_ms() takes a float and therefore much finer granularity (at the expense of requiring a compile time constant).

Go on. Tell us when you have ever used fractional milliseconds.

I guess that most people use integer values. 1, 2, .. 1000, 2000 ...
Although they may use delay_us(1040) or delay_us(2500), I doubt that you often need fractional milliseconds above say 3.3ms.

David.

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

Sheesh--how much 'Freak-ing effort has been expended on AVR8 delay with no useful significance?

BTW, as the CodeVision equivalent of F_CPU is only used for a few things, one could lie about the AVR's clock speed and get a "fractional" parameter.

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

It's passion.. Sometimes it is well spent - but from time to time people can eternally discuss how to get some delay routine to be a little more precise, flexible, small or slightly pink.

If precise delays are needed, use hardware (i.e. a timer). If roughly accurate run-time variable delays are needed, then David gave a solution a few posts above.

This has been up more times than we can count. I hope a mod locks this thread..

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:
Although they may use delay_us(1040) or delay_us(2500)
There is no need for _delay_us() at all, _delay_ms() is capable of getting delays down to the clock cycle.

_delay_us() uses an 8 bit counter, making its usable range rather small.

Quote:
If precise delays are needed, use hardware (i.e. a timer).
Not always accurate enough. If using interrupts, the 12 cycle or more response time could be fatal. Even waiting in a loop adds a few cycles of overhead. Admittedly these situations will be rare, and these things can be compensated for, but sometimes a simple delay routine is the best way to go.

Regards,
Steve A.

The Board helps those that help themselves.

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

Steve,

I was using the CV approach for my example. i.e.
macro: delay_us(CONSTANT) covers 1us to 16000us
function: delay_ms(int) covers 1ms to 65000ms

From memory the avr-gcc approach uses macros for both
_delay_us() and for _delay_ms()
If you use a variable expression, it forces floating point math.

Personally, I think that the CV approach is wiser but avr-gcc is stuck historically with an unfortunate design.

I don't want to rush into any flame war. Suffice it to say that avr-gcc is more clever in other ways.

Anyway, the 'solution' that I posted should keep the OP happy for his variable delay. Mind you, the OP posted exactly the same question some 3 years ago with exactly the same answers.

David.

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

david.prentice wrote:
Personally, I think that the CV approach is wiser but avr-gcc is stuck historically with an unfortunate design.
Using delay stuff is a design bug in the applications.

Delsay can be useful for short delays to wait for slow hardware, but then you know the number of ticks.

For a program that's more complex than cplletely trivial, many programmers use schemes that remind of a stupid cook. Let's go to a restorant and order chicken, potatoes, vegetables and a beer.

Stupid cook

  1. Start chicken
  2. Wait until chicken is ready
  3. Deliver chicken
  4. Start potatoes
  5. Wait until potatoes are ready
  6. Deliver potatoes
  7. Start vegetables
  8. Wait until vegetables are ready
  9. Deliver vegetables
  10. Start pils
  11. Wait until pils is ready
  12. Deliver pils
  13. Goto 1.

Smart cook

  1. If there is a new order (chicken, potatoes, vegetables or pils), then start preparing it.
  2. If some order (chicken, potatoes, vegetables or pils) is ready, deliver it.
  3. Goto 1.

If programmers were cooks, most of them were fired immediately...

avrfreaks does not support Opera. Profile inactive.

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

Any restaurant that does not deliver the beer first is not worth going to!

Cycle-wasting in an embedded project is generally unwise. All the same, punters like to use it. So libc.a or avr-gcc should implement it properly.

David.

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

I'm the stupid cook but then, as my wife will tell you, I'm only a man and not capable of multi-tasking ;-)

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

Using a properly supported design flaw is still using a design flaw.

avr-gcc currently stops with an error for non-const delays. It straight forward to implement variable number of ticks. But the problem is not looping ticks, it is computing ticks.

avrfreaks does not support Opera. Profile inactive.

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

Funny
Passionate
International

The good way of the internet. Thank you.
Good bye.

computer : GNU Linux / e6750
ship : Attiny 2313 / ATmega8
compiler : avr-gcc 1:4.3.2-1

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

Quote:

If precise delays are needed,...

In one of the past "discussions" didn't one of the GCC gurus come up with an alternate delay setup that was cycle-accurate (or nearly so)?

Quote:

Using delay stuff is a design bug in the applications.

LOL. I tend to agree, with a caveat of "important" or "integral" in there. I'll confess--nearly all of my many CV production apps include delay.h and use delay_ms() -- for an arbitrarily-long startup delay to let peripheral devices settle, especially after a powerup. I usually use about 100ms. Longer if the app can tolerate it. Quite a bit shorter for some remote modules.

And it isn't unusual for me to throw in a delay_us() sometimes, when needed for (as you mentioned) for slow hardware. If the wasted time is at all important, then I'll re-order the code to do something useful instead of sitting and waiting.

Quote:

Funny
Passionate
International

The thread title becomes even more pertinent-- delay_ms() WITH ARGUMENT. ;)

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

because of the two "g"??

computer : GNU Linux / e6750
ship : Attiny 2313 / ATmega8
compiler : avr-gcc 1:4.3.2-1

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

theusch wrote:
Quote:
If precise delays are needed,...
In one of the past "discussions" didn't one of the GCC gurus come up with an alternate delay setup that was cycle-accurate (or nearly so)?
A respective patch has been rejected.

Quote:
Quote:
Using delay stuff is a design bug in the applications.
LOL. I tend to agree, with a caveat of "important" or "integral" in there. I'll confess--nearly all of my many CV production apps include delay.h and use delay_ms()
I confess too, I use _delay_loop_1 in one application:

It's a display made of LEDs. The LEDs are wired in a matrix and controlled by software-PWM to control their brightness.

During the display gaps (PWM off phase) some of the LEDs are wired to work as photo diodes. This works depending on LED substrate. This measures environment brightness and adjusts the brightness of the display to the brightness of the environment (night, bright day with sunshine outside, ...)

That way the display has comfortable brightness independent of lighting, and the sensors to measure the brightness are "invisible" because there are no extra sensors 8)

The delay loop waits 10 Ticks until the LEDs settled their change, i.e. they behave like condensator when used at that stage of the measurement.

avrfreaks does not support Opera. Profile inactive.