Change the LPM locks API:

Instead of using a separate data structure to request that a PD remain powered during deep sleep,
we do the same within the main LPM data structure through an additional field.

This allows us to maintain only one linked list of LPM modules and overall improves code clarity
This commit is contained in:
George Oikonomou 2015-05-01 16:42:03 +01:00
parent b3ac3ac0c1
commit 421fbfae25
9 changed files with 38 additions and 96 deletions

View File

@ -1150,7 +1150,7 @@ request(void)
return LPM_MODE_MAX_SUPPORTED;
}
/*---------------------------------------------------------------------------*/
LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL);
LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE);
/*---------------------------------------------------------------------------*/
static int
init(void)

View File

@ -64,9 +64,6 @@ static unsigned long irq_energest = 0;
/*---------------------------------------------------------------------------*/
LIST(modules_list);
/*---------------------------------------------------------------------------*/
/* Control what power domains we are allow to run under what mode */
LIST(power_domain_locks_list);
/* PDs that may stay on in deep sleep */
#define LOCKABLE_DOMAINS ((uint32_t)(PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH))
/*---------------------------------------------------------------------------*/
@ -399,7 +396,6 @@ void
lpm_init()
{
list_init(modules_list);
list_init(power_domain_locks_list);
}
/*---------------------------------------------------------------------------*/
void

View File

@ -49,17 +49,22 @@
#include <stdint.h>
/*---------------------------------------------------------------------------*/
#define LPM_MODE_SLEEP PWRCTRL_ACTIVE
#define LPM_MODE_DEEP_SLEEP PWRCTRL_POWER_DOWN
#define LPM_MODE_SHUTDOWN PWRCTRL_SHUTDOWN
#define LPM_MODE_SLEEP 1
#define LPM_MODE_DEEP_SLEEP 2
#define LPM_MODE_SHUTDOWN 3
#define LPM_MODE_MAX_SUPPORTED LPM_MODE_DEEP_SLEEP
/*---------------------------------------------------------------------------*/
#define LPM_DOMAIN_NONE 0
#define LPM_DOMAIN_SERIAL PRCM_DOMAIN_SERIAL
#define LPM_DOMAIN_PERIPH PRCM_DOMAIN_PERIPH
/*---------------------------------------------------------------------------*/
typedef struct lpm_registered_module {
struct lpm_registered_module *next;
uint8_t (*request_max_pm)(void);
void (*shutdown)(uint8_t mode);
void (*wakeup)(void);
uint32_t domain_lock;
} lpm_registered_module_t;
/*---------------------------------------------------------------------------*/
/**
@ -78,46 +83,14 @@ typedef struct lpm_registered_module {
* woken up. This can be used to e.g. turn a peripheral back on. This
* function is in charge of turning power domains back on. This
* function will normally be called within an interrupt context.
* \param l Power domain locks, if any are required. The module can request
* that the SERIAL or PERIPH PD be kept powered up at the transition
* to deep sleep. This field can be a bitwise OR of LPM_DOMAIN_x, so
* if required multiple domains can be kept powered.
*/
#define LPM_MODULE(n, m, s, w) static lpm_registered_module_t n = \
{ NULL, m, s, w }
#define LPM_MODULE(n, m, s, w, l) static lpm_registered_module_t n = \
{ NULL, m, s, w, l }
/*---------------------------------------------------------------------------*/
/**
*
* \brief Data type used to control whether a PD will get shut down when the
* CM3 drops to deep sleep
*
* Modules using these facilities must allocate a variable of this type, but
* they must not try to manipulate it directly. Instead, the respective
* functions must be used
*
* \sa lpm_pd_lock_obtain(), lpm_pd_lock_release()
*/
typedef struct lpm_power_domain_lock {
struct lpm_power_domain_lock *next;
uint32_t domains;
} lpm_power_domain_lock_t;
/*---------------------------------------------------------------------------*/
/**
* \brief Prohibit a PD from turning off in standby mode
* \param lock A pointer to a lpm_power_domain_lock_t
* \param domains Bitwise OR from PRCM_DOMAIN_PERIPH, PRCM_DOMAIN_SERIAL
*
* The caller is responsible for allocating lpm_power_domain_lock_t
*
* Only the domains listed above can be locked / released, but a single lock
* can be used for multiple domains
*/
void lpm_pd_lock_obtain(lpm_power_domain_lock_t *lock, uint32_t domains);
/**
* \brief Permit a PD to turn off in standby mode
* \param pd A pointer to a previously used lock
*
* \sa lpm_pd_lock_obtain()
*/
void lpm_pd_lock_release(lpm_power_domain_lock_t *pd);
/**
* \brief Drop the cortex to sleep / deep sleep and shut down peripherals
*

View File

@ -58,6 +58,10 @@ slip_arch_writeb(unsigned char c)
void
slip_arch_init(unsigned long ubr)
{
/*
* Enable an input handler. In doing so, the driver will make sure that UART
* RX stays operational during deep sleep
*/
cc26xx_uart_set_input(slip_input_byte);
}
/*---------------------------------------------------------------------------*/

