diff options
Diffstat (limited to 'cc3200/mods/pybsleep.c')
-rw-r--r-- | cc3200/mods/pybsleep.c | 260 |
1 files changed, 100 insertions, 160 deletions
diff --git a/cc3200/mods/pybsleep.c b/cc3200/mods/pybsleep.c index 2cdb10fd36..640a7269e0 100644 --- a/cc3200/mods/pybsleep.c +++ b/cc3200/mods/pybsleep.c @@ -72,7 +72,7 @@ #define WAKEUP_TIME_HIB (32768) // 1 s #define FORCED_TIMER_INTERRUPT_MS (PYB_RTC_MIN_ALARM_TIME_MS) -#define FAILED_SLEEP_DELAY_MS (FORCED_TIMER_INTERRUPT_MS * 2) +#define FAILED_SLEEP_DELAY_MS (FORCED_TIMER_INTERRUPT_MS * 3) /****************************************************************************** DECLARE PRIVATE TYPES @@ -111,7 +111,7 @@ typedef struct { mp_obj_base_t base; mp_obj_t obj; WakeUpCB_t wakeup; -} pybsleep_obj_t; +} pyb_sleep_obj_t; typedef struct { mp_obj_t gpio_lpds_wake_cb; @@ -122,23 +122,26 @@ typedef struct { /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ -STATIC const mp_obj_type_t pybsleep_type; STATIC nvic_reg_store_t *nvic_reg_store; STATIC pybsleep_data_t pybsleep_data = {NULL, NULL, NULL}; volatile arm_cm4_core_regs_t vault_arm_registers; STATIC pybsleep_reset_cause_t pybsleep_reset_cause = PYB_SLP_PWRON_RESET; STATIC pybsleep_wake_reason_t pybsleep_wake_reason = PYB_SLP_WAKED_PWRON; +STATIC const mp_obj_type_t pyb_sleep_type = { + { &mp_type_type }, + .name = MP_QSTR_sleep, +}; /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ -STATIC pybsleep_obj_t *pybsleep_find (mp_obj_t obj); -STATIC void pybsleep_flash_powerdown (void); -STATIC NORETURN void pybsleep_suspend_enter (void); -void pybsleep_suspend_exit (void); -STATIC void pybsleep_obj_wakeup (void); +STATIC pyb_sleep_obj_t *pyb_sleep_find (mp_obj_t obj); +STATIC void pyb_sleep_flash_powerdown (void); +STATIC NORETURN void pyb_sleep_suspend_enter (void); +void pyb_sleep_suspend_exit (void); +STATIC void pyb_sleep_obj_wakeup (void); STATIC void PRCMInterruptHandler (void); -STATIC void pybsleep_iopark (bool hibernate); +STATIC void pyb_sleep_iopark (bool hibernate); STATIC bool setup_timer_lpds_wake (void); STATIC bool setup_timer_hibernate_wake (void); @@ -146,14 +149,14 @@ STATIC bool setup_timer_hibernate_wake (void); DEFINE PUBLIC FUNCTIONS ******************************************************************************/ __attribute__ ((section (".boot"))) -void pybsleep_pre_init (void) { +void pyb_sleep_pre_init (void) { // allocate memory for nvic registers vault ASSERT ((nvic_reg_store = mem_Malloc(sizeof(nvic_reg_store_t))) != NULL); } -void pybsleep_init0 (void) { +void pyb_sleep_init0 (void) { // initialize the sleep objects list - mp_obj_list_init(&MP_STATE_PORT(pybsleep_obj_list), 0); + mp_obj_list_init(&MP_STATE_PORT(pyb_sleep_obj_list), 0); // register and enable the PRCM interrupt osi_InterruptRegister(INT_PRCM, (P_OSI_INTR_ENTRY)PRCMInterruptHandler, INT_PRIORITY_LVL_1); @@ -204,50 +207,109 @@ void pybsleep_init0 (void) { } } -void pybsleep_signal_soft_reset (void) { +void pyb_sleep_signal_soft_reset (void) { pybsleep_reset_cause = PYB_SLP_SOFT_RESET; } -void pybsleep_add (const mp_obj_t obj, WakeUpCB_t wakeup) { - pybsleep_obj_t * sleep_obj = m_new_obj(pybsleep_obj_t); - sleep_obj->base.type = &pybsleep_type; +void pyb_sleep_add (const mp_obj_t obj, WakeUpCB_t wakeup) { + pyb_sleep_obj_t *sleep_obj = m_new_obj(pyb_sleep_obj_t); + sleep_obj->base.type = &pyb_sleep_type; sleep_obj->obj = obj; sleep_obj->wakeup = wakeup; // remove it in case it was already registered - pybsleep_remove (obj); - mp_obj_list_append(&MP_STATE_PORT(pybsleep_obj_list), sleep_obj); + pyb_sleep_remove (obj); + mp_obj_list_append(&MP_STATE_PORT(pyb_sleep_obj_list), sleep_obj); } -void pybsleep_remove (const mp_obj_t obj) { - pybsleep_obj_t *sleep_obj; - if ((sleep_obj = pybsleep_find(obj))) { - mp_obj_list_remove(&MP_STATE_PORT(pybsleep_obj_list), sleep_obj); +void pyb_sleep_remove (const mp_obj_t obj) { + pyb_sleep_obj_t *sleep_obj; + if ((sleep_obj = pyb_sleep_find(obj))) { + mp_obj_list_remove(&MP_STATE_PORT(pyb_sleep_obj_list), sleep_obj); } } -void pybsleep_set_gpio_lpds_callback (mp_obj_t cb_obj) { +void pyb_sleep_set_gpio_lpds_callback (mp_obj_t cb_obj) { pybsleep_data.gpio_lpds_wake_cb = cb_obj; } -void pybsleep_set_wlan_obj (mp_obj_t wlan_obj) { +void pyb_sleep_set_wlan_obj (mp_obj_t wlan_obj) { pybsleep_data.wlan_obj = (wlan_obj_t *)wlan_obj; } -void pybsleep_set_rtc_obj (mp_obj_t rtc_obj) { +void pyb_sleep_set_rtc_obj (mp_obj_t rtc_obj) { pybsleep_data.rtc_obj = (pyb_rtc_obj_t *)rtc_obj; } -pybsleep_reset_cause_t pybsleep_get_reset_cause (void) { +void pyb_sleep_sleep (void) { + nlr_buf_t nlr; + + // check if we should enable timer wake-up + if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_LPDS)) { + if (!setup_timer_lpds_wake()) { + // lpds entering is not possible, wait for the forced interrupt and return + HAL_Delay (FAILED_SLEEP_DELAY_MS); + return; + } + } else { + // disable the timer as wake source + MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER); + } + + // do we need network wake-up? + if (pybsleep_data.wlan_obj->irq_enabled) { + MAP_PRCMLPDSWakeupSourceEnable (PRCM_LPDS_HOST_IRQ); + server_sleep_sockets(); + } else { + MAP_PRCMLPDSWakeupSourceDisable (PRCM_LPDS_HOST_IRQ); + } + + // entering and exiting suspended mode must be an atomic operation + // therefore interrupts need to be disabled + uint primsk = disable_irq(); + if (nlr_push(&nlr) == 0) { + pyb_sleep_suspend_enter(); + nlr_pop(); + } + + // an exception is always raised when exiting suspend mode + enable_irq(primsk); +} + +void pyb_sleep_deepsleep (void) { + // check if we should enable timer wake-up + if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_HIBERNATE)) { + if (!setup_timer_hibernate_wake()) { + // hibernating is not possible, wait for the forced interrupt and return + HAL_Delay (FAILED_SLEEP_DELAY_MS); + return; + } + } else { + // disable the timer as hibernate wake source + MAP_PRCMLPDSWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR); + } + + wlan_stop(SL_STOP_TIMEOUT); + pyb_sleep_flash_powerdown(); + // must be done just before entering hibernate mode + pyb_sleep_iopark(true); + MAP_PRCMHibernateEnter(); +} + +pybsleep_reset_cause_t pyb_sleep_get_reset_cause (void) { return pybsleep_reset_cause; } +pybsleep_wake_reason_t pyb_sleep_get_wake_reason (void) { + return pybsleep_wake_reason; +} + /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ -STATIC pybsleep_obj_t *pybsleep_find (mp_obj_t obj) { - for (mp_uint_t i = 0; i < MP_STATE_PORT(pybsleep_obj_list).len; i++) { +STATIC pyb_sleep_obj_t *pyb_sleep_find (mp_obj_t obj) { + for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_sleep_obj_list).len; i++) { // search for the object and then remove it - pybsleep_obj_t *sleep_obj = ((pybsleep_obj_t *)(MP_STATE_PORT(pybsleep_obj_list).items[i])); + pyb_sleep_obj_t *sleep_obj = ((pyb_sleep_obj_t *)(MP_STATE_PORT(pyb_sleep_obj_list).items[i])); if (sleep_obj->obj == obj) { return sleep_obj; } @@ -255,7 +317,7 @@ STATIC pybsleep_obj_t *pybsleep_find (mp_obj_t obj) { return NULL; } -STATIC void pybsleep_flash_powerdown (void) { +STATIC void pyb_sleep_flash_powerdown (void) { uint32_t status; // Enable clock for SSPI module @@ -300,7 +362,7 @@ STATIC void pybsleep_flash_powerdown (void) { MAP_SPICSDisable(SSPI_BASE); } -STATIC NORETURN void pybsleep_suspend_enter (void) { +STATIC NORETURN void pyb_sleep_suspend_enter (void) { // enable full RAM retention MAP_PRCMSRAMRetentionEnable(PRCM_SRAM_COL_1 | PRCM_SRAM_COL_2 | PRCM_SRAM_COL_3 | PRCM_SRAM_COL_4, PRCM_SRAM_LPDS_RET); @@ -337,7 +399,7 @@ STATIC NORETURN void pybsleep_suspend_enter (void) { mperror_heartbeat_switch_off(); // park the gpio pins - pybsleep_iopark(false); + pyb_sleep_iopark(false); // store the cpu registers sleep_store(); @@ -350,7 +412,7 @@ STATIC NORETURN void pybsleep_suspend_enter (void) { for ( ; ; ); } -void pybsleep_suspend_exit (void) { +void pyb_sleep_suspend_exit (void) { // take the I2C semaphore uint32_t reg = HWREG(COMMON_REG_BASE + COMMON_REG_O_I2C_Properties_Register); reg = (reg & ~0x3) | 0x1; @@ -404,7 +466,7 @@ void pybsleep_suspend_exit (void) { sl_IfOpen (NULL, 0); // restore the configuration of all active peripherals - pybsleep_obj_wakeup(); + pyb_sleep_obj_wakeup(); // reconfigure all the previously enabled interrupts mp_irq_wake_all(); @@ -459,14 +521,14 @@ STATIC void PRCMInterruptHandler (void) { } } -STATIC void pybsleep_obj_wakeup (void) { - for (mp_uint_t i = 0; i < MP_STATE_PORT(pybsleep_obj_list).len; i++) { - pybsleep_obj_t *sleep_obj = ((pybsleep_obj_t *)MP_STATE_PORT(pybsleep_obj_list).items[i]); +STATIC void pyb_sleep_obj_wakeup (void) { + for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_sleep_obj_list).len; i++) { + pyb_sleep_obj_t *sleep_obj = ((pyb_sleep_obj_t *)MP_STATE_PORT(pyb_sleep_obj_list).items[i]); sleep_obj->wakeup(sleep_obj->obj); } } -STATIC void pybsleep_iopark (bool hibernate) { +STATIC void pyb_sleep_iopark (bool hibernate) { mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict); for (uint i = 0; i < named_map->used; i++) { pin_obj_t * pin = (pin_obj_t *)named_map->table[i].value; @@ -593,125 +655,3 @@ STATIC bool setup_timer_hibernate_wake (void) { return false; } -/******************************************************************************/ -// Micro Python bindings; Sleep class - -/// \function idle() -/// Gates the processor clock until an interrupt is triggered -STATIC mp_obj_t pyb_sleep_idle (mp_obj_t self_in) { - __WFI(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_idle_obj, pyb_sleep_idle); - -/// \function suspend(wlan) -/// Enters suspended mode. Wake up sources should have been enable prior to -/// calling this method. -STATIC mp_obj_t pyb_sleep_suspend (mp_obj_t self_in) { - nlr_buf_t nlr; - - // check if we should enable timer wake-up - if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_LPDS)) { - if (!setup_timer_lpds_wake()) { - // lpds entering is not possible, wait for the forced interrupt and return - HAL_Delay (FAILED_SLEEP_DELAY_MS); - return mp_const_none; - } - } else { - // disable the timer as wake source - MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER); - } - - // do we need network wake-up? - if (pybsleep_data.wlan_obj->irq_enabled) { - MAP_PRCMLPDSWakeupSourceEnable (PRCM_LPDS_HOST_IRQ); - server_sleep_sockets(); - } else { - MAP_PRCMLPDSWakeupSourceDisable (PRCM_LPDS_HOST_IRQ); - } - - // entering and exiting suspended mode must be an atomic operation - // therefore interrupts need to be disabled - uint primsk = disable_irq(); - if (nlr_push(&nlr) == 0) { - pybsleep_suspend_enter(); - nlr_pop(); - } - - // an exception is always raised when exiting suspend mode - enable_irq(primsk); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_suspend_obj, pyb_sleep_suspend); - -/// \function hibernate() -/// Enters hibernate mode. Wake up sources should have been enable prior to -/// calling this method. -STATIC mp_obj_t pyb_sleep_hibernate (mp_obj_t self_in) { - // check if we should enable timer wake-up - if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_HIBERNATE)) { - if (!setup_timer_hibernate_wake()) { - // hibernating is not possible, wait for the forced interrupt and return - HAL_Delay (FAILED_SLEEP_DELAY_MS); - return mp_const_none; - } - } else { - // disable the timer as hibernate wake source - MAP_PRCMLPDSWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR); - } - - wlan_stop(SL_STOP_TIMEOUT); - pybsleep_flash_powerdown(); - // must be done just before entering hibernate mode - pybsleep_iopark(true); - MAP_PRCMHibernateEnter(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_hibernate_obj, pyb_sleep_hibernate); - -/// \function reset_cause() -/// Returns the last reset casue -STATIC mp_obj_t pyb_sleep_reset_cause (mp_obj_t self_in) { - return MP_OBJ_NEW_SMALL_INT(pybsleep_reset_cause); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_reset_cause_obj, pyb_sleep_reset_cause); - -/// \function wake_reason() -/// Returns the wake up reson from ldps or hibernate -STATIC mp_obj_t pyb_sleep_wake_reason (mp_obj_t self_in) { - return MP_OBJ_NEW_SMALL_INT(pybsleep_wake_reason); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_wake_reason_obj, pyb_sleep_wake_reason); - -STATIC const mp_map_elem_t pybsleep_locals_dict_table[] = { - // instance methods - { MP_OBJ_NEW_QSTR(MP_QSTR_idle), (mp_obj_t)&pyb_sleep_idle_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_suspend), (mp_obj_t)&pyb_sleep_suspend_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_hibernate), (mp_obj_t)&pyb_sleep_hibernate_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_reset_cause), (mp_obj_t)&pyb_sleep_reset_cause_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_wake_reason), (mp_obj_t)&pyb_sleep_wake_reason_obj }, - - // class constants - { MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_ACTIVE) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SUSPENDED), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_LPDS) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_HIBERNATING), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HARD_RESET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WDT_RESET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_HIB_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HIB_RESET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOFT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_SOFT_RESET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_WLAN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_WLAN) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_PIN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_GPIO) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_RTC_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_RTC) }, -}; - -STATIC MP_DEFINE_CONST_DICT(pybsleep_locals_dict, pybsleep_locals_dict_table); - -STATIC const mp_obj_type_t pybsleep_type = { - { &mp_type_type }, - .name = MP_QSTR_Sleep, - .locals_dict = (mp_obj_t)&pybsleep_locals_dict, -}; - -const mp_obj_base_t pyb_sleep_obj = {&pybsleep_type}; |