summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authordanicampora <danicampora@gmail.com>2015-03-12 16:14:55 +0100
committerdanicampora <danicampora@gmail.com>2015-03-12 16:22:17 +0100
commit04749e677fdc11faec415682e58ac11faa7667db (patch)
treec68fcf163bfce8f431bffdb803b0343aa66a468d
parent10f7ef08321e535d62b024d8eb2b363d0fe0f2c1 (diff)
downloadmicropython-04749e677fdc11faec415682e58ac11faa7667db.tar.gz
micropython-04749e677fdc11faec415682e58ac11faa7667db.zip
cc3200: Allow separate selection of the power mode in Pin callbacks.
-rw-r--r--cc3200/misc/mpcallback.c2
-rw-r--r--cc3200/mods/modwlan.c18
-rw-r--r--cc3200/mods/pybpin.c225
-rw-r--r--cc3200/mods/pybsleep.c13
-rw-r--r--cc3200/mods/pybsleep.h12
-rw-r--r--cc3200/qstrdefsport.h1
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)