View File

@ -100,7 +100,6 @@
#include "button-sensor.h"
#include "batmon-sensor.h"
#include "board-peripherals.h"
#include "lpm.h"
#include "cc26xx-rf.h"
#include "ti-lib.h"
@ -368,26 +367,6 @@ init_sensor_readings(void)
#endif
}
/*---------------------------------------------------------------------------*/
static lpm_power_domain_lock_t lock;
/*---------------------------------------------------------------------------*/
/*
* In order to maintain UART input operation:
* - Keep the uart clocked in sleep and deep sleep
* - Keep the serial PD on in deep sleep
*/
static void
keep_uart_on(void)
{
/* Keep the serial PD on */
lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_SERIAL);
/* Keep the UART clock on during Sleep and Deep Sleep */
ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0);
ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(cc26xx_demo_process, ev, data)
{

View File

@ -59,10 +59,10 @@
#include "contiki-conf.h"
#include "sys/process.h"
#include "dev/serial-line.h"
#include "dev/cc26xx-uart.h"
#include "net/ip/uip.h"
#include "net/ip/uip-udp-packet.h"
#include "net/ip/uiplib.h"
#include "lpm.h"
#include "net-uart.h"
#include "httpd-simple.h"
@ -148,37 +148,16 @@ net_input(void)
return;
}
/*---------------------------------------------------------------------------*/
/*
* In order to maintain UART input operation:
* - Keep the uart clocked in sleep and deep sleep
* - Keep the serial PD on in deep sleep
*/
static lpm_power_domain_lock_t lock;
/*---------------------------------------------------------------------------*/
static void
release_uart(void)
{
/* Release serial PD lock */
lpm_pd_lock_release(&lock);
/* Let the UART turn off during Sleep and Deep Sleep */
ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_UART0);
ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_UART0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
cc26xx_uart_set_input(NULL);
}
/*---------------------------------------------------------------------------*/
static void
keep_uart_on(void)
{
/* Keep the serial PD on */
lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_SERIAL);
/* Keep the UART clock on during Sleep and Deep Sleep */
ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0);
ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
cc26xx_uart_set_input(serial_line_input_byte);
}
/*---------------------------------------------------------------------------*/
static int

View File

@ -88,7 +88,8 @@ shutdown_handler(uint8_t mode)
* wake up so we can turn power domains back on for I2C and SSI, and to make
* sure everything on the board is off before CM3 shutdown.
*/
LPM_MODULE(sensortag_module, NULL, shutdown_handler, lpm_wakeup_handler);
LPM_MODULE(sensortag_module, NULL, shutdown_handler, lpm_wakeup_handler,
LPM_DOMAIN_NONE);
/*---------------------------------------------------------------------------*/
void
board_init()

View File

@ -46,7 +46,7 @@
#include <stdio.h>
/*---------------------------------------------------------------------------*/
static uint8_t buzzer_on;
static lpm_power_domain_lock_t lock;
LPM_MODULE(buzzer_module, NULL, NULL, NULL, LPM_DOMAIN_PERIPH);
/*---------------------------------------------------------------------------*/
void
buzzer_init()
@ -74,7 +74,12 @@ buzzer_start(int freq)
buzzer_on = 1;
lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_PERIPH);
/*
* Register ourself with LPM. This will keep the PERIPH PD powered on
* during deep sleep, allowing the buzzer to keep working while the chip is
* being power-cycled
*/
lpm_register_module(&buzzer_module);
/* Stop the timer */
ti_lib_timer_disable(GPT0_BASE, TIMER_A);
@ -101,7 +106,12 @@ buzzer_stop()
{
buzzer_on = 0;
lpm_pd_lock_release(&lock);
/*
* Unregister the buzzer module from LPM. This will effectively release our
* lock for the PERIPH PD allowing it to be powered down (unless some other
* module keeps it on)
*/
lpm_unregister_module(&buzzer_module);
/* Stop the timer */
ti_lib_timer_disable(GPT0_BASE, TIMER_A);

View File

@ -60,7 +60,7 @@ wakeup_handler(void)
* getting notified before deep sleep. All we need is to be notified when we
* wake up so we can turn power domains back on
*/
LPM_MODULE(srf_module, NULL, NULL, lpm_wakeup_handler);
LPM_MODULE(srf_module, NULL, NULL, wakeup_handler, LPM_DOMAIN_NONE);
/*---------------------------------------------------------------------------*/
static void
configure_unused_pins(void)