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
This commit is contained in:
patacongo 2011-09-05 14:58:36 +00:00
parent 3e6a20e729
commit a4a6c0f075
5 changed files with 100 additions and 28 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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 */

View File

@ -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