1
0
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:
Benjamin Valentin 2022-04-02 19:19:40 +02:00
parent 5f597b56e1
commit 79de7ea5e5
2 changed files with 33 additions and 18 deletions

View File

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

View File

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