drivers/power/pm: Use the start time of state btime) to calculate thrcnt; remove the loop whose count may be very big after the long idle
This commit is contained in:
parent
f4a3541d26
commit
e1622f60a6
@ -68,7 +68,6 @@
|
||||
|
||||
#define TIME_SLICE_TICKS ((CONFIG_PM_SLICEMS * CLOCKS_PER_SEC) / 1000)
|
||||
|
||||
/* Function-like macros *****************************************************/
|
||||
/****************************************************************************
|
||||
* Name: pm_lock
|
||||
*
|
||||
@ -93,6 +92,7 @@
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This describes the activity and state for one domain */
|
||||
|
||||
struct pm_domain_s
|
||||
@ -112,13 +112,11 @@ struct pm_domain_s
|
||||
uint8_t mndx;
|
||||
uint8_t mcnt;
|
||||
|
||||
/* accum - The accumulated counts in this time interval
|
||||
* thrcnt - The number of below threshold counts seen.
|
||||
*/
|
||||
/* accum - The accumulated counts in this time interval */
|
||||
|
||||
int16_t accum;
|
||||
uint16_t thrcnt;
|
||||
|
||||
#if CONFIG_PM_MEMORY > 1
|
||||
/* This is the averaging "memory." 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
|
||||
@ -128,7 +126,6 @@ struct pm_domain_s
|
||||
* CONFIG_PM_COEFn provides weight for each sample. Default: 1
|
||||
*/
|
||||
|
||||
#if CONFIG_PM_MEMORY > 1
|
||||
int16_t memory[CONFIG_PM_MEMORY-1];
|
||||
#endif
|
||||
|
||||
@ -136,6 +133,10 @@ struct pm_domain_s
|
||||
|
||||
clock_t stime;
|
||||
|
||||
/* btime - The time (in ticks) at the start of the current state */
|
||||
|
||||
clock_t btime;
|
||||
|
||||
/* The power state lock count */
|
||||
|
||||
uint16_t stay[PM_COUNT];
|
||||
@ -199,7 +200,6 @@ EXTERN struct pm_global_s g_pmglobals;
|
||||
* domain - The domain associated with the accumulator.
|
||||
* accum - The value of the activity accumulator at the end of the time
|
||||
* slice.
|
||||
* elapsed - The elapsed time from last called pm_update, unit ms
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
@ -211,7 +211,7 @@ EXTERN struct pm_global_s g_pmglobals;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void pm_update(int domain, int16_t accum, clock_t elapsed);
|
||||
void pm_update(int domain, int16_t accum);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
|
@ -138,7 +138,7 @@ void pm_activity(int domain, int priority)
|
||||
pdom->stime = now;
|
||||
pdom->accum = 0;
|
||||
|
||||
(void)pm_update(domain, tmp, elapsed);
|
||||
(void)pm_update(domain, tmp);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* drivers/power/pm_changestate.c
|
||||
*
|
||||
* Copyright (C) 2011-2012, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2012, 2016, 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -41,6 +41,7 @@
|
||||
|
||||
#include <queue.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <nuttx/power/pm.h>
|
||||
#include <nuttx/irq.h>
|
||||
@ -49,6 +50,12 @@
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define PM_TIMER_GAP (TIME_SLICE_TICKS * 2)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -78,24 +85,28 @@ static void pm_timer_cb(int argc, wdparm_t arg1, ...)
|
||||
static void pm_timer(int domain)
|
||||
{
|
||||
FAR struct pm_domain_s *pdom = &g_pmglobals.domain[domain];
|
||||
uint32_t delay;
|
||||
static const int pmtick[3] =
|
||||
{
|
||||
TIME_SLICE_TICKS * CONFIG_PM_IDLEENTER_COUNT,
|
||||
TIME_SLICE_TICKS * CONFIG_PM_STANDBYENTER_COUNT,
|
||||
TIME_SLICE_TICKS * CONFIG_PM_SLEEPENTER_COUNT
|
||||
};
|
||||
|
||||
if (!pdom->wdog)
|
||||
{
|
||||
pdom->wdog = wd_create();
|
||||
}
|
||||
|
||||
if (pdom->state < PM_SLEEP)
|
||||
if (pdom->state < PM_SLEEP && !pdom->stay[pdom->state] &&
|
||||
pmtick[pdom->state])
|
||||
{
|
||||
const uint16_t g_pmcount[3] =
|
||||
{
|
||||
CONFIG_PM_IDLEENTER_COUNT,
|
||||
CONFIG_PM_STANDBYENTER_COUNT,
|
||||
CONFIG_PM_SLEEPENTER_COUNT
|
||||
};
|
||||
int delay = pmtick[pdom->state] + pdom->btime - clock_systimer();
|
||||
int left = wd_gettime(pdom->wdog);
|
||||
|
||||
delay = (g_pmcount[pdom->state] - pdom->thrcnt) * CONFIG_PM_SLICEMS;
|
||||
wd_start(pdom->wdog, MSEC2TICK(delay), pm_timer_cb, 0);
|
||||
if (!WDOG_ISACTIVE(pdom->wdog) || abs(delay - left) > PM_TIMER_GAP)
|
||||
{
|
||||
wd_start(pdom->wdog, delay, pm_timer_cb, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -126,7 +126,7 @@ enum pm_state_e pm_checkstate(int domain)
|
||||
pdom->stime = now;
|
||||
pdom->accum = 0;
|
||||
|
||||
(void)pm_update(domain, accum, elapsed);
|
||||
(void)pm_update(domain, accum);
|
||||
}
|
||||
|
||||
/* Consider the possible power state lock here */
|
||||
|
@ -98,6 +98,7 @@ void pm_initialize(void)
|
||||
{
|
||||
pdom = &g_pmglobals.domain[i];
|
||||
pdom->stime = clock_systimer();
|
||||
pdom->btime = clock_systimer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* drivers/power/pm_update.c
|
||||
*
|
||||
* Copyright (C) 2011-2012, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2012, 2016, 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -52,8 +52,9 @@
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* CONFIG_PM_MEMORY is the total number of time slices (including the current
|
||||
* time slice. The histor or previous values is then CONFIG_PM_MEMORY-1.
|
||||
* time slice). The history of previous values is then CONFIG_PM_MEMORY-1.
|
||||
*/
|
||||
|
||||
#if CONFIG_PM_MEMORY > 1
|
||||
@ -126,7 +127,6 @@ static const uint16_t g_pmcount[3] =
|
||||
* domain - The PM domain associated with the accumulator
|
||||
* accum - The value of the activity accumulator at the end of the time
|
||||
* slice.
|
||||
* elapsed - The elapsed time from last called pm_update, unit ms
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
@ -138,10 +138,9 @@ static const uint16_t g_pmcount[3] =
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void pm_update(int domain, int16_t accum_, clock_t elapsed)
|
||||
void pm_update(int domain, int16_t accum)
|
||||
{
|
||||
FAR struct pm_domain_s *pdom;
|
||||
int16_t accum = 0;
|
||||
int32_t Y;
|
||||
int index;
|
||||
#if CONFIG_PM_MEMORY > 1
|
||||
@ -155,13 +154,6 @@ void pm_update(int domain, int16_t accum_, clock_t elapsed)
|
||||
DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
|
||||
pdom = &g_pmglobals.domain[domain];
|
||||
|
||||
while (elapsed >= TIME_SLICE_TICKS)
|
||||
{
|
||||
if (elapsed - TIME_SLICE_TICKS < TIME_SLICE_TICKS)
|
||||
{
|
||||
accum = accum_;
|
||||
}
|
||||
|
||||
#if CONFIG_PM_MEMORY > 1
|
||||
/* We won't bother to do anything until we have accumulated
|
||||
* CONFIG_PM_MEMORY-1 samples.
|
||||
@ -171,7 +163,7 @@ void pm_update(int domain, int16_t accum_, clock_t elapsed)
|
||||
{
|
||||
index = pdom->mcnt++;
|
||||
pdom->memory[index] = accum;
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
/* The averaging algorithm is simply: Y = (An*X + SUM(Ai*Yi))/SUM(Aj), where
|
||||
@ -181,7 +173,7 @@ void pm_update(int domain, int16_t accum_, clock_t elapsed)
|
||||
* CONFIG_PM_MEMORY provides the memory for the algorithm. Default: 2
|
||||
* CONFIG_PM_COEFn provides weight for each sample. Default: 1
|
||||
*
|
||||
* First, calclate Y = An*X
|
||||
* First, calculate Y = An*X
|
||||
*/
|
||||
|
||||
Y = CONFIG_PM_COEFN * accum;
|
||||
@ -215,13 +207,11 @@ void pm_update(int domain, int16_t accum_, clock_t elapsed)
|
||||
{
|
||||
pdom->mndx = 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* No smoothing */
|
||||
|
||||
Y = accum;
|
||||
|
||||
#endif
|
||||
|
||||
/* First check if increased activity should cause us to return to the
|
||||
@ -246,7 +236,7 @@ void pm_update(int domain, int16_t accum_, clock_t elapsed)
|
||||
{
|
||||
/* Yes... reset the count and recommend the normal state. */
|
||||
|
||||
pdom->thrcnt = 0;
|
||||
pdom->btime = clock_systimer();
|
||||
pdom->recommended = PM_NORMAL;
|
||||
return;
|
||||
}
|
||||
@ -277,7 +267,7 @@ void pm_update(int domain, int16_t accum_, clock_t elapsed)
|
||||
{
|
||||
/* No... reset the count and recommend the current state */
|
||||
|
||||
pdom->thrcnt = 0;
|
||||
pdom->btime = clock_systimer();
|
||||
pdom->recommended = pdom->state;
|
||||
}
|
||||
|
||||
@ -285,24 +275,22 @@ void pm_update(int domain, int16_t accum_, clock_t elapsed)
|
||||
|
||||
else if (pdom->recommended < nextstate)
|
||||
{
|
||||
/* No.. increment the count. Has it passed the count required
|
||||
/* No.. calculate the count. Has it passed the count required
|
||||
* for a state transition?
|
||||
*/
|
||||
|
||||
if (++pdom->thrcnt >= g_pmcount[index])
|
||||
if (clock_systimer() - pdom->btime >=
|
||||
g_pmcount[index] * TIME_SLICE_TICKS)
|
||||
{
|
||||
/* Yes, recommend the new state and set up for the next
|
||||
* transition.
|
||||
*/
|
||||
|
||||
pdom->thrcnt = 0;
|
||||
pdom->btime = clock_systimer();
|
||||
pdom->recommended = nextstate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elapsed -= TIME_SLICE_TICKS;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
Loading…
Reference in New Issue
Block a user