44 #include "contiki-conf.h"
51 #include "dev/watchdog.h"
60 static unsigned long irq_energest = 0;
62 #define ENERGEST_IRQ_SAVE(a) do { \
63 a = energest_type_time(ENERGEST_TYPE_IRQ); } while(0)
64 #define ENERGEST_IRQ_RESTORE(a) do { \
65 energest_type_set(ENERGEST_TYPE_IRQ, a); } while(0)
67 #define ENERGEST_IRQ_SAVE(a) do {} while(0)
68 #define ENERGEST_IRQ_RESTORE(a) do {} while(0)
74 #define LOCKABLE_DOMAINS ((uint32_t)(PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH))
80 #define STANDBY_MIN_DURATION (RTIMER_SECOND >> 11)
81 #define MINIMAL_SAFE_SCHEDUAL 8u
82 #define MAX_SLEEP_TIME RTIMER_SECOND
83 #define DEFAULT_SLEEP_TIME RTIMER_SECOND
85 #define CLK_TO_RT(c) ((c) * (RTIMER_SECOND / CLOCK_SECOND))
88 void clock_update(
void);
91 lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
93 lpm_registered_module_t *module;
95 uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull | wake_on;
99 ti_lib_int_master_disable();
102 ti_lib_aon_rtc_disable();
103 ti_lib_aon_rtc_event_clear(AON_RTC_CH0);
104 ti_lib_aon_rtc_event_clear(AON_RTC_CH1);
105 ti_lib_aon_rtc_event_clear(AON_RTC_CH2);
108 for(i = AON_EVENT_MCU_WU0; i <= AON_EVENT_MCU_WU3; i++) {
109 ti_lib_aon_event_mcu_wake_up_set(i, AON_EVENT_NONE);
111 for(i = AON_EVENT_AUX_WU0; i <= AON_EVENT_AUX_WU2; i++) {
112 ti_lib_aon_event_aux_wake_up_set(i, AON_EVENT_NONE);
115 ti_lib_sys_ctrl_aon_sync();
121 module = module->next) {
122 if(module->shutdown) {
123 module->shutdown(LPM_MODE_SHUTDOWN);
128 if(wakeup_pin != IOID_UNUSED) {
129 ti_lib_gpio_dir_mode_set((1 << wakeup_pin), GPIO_DIR_MODE_IN);
130 ti_lib_ioc_port_configure_set(wakeup_pin, IOC_PORT_GPIO, io_cfg);
134 ti_lib_aon_ioc_freeze_enable();
137 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL |
146 ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
149 ti_lib_aon_wuc_mcu_sram_config(0);
155 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_CPU | PRCM_DOMAIN_VIMS |
159 ti_lib_aon_wuc_jtag_power_off();
163 ti_lib_aon_wuc_domain_power_down_enable();
169 ti_lib_prcm_mcu_power_off();
172 ti_lib_aon_wuc_mcu_wake_up_config(MCU_IMM_WAKE_UP);
173 ti_lib_aon_wuc_mcu_power_off_config(MCU_VIRT_PWOFF_DISABLE);
176 ti_lib_pwr_ctrl_io_freeze_enable();
179 ti_lib_prcm_cache_retention_disable();
180 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);
183 ti_lib_aon_wuc_shut_down_enable();
184 ti_lib_sys_ctrl_aon_sync();
187 ti_lib_prcm_deep_sleep();
197 lpm_registered_module_t *module;
200 ENERGEST_IRQ_SAVE(irq_energest);
201 ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
204 ti_lib_sys_ctrl_aon_sync();
207 ti_lib_sys_ctrl_adjust_recharge_after_power_down();
214 ti_lib_prcm_mcu_uldo_configure(
false);
217 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED);
218 ti_lib_prcm_cache_retention_enable();
220 ti_lib_aon_ioc_freeze_disable();
221 ti_lib_sys_ctrl_aon_sync();
224 ti_lib_sys_ctrl_dcdc_voltage_conditional_control();
239 module = module->next) {
249 uint32_t domains = LOCKABLE_DOMAINS;
250 lpm_registered_module_t *module;
267 module = module->next) {
268 if(module->shutdown) {
269 module->shutdown(LPM_MODE_DEEP_SLEEP);
273 domains &= ~module->domain_lock;
280 domains &= LOCKABLE_DOMAINS;
286 if(domains & PRCM_DOMAIN_PERIPH) {
287 ti_lib_aon_ioc_freeze_enable();
296 ti_lib_prcm_power_domain_off(domains);
317 ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
320 ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION |
321 MCU_RAM2_RETENTION | MCU_RAM3_RETENTION);
327 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU |
328 PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS);
331 ti_lib_aon_wuc_jtag_power_off();
334 ti_lib_aon_wuc_domain_power_down_enable();
337 ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE);
343 if(domains == LOCKABLE_DOMAINS) {
344 ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO);
348 ENERGEST_IRQ_RESTORE(irq_energest);
349 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
352 ti_lib_sys_ctrl_aon_sync();
360 ti_lib_prcm_cache_retention_disable();
361 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);
364 ti_lib_prcm_deep_sleep();
376 safe_schedule_rtimer(rtimer_clock_t time, rtimer_clock_t now,
int pm)
378 rtimer_clock_t min_sleep;
379 rtimer_clock_t max_sleep;
381 min_sleep = now + MINIMAL_SAFE_SCHEDUAL;
382 max_sleep = now + MAX_SLEEP_TIME;
384 if(RTIMER_CLOCK_LT(time, min_sleep)) {
388 }
else if((pm == LPM_MODE_SLEEP) && RTIMER_CLOCK_LT(max_sleep, time)) {
398 setup_sleep_mode(
void)
400 rtimer_clock_t et_distance = 0;
402 lpm_registered_module_t *module;
405 int etimer_is_pending;
407 rtimer_clock_t et_time;
408 rtimer_clock_t next_trig;
410 max_pm = LPM_MODE_MAX_SUPPORTED;
414 return LPM_MODE_AWAKE;
419 if(etimer_is_pending) {
422 if(RTIMER_CLOCK_LT(et_distance, 1)) {
425 return LPM_MODE_AWAKE;
430 if(RTIMER_CLOCK_LT(next_trig, now + STANDBY_MIN_DURATION)) {
431 return LPM_MODE_SLEEP;
436 module = module->next) {
437 if(module->request_max_pm) {
438 module_pm = module->request_max_pm();
439 if(module_pm < max_pm) {
446 if(etimer_is_pending) {
447 et_time = soc_rtc_last_isr_time() + et_distance;
449 safe_schedule_rtimer(et_time, now, max_pm);
464 ti_lib_int_master_disable();
466 max_pm = setup_sleep_mode();
469 if(max_pm == LPM_MODE_SLEEP) {
471 }
else if(max_pm == LPM_MODE_DEEP_SLEEP) {
475 ti_lib_int_master_enable();
481 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
484 ENERGEST_IRQ_RESTORE(irq_energest);
487 HWREG(NVIC_SYS_CTRL) &= ~(NVIC_SYS_CTRL_SLEEPDEEP);
492 ENERGEST_IRQ_SAVE(irq_energest);
494 ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
515 ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU2, AON_EVENT_IO);
521 if(ioid == IOID_UNUSED) {
525 ti_lib_ioc_port_configure_set(ioid, IOC_PORT_GPIO, IOC_STD_OUTPUT);
526 ti_lib_gpio_dir_mode_set((1 << ioid), GPIO_DIR_MODE_IN);
void aux_ctrl_register_consumer(aux_consumer_module_t *consumer)
Register a module that no longer requires access to the AUX power domain.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
void soc_rtc_schedule_one_shot(uint32_t channel, uint32_t ticks)
Schedule an AON RTC channel 0 one-shot compare event.
#define LIST(name)
Declare a linked list.
Header file with macros which rename TI CC26xxware functions.
Header file for the management of the CC13xx/CC26xx AUX domain.
void lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
Put the chip in shutdown power mode.
clock_time_t etimer_next_expiration_time(void)
Get next event timer expiration time.
#define RTIMER_NOW()
Get the current clock time.
int etimer_pending(void)
Check if there are any non-expired event timers.
void lpm_drop()
Drop the cortex to sleep / deep sleep and shut down peripherals.
CCIF clock_time_t clock_time(void)
Get the current clock time.
void lpm_sleep(void)
Enter sleep mode.
void aux_ctrl_power_down(bool force)
Power down the AUX power domain.
void lpm_init()
Initialise the low-power mode management module.
Header file for the CC13xx/CC26xx AON RTC driver.
Header file for the energy estimation mechanism
void lpm_register_module(lpm_registered_module_t *module)
Register a module for LPM notifications.
The data structure to be used for modules that require access to AUX.
void list_init(list_t list)
Initialize a list.
Header file for the management of CC13xx/CC26xx low-power operation.
void * list_head(list_t list)
Get a pointer to the first element of a list.
void lpm_pin_set_default_state(uint32_t ioid)
Sets an IOID to a default state.
#define NULL
The null pointer.
void oscillators_switch_to_hf_rc(void)
Switches MF and HF clock source to be the HF RC OSC.
void watchdog_periodic(void)
Writes the WDT clear sequence.
void list_add(list_t list, void *item)
Add an item at the end of a list.
Linked list manipulation routines.
void aux_ctrl_power_up()
Power-up the AUX power domain.
rtimer_clock_t soc_rtc_get_next_trigger()
Return the time of the next scheduled rtimer event.
int process_nevents(void)
Number of events waiting to be processed.
Header file for the CC13xx/CC26xx oscillator control.
void lpm_unregister_module(lpm_registered_module_t *module)
Unregister a module from LPM notifications.
void oscillators_select_lf_rcosc(void)
Set the LF clock source to be the LF RCOSC.