diff options
author | danicampora <danicampora@gmail.com> | 2015-03-12 16:14:55 +0100 |
---|---|---|
committer | danicampora <danicampora@gmail.com> | 2015-03-12 16:22:17 +0100 |
commit | 04749e677fdc11faec415682e58ac11faa7667db (patch) | |
tree | c68fcf163bfce8f431bffdb803b0343aa66a468d | |
parent | 10f7ef08321e535d62b024d8eb2b363d0fe0f2c1 (diff) | |
download | micropython-04749e677fdc11faec415682e58ac11faa7667db.tar.gz micropython-04749e677fdc11faec415682e58ac11faa7667db.zip |
cc3200: Allow separate selection of the power mode in Pin callbacks.
-rw-r--r-- | cc3200/misc/mpcallback.c | 2 | ||||
-rw-r--r-- | cc3200/mods/modwlan.c | 18 | ||||
-rw-r--r-- | cc3200/mods/pybpin.c | 225 | ||||
-rw-r--r-- | cc3200/mods/pybsleep.c | 13 | ||||
-rw-r--r-- | cc3200/mods/pybsleep.h | 12 | ||||
-rw-r--r-- | cc3200/qstrdefsport.h | 1 |
6 files changed, 181 insertions, 90 deletions
diff --git a/cc3200/misc/mpcallback.c b/cc3200/misc/mpcallback.c index 3a5611f5df..edf3673b5a 100644 --- a/cc3200/misc/mpcallback.c +++ b/cc3200/misc/mpcallback.c @@ -50,7 +50,7 @@ const mp_arg_t mpcallback_init_args[] = { { MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_priority, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_wake, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYB_PWR_MODE_ACTIVE_IDLE } }, + { MP_QSTR_wake, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYB_PWR_MODE_ACTIVE} }, }; /****************************************************************************** diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c index 55affab79c..c637dccf64 100644 --- a/cc3200/mods/modwlan.c +++ b/cc3200/mods/modwlan.c @@ -166,8 +166,8 @@ STATIC void wlan_reenable (SlWlanMode_t mode); STATIC void wlan_get_sl_mac (void); STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec, const char* key, uint32_t key_len); -STATIC void wlan_callback_enable (mp_obj_t self_in); -STATIC void wlan_callback_disable (mp_obj_t self_in); +STATIC void wlan_lpds_callback_enable (mp_obj_t self_in); +STATIC void wlan_lpds_callback_disable (mp_obj_t self_in); //***************************************************************************** // @@ -668,12 +668,12 @@ STATIC mp_obj_t wlan_init_helper(mp_uint_t n_args, const mp_obj_t *pos_args, mp_ return mp_const_none; } -STATIC void wlan_callback_enable (mp_obj_t self_in) { - pybsleep_set_wlan_wake_callback (wlan_obj.callback); +STATIC void wlan_lpds_callback_enable (mp_obj_t self_in) { + pybsleep_set_wlan_lpds_callback (wlan_obj.callback); } -STATIC void wlan_callback_disable (mp_obj_t self_in) { - pybsleep_set_wlan_wake_callback (NULL); +STATIC void wlan_lpds_callback_disable (mp_obj_t self_in) { + pybsleep_set_wlan_lpds_callback (NULL); } /******************************************************************************/ @@ -957,7 +957,7 @@ STATIC mp_obj_t wlan_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma self->callback = mpcallback_new (self, args[1].u_obj, &wlan_cb_methods); // enable network wakeup - pybsleep_set_wlan_wake_callback (self->callback); + pybsleep_set_wlan_lpds_callback (self->callback); } return self->callback; } @@ -1020,8 +1020,8 @@ STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table); STATIC const mp_cb_methods_t wlan_cb_methods = { .init = wlan_callback, - .enable = wlan_callback_enable, - .disable = wlan_callback_disable, + .enable = wlan_lpds_callback_enable, + .disable = wlan_lpds_callback_disable, }; /******************************************************************************/ diff --git a/cc3200/mods/pybpin.c b/cc3200/mods/pybpin.c index 7e561064ce..ca00d765e6 100644 --- a/cc3200/mods/pybpin.c +++ b/cc3200/mods/pybpin.c @@ -119,13 +119,36 @@ STATIC void GPIOA2IntHandler (void); STATIC void GPIOA3IntHandler (void); STATIC void EXTI_Handler(uint port); STATIC void pin_obj_configure (const pin_obj_t *self); +STATIC void pin_get_hibernate_pin_and_idx (const pin_obj_t *self, uint *wake_pin, uint *idx); STATIC void pin_extint_enable (mp_obj_t self_in); STATIC void pin_extint_disable (mp_obj_t self_in); /****************************************************************************** +DEFINE CONSTANTS +******************************************************************************/ +#define PYBPIN_NUM_WAKE_PINS (6) +#define PYBPIN_WAKES_NOT (-1) + +/****************************************************************************** +DEFINE TYPES +******************************************************************************/ +typedef struct { + bool active; + int8_t lpds; + int8_t hib; +} pybpin_wake_pin_t; + +/****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC const mp_cb_methods_t pin_cb_methods; +STATIC pybpin_wake_pin_t pybpin_wake_pin[PYBPIN_NUM_WAKE_PINS] = + { {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT}, + {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT}, + {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT}, + {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT}, + {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT}, + {.active = false, .lpds = PYBPIN_WAKES_NOT, .hib = PYBPIN_WAKES_NOT} } ; /****************************************************************************** DEFINE PUBLIC FUNCTIONS @@ -248,14 +271,83 @@ STATIC void pin_obj_configure (const pin_obj_t *self) { MAP_PinConfigSet(self->pin_num, self->strength, self->type); } +STATIC void pin_get_hibernate_pin_and_idx (const pin_obj_t *self, uint *hib_pin, uint *idx) { + // pin_num is actually : (package_pin - 1) + switch (self->pin_num) { + case 56: // GPIO2 + *hib_pin = PRCM_HIB_GPIO2; + *idx = 0; + break; + case 58: // GPIO4 + *hib_pin = PRCM_HIB_GPIO4; + *idx = 1; + break; + case 3: // GPIO13 + *hib_pin = PRCM_HIB_GPIO13; + *idx = 2; + break; + case 7: // GPIO17 + *hib_pin = PRCM_HIB_GPIO17; + *idx = 3; + break; + case 1: // GPIO11 + *hib_pin = PRCM_HIB_GPIO11; + *idx = 4; + break; + case 16: // GPIO24 + *hib_pin = PRCM_HIB_GPIO24; + *idx = 5; + break; + default: + *idx = 0xFF; + break; + } +} + STATIC void pin_extint_enable (mp_obj_t self_in) { - pin_obj_t *self = self_in; - MAP_GPIOIntClear(self->port, self->bit); - MAP_GPIOIntEnable(self->port, self->bit); + const pin_obj_t *self = self_in; + uint hib_pin, idx; + + pin_get_hibernate_pin_and_idx (self, &hib_pin, &idx); + if (idx < PYBPIN_NUM_WAKE_PINS) { + if (pybpin_wake_pin[idx].lpds != PYBPIN_WAKES_NOT) { + // enable GPIO as a wake source during LPDS + MAP_PRCMLPDSWakeUpGPIOSelect(idx, pybpin_wake_pin[idx].lpds); + MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_GPIO); + } + + if (pybpin_wake_pin[idx].hib != PYBPIN_WAKES_NOT) { + // enable GPIO as a wake source during hibernate + MAP_PRCMHibernateWakeUpGPIOSelect(hib_pin, pybpin_wake_pin[idx].hib); + MAP_PRCMHibernateWakeupSourceEnable(hib_pin); + } + else { + MAP_PRCMHibernateWakeupSourceDisable(hib_pin); + } + } + // if idx is invalid, the the pin supports active_idle interrupts for sure + if (idx >= PYBPIN_NUM_WAKE_PINS || pybpin_wake_pin[idx].active) { + MAP_GPIOIntClear(self->port, self->bit); + MAP_GPIOIntEnable(self->port, self->bit); + } } STATIC void pin_extint_disable (mp_obj_t self_in) { - pin_obj_t *self = self_in; + const pin_obj_t *self = self_in; + uint hib_pin, idx; + + pin_get_hibernate_pin_and_idx (self, &hib_pin, &idx); + if (idx < PYBPIN_NUM_WAKE_PINS) { + if (pybpin_wake_pin[idx].lpds != PYBPIN_WAKES_NOT) { + // disable GPIO as a wake source during LPDS + MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_GPIO); + } + if (pybpin_wake_pin[idx].hib != PYBPIN_WAKES_NOT) { + // disable GPIO as a wake source during hibernate + MAP_PRCMHibernateWakeupSourceDisable(hib_pin); + } + } + // not need to check for the active flag, it's safe to disable it anyway MAP_GPIOIntDisable(self->port, self->bit); } @@ -534,35 +626,20 @@ STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); } - if (args[4].u_int & PYB_PWR_MODE_LPDS) { - uint wake_pin; - uint wake_mode; - // pin_num is actually : (package_pin - 1) - switch (self->pin_num) { - case 56: // GPIO2 - wake_pin = PRCM_LPDS_GPIO2; - break; - case 58: // GPIO4 - wake_pin = PRCM_LPDS_GPIO4; - break; - case 3: // GPIO13 - wake_pin = PRCM_LPDS_GPIO13; - break; - case 7: // GPIO17 - wake_pin = PRCM_LPDS_GPIO17; - break; - case 1: // GPIO11 - wake_pin = PRCM_LPDS_GPIO11; - break; - case 16: // GPIO24 - wake_pin = PRCM_LPDS_GPIO24; - break; - default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); - break; - } + uint pwrmode = args[4].u_int; + if (pwrmode > (PYB_PWR_MODE_ACTIVE | PYB_PWR_MODE_LPDS | PYB_PWR_MODE_HIBERNATE)) { + goto invalid_args; + } - // intmodes are different in LDPS + // get the wake info from this pin + uint hib_pin, idx; + pin_get_hibernate_pin_and_idx ((const pin_obj_t *)self, &hib_pin, &idx); + if (pwrmode & PYB_PWR_MODE_LPDS) { + if (idx >= PYBPIN_NUM_WAKE_PINS) { + goto invalid_args; + } + // wake modes are different in LDPS + uint wake_mode; switch (intmode) { case GPIO_FALLING_EDGE: wake_mode = PRCM_LPDS_FALL_EDGE; @@ -577,44 +654,32 @@ STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map wake_mode = PRCM_LPDS_HIGH_LEVEL; break; default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + goto invalid_args; break; } - // enable GPIO as a wake source during LPDS - MAP_PRCMLPDSWakeUpGPIOSelect(wake_pin, wake_mode); - MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_GPIO); - } + // first clear the lpds value from all wake-able pins + for (uint i = 0; i < PYBPIN_NUM_WAKE_PINS; i++) { + pybpin_wake_pin[i].lpds = PYBPIN_WAKES_NOT; + } - if (args[4].u_int & PYB_PWR_MODE_HIBERNATE) { - uint wake_pin; - uint wake_mode; - // pin_num is actually : (package_pin - 1) - switch (self->pin_num) { - case 56: // GPIO2 - wake_pin = PRCM_HIB_GPIO2; - break; - case 58: // GPIO4 - wake_pin = PRCM_HIB_GPIO4; - break; - case 3: // GPIO13 - wake_pin = PRCM_HIB_GPIO13; - break; - case 7: // GPIO17 - wake_pin = PRCM_HIB_GPIO17; - break; - case 1: // GPIO11 - wake_pin = PRCM_HIB_GPIO11; - break; - case 16: // GPIO24 - wake_pin = PRCM_HIB_GPIO24; - break; - default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); - break; + // enable this pin as a wake-up source during LPDS + pybpin_wake_pin[idx].lpds = wake_mode; + } + else { + // this pin was the previous LPDS wake source, so disable it completely + if (pybpin_wake_pin[idx].lpds != PYBPIN_WAKES_NOT) { + MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_GPIO); } + pybpin_wake_pin[idx].lpds = PYBPIN_WAKES_NOT; + } - // intmodes are bit different in hibernate + if (pwrmode & PYB_PWR_MODE_HIBERNATE) { + if (idx >= PYBPIN_NUM_WAKE_PINS) { + goto invalid_args; + } + // wake modes are different in hibernate + uint wake_mode; switch (intmode) { case GPIO_FALLING_EDGE: wake_mode = PRCM_HIB_FALL_EDGE; @@ -629,26 +694,44 @@ STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map wake_mode = PRCM_HIB_HIGH_LEVEL; break; default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + goto invalid_args; break; } - // enable GPIO as a wake source during hibernate - MAP_PRCMHibernateWakeUpGPIOSelect(wake_pin, wake_mode); - MAP_PRCMHibernateWakeupSourceEnable(wake_pin); + // enable this pin as wake-up source during hibernate + pybpin_wake_pin[idx].hib = wake_mode; + } + else { + pybpin_wake_pin[idx].hib = PYBPIN_WAKES_NOT; } // we need to update the callback atomically, so we disable the // interrupt before we update anything. pin_extint_disable(self); - // register the interrupt - pin_extint_register((pin_obj_t *)self, intmode, priority); - // create the callback + if (pwrmode & PYB_PWR_MODE_ACTIVE) { + // register the interrupt + pin_extint_register((pin_obj_t *)self, intmode, priority); + if (idx < PYBPIN_NUM_WAKE_PINS) { + pybpin_wake_pin[idx].active = true; + } + } + else if (idx < PYBPIN_NUM_WAKE_PINS) { + pybpin_wake_pin[idx].active = false; + } + + // all checks have passed, now we can create the callback self->callback = mpcallback_new (self, args[1].u_obj, &pin_cb_methods); + if (pwrmode & PYB_PWR_MODE_LPDS) { + pybsleep_set_gpio_lpds_callback (self->callback); + } + // enable the interrupt just before leaving pin_extint_enable(self); } return self->callback; + +invalid_args: + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_callback_obj, 1, pin_callback); diff --git a/cc3200/mods/pybsleep.c b/cc3200/mods/pybsleep.c index 1427885f35..bbaeddefb5 100644 --- a/cc3200/mods/pybsleep.c +++ b/cc3200/mods/pybsleep.c @@ -159,15 +159,15 @@ void pybsleep_remove (const mp_obj_t obj) { } } -void pybsleep_set_wlan_wake_callback (mp_obj_t cb_obj) { +void pybsleep_set_wlan_lpds_callback (mp_obj_t cb_obj) { pybsleep_wake_cb.wlan_wake_cb = cb_obj; } -void pybsleep_set_gpio_wake_callback (mp_obj_t cb_obj) { +void pybsleep_set_gpio_lpds_callback (mp_obj_t cb_obj) { pybsleep_wake_cb.gpio_wake_cb = cb_obj; } -void pybsleep_set_timer_wake_callback (mp_obj_t cb_obj) { +void pybsleep_set_timer_lpds_callback (mp_obj_t cb_obj) { pybsleep_wake_cb.timer_wake_cb = cb_obj; } @@ -356,6 +356,12 @@ STATIC void PRCMInterruptHandler (void) { if (pybsleep_wake_cb.gpio_wake_cb) { mpcallback_handler(pybsleep_wake_cb.gpio_wake_cb); } + // clear all pending GPIO interrupts in order to + // avoid duplicated calls to the handler + MAP_IntPendClear(INT_GPIOA0); + MAP_IntPendClear(INT_GPIOA1); + MAP_IntPendClear(INT_GPIOA2); + MAP_IntPendClear(INT_GPIOA3); break; case PRCM_LPDS_TIMER: if (pybsleep_wake_cb.timer_wake_cb) { @@ -476,6 +482,7 @@ STATIC const mp_map_elem_t pybsleep_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_hibernate), (mp_obj_t)&pyb_sleep_hibernate_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) }, }; diff --git a/cc3200/mods/pybsleep.h b/cc3200/mods/pybsleep.h index 97997080d8..5abb49be80 100644 --- a/cc3200/mods/pybsleep.h +++ b/cc3200/mods/pybsleep.h @@ -30,9 +30,9 @@ /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ -#define PYB_PWR_MODE_ACTIVE_IDLE (0x00) -#define PYB_PWR_MODE_LPDS (0x01) -#define PYB_PWR_MODE_HIBERNATE (0x02) +#define PYB_PWR_MODE_ACTIVE (0x01) +#define PYB_PWR_MODE_LPDS (0x02) +#define PYB_PWR_MODE_HIBERNATE (0x04) /****************************************************************************** DEFINE TYPES @@ -50,8 +50,8 @@ extern const mp_obj_base_t pyb_sleep_obj; void pyblsleep_init0 (void); void pybsleep_add (const mp_obj_t obj, WakeUpCB_t wakeup); void pybsleep_remove (const mp_obj_t obj); -void pybsleep_set_wlan_wake_callback (mp_obj_t cb_obj); -void pybsleep_set_gpio_wake_callback (mp_obj_t cb_obj); -void pybsleep_set_timer_wake_callback (mp_obj_t cb_obj); +void pybsleep_set_wlan_lpds_callback (mp_obj_t cb_obj); +void pybsleep_set_gpio_lpds_callback (mp_obj_t cb_obj); +void pybsleep_set_timer_lpds_callback (mp_obj_t cb_obj); #endif /* PYBSLEEP_H_ */ diff --git a/cc3200/qstrdefsport.h b/cc3200/qstrdefsport.h index 6ddc1d8c87..65ac04680b 100644 --- a/cc3200/qstrdefsport.h +++ b/cc3200/qstrdefsport.h @@ -251,5 +251,6 @@ Q(Sleep) Q(idle) Q(suspend) Q(hibernate) +Q(ACTIVE) Q(SUSPENDED) Q(HIBERNATING) |