From 3110ae0831fa4ba081c9206663390e21c7a4f78a Mon Sep 17 00:00:00 2001 From: batt Date: Tue, 23 Oct 2007 15:57:59 +0000 Subject: [PATCH 1/1] Add DIV_ROUND macro. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@932 38d2e660-2303-0410-9eaa-f027e97ec537 --- cfg/macros.h | 94 +++--------------------------------- cpu/arm/drv/kdebug_at91.c | 4 +- cpu/avr/drv/kdebug_avr.c | 4 +- cpu/avr/drv/ser_avr.c | 5 +- cpu/avr/drv/ser_simple_avr.c | 2 +- cpu/avr/drv/timer_avr.h | 9 ++-- drv/phase.c | 2 +- drv/timer.h | 12 +++-- 8 files changed, 29 insertions(+), 103 deletions(-) diff --git a/cfg/macros.h b/cfg/macros.h index 5e9e25ed..b3be457f 100644 --- a/cfg/macros.h +++ b/cfg/macros.h @@ -36,91 +36,8 @@ * \author Bernardo Innocenti * \author Giovanni Bajo */ - -/*#* - *#* $Log$ - *#* Revision 1.11 2007/02/06 15:22:12 asterix - *#* Add ROTL and ROTR macros for bit rotating. - *#* - *#* Revision 1.10 2006/09/13 18:31:37 bernie - *#* BV8(), BV16(), BV32(): New macros for CPUs with small word size; SWAP_T(): New macro to support old compilers. - *#* - *#* Revision 1.9 2006/07/19 12:56:25 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.8 2006/03/13 02:06:55 bernie - *#* ROUND_UP2: Rename from ROUND2. - *#* - *#* Revision 1.7 2006/02/20 14:34:58 bernie - *#* Use portable type checking. - *#* - *#* Revision 1.6 2006/02/10 12:36:57 bernie - *#* Pacify IAR warnings for side-effects. - *#* - *#* Revision 1.5 2005/11/04 16:20:01 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.4 2005/07/03 15:19:09 bernie - *#* Doxygen fix. - *#* - *#* Revision 1.3 2005/06/27 21:23:32 bernie - *#* ROUND_DOWN, ROUND_UP, ROUND_NEAREST: New macros. - *#* - *#* Revision 1.2 2005/04/11 19:10:27 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.1 2005/04/11 19:04:13 bernie - *#* Move top-level headers to cfg/ subdir. - *#* - *#* Revision 1.10 2005/01/22 04:19:50 bernie - *#* Use non-uglified typeof(). - *#* - *#* Revision 1.9 2004/12/08 08:51:34 bernie - *#* Add type-generic macros for C++. - *#* - *#* Revision 1.8 2004/10/19 07:14:20 bernie - *#* Add macros to test for specific compiler features. - *#* - *#* Revision 1.7 2004/09/20 03:30:45 bernie - *#* C++ also has variadic macros. - *#* - *#* Revision 1.6 2004/09/14 21:02:04 bernie - *#* SWAP(), MINMAX(): New macros. - *#* - *#* Revision 1.5 2004/08/29 21:57:58 bernie - *#* Move back STATIC_ASSERT() to compiler.h as it's needed in cpu.h; - *#* iptr_t, const_iptr_t: Replace IPTR macro with a real typedef. - *#* - *#* Revision 1.3 2004/08/24 14:13:48 bernie - *#* Restore a few macros that were lost in the way. - *#* - *#* Revision 1.2 2004/08/24 13:32:14 bernie - *#* PP_CAT(), PP_STRINGIZE(): Move back to compiler.h to break circular dependency between cpu.h/compiler.h/macros.h; - *#* offsetof(), countof(): Move back to compiler.h to avoid including macros.h almost everywhere; - *#* Trim CVS log; - *#* Rename header guards; - *#* Don't include arch_config.h in compiler.h as it's not needed there. - *#* - *#* Revision 1.1 2004/08/14 19:37:57 rasky - *#* Merge da SC: macros.h, pool.h, BIT_CHANGE, nome dei processi, etc. - *#* - *#* Revision 1.4 2004/08/14 18:36:50 rasky - *#* Doxygen fix e un livello di parentesi aggiuntivi per la macro - *#* - *#* Revision 1.3 2004/08/12 20:01:32 rasky - *#* Aggiunte macro BIT_CHANGE e BIT_CHANGE_BV - *#* - *#* Revision 1.2 2004/08/10 21:36:14 rasky - *#* Aggiunto include macros.h dove serve - *#* Aggiunta dipendenza da compiler.h in macros.h - *#* - *#* Revision 1.1 2004/08/10 21:30:00 rasky - *#* Estratte le funzioni macro in macros.h - *#* - *#*/ - -#ifndef MACROS_H -#define MACROS_H +#ifndef CFG_MACROS_H +#define CFG_MACROS_H #include @@ -219,7 +136,12 @@ /** Same as BV() but with 8 bit result */ #define BV8(x) ((uint8_t)1<<(x)) - +/** + * Perform an integer division rounding the result to the nearest int value. + * \note \a divisor should preferibly be a costant, otherwise this macro generates + * 2 division. Also divisor is evaluated twice. + */ +#define DIV_ROUND(dividend, divisor) (((dividend) + (divisor) / 2) / (divisor)) /** Round up \a x to an even multiple of the 2's power \a pad. */ #define ROUND_UP2(x, pad) (((x) + ((pad) - 1)) & ~((pad) - 1)) diff --git a/cpu/arm/drv/kdebug_at91.c b/cpu/arm/drv/kdebug_at91.c index 7de1c6d9..a5ec8343 100644 --- a/cpu/arm/drv/kdebug_at91.c +++ b/cpu/arm/drv/kdebug_at91.c @@ -37,7 +37,7 @@ */ #include "kdebug_at91.h" -#include /* for BV() */ +#include /* for BV(), DIV_ROUND */ #include #include /* for CLOCK_FREQ */ #include /* Required for bus macros overrides */ @@ -71,7 +71,7 @@ INLINE void kdbg_hw_init(void) /* Reset DBGU */ DBGU_CR = BV(US_RSTRX) | BV(US_RSTTX) | BV(US_RXDIS) | BV(US_TXDIS); /* Set baudrate */ - DBGU_BRGR = (CLOCK_FREQ + (16 * CONFIG_KDEBUG_BAUDRATE) / 2) / (16 * CONFIG_KDEBUG_BAUDRATE); + DBGU_BRGR = DIV_ROUND(CLOCK_FREQ, 16 * CONFIG_KDEBUG_BAUDRATE); /* Set DBGU mode to 8 data bits, no parity and 1 stop bit. */ DBGU_MR = US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1; /* Enable DBGU transmitter. */ diff --git a/cpu/avr/drv/kdebug_avr.c b/cpu/avr/drv/kdebug_avr.c index d3a77615..35d0645d 100644 --- a/cpu/avr/drv/kdebug_avr.c +++ b/cpu/avr/drv/kdebug_avr.c @@ -41,7 +41,7 @@ #include #include -#include /* for BV() */ +#include /* for BV(), DIV_ROUND */ #include #include /* for CLOCK_FREQ */ #include /* Required for bus macros overrides */ @@ -223,7 +223,7 @@ INLINE void kdbg_hw_init(void) SER_BITBANG_INIT; #else /* CONFIG_KDEBUG_PORT != 666 */ /* Compute the baud rate */ - uint16_t period = (((CLOCK_FREQ / 16UL) + (CONFIG_KDEBUG_BAUDRATE / 2)) / CONFIG_KDEBUG_BAUDRATE) - 1; + uint16_t period = DIV_ROUND(CLOCK_FREQ / 16UL, CONFIG_KDEBUG_BAUDRATE) - 1; #if (CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128) #if CONFIG_KDEBUG_PORT == 0 diff --git a/cpu/avr/drv/ser_avr.c b/cpu/avr/drv/ser_avr.c index 495c52ba..d690a65f 100644 --- a/cpu/avr/drv/ser_avr.c +++ b/cpu/avr/drv/ser_avr.c @@ -168,6 +168,7 @@ #include /* CLOCK_FREQ */ #include +#include /* DIV_ROUND */ #include #include #include @@ -509,7 +510,7 @@ static void uart0_enabletxirq(struct SerialHardware *_hw) static void uart0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate) { /* Compute baud-rate period */ - uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1; + uint16_t period = DIV_ROUND(CLOCK_FREQ / 16UL, rate) - 1; #if !CPU_AVR_ATMEGA103 UBRR0H = (period) >> 8; @@ -562,7 +563,7 @@ static void uart1_enabletxirq(struct SerialHardware *_hw) static void uart1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate) { /* Compute baud-rate period */ - uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1; + uint16_t period = DIV_ROUND(CLOCK_FREQ / 16UL, rate) - 1; UBRR1H = (period) >> 8; UBRR1L = (period); diff --git a/cpu/avr/drv/ser_simple_avr.c b/cpu/avr/drv/ser_simple_avr.c index 7805892a..d71ce585 100644 --- a/cpu/avr/drv/ser_simple_avr.c +++ b/cpu/avr/drv/ser_simple_avr.c @@ -136,7 +136,7 @@ void _ser_settimeouts(void) void _ser_setbaudrate(unsigned long rate) { /* Compute baud-rate period */ - uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1; + uint16_t period = DIV_ROUND(CLOCK_FREQ / 16UL, rate) - 1; UBRR0H = (period) >> 8; UBRR0L = (period); diff --git a/cpu/avr/drv/timer_avr.h b/cpu/avr/drv/timer_avr.h index 5d0eba36..74414263 100644 --- a/cpu/avr/drv/timer_avr.h +++ b/cpu/avr/drv/timer_avr.h @@ -88,6 +88,7 @@ #include /* CONFIG_TIMER */ #include /* uint8_t */ +#include /* DIV_ROUND */ #include /* CLOCK_FREQ */ /** @@ -127,7 +128,7 @@ /** This value is the maximum in overflow based timers. */ #define TIMER_HW_CNT (1 << TIMER_HW_BITS) #define DEFINE_TIMER_ISR SIGNAL(SIG_OVERFLOW1) - #define TIMER_TICKS_PER_SEC ((TIMER_HW_HPTICKS_PER_SEC + TIMER_HW_CNT / 2) / TIMER_HW_CNT) + #define TIMER_TICKS_PER_SEC DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, TIMER_HW_CNT) /// Type of time expressed in ticks of the hardware high precision timer typedef uint16_t hptime_t; @@ -156,7 +157,7 @@ /** This value is the maximum in overflow based timers. */ #define TIMER_HW_CNT (1 << TIMER_HW_BITS) #define DEFINE_TIMER_ISR SIGNAL(SIG_OVERFLOW3) - #define TIMER_TICKS_PER_SEC ((TIMER_HW_HPTICKS_PER_SEC + TIMER_HW_CNT / 2) / TIMER_HW_CNT) + #define TIMER_TICKS_PER_SEC DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, TIMER_HW_CNT) /// Type of time expressed in ticks of the hardware high precision timer typedef uint16_t hptime_t; @@ -167,13 +168,13 @@ /** Frequency of the hardware high precision timer. */ -#define TIMER_HW_HPTICKS_PER_SEC ((CLOCK_FREQ + TIMER_PRESCALER / 2) / TIMER_PRESCALER) +#define TIMER_HW_HPTICKS_PER_SEC DIV_ROUND(CLOCK_FREQ, TIMER_PRESCALER) /** * System timer: additional division after the prescaler * 12288000 / 64 / 192 (0..191) = 1 ms */ -#define OCR_DIVISOR (((CLOCK_FREQ + TIMER_PRESCALER / 2) / TIMER_PRESCALER + TIMER_TICKS_PER_SEC / 2) / TIMER_TICKS_PER_SEC - 1) +#define OCR_DIVISOR (DIV_ROUND(DIV_ROUND(CLOCK_FREQ, TIMER_PRESCALER), TIMER_TICKS_PER_SEC) - 1) /** Not needed, IRQ timer flag cleared automatically */ #define timer_hw_irq() do {} while (0) diff --git a/drv/phase.c b/drv/phase.c index 04c895d7..e30f4668 100644 --- a/drv/phase.c +++ b/drv/phase.c @@ -78,7 +78,7 @@ DEFINE_ZEROCROSS_ISR() if (triacs[dev].duty != TRIAC_MAX_DUTY) TRIAC_OFF(dev); /* Compute delay from duty */ - timer_setDelay(&triacs[dev].timer, ((period * (TRIAC_MAX_DUTY - triacs[dev].duty) + TRIAC_MAX_DUTY / 2) / TRIAC_MAX_DUTY)); + timer_setDelay(&triacs[dev].timer, DIV_ROUND(period * (TRIAC_MAX_DUTY - triacs[dev].duty), TRIAC_MAX_DUTY)); /* This check avoids inserting the same timer twice * in case of an intempestive zerocross or spike */ diff --git a/drv/timer.h b/drv/timer.h index bcf10200..cd7aa1b4 100644 --- a/drv/timer.h +++ b/drv/timer.h @@ -42,9 +42,11 @@ #define DRV_TIMER_H #include +#include #include #include + /* * Include platform-specific binding header if we're hosted. * Try the CPU specific one for bare-metal environments. @@ -113,7 +115,7 @@ INLINE ticks_t ms_to_ticks(mtime_t ms) return (ms * TIMER_TICKS_PER_SEC) / 1000; #else /* Fast timer: don't overflow ticks_t. */ - return ms * ((TIMER_TICKS_PER_SEC + 500) / 1000); + return ms * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000); #endif } @@ -125,7 +127,7 @@ INLINE ticks_t us_to_ticks(utime_t us) return ((us / 1000) * TIMER_TICKS_PER_SEC) / 1000; #else /* Fast timer: don't overflow ticks_t. */ - return (us * ((TIMER_TICKS_PER_SEC + 500) / 1000)) / 1000; + return (us * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000)) / 1000; #endif } @@ -157,7 +159,7 @@ INLINE utime_t ticks_to_us(ticks_t ticks) INLINE hptime_t us_to_hptime(utime_t us) { #if TIMER_HW_HPTICKS_PER_SEC > 10000000UL - return us * ((TIMER_HW_HPTICKS_PER_SEC + 500000UL) / 1000000UL); + return us * DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000000UL); #else return (us * ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL) + 500) / 1000UL; #endif @@ -167,9 +169,9 @@ INLINE hptime_t us_to_hptime(utime_t us) INLINE utime_t hptime_to_us(hptime_t hpticks) { #if TIMER_HW_HPTICKS_PER_SEC < 100000UL - return hpticks * ((1000000UL + TIMER_HW_HPTICKS_PER_SEC / 2) / TIMER_HW_HPTICKS_PER_SEC); + return hpticks * DIV_ROUND(1000000UL, TIMER_HW_HPTICKS_PER_SEC); #else - return (hpticks * 1000UL) / ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL); + return (hpticks * 1000UL) / DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000UL); #endif /* TIMER_HW_HPTICKS_PER_SEC < 100000UL */ } -- 2.25.1