summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-09-05 14:58:36 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-09-05 14:58:36 +0000
commitca6a50135e04d530ddf75b38f7fff1081ced6de4 (patch)
tree3e59d2e6776862931fbc1a6d0b9418613bac8e40
parent0233d0342900484f1f70d5f95473d9ed262b843f (diff)
downloadpx4-nuttx-ca6a50135e04d530ddf75b38f7fff1081ced6de4.tar.gz
px4-nuttx-ca6a50135e04d530ddf75b38f7fff1081ced6de4.tar.bz2
px4-nuttx-ca6a50135e04d530ddf75b38f7fff1081ced6de4.zip
PM.. Allow negative coeffients; support revert to normal state
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3939 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/drivers/pm/pm_activity.c8
-rw-r--r--nuttx/drivers/pm/pm_checkstate.c2
-rw-r--r--nuttx/drivers/pm/pm_internal.h6
-rw-r--r--nuttx/drivers/pm/pm_update.c79
-rw-r--r--nuttx/include/nuttx/pm.h33
5 files changed, 100 insertions, 28 deletions
diff --git a/nuttx/drivers/pm/pm_activity.c b/nuttx/drivers/pm/pm_activity.c
index a0bae76fa..dd908b949 100644
--- a/nuttx/drivers/pm/pm_activity.c
+++ b/nuttx/drivers/pm/pm_activity.c
@@ -120,14 +120,14 @@ void pm_activity(int priority)
/* Make sure that we do not overflow the underlying uint16_t representation */
- if (accum > UINT16_MAX)
+ if (accum > INT16_MAX)
{
- accum = UINT16_MAX;
+ accum = INT16_MAX;
}
/* Save the updated count */
- g_pmglobals.accum = accum;
+ g_pmglobals.accum = (int16_t)accum;
/* Check the elapsed time. In periods of low activity, time slicing is
* controlled by IDLE loop polling; in periods of higher activity, time
@@ -140,7 +140,7 @@ void pm_activity(int priority)
now = clock_systimer();
if (now - g_pmglobals.stime >= TIME_SLICE_TICKS)
{
- uint16_t tmp;
+ int16_t tmp;
/* Sample the count, reset the time and count, and assess the PM
* state. This is an atomic operation because interrupts are
diff --git a/nuttx/drivers/pm/pm_checkstate.c b/nuttx/drivers/pm/pm_checkstate.c
index 3a7f13d47..93f19a502 100644
--- a/nuttx/drivers/pm/pm_checkstate.c
+++ b/nuttx/drivers/pm/pm_checkstate.c
@@ -129,7 +129,7 @@ enum pm_state_e pm_checkstate(void)
now = clock_systimer();
if (now - g_pmglobals.stime >= TIME_SLICE_TICKS)
{
- uint16_t accum;
+ int16_t accum;
/* Sample the count, reset the time and count, and assess the PM
* state. This is an atomic operation because interrupts are
diff --git a/nuttx/drivers/pm/pm_internal.h b/nuttx/drivers/pm/pm_internal.h
index e0cb3fb1a..b3e610ba0 100644
--- a/nuttx/drivers/pm/pm_internal.h
+++ b/nuttx/drivers/pm/pm_internal.h
@@ -118,7 +118,7 @@ struct pm_global_s
* thrcnt - The number of below threshold counts seen.
*/
- uint16_t accum;
+ int16_t accum;
uint16_t thrcnt;
/* This is the averaging "memory." The averaging algorithm is simply:
@@ -131,7 +131,7 @@ struct pm_global_s
*/
#if CONFIG_PM_MEMORY > 1
- uint16_t memory[CONFIG_PM_MEMORY-1];
+ int16_t memory[CONFIG_PM_MEMORY-1];
#endif
/* stime - The time (in ticks) at the start of the current time slice */
@@ -199,7 +199,7 @@ EXTERN struct pm_global_s g_pmglobals;
*
****************************************************************************/
-EXTERN void pm_update(uint16_t accum);
+EXTERN void pm_update(int16_t accum);
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/drivers/pm/pm_update.c b/nuttx/drivers/pm/pm_update.c
index d3ff75090..336bee5ef 100644
--- a/nuttx/drivers/pm/pm_update.c
+++ b/nuttx/drivers/pm/pm_update.c
@@ -68,7 +68,7 @@
*/
#if CONFIG_PM_MEMORY > 1
-static const uint16_t g_pmcoeffs[CONFIG_PM_MEMORY-1] =
+static const int16_t g_pmcoeffs[CONFIG_PM_MEMORY-1] =
{
CONFIG_PM_COEF1
#if CONFIG_PM_MEMORY > 2
@@ -89,13 +89,32 @@ static const uint16_t g_pmcoeffs[CONFIG_PM_MEMORY-1] =
};
#endif
-static const uint16_t g_pmthresh[3] =
+/* Threshold activity values to enter into the next lower power consumption
+ * state. Indexing is next state 0:IDLE, 1:STANDBY, 2:SLEEP.
+ */
+
+static const int16_t g_pmenterthresh[3] =
{
CONFIG_PM_IDLEENTER_THRESH,
CONFIG_PM_STANDBYENTER_THRESH,
CONFIG_PM_SLEEPENTER_THRESH
};
+/* Threshold activity values to leave the current low power consdumption
+ * state. Indexing is current state 0:IDLE, 1: STANDBY, 2: SLEEP.
+ */
+
+static const int16_t g_pmexitthresh[3] =
+{
+ CONFIG_PM_IDLEEXIT_THRESH,
+ CONFIG_PM_STANDBYEXIT_THRESH,
+ CONFIG_PM_SLEEPEXIT_THRESH
+};
+
+/* Threshold time slice count to enter the next low power consdumption
+ * state. Indexing is next state 0:IDLE, 1: STANDBY, 2: SLEEP.
+ */
+
static const uint16_t g_pmcount[3] =
{
CONFIG_PM_IDLEENTER_COUNT,
@@ -132,11 +151,12 @@ static const uint16_t g_pmcount[3] =
void pm_worker(FAR void *arg)
{
- uint16_t accum = (uint16_t)((uintptr_t)arg);
- uint32_t Y;
+ int16_t accum = (int16_t)((intptr_t)arg);
+ int32_t Y;
+ int index;
#if CONFIG_PM_MEMORY > 1
- uint32_t denom;
+ int32_t denom;
int i, j;
/* We won't bother to do anything until we have accumulated
@@ -197,18 +217,43 @@ void pm_worker(FAR void *arg)
#endif
+ /* First check if increased activity should cause us to return to the
+ * normal operating state. This would be unlikely for the lowest power
+ * consumption states because the CPU is probably asleep. However this
+ * probably does apply for the IDLE state.
+ */
+
+ if (g_pmglobals.state > PM_NORMAL)
+ {
+ /* Get the table index for the current state (which will be the
+ * current state minus one)
+ */
+
+ index = g_pmglobals.state - 1;
+
+ /* Has the threshold to return to normal power consumption state been
+ * exceeded?
+ */
+
+ if (Y > g_pmexitthresh[index])
+ {
+ /* Yes... reset the count and recommend the normal state. */
+
+ g_pmglobals.thrcnt = 0;
+ g_pmglobals.recommended = PM_NORMAL;
+ return;
+ }
+ }
+
/* Now, compare this new activity level to the thresholds and counts for
- * the next state. Determine if it is appropriate to switch to a new,
- * lower power consumption state.
- *
- * If we are already in the SLEEP state, then there is nothing more to be
- * done (in fact, I would be surprised to be executing!).
+ * the next lower power consumption state. If we are already in the SLEEP
+ * state, then there is nothing more to be done (in fact, I would be
+ * surprised to be executing!).
*/
if (g_pmglobals.state < PM_SLEEP)
{
unsigned int nextstate;
- int index;
/* Get the next state and the table index for the next state (which will
* be the current state)
@@ -217,14 +262,16 @@ void pm_worker(FAR void *arg)
index = g_pmglobals.state;
nextstate = g_pmglobals.state + 1;
- /* Has the threshold for the next state been exceeded? */
+ /* Has the threshold to enter the next lower power consumption state
+ * been exceeded?
+ */
- if (Y > g_pmthresh[index])
+ if (Y > g_pmenterthresh[index])
{
/* No... reset the count and recommend the current state */
g_pmglobals.thrcnt = 0;
- g_pmglobals.recommended = g_pmglobals.state;
+ g_pmglobals.recommended = g_pmglobals.state;
}
/* Yes.. have we already recommended this state? If so, do nothing */
@@ -276,12 +323,12 @@ void pm_worker(FAR void *arg)
*
****************************************************************************/
-void pm_update(uint16_t accum)
+void pm_update(int16_t accum)
{
/* The work will be performed on the worker thread */
DEBUGASSERT(g_pmglobals.work.worker == NULL);
- (void)work_queue(&g_pmglobals.work, pm_worker, (FAR void*)((uintptr_t)accum), 0);
+ (void)work_queue(&g_pmglobals.work, pm_worker, (FAR void*)((intptr_t)accum), 0);
}
#endif /* CONFIG_PM */ \ No newline at end of file
diff --git a/nuttx/include/nuttx/pm.h b/nuttx/include/nuttx/pm.h
index f5375fc6a..898a82b88 100644
--- a/nuttx/include/nuttx/pm.h
+++ b/nuttx/include/nuttx/pm.h
@@ -93,7 +93,8 @@
/* The averaging algorithm is simply: Y = (An*X + SUM(Ai*Yi))/SUM(Aj), where
* i = 1..n-1 and j= 1..n, n is the length of the "memory", Ai is the
- * weight applied to each value, and X is the current activity.
+ * weight applied to each value, and X is the current activity. These weights
+ * may be negative and a limited to the range of int16_t.
*
* CONFIG_PM_MEMORY provides the memory for the algorithm. Default: 2
* CONFIG_PM_COEFn provides weight for each sample. Default: 1
@@ -149,7 +150,15 @@
*/
#ifndef CONFIG_PM_IDLEENTER_THRESH
-# define CONFIG_PM_IDLEENTER_THRESH 1 /* Essentially no activity */
+# define CONFIG_PM_IDLEENTER_THRESH 1 /* <=1: Essentially no activity */
+#endif
+
+#ifndef CONFIG_PM_IDLEEXIT_THRESH
+# define CONFIG_PM_IDLEEXIT_THRESH 2 /* >=2: Active */
+#endif
+
+#if CONFIG_PM_IDLEENTER_THRESH >= CONFIG_PM_IDLEEXIT_THRESH
+# error "Must have CONFIG_PM_IDLEENTER_THRESH < CONFIG_PM_IDLEEXIT_THRESH
#endif
#ifndef CONFIG_PM_IDLEENTER_COUNT
@@ -159,7 +168,15 @@
#endif
#ifndef CONFIG_PM_STANDBYENTER_THRESH
-# define CONFIG_PM_STANDBYENTER_THRESH 1 /* Essentially no activity */
+# define CONFIG_PM_STANDBYENTER_THRESH 1 /* <=1: Essentially no activity */
+#endif
+
+#ifndef CONFIG_PM_STANDBYEXIT_THRESH
+# define CONFIG_PM_STANDBYEXIT_THRESH 2 /* >=2: Active */
+#endif
+
+#if CONFIG_PM_STANDBYENTER_THRESH >= CONFIG_PM_STANDBYEXIT_THRESH
+# error "Must have CONFIG_PM_STANDBYENTER_THRESH < CONFIG_PM_STANDBYEXIT_THRESH
#endif
#ifndef CONFIG_PM_STANDBYENTER_COUNT
@@ -169,7 +186,15 @@
#endif
#ifndef CONFIG_PM_SLEEPENTER_THRESH
-# define CONFIG_PM_SLEEPENTER_THRESH 1 /* Essentially no activity */
+# define CONFIG_PM_SLEEPENTER_THRESH 1 /* <=1: Essentially no activity */
+#endif
+
+#ifndef CONFIG_PM_SLEEPEXIT_THRESH
+# define CONFIG_PM_SLEEPEXIT_THRESH 2 /* >=2: Active */
+#endif
+
+#if CONFIG_PM_SLEEPENTER_THRESH >= CONFIG_PM_SLEEPEXIT_THRESH
+# error "Must have CONFIG_PM_SLEEPENTER_THRESH < CONFIG_PM_SLEEPEXIT_THRESH
#endif
#ifndef CONFIG_PM_SLEEPENTER_COUNT