From 81ac20d5d87b2262381f15e0a2d1cdb46ea80791 Mon Sep 17 00:00:00 2001 From: bernie Date: Mon, 11 Aug 2008 11:32:19 +0000 Subject: [PATCH] cpu_relax(): New function. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@1624 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/power.h | 111 +++++++++++++++++++++++++++++++++++++++++ bertos/drv/dataflash.c | 10 +--- bertos/drv/flash25.c | 13 ++--- bertos/drv/ser.c | 28 +++-------- 4 files changed, 123 insertions(+), 39 deletions(-) create mode 100644 bertos/cpu/power.h diff --git a/bertos/cpu/power.h b/bertos/cpu/power.h new file mode 100644 index 00000000..04c06076 --- /dev/null +++ b/bertos/cpu/power.h @@ -0,0 +1,111 @@ +/** + * \file + * + * + * \brief CPU power management functions + * + * \author Bernie Innocenti + */ + +#ifndef CPU_POWER_H +#define CPU_POWER_H + +#include +#include + +#if CONFIG_KERNEL + #include +#endif + +#if CONFIG_WATCHDOG + #include +#endif + +/** + * Let the CPU rest in tight busy loops + * + * User code that sits in a busy loop should call cpu_relax() every + * once in a while to perform system-depndent idle processing. + * + * Depending on the system configuration, this might perform different + * actions: + * + * - yield the CPU to other processes + * - reset the watchdog timer to avoid it from triggering + * - scale the CPU speed down to save power (unimplemented) + * - let the event loop of the emulator process a few events + */ +INLINE void cpu_relax(void) +{ +#if CONFIG_KERNEL + proc_yield(); +#endif + +#if CONFIG_WATCHDOG + wdt_reset(); +#endif +} + +/** + * Stop the processor until the next interrupt occurs. + * + * Pausing the CPU effectively reduces power usage, and should be used + * whenever the program is idle waiting for the next event to occur. + * + * To avoid deadlocking, the caller should normally check for the + * desired condition with interrupts disabled, and enter this function + * while interrupts are still disabled: + * + * \code + * IRQ_DISABLE(); + * while (!event_occurred) + * cpu_pause(); + * IRQ_ENABLE(); + * \endcode + * + * \note Some implementations of cpu_pause() may return before any interrupt has occurred + * Caller code should be written taking this into account. + * + * \note This function is currently unimplemented + */ +INLINE void cpu_pause(void) +{ + //ASSERT_IRQ_DISABLED(); + //IRQ_ENABLE(); + cpu_relax(); + //IRQ_DISABLE(); +} + +/** + * Safely call cpu_pause() until the COND predicate becomes true. + */ +#define CPU_PAUSE_ON(COND) ATOMIC(while (!(COND)) { cpu_pause(); }) + +#endif /* CPU_POWER_H */ diff --git a/bertos/drv/dataflash.c b/bertos/drv/dataflash.c index ac1eeaf5..68047d5b 100644 --- a/bertos/drv/dataflash.c +++ b/bertos/drv/dataflash.c @@ -27,12 +27,10 @@ * the GNU General Public License. * * Copyright 2007 Develer S.r.l. (http://www.develer.com/) - * * --> * * \brief Function library for dataflash AT45DB family (implementation). * - * * \version $Id: dataflash.c 21658 2008-06-05 16:42:54Z asterix $ * \author Daniele Basile * \author Francesco Sacchi @@ -54,11 +52,7 @@ #include -#if CONFIG_KERNEL - #include -#else - #define proc_yield() do {} while(0) -#endif +#include /* cpu_relax() */ #include @@ -215,7 +209,7 @@ static uint8_t dataflash_cmd(DataFlash *fd, dataflash_page_t page_addr, dataflas * is high. */ while (!(dataflash_stat(fd) & BUSY_BIT)) - proc_yield(); + cpu_relax(); stat = dataflash_stat(fd); diff --git a/bertos/drv/flash25.c b/bertos/drv/flash25.c index 807ff211..793fab01 100644 --- a/bertos/drv/flash25.c +++ b/bertos/drv/flash25.c @@ -27,10 +27,9 @@ * the GNU General Public License. * * Copyright 2007 Develer S.r.l. (http://www.develer.com/) - * * --> * - * \brief Function library for serial Flash memory. + * \brief Function library for serial Flash memory. * * Module provide a kfile interface, that ensure an abstraction * from comunication channel and give a standard interface. @@ -55,11 +54,7 @@ #include -#if CONFIG_KERNEL - #include -#else - #define proc_yield() do {} while(0) -#endif +#include /* cpu_relax() */ #warning FIXME:This file was change, but is untest! @@ -81,8 +76,8 @@ static void flash25_waitReady(Flash25 *fd) if (!(stat & RDY_BIT)) break; - else - proc_yield(); + + cpu_relax(); } } diff --git a/bertos/drv/ser.c b/bertos/drv/ser.c index 5f2b6fcd..cbcc33a3 100644 --- a/bertos/drv/ser.c +++ b/bertos/drv/ser.c @@ -60,7 +60,9 @@ #include -#include /* memset */ +#include /* cpu_relax() */ + +#include /* memset() */ /* * Sanity check for config parameters required by this module. @@ -78,16 +80,6 @@ #error CONFIG_SER_DEFBAUDRATE missing in config.h #endif -#if CONFIG_KERNEL && CONFIG_KERN_SCHED - #include -#else - #define proc_yield() do {} while(0) -#endif - -#if CONFIG_SER_TXTIMEOUT != -1 || CONFIG_SER_RXTIMEOUT != -1 - #include -#endif - struct Serial *ser_handles[SER_CNT]; @@ -114,9 +106,7 @@ static int ser_putchar(int c, struct Serial *port) /* Wait while buffer is full... */ do { - /* Give up timeslice to other processes. */ - proc_yield(); - wdt_reset(); + cpu_relax(); #if CONFIG_SER_TXTIMEOUT != -1 if (timer_clock() - start_time >= port->txtimeout) @@ -162,9 +152,7 @@ static int ser_getchar(struct Serial *port) /* Wait while buffer is empty */ do { - /* Give up timeslice to other processes. */ - proc_yield(); - wdt_reset(); + cpu_relax(); #if CONFIG_SER_RXTIMEOUT != -1 if (timer_clock() - start_time >= port->rxtimeout) @@ -354,11 +342,7 @@ static int ser_flush(struct KFile *fd) */ while (!fifo_isempty(&fds->txfifo) || fds->hw->table->txSending(fds->hw)) - { - /* Give up timeslice to other processes. */ - proc_yield(); - wdt_reset(); - } + cpu_relax(); return 0; } -- 2.25.1