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) 73 #define MAX_SLEEP_TIME RTIMER_SECOND 74 #define MIN_SAFE_SCHEDULE 8u 77 void clock_update(
void);
80 lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
82 lpm_registered_module_t *module;
84 uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull | wake_on;
88 ti_lib_int_master_disable();
91 ti_lib_aon_rtc_disable();
92 ti_lib_aon_rtc_event_clear(AON_RTC_CH0);
93 ti_lib_aon_rtc_event_clear(AON_RTC_CH1);
94 ti_lib_aon_rtc_event_clear(AON_RTC_CH2);
97 for(i = AON_EVENT_MCU_WU0; i <= AON_EVENT_MCU_WU3; i++) {
98 ti_lib_aon_event_mcu_wake_up_set(i, AON_EVENT_NONE);
100 for(i = AON_EVENT_AUX_WU0; i <= AON_EVENT_AUX_WU2; i++) {
101 ti_lib_aon_event_aux_wake_up_set(i, AON_EVENT_NONE);
104 ti_lib_sys_ctrl_aon_sync();
109 for(module =
list_head(modules_list); module != NULL;
110 module = module->next) {
111 if(module->shutdown) {
112 module->shutdown(LPM_MODE_SHUTDOWN);
117 if(wakeup_pin != IOID_UNUSED) {
118 ti_lib_gpio_set_output_enable_dio(wakeup_pin, GPIO_OUTPUT_DISABLE);
119 ti_lib_ioc_port_configure_set(wakeup_pin, IOC_PORT_GPIO, io_cfg);
123 ti_lib_aon_ioc_freeze_enable();
126 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL |
135 ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
138 ti_lib_aon_wuc_mcu_sram_config(0);
144 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_CPU | PRCM_DOMAIN_VIMS |
148 ti_lib_aon_wuc_jtag_power_off();
152 ti_lib_aon_wuc_domain_power_down_enable();
158 ti_lib_prcm_mcu_power_off();
161 ti_lib_aon_wuc_mcu_wake_up_config(MCU_IMM_WAKE_UP);
162 ti_lib_aon_wuc_mcu_power_off_config(MCU_VIRT_PWOFF_DISABLE);
165 ti_lib_pwr_ctrl_io_freeze_enable();
168 ti_lib_prcm_cache_retention_disable();
169 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);
172 ti_lib_aon_wuc_shut_down_enable();
173 ti_lib_sys_ctrl_aon_sync();
176 ti_lib_prcm_deep_sleep();
186 lpm_registered_module_t *module;
188 ENERGEST_SWITCH(ENERGEST_TYPE_DEEP_LPM, ENERGEST_TYPE_CPU);
191 ti_lib_sys_ctrl_aon_sync();
194 ti_lib_sys_ctrl_adjust_recharge_after_power_down();
201 ti_lib_prcm_mcu_uldo_configure(
false);
204 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED);
205 ti_lib_prcm_cache_retention_enable();
207 ti_lib_aon_ioc_freeze_disable();
208 ti_lib_sys_ctrl_aon_sync();
211 ti_lib_sys_ctrl_dcdc_voltage_conditional_control();
225 for(module =
list_head(modules_list); module != NULL;
226 module = module->next) {
232 #if CC2650_FAST_RADIO_STARTUP 241 check_next_rtimer(rtimer_clock_t now, rtimer_clock_t *next_rtimer,
bool *next_rtimer_set)
243 uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
245 if(ti_lib_aon_rtc_channel_active(AON_RTC_CH0)) {
246 *next_rtimer_set =
true;
249 *next_rtimer = ti_lib_aon_rtc_compare_value_get(AON_RTC_CH0);
251 if(RTIMER_CLOCK_LT(*next_rtimer, now + 2)) {
252 max_pm = MIN(max_pm, LPM_MODE_AWAKE);
253 }
else if(RTIMER_CLOCK_LT(*next_rtimer, now + STANDBY_MIN_DURATION)) {
254 max_pm = MIN(max_pm, LPM_MODE_SLEEP);
257 *next_rtimer_set =
false;
264 check_next_etimer(rtimer_clock_t now, rtimer_clock_t *next_etimer,
bool *next_etimer_set)
266 uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
268 *next_etimer_set =
false;
273 if(until_next_etimer < 1) {
274 max_pm = MIN(max_pm, LPM_MODE_AWAKE);
276 *next_etimer_set =
true;
277 *next_etimer = soc_rtc_last_isr_time() + (until_next_etimer * (RTIMER_SECOND /
CLOCK_SECOND));
278 if(RTIMER_CLOCK_LT(*next_etimer, now + STANDBY_MIN_DURATION)) {
279 max_pm = MIN(max_pm, LPM_MODE_SLEEP);
288 setup_sleep_mode(
void)
290 lpm_registered_module_t *module;
291 uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
295 rtimer_clock_t next_rtimer = 0;
296 rtimer_clock_t next_etimer = 0;
297 bool next_rtimer_set =
false;
298 bool next_etimer_set =
false;
302 return LPM_MODE_AWAKE;
306 for(module =
list_head(modules_list); module != NULL;
307 module = module->next) {
308 if(module->request_max_pm) {
309 uint8_t module_pm = module->request_max_pm();
310 if(module_pm < max_pm) {
318 pm = check_next_rtimer(now, &next_rtimer, &next_rtimer_set);
322 pm = check_next_etimer(now, &next_etimer, &next_etimer_set);
327 if(max_pm == LPM_MODE_SLEEP) {
328 if(next_etimer_set) {
330 if(RTIMER_CLOCK_LT(next_etimer, now + MIN_SAFE_SCHEDULE)) {
332 next_etimer = now + MIN_SAFE_SCHEDULE;
333 }
else if(RTIMER_CLOCK_LT(now + MAX_SLEEP_TIME, next_etimer)) {
335 next_etimer = now + MAX_SLEEP_TIME;
345 }
else if(max_pm == LPM_MODE_DEEP_SLEEP) {
350 #if CC2650_FAST_RADIO_STARTUP 351 if(next_rtimer_set) {
352 if(!next_etimer_set || RTIMER_CLOCK_LT(next_rtimer - SLEEP_GUARD_TIME, next_etimer)) {
359 if(next_etimer_set) {
376 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
379 HWREG(NVIC_SYS_CTRL) &= ~(NVIC_SYS_CTRL_SLEEPDEEP);
383 ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
389 uint32_t domains = LOCKABLE_DOMAINS;
390 lpm_registered_module_t *module;
406 for(module =
list_head(modules_list); module != NULL;
407 module = module->next) {
408 if(module->shutdown) {
409 module->shutdown(LPM_MODE_DEEP_SLEEP);
413 domains &= ~module->domain_lock;
420 domains &= LOCKABLE_DOMAINS;
426 if(domains & PRCM_DOMAIN_PERIPH) {
427 ti_lib_aon_ioc_freeze_enable();
436 ti_lib_prcm_power_domain_off(domains);
458 ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
461 ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION |
462 MCU_RAM2_RETENTION | MCU_RAM3_RETENTION);
468 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU |
469 PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS);
472 ti_lib_aon_wuc_jtag_power_off();
475 ti_lib_aon_wuc_domain_power_down_enable();
478 ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE);
484 if(domains == LOCKABLE_DOMAINS) {
485 ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO);
488 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_DEEP_LPM);
491 ti_lib_sys_ctrl_aon_sync();
499 ti_lib_prcm_cache_retention_disable();
500 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);
503 ti_lib_prcm_deep_sleep();
513 ti_lib_int_master_enable();
522 ti_lib_int_master_disable();
524 max_pm = setup_sleep_mode();
527 if(max_pm == LPM_MODE_SLEEP) {
529 }
else if(max_pm == LPM_MODE_DEEP_SLEEP) {
533 ti_lib_int_master_enable();
554 ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU3, AON_EVENT_IO);
560 if(ioid == IOID_UNUSED) {
564 ti_lib_ioc_port_configure_set(ioid, IOC_PORT_GPIO, IOC_STD_OUTPUT);
565 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
Header file for the management of CC13xx/CC26xx low-power operation.
void lpm_sleep(void)
Enter sleep mode.
clock_time_t etimer_next_expiration_time(void)
Get next event timer expiration time.
#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.
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.