diff options
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/drivers/pm/pm_activity.c | 8 | ||||
-rw-r--r-- | nuttx/drivers/pm/pm_checkstate.c | 2 | ||||
-rw-r--r-- | nuttx/drivers/pm/pm_internal.h | 6 | ||||
-rw-r--r-- | nuttx/drivers/pm/pm_update.c | 79 | ||||
-rw-r--r-- | nuttx/include/nuttx/pm.h | 33 |
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 |