delay.h?

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

When using '_delay_loop_x()' in 'delay.h' it seems that the actual
delay is not correct.
When looking at the code there is no init of the '__count' to any
register.
Maybe this dependant of optimization. I use -Os?

So I changed the code to:
...
asm volatile (
"L%=: dec %0" "\n\t"
"brne L%="
:
: "r" (__count)
);

Which at least seems to produce correct code.
Can someone (Joerg?) that does understand all the i/o operands of
the inline asm comment this.

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

Well, I can't seem to find a problem with the generated code. (Btw.,
it would surprise me if these 4-liners from one of the principal
authors of avr-libc still had a fatal bug in them. ;-)

For me, a call to

_delay_loop_2(23);

properly expands to:

    ldi r24,lo8(23)
    ldi r25,hi8(23)
/* #APP */
    1: sbiw r24,1
    brne 1b
/* #NOAPP */

which looks quite correct to me.

Btw., using unix-assembler style local labels (as Marek did) is much
preferrable to using the %= macro feature.

No, I don't pretend to understand all the inline asm constraints ;-),
I usually avoid inline asm wherever possible. Still, the inline asm
cookbook in the docs should explain the "r" and "0" constraints
Marek's macros are using.

Yes, of course, all this depends on optimization. If you compile with
-O0, the compiler ignores the request to inline the code, and puts it
into a separate function, which obviously will completely trash the
timing (even though the generated code is still basically OK).

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

Yes, it would surprise me too.

The fact was, however, that I noticed in runtime that the delay was
much longer than it should be.
So I checked the asm list and couldn't find the 2 'ldi' s that you show.

Will go digging deeper and try other -O.

About, the %=, for the local labels. I found that in the avr-libc docs.
So, maybe it's wise to change that to the prefered unix-asm style.

BTW. THX for your help.

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

Please make sure you're using the recent tools. I remember there has
once been a problem with the delay macros, but I'm not sure whether
it's been the compiler version or what else.

IIRC, the avr-libc docs mention the %= feature itself, but they also
mention the unix-assembler style local labels (at least in the
assembler chapter I wrote ;-). The latter is just much simpler, and
is guaranteed to never generate symbol table entries that could
confuse debuggers (while I've observed that behaviour for standard
labels starting with "L").

These unix-assembler labels have the advantage that they are
re-usable. The jump/call just looks for the target label with the
same number that is found closest to the origin in the indicated
direction (`b' - backwards, `f' - forwards).

So:

1: do something
   brne 1b
   rjmp 1f
   ...
1:

The "brne" will jump back to the first label "1", while the rjmp will
jump forth to the final label "1".

Presumably, Harald Kipp (who originally wrote the inline asm cookbook)
simply didn't know at all about this feature.

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

Thanks again Joerg,

Yes, that could be problem. I don't use the latest but the 20030421 release.
Dare not change right now as I'm in the ending phase of the project.
Will upgrade very soon hopefully.

I guess you also increased my knowledge about locals labels
by aprox 100%.

Harald did a good job anyhow as these parts of the docs are not the most
trivial to understand.

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

I didn't want to belittle Harald's work in any way. The inline asm
cookbook is really a great resource.

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

How can I write a delay that I can use as a header file and just call it when ever I nedd a delay. But I should be able to call it maybe delay(10) for 10mS etc.

admin's test signature
 

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

Most of the work is already done in . Left as an
exercise for the reader: some preprocessor magic to calculate the
required timing divisor out of your CPU frequency.