mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
sys/pm_layered: use array representation, get rid of implicit IDLE mode
This commit is contained in:
parent
5f597b56e1
commit
79de7ea5e5
@ -16,9 +16,10 @@
|
||||
*
|
||||
* This simple power management interface is based on the following assumptions:
|
||||
*
|
||||
* - CPUs define up to 4 power modes (from zero, the lowest power mode, to
|
||||
* PM_NUM_MODES-1, the highest)
|
||||
* - there is an implicit extra idle mode (which has the number PM_NUM_MODES)
|
||||
* - CPUs define a number of power modes (from zero, the lowest power mode, to
|
||||
* PM_NUM_MODES, the highest)
|
||||
* - there is an implicit extra busy-wait mode (which has the number PM_NUM_MODES)
|
||||
* where the CPU is kept spinning if all modes are blocked.
|
||||
* - individual power modes can be blocked/unblocked, e.g., by peripherals
|
||||
* - if a mode is blocked, so are implicitly all lower modes
|
||||
* - the idle thread automatically selects and sets the lowest unblocked mode
|
||||
@ -52,8 +53,7 @@ extern "C" {
|
||||
/**
|
||||
* @brief Power Management mode blocker typedef
|
||||
*/
|
||||
typedef union {
|
||||
uint32_t val_u32; /**< power mode blockers u32 */
|
||||
typedef struct {
|
||||
uint8_t val_u8[PM_NUM_MODES]; /**< power mode blockers u8 */
|
||||
} pm_blocker_t;
|
||||
|
||||
|
@ -19,9 +19,9 @@
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "atomic_utils.h"
|
||||
#include "irq.h"
|
||||
#include "periph/pm.h"
|
||||
#include "pm_layered.h"
|
||||
@ -34,34 +34,44 @@
|
||||
#endif
|
||||
|
||||
#ifndef PM_BLOCKER_INITIAL
|
||||
#define PM_BLOCKER_INITIAL 0x01010101 /* block all by default */
|
||||
#if PM_NUM_MODES == 1
|
||||
#define PM_BLOCKER_INITIAL { 0 }
|
||||
#endif
|
||||
#if PM_NUM_MODES == 2
|
||||
#define PM_BLOCKER_INITIAL { 1, 0 }
|
||||
#endif
|
||||
#if PM_NUM_MODES == 3
|
||||
#define PM_BLOCKER_INITIAL { 1, 1, 0 }
|
||||
#endif
|
||||
#if PM_NUM_MODES == 4
|
||||
#define PM_BLOCKER_INITIAL { 1, 1, 1, 0 }
|
||||
#endif
|
||||
#if PM_NUM_MODES == 5
|
||||
#define PM_BLOCKER_INITIAL { 1, 1, 1, 1, 0 }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Global variable for keeping track of blocked modes
|
||||
*/
|
||||
static pm_blocker_t pm_blocker = { .val_u32 = PM_BLOCKER_INITIAL };
|
||||
static pm_blocker_t pm_blocker = { .val_u8 = PM_BLOCKER_INITIAL };
|
||||
|
||||
void pm_set_lowest(void)
|
||||
{
|
||||
pm_blocker_t blocker = { .val_u32 = atomic_load_u32(&pm_blocker.val_u32) };
|
||||
unsigned mode = PM_NUM_MODES;
|
||||
|
||||
/* set lowest mode if blocker is still the same */
|
||||
unsigned state = irq_disable();
|
||||
while (mode) {
|
||||
if (blocker.val_u8[mode-1]) {
|
||||
if (pm_blocker.val_u8[mode-1]) {
|
||||
break;
|
||||
}
|
||||
mode--;
|
||||
}
|
||||
|
||||
/* set lowest mode if blocker is still the same */
|
||||
unsigned state = irq_disable();
|
||||
if (blocker.val_u32 == pm_blocker.val_u32) {
|
||||
DEBUG("pm: setting mode %u\n", mode);
|
||||
if (mode != PM_NUM_MODES) {
|
||||
pm_set(mode);
|
||||
}
|
||||
else {
|
||||
DEBUG("pm: mode block changed\n");
|
||||
}
|
||||
irq_restore(state);
|
||||
}
|
||||
|
||||
@ -85,7 +95,12 @@ void pm_unblock(unsigned mode)
|
||||
|
||||
pm_blocker_t pm_get_blocker(void)
|
||||
{
|
||||
pm_blocker_t result = { .val_u32 = atomic_load_u32(&pm_blocker.val_u32) };
|
||||
pm_blocker_t result;
|
||||
|
||||
unsigned state = irq_disable();
|
||||
memcpy(&result, &pm_blocker, sizeof(result));
|
||||
irq_restore(state);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user