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

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

[avr-libc-dev] macros for delay.h


From: Tomas Vanek
Subject: [avr-libc-dev] macros for delay.h
Date: Sat, 15 Nov 2003 23:03:47 +0100
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.2a) Gecko/20020910

Hi all,

I think that the following macros would fit to delay.h.

I'd appreciate if you know better way to manage argument errors than
link with undefined functions.

All macros are tested. Doxygen comments are incomplete, there is no
defgroup avr_delay in the version I have.

I also recommend change name of _delay_loop_1 to little more
descriptive _delay_loop_3clk and _delay_loop_2 to _delay_loop_4clk.

Tom

=====================================================================

extern uint8_t _DELAY_ARGUMENT_IS_NOT_CONST_ERROR();
     /* intentionally undefined function */
extern uint8_t _DELAY_ARGUMENT_IS_NEGATIVE();
     /* intentionally undefined function */
extern uint8_t _DELAY_ARGUMENT_IS_OUT_OF_RANGE();
     /* intentionally undefined function */

#define _DELAY_NOPS(cyc) \
{ \
   if ((cyc) % 2) { \
     asm volatile("nop"); \
   } \
   if ((cyc) >= 2) { \
     asm volatile( \
       "rjmp 1f" "\n" \
       "1:"); \
   } \
   if ((cyc) >= 4) { \
     asm volatile( \
       "rjmp 1f" "\n" "1:"); \
   } \
}

/** \ingroup avr_delay
     \def _DELAY_CLKS(cyc)
     Delays program execution by cyc clock cycles.
     \note Parameter cyc should be in range from 0 to 0x40000.
     For short delays up to 50 clock cycles, execution of instructions
     emitted by the macro takes exactly cyc clock cycles.
     Longer delays are rounded to nearest multiple of 3 or 4 (above
     0x300 cycles). Delay accuracy is better than +-2%.

     Emitted delay code relies on inlining of _delay_loop procedures
     and enabled optimization. So the macro is defined only if both
     conditions are met. */
#if ! defined(__NO_INLINE__) && defined(__OPTIMIZE__)
#define _DELAY_CLKS(cyc) \
{ \
   if (! __builtin_constant_p((cyc))) {  \
     _DELAY_ARGUMENT_IS_NOT_CONST_ERROR(); \
   } else if ((cyc) < 0) { \
     _DELAY_ARGUMENT_IS_NEGATIVE(); \
   } else if ((cyc) < 6) { \
     _DELAY_NOPS(cyc); \
   } else if ((cyc) < 30) { \
     _DELAY_NOPS((cyc) % 3); \
      /* use nops to delay exact number of cycles */ \
     _delay_loop_1((uint8_t)((cyc) / 3)); \
   } else if ((cyc) <= 3 * 0x100) { \
     _delay_loop_1((uint8_t)(((cyc) + 1) / 3)); \
   } else if ((cyc) <= 4 * 0x10000LL + 3) { \
     _delay_loop_2((uint16_t)((cyc) / 4)); \
   } else { \
     _delay_loop_2(0); /* maximal delay 65 msec */ \
     _DELAY_ARGUMENT_IS_OUT_OF_RANGE(); \
   } \
}

/** \ingroup avr_delay
     \def _DELAY_USEC(usec)
     Delays program execution by usec microseconds.
     \note MCU clock frequency should be defined like in
     following example:
     \code
         #define F_OSC 4000000
     \endcode */

#define _DELAY_USEC(usec) _DELAY_CLKS(F_OSC * (usec) / 1000000LL)

/** \ingroup avr_delay
     \def _DELAY_MSEC(msec)
     Delays program execution by msec miliseconds.
     \note MCU clock frequency should be defined like in
     following example:
     \code
         #define F_OSC 4000000
     \endcode
     \note Maximum delay is 262144 clock cycles,
     it is 65msec at clock frequency 4MHz */

#define _DELAY_MSEC(msec) _DELAY_CLKS(F_OSC * (msec) / 1000LL)
#endif







reply via email to

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