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_aon_ioc_freeze_enable();
166 HWREG(AON_SYSCTL_BASE + AON_SYSCTL_O_SLEEPCTL) = 0;
167 ti_lib_sys_ctrl_aon_sync();
170 ti_lib_prcm_cache_retention_disable();
171 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);
174 ti_lib_aon_wuc_shut_down_enable();
175 ti_lib_sys_ctrl_aon_sync();
178 ti_lib_prcm_deep_sleep();
188 lpm_registered_module_t *module;
190 ENERGEST_SWITCH(ENERGEST_TYPE_DEEP_LPM, ENERGEST_TYPE_CPU);
193 ti_lib_sys_ctrl_aon_sync();
196 ti_lib_sys_ctrl_adjust_recharge_after_power_down();
203 ti_lib_prcm_mcu_uldo_configure(
false);
206 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED);
207 ti_lib_prcm_cache_retention_enable();
209 ti_lib_aon_ioc_freeze_disable();
210 ti_lib_sys_ctrl_aon_sync();
213 ti_lib_sys_ctrl_dcdc_voltage_conditional_control();
227 for(module =
list_head(modules_list); module != NULL;
228 module = module->next) {
234 #if CC2650_FAST_RADIO_STARTUP 243 check_next_rtimer(rtimer_clock_t now, rtimer_clock_t *next_rtimer,
bool *next_rtimer_set)
245 uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
247 if(ti_lib_aon_rtc_channel_active(AON_RTC_CH0)) {
248 *next_rtimer_set =
true;
251 *next_rtimer = ti_lib_aon_rtc_compare_value_get(AON_RTC_CH0);
253 if(RTIMER_CLOCK_LT(*next_rtimer, now + 2)) {
254 max_pm = MIN(max_pm, LPM_MODE_AWAKE);
255 }
else if(RTIMER_CLOCK_LT(*next_rtimer, now + STANDBY_MIN_DURATION)) {
256 max_pm = MIN(max_pm, LPM_MODE_SLEEP);
259 *next_rtimer_set =
false;
266 check_next_etimer(rtimer_clock_t now, rtimer_clock_t *next_etimer,
bool *next_etimer_set)
268 uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
270 *next_etimer_set =
false;
275 if(until_next_etimer < 1) {
276 max_pm = MIN(max_pm, LPM_MODE_AWAKE);
278 *next_etimer_set =
true;
279 *next_etimer = soc_rtc_last_isr_time() + (until_next_etimer * (RTIMER_SECOND /
CLOCK_SECOND));
280 if(RTIMER_CLOCK_LT(*next_etimer, now + STANDBY_MIN_DURATION)) {
281 max_pm = MIN(max_pm, LPM_MODE_SLEEP);
290 setup_sleep_mode(
void)
292 lpm_registered_module_t *module;
293 uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
297 rtimer_clock_t next_rtimer = 0;
298 rtimer_clock_t next_etimer = 0;
299 bool next_rtimer_set =
false;
300 bool next_etimer_set =
false;
304 return LPM_MODE_AWAKE;
308 for(module =
list_head(modules_list); module != NULL;
309 module = module->next) {
310 if(module->request_max_pm) {
311 uint8_t module_pm = module->request_max_pm();
312 if(module_pm < max_pm) {
320 pm = check_next_rtimer(now, &next_rtimer, &next_rtimer_set);
324 pm = check_next_etimer(now, &next_etimer, &next_etimer_set);
329 if(max_pm == LPM_MODE_SLEEP) {
330 if(next_etimer_set) {
332 if(RTIMER_CLOCK_LT(next_etimer, now + MIN_SAFE_SCHEDULE)) {
334 next_etimer = now + MIN_SAFE_SCHEDULE;
335 }
else if(RTIMER_CLOCK_LT(now + MAX_SLEEP_TIME, next_etimer)) {
337 next_etimer = now + MAX_SLEEP_TIME;
347 }
else if(max_pm == LPM_MODE_DEEP_SLEEP) {
352 #if CC2650_FAST_RADIO_STARTUP 353 if(next_rtimer_set) {
354 if(!next_etimer_set || RTIMER_CLOCK_LT(next_rtimer - SLEEP_GUARD_TIME, next_etimer)) {
361 if(next_etimer_set) {
378 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
381 HWREG(NVIC_SYS_CTRL) &= ~(NVIC_SYS_CTRL_SLEEPDEEP);
385 ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
391 uint32_t domains = LOCKABLE_DOMAINS;
392 lpm_registered_module_t *module;
408 for(module =
list_head(modules_list); module != NULL;
409 module = module->next) {
410 if(module->shutdown) {
411 module->shutdown(LPM_MODE_DEEP_SLEEP);
415 domains &= ~module->domain_lock;
422 domains &= LOCKABLE_DOMAINS;
428 if(domains & PRCM_DOMAIN_PERIPH) {
429 ti_lib_aon_ioc_freeze_enable();
438 ti_lib_prcm_power_domain_off(domains);
460 ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
463 ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION |
464 MCU_RAM2_RETENTION | MCU_RAM3_RETENTION);
470 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU |
471 PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS);
474 ti_lib_aon_wuc_jtag_power_off();
477 ti_lib_aon_wuc_domain_power_down_enable();
480 ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE);
486 if(domains == LOCKABLE_DOMAINS) {
487 ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO);
490 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_DEEP_LPM);
493 ti_lib_sys_ctrl_aon_sync();
501 ti_lib_prcm_cache_retention_disable();
502 ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);
505 ti_lib_prcm_deep_sleep();
515 ti_lib_int_master_enable();
524 ti_lib_int_master_disable();
526 max_pm = setup_sleep_mode();
529 if(max_pm == LPM_MODE_SLEEP) {
531 }
else if(max_pm == LPM_MODE_DEEP_SLEEP) {
535 ti_lib_int_master_enable();
556 ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU3, AON_EVENT_IO);
562 if(ioid == IOID_UNUSED) {
566 ti_lib_ioc_port_configure_set(ioid, IOC_PORT_GPIO, IOC_STD_OUTPUT);
567 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.