cc2538: lpm: Add registration mechanism for peripherals

Some peripherals have their clocks automatically gated in PM1+ modes, so they
cannot operate. This new mechanism gives peripherals a way to prohibit PM1+
modes so that they can properly complete their current operations before
entering PM1+.

This mechanism is implemented with peripheral functions registered to the LPM
module. These functions return whether the associated peripheral permits or not
PM1+ modes. They are called by the LPM module each time PM1+ might be possible.
If any of the peripherals wants to block PM1+, then the system is only dropped
to PM0.

Partly from: George Oikonomou
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
This commit is contained in:
Benoît Thébaudeau 2013-11-15 16:21:34 +01:00
parent a6227e1e3e
commit d35732505b
3 changed files with 71 additions and 6 deletions

View file

@ -47,6 +47,7 @@
#include "contiki-conf.h"
#include "rtimer.h"
#include <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/**
@ -101,6 +102,7 @@ void lpm_init(void);
* This PM selection heuristic has the following primary criteria:
* - Is the RF off?
* - Is the USB PLL off?
* - Are all registered peripherals permitting PM1+?
* - Is the Sleep Timer scheduled to fire an interrupt?
*
* If the answer to any of those questions is no, we will drop to PM0 and
@ -173,6 +175,25 @@ void lpm_exit(void);
*/
void lpm_set_max_pm(uint8_t pm);
/*---------------------------------------------------------------------------*/
typedef bool (*lpm_periph_permit_pm1_func_t)(void);
/**
* \brief Register a peripheral function which will get called by the LPM
* module to get 'permission' to drop to PM1+
* \param permit_pm1_func Pointer to the function
*
* Some peripherals are sensitive to PM changes.
*
* When changing power modes, the LPM driver will call all FPs registered with
* this function. The peripheral's function will return true or false to permit
* / prohibit PM1+ respectively. If at least one peripheral returns false, the
* SoC will drop to PM0 Deep Sleep instead.
*
* Registering several times the same function makes the LPM module behave as if
* the function had been registered once.
*/
void lpm_register_peripheral(lpm_periph_permit_pm1_func_t permit_pm1_func);
/*---------------------------------------------------------------------------*/
/* Disable the entire module if required */
#if LPM_CONF_ENABLE==0
#define lpm_init()