avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-dev] [patch #6418] Yet another delay routines


From: Carlos Lamas
Subject: [avr-libc-dev] [patch #6418] Yet another delay routines
Date: Wed, 13 Feb 2008 22:26:52 +0000
User-agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6

URL:
  <http://savannah.nongnu.org/patch/?6418>

                 Summary: Yet another delay routines
                 Project: AVR C Runtime Library
            Submitted by: carloslamas
            Submitted on: Wednesday 02/13/2008 at 22:26
                Category: None
                Priority: 5 - Normal
                  Status: None
                 Privacy: Public
             Assigned to: None
        Originator Email: 
             Open/Closed: Open
         Discussion Lock: Any

    _______________________________________________________

Details:

This code is proposed to replace actual avr-libc delay routines. Current
delay routines in <util/basic_delay.h> and <util/delay.h> present several
problems:

1) They require the optimization enabled to avoid floating point libraries
code bloating the executable.

2) The arguments passed must be constant but the compiler does not warn the
user when a variable is passed. This can also bloat the code with floating
point libraries and delay's accuracy loss. 

3) There is a lot of asymmetry between the functions used for microseconds
and for milliseconds: the time is not continuous, the 1/10 millisecond
precision is arbitrary (F_CPU value is not considered) and inaccurate, and
delays are short for high frequency processors...


Solutions

Problem 1. Can be solved eliminating temporary intermediate variables and
letting the compiler to do all the arithmetics. If the variables are not
defined the intermediate integer and floating point constant values do not
need to be stored, even when optimization level is -O0. To accomplish this
it's mandatory a conversion from inline function (the argument is an automatic
storage class variable) to macro.

Problem 2. The proposed solution is to check the constant parameter passed
against an inline assembler constraint in an empty dummy asm() instruction.
This also requires to transform the inline function in a macro. Passing a
variable as the argument to the macro generates an error a bit obfuscated.

Problem 3. The compiler can choose the delay with the minimum penalty in
size. Frequency and time should be taken as a whole, i.e. the number of CPU
cycles that must elapse to obtain the delay. And big sized delay loops can
produce accurate delays by increasing the counter word size from 16 bit
maximum to 24 bit and 32 bit.


Attached files

The new files <util/delay_basic.h> and <util/delay.h> are downwards
compatible with currently existing routines.

Another two delay loop functions have been defined: _delay_loop3() and
_delay_loop4() to get 24 bit and 32 bit counter values. The code size of this
loops is somewhat big including compiler overhead but they allow really,
really long delays.

Additionaly, constant argument versions delay loop macros were defined to
reduce the code generated and minimize errors when optimization is disabled. 

The core of these header files are two delay macros named _delay_cycles() and
_delay_exact_cycles(). They do not depend on F_CPU and as such they are placed
in delay_basic.h. They wrap to the shortest loop  suitable to obtain a delay
in CPU cycles (_delay_cycles() accuracy is +/- 0.5 loop step size and
_delay_exact_cycles() is +/- 0.5 CPU cycles). Single instruction sequences
without loops are used for very short delays (less than 7 CPU cycles).
_delay_cycles_exact() inserts padding instructions after the loops at the
expense of increasing code size to obtain the best delay accuracy.

Padding instructions used in the code are NOP (1 word, 1 CPU cycle) and RJMP
(1 word, 2 CPU cycles). LPM (1 word, 3 cycles) was discarded due to lack of
documentation about the behaviour accessing inexistent Flash addresses and
other possible fuses and lock bits issues. Also, LPM is not available in all
the AVR devices.

The constraint 'd' was preferred to 'w' in 32 bit data sizes to facilitate to
the compiler the allocation of the loop variable, at the expense of increasing
the code in one instruction (sbiw could be used instead of subi + sbci).
Internal constant loop version macros for optimization enabled use a different
approach splitting the big data counters (24 bit and 32 bit) in two parts,
with 'w' constraint applied only to the less significant 16 bit of the data.
For the remaining data part (8 bit or 16 bit) is up to the compiler
(constraint 'r') to decide the registers to be used. Optimization disabled
counterparts avoid the compiler overhead previous to the loop (not fixed time)
moving the counter precharge to the first loop instructions and the compiler
overhead after the loop storing data in the temporary and zero registers
(complete for loops 1 and 2, partial for loop 3, nothing for loop 4)

The code philosophy remains the same: despite of the increased code
complexity in the header files the compiler performs all the arithmetics and
the resulting delay code remains short. The only incompatibility can arise
with the imposition of using constant values.


Interface summary <util/delay_basic.h>

static inline void _delay_loop_1(uint8_t __count);
static inline void _delay_loop_2(uint16_t __count);
static inline void _delay_loop_3(uint32_t __count);
static inline void _delay_loop_4(uint32_t __count);

#define _delay_cycles(__cycles)
#define _delay_exact_cycles(__cycles)

#define _delay_f_us(__freq, __us)
#define _delay_f_ms(__freq, __ms)
#define _delay_f_s(__freq, __s)

#define _delay_exact_f_us(__freq, __us)
#define _delay_exact_f_ms(__freq, __ms)
#define _delay_exact_f_s(__freq, __s)


Interface summary <util/delay.h>

#define _delay_us(__us)
#define _delay_ms(__ms)
#define _delay_s(__s)

#define _delay_exact_us(__us)
#define _delay_exact_ms(__ms)
#define _delay_exact_s(__s)


Note. Doxygen comments haven't been compiled/tested.




    _______________________________________________________

File Attachments:


-------------------------------------------------------
Date: Wednesday 02/13/2008 at 22:26  Name: delay.tgz  Size: 6kB   By:
carloslamas
new header files &lt;util/delay.h&gt; and &lt;util/delay_basic.h&gt;
<http://savannah.nongnu.org/patch/download.php?file_id=15033>

    _______________________________________________________

Reply to this item at:

  <http://savannah.nongnu.org/patch/?6418>

_______________________________________________
  Message sent via/by Savannah
  http://savannah.nongnu.org/





reply via email to

[Prev in Thread] Current Thread [Next in Thread]