51 #include "dev/watchdog.h" 62 #define LOCKABLE_DOMAINS ((uint32_t)(PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH)) 68 #define STANDBY_MIN_DURATION (RTIMER_SECOND / 100) 71 #define SLEEP_GUARD_TIME (RTIMER_SECOND / 1000) 74 #define MAX_SLEEP_TIME RTIMER_SECOND 77 #define MIN_SAFE_SCHEDULE 8u 80 void clock_update(
void);
83 lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
85 lpm_registered_module_t *module;
87 uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull | wake_on;
91 ti_lib_int_master_disable();
94 ti_lib_aon_rtc_disable();
95 ti_lib_aon_rtc_event_clear(AON_RTC_CH0);
96 ti_lib_aon_rtc_event_clear(AON_RTC_CH1);
97 ti_lib_aon_rtc_event_clear(AON_RTC_CH2);
100 for(i = AON_EVENT_MCU_WU0; i <= AON_EVENT_MCU_WU3; i++) {
101 ti_lib_aon_event_mcu_wake_up_set(i, AON_EVENT_NONE);
103 for(i = AON_EVENT_AUX_WU0; i <= AON_EVENT_AUX_WU2; i++) {
104 ti_lib_aon_event_aux_wake_up_set(i, AON_EVENT_NONE);
107 ti_lib_sys_ctrl_aon_sync();
112 for(module =
list_head(modules_list); module != NULL;
113 module = module->next) {
114 if(module->shutdown) {
115 module->shutdown(LPM_MODE_SHUTDOWN);
120 if(wakeup_pin != IOID_UNUSED) {
121 ti_lib_gpio_set_output_enable_dio(wakeup_pin, GPIO_OUTPUT_DISABLE);
122 ti_lib_ioc_port_configure_set(wakeup_pin, IOC_PORT_GPIO, io_cfg);
126 ti_lib_aon_ioc_freeze_enable();
129 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL |
138 ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
141 ti_lib_aon_wuc_mcu_sram_config(0);
147 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_CPU | PRCM_DOMAIN_VIMS |
151 ti_lib_aon_wuc_jtag_power_off();
155 ti_lib_aon_wuc_domain_power_down_enable();
161 ti_lib_prcm_mcu_power_off();
164 ti_lib_aon_wuc_mcu_wake_up_config(MCU_IMM_WAKE_UP);
165 ti_lib_aon_wuc_mcu_power_off_config(MCU_VIRT_PWOFF_DISABLE);
168 ti_lib_aon_ioc_freeze_enable();
169 HWREG(AON_SYSCTL_BASE + AON_SYSCTL_O_SLEEPCTL) = 0;
170 ti_lib_sys_ctrl_aon_sync();
173 ti_lib_prcm_cache_retention_disable();
174 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);
177 ti_lib_aon_wuc_shut_down_enable();
178 ti_lib_sys_ctrl_aon_sync();
181 ti_lib_prcm_deep_sleep();
191 lpm_registered_module_t *module;
193 ENERGEST_SWITCH(ENERGEST_TYPE_DEEP_LPM, ENERGEST_TYPE_CPU);
196 ti_lib_sys_ctrl_aon_sync();
199 ti_lib_sys_ctrl_adjust_recharge_after_power_down();
206 ti_lib_prcm_mcu_uldo_configure(
false);
209 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED);
210 ti_lib_prcm_cache_retention_enable();
212 ti_lib_aon_ioc_freeze_disable();
213 ti_lib_sys_ctrl_aon_sync();
216 ti_lib_sys_ctrl_dcdc_voltage_conditional_control();
230 for(module =
list_head(modules_list); module != NULL;
231 module = module->next) {
237 #if CC2650_FAST_RADIO_STARTUP 246 check_next_rtimer(rtimer_clock_t now, rtimer_clock_t *next_rtimer,
bool *next_rtimer_set)
248 uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
250 if(ti_lib_aon_rtc_channel_active(AON_RTC_CH0)) {
251 *next_rtimer_set =
true;
254 *next_rtimer = ti_lib_aon_rtc_compare_value_get(AON_RTC_CH0);
256 if(RTIMER_CLOCK_LT(*next_rtimer, now + 2)) {
257 max_pm = MIN(max_pm, LPM_MODE_AWAKE);
258 }
else if(RTIMER_CLOCK_LT(*next_rtimer, now + STANDBY_MIN_DURATION)) {
259 max_pm = MIN(max_pm, LPM_MODE_SLEEP);
262 *next_rtimer_set =
false;
269 check_next_etimer(rtimer_clock_t now, rtimer_clock_t *next_etimer,
bool *next_etimer_set)
271 uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
273 *next_etimer_set =
false;
278 if(until_next_etimer < 1) {
279 max_pm = MIN(max_pm, LPM_MODE_AWAKE);
281 *next_etimer_set =
true;
283 if(RTIMER_CLOCK_LT(*next_etimer, now + STANDBY_MIN_DURATION)) {
284 max_pm = MIN(max_pm, LPM_MODE_SLEEP);
293 setup_sleep_mode(
void)
295 lpm_registered_module_t *module;
296 uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
300 rtimer_clock_t next_rtimer = 0;
301 rtimer_clock_t next_etimer = 0;
302 bool next_rtimer_set =
false;
303 bool next_etimer_set =
false;
307 return LPM_MODE_AWAKE;
311 for(module =
list_head(modules_list); module != NULL;
312 module = module->next) {
313 if(module->request_max_pm) {
314 uint8_t module_pm = module->request_max_pm();
315 if(module_pm < max_pm) {
323 pm = check_next_rtimer(now, &next_rtimer, &next_rtimer_set);
327 pm = check_next_etimer(now, &next_etimer, &next_etimer_set);
332 if(max_pm == LPM_MODE_SLEEP) {
333 if(next_etimer_set) {
335 if(RTIMER_CLOCK_LT(next_etimer, now + MIN_SAFE_SCHEDULE)) {
337 next_etimer = now + MIN_SAFE_SCHEDULE;
338 }
else if(RTIMER_CLOCK_LT(now + MAX_SLEEP_TIME, next_etimer)) {
340 next_etimer = now + MAX_SLEEP_TIME;
350 }
else if(max_pm == LPM_MODE_DEEP_SLEEP) {
355 #if CC2650_FAST_RADIO_STARTUP 356 if(next_rtimer_set) {
357 if(!next_etimer_set || RTIMER_CLOCK_LT(next_rtimer - SLEEP_GUARD_TIME, next_etimer)) {
364 if(next_etimer_set) {
381 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
384 HWREG(NVIC_SYS_CTRL) &= ~(NVIC_SYS_CTRL_SLEEPDEEP);
391 ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
397 uint32_t domains = LOCKABLE_DOMAINS;
398 lpm_registered_module_t *module;
414 for(module =
list_head(modules_list); module != NULL;
415 module = module->next) {
416 if(module->shutdown) {
417 module->shutdown(LPM_MODE_DEEP_SLEEP);
421 domains &= ~module->domain_lock;
428 domains &= LOCKABLE_DOMAINS;
434 if(domains & PRCM_DOMAIN_PERIPH) {
435 ti_lib_aon_ioc_freeze_enable();
444 ti_lib_prcm_power_domain_off(domains);
466 ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
469 ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION |
470 MCU_RAM2_RETENTION | MCU_RAM3_RETENTION);
476 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU |
477 PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS);
480 ti_lib_aon_wuc_jtag_power_off();
483 ti_lib_aon_wuc_domain_power_down_enable();
486 ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE);
492 if(domains == LOCKABLE_DOMAINS) {
493 ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO);
496 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_DEEP_LPM);
499 ti_lib_sys_ctrl_aon_sync();
507 ti_lib_prcm_cache_retention_disable();
508 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);
511 ti_lib_prcm_deep_sleep();
521 ti_lib_int_master_enable();
530 ti_lib_int_master_disable();
532 max_pm = setup_sleep_mode();
535 if(max_pm == LPM_MODE_SLEEP) {
537 }
else if(max_pm == LPM_MODE_DEEP_SLEEP) {
541 ti_lib_int_master_enable();
562 ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU3, AON_EVENT_IO);
568 if(ioid == IOID_UNUSED) {
572 ti_lib_ioc_port_configure_set(ioid, IOC_PORT_GPIO, IOC_STD_OUTPUT);
573 ti_lib_gpio_set_output_enable_dio(ioid, GPIO_OUTPUT_DISABLE);
void oscillators_request_hf_xosc(void)
Requests the HF XOSC as the source for the HF clock, but does not perform the actual switch...
void soc_rtc_schedule_one_shot(uint32_t channel, uint32_t ticks)
Schedule an AON RTC channel 0 one-shot compare event.
void lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
Put the chip in shutdown power mode.
Header file with macros which rename TI CC26xxware functions.
Header file for the energy estimation mechanism
void lpm_sleep(void)
Enter sleep mode.
clock_time_t etimer_next_expiration_time(void)
Get next event timer expiration time.
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
#define RTIMER_NOW()
Get the current clock time.
Header file for the CC13xx/CC26xx oscillator control.
void lpm_drop()
Drop the cortex to sleep / deep sleep and shut down peripherals.
Header file for the management of CC13xx/CC26xx low-power operation.
void oscillators_switch_to_hf_rc(void)
Switches MF and HF clock source to be the HF RC OSC.
#define CLOCK_SECOND
A second, measured in system clock time.
Linked list manipulation routines.
void * list_head(list_t list)
Get a pointer to the first element of a list.
int etimer_pending(void)
Check if there are any non-expired event timers.
clock_time_t clock_time(void)
Get the current clock time.
Header file for the management of the CC13xx/CC26xx AUX domain.
void list_add(list_t list, void *item)
Add an item at the end of a list.
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_init(list_t list)
Initialize a list.
int process_nevents(void)
Number of events waiting to be processed.
#define LIST(name)
Declare a linked list.
void aux_ctrl_power_up()
Power-up the AUX power domain.
void aux_ctrl_power_down(bool force)
Power down the AUX power domain.
void lpm_init()
Initialise the low-power mode management module.
The data structure to be used for modules that require access to AUX.
void lpm_pin_set_default_state(uint32_t ioid)
Sets an IOID to a default state.
void watchdog_periodic(void)
Writes the WDT clear sequence.
Header file for the CC13xx/CC26xx AON RTC driver.
Header file for the LED HAL.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
void lpm_unregister_module(lpm_registered_module_t *module)
Unregister a module from LPM notifications.
void lpm_register_module(lpm_registered_module_t *module)
Register a module for LPM notifications.
void oscillators_select_lf_rcosc(void)
Set the LF clock source to be the LF RCOSC.