Commit 04749e67 authored by danicampora's avatar danicampora
Browse files

cc3200: Allow separate selection of the power mode in Pin callbacks.

parent 10f7ef08
...@@ -50,7 +50,7 @@ const mp_arg_t mpcallback_init_args[] = { ...@@ -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_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_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_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} },
}; };
/****************************************************************************** /******************************************************************************
......
...@@ -166,8 +166,8 @@ STATIC void wlan_reenable (SlWlanMode_t mode); ...@@ -166,8 +166,8 @@ STATIC void wlan_reenable (SlWlanMode_t mode);
STATIC void wlan_get_sl_mac (void); 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, 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); const char* key, uint32_t key_len);
STATIC void wlan_callback_enable (mp_obj_t self_in); STATIC void wlan_lpds_callback_enable (mp_obj_t self_in);
STATIC void wlan_callback_disable (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_ ...@@ -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; return mp_const_none;
} }
STATIC void wlan_callback_enable (mp_obj_t self_in) { STATIC void wlan_lpds_callback_enable (mp_obj_t self_in) {
pybsleep_set_wlan_wake_callback (wlan_obj.callback); pybsleep_set_wlan_lpds_callback (wlan_obj.callback);
} }
STATIC void wlan_callback_disable (mp_obj_t self_in) { STATIC void wlan_lpds_callback_disable (mp_obj_t self_in) {
pybsleep_set_wlan_wake_callback (NULL); 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 ...@@ -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); self->callback = mpcallback_new (self, args[1].u_obj, &wlan_cb_methods);
// enable network wakeup // enable network wakeup
pybsleep_set_wlan_wake_callback (self->callback); pybsleep_set_wlan_lpds_callback (self->callback);
} }
return self->callback; return self->callback;
} }
...@@ -1020,8 +1020,8 @@ STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table); ...@@ -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 = { STATIC const mp_cb_methods_t wlan_cb_methods = {
.init = wlan_callback, .init = wlan_callback,
.enable = wlan_callback_enable, .enable = wlan_lpds_callback_enable,
.disable = wlan_callback_disable, .disable = wlan_lpds_callback_disable,
}; };
/******************************************************************************/ /******************************************************************************/
......
...@@ -119,13 +119,36 @@ STATIC void GPIOA2IntHandler (void); ...@@ -119,13 +119,36 @@ STATIC void GPIOA2IntHandler (void);
STATIC void GPIOA3IntHandler (void); STATIC void GPIOA3IntHandler (void);
STATIC void EXTI_Handler(uint port); STATIC void EXTI_Handler(uint port);
STATIC void pin_obj_configure (const pin_obj_t *self); 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_enable (mp_obj_t self_in);
STATIC void pin_extint_disable (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 DECLARE PRIVATE DATA
******************************************************************************/ ******************************************************************************/
STATIC const mp_cb_methods_t pin_cb_methods; 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 DEFINE PUBLIC FUNCTIONS
...@@ -248,14 +271,83 @@ STATIC void pin_obj_configure (const pin_obj_t *self) { ...@@ -248,14 +271,83 @@ STATIC void pin_obj_configure (const pin_obj_t *self) {
MAP_PinConfigSet(self->pin_num, self->strength, self->type); 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) { STATIC void pin_extint_enable (mp_obj_t self_in) {
pin_obj_t *self = self_in; const pin_obj_t *self = self_in;
MAP_GPIOIntClear(self->port, self->bit); uint hib_pin, idx;
MAP_GPIOIntEnable(self->port, self->bit);
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) { 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); 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 ...@@ -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)); nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
} }
if (args[4].u_int & PYB_PWR_MODE_LPDS) { uint pwrmode = args[4].u_int;
uint wake_pin; if (pwrmode > (PYB_PWR_MODE_ACTIVE | PYB_PWR_MODE_LPDS | PYB_PWR_MODE_HIBERNATE)) {
uint wake_mode; goto invalid_args;
// 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;
}
// 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) { switch (intmode) {
case GPIO_FALLING_EDGE: case GPIO_FALLING_EDGE:
wake_mode = PRCM_LPDS_FALL_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 ...@@ -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; wake_mode = PRCM_LPDS_HIGH_LEVEL;
break; break;
default: default:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); goto invalid_args;
break; break;
} }
// enable GPIO as a wake source during LPDS // first clear the lpds value from all wake-able pins
MAP_PRCMLPDSWakeUpGPIOSelect(wake_pin, wake_mode); for (uint i = 0; i < PYBPIN_NUM_WAKE_PINS; i++) {
MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_GPIO); pybpin_wake_pin[i].lpds = PYBPIN_WAKES_NOT;
} }
if (args[4].u_int & PYB_PWR_MODE_HIBERNATE) { // enable this pin as a wake-up source during LPDS
uint wake_pin; pybpin_wake_pin[idx].lpds = wake_mode;
uint wake_mode; }
// pin_num is actually : (package_pin - 1) else {
switch (self->pin_num) { // this pin was the previous LPDS wake source, so disable it completely
case 56: // GPIO2 if (pybpin_wake_pin[idx].lpds != PYBPIN_WAKES_NOT) {
wake_pin = PRCM_HIB_GPIO2; MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_GPIO);
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;
} }
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) { switch (intmode) {
case GPIO_FALLING_EDGE: case GPIO_FALLING_EDGE:
wake_mode = PRCM_HIB_FALL_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 ...@@ -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; wake_mode = PRCM_HIB_HIGH_LEVEL;
break; break;
default: default:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); goto invalid_args;
break; break;
} }
// enable GPIO as a wake source during hibernate // enable this pin as wake-up source during hibernate
MAP_PRCMHibernateWakeUpGPIOSelect(wake_pin, wake_mode); pybpin_wake_pin[idx].hib = wake_mode;
MAP_PRCMHibernateWakeupSourceEnable(wake_pin); }
else {
pybpin_wake_pin[idx].hib = PYBPIN_WAKES_NOT;
} }
// we need to update the callback atomically, so we disable the // we need to update the callback atomically, so we disable the
// interrupt before we update anything. // interrupt before we update anything.
pin_extint_disable(self); pin_extint_disable(self);
// register the interrupt if (pwrmode & PYB_PWR_MODE_ACTIVE) {
pin_extint_register((pin_obj_t *)self, intmode, priority); // register the interrupt
// create the callback 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); 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 // enable the interrupt just before leaving
pin_extint_enable(self); pin_extint_enable(self);
} }
return self->callback; 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); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_callback_obj, 1, pin_callback);
......
...@@ -159,15 +159,15 @@ void pybsleep_remove (const mp_obj_t obj) { ...@@ -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; 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; 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; pybsleep_wake_cb.timer_wake_cb = cb_obj;
} }
...@@ -356,6 +356,12 @@ STATIC void PRCMInterruptHandler (void) { ...@@ -356,6 +356,12 @@ STATIC void PRCMInterruptHandler (void) {
if (pybsleep_wake_cb.gpio_wake_cb) { if (pybsleep_wake_cb.gpio_wake_cb) {
mpcallback_handler(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; break;
case PRCM_LPDS_TIMER: case PRCM_LPDS_TIMER:
if (pybsleep_wake_cb.timer_wake_cb) { if (pybsleep_wake_cb.timer_wake_cb) {
...@@ -476,6 +482,7 @@ STATIC const mp_map_elem_t pybsleep_locals_dict_table[] = { ...@@ -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 }, { MP_OBJ_NEW_QSTR(MP_QSTR_hibernate), (mp_obj_t)&pyb_sleep_hibernate_obj },
// class constants // 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_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_HIBERNATING), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) },
}; };
......
...@@ -30,9 +30,9 @@ ...@@ -30,9 +30,9 @@
/****************************************************************************** /******************************************************************************
DEFINE CONSTANTS DEFINE CONSTANTS
******************************************************************************/ ******************************************************************************/
#define PYB_PWR_MODE_ACTIVE_IDLE (0x00) #define PYB_PWR_MODE_ACTIVE (0x01)
#define PYB_PWR_MODE_LPDS (0x01) #define PYB_PWR_MODE_LPDS (0x02)
#define PYB_PWR_MODE_HIBERNATE (0x02) #define PYB_PWR_MODE_HIBERNATE (0x04)
/****************************************************************************** /******************************************************************************
DEFINE TYPES DEFINE TYPES
...@@ -50,8 +50,8 @@ extern const mp_obj_base_t pyb_sleep_obj; ...@@ -50,8 +50,8 @@ extern const mp_obj_base_t pyb_sleep_obj;
void pyblsleep_init0 (void); void pyblsleep_init0 (void);
void pybsleep_add (const mp_obj_t obj, WakeUpCB_t wakeup); void pybsleep_add (const mp_obj_t obj, WakeUpCB_t wakeup);
void pybsleep_remove (const mp_obj_t obj); 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);
void pybsleep_set_gpio_wake_callback (mp_obj_t cb_obj); void pybsleep_set_gpio_lpds_callback (mp_obj_t cb_obj);
void pybsleep_set_timer_wake_callback (mp_obj_t cb_obj); void pybsleep_set_timer_lpds_callback (mp_obj_t cb_obj);
#endif /* PYBSLEEP_H_ */ #endif /* PYBSLEEP_H_ */
...@@ -251,5 +251,6 @@ Q(Sleep) ...@@ -251,5 +251,6 @@ Q(Sleep)
Q(idle) Q(idle)
Q(suspend) Q(suspend)
Q(hibernate) Q(hibernate)
Q(ACTIVE)
Q(SUSPENDED) Q(SUSPENDED)
Q(HIBERNATING) Q(HIBERNATING)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment