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:
parent
3e6a20e729
commit
a4a6c0f075
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user