summaryrefslogtreecommitdiffstatshomepage
path: root/cc3200/mods
diff options
context:
space:
mode:
authorDaniel Campora <daniel@wipy.io>2015-09-22 23:20:29 +0200
committerDaniel Campora <daniel@wipy.io>2015-09-27 01:48:20 +0200
commitdbdcb58d6413a907e5f4aed25eee85073ff7e575 (patch)
tree0ecc90d3a3a947639549afde2b94c3d35b13fc2a /cc3200/mods
parent81d64ab939ff45e74b0154e4ce2d9c5d2cfe6328 (diff)
downloadmicropython-dbdcb58d6413a907e5f4aed25eee85073ff7e575.tar.gz
micropython-dbdcb58d6413a907e5f4aed25eee85073ff7e575.zip
cc3200: New irq API, affects all classes that provide the irq method.
Diffstat (limited to 'cc3200/mods')
-rw-r--r--cc3200/mods/modutime.c11
-rw-r--r--cc3200/mods/modwlan.c108
-rw-r--r--cc3200/mods/modwlan.h30
-rw-r--r--cc3200/mods/pybpin.c303
-rw-r--r--cc3200/mods/pybpin.h8
-rw-r--r--cc3200/mods/pybrtc.c334
-rw-r--r--cc3200/mods/pybrtc.h24
-rw-r--r--cc3200/mods/pybsd.c2
-rw-r--r--cc3200/mods/pybsleep.c157
-rw-r--r--cc3200/mods/pybsleep.h5
-rw-r--r--cc3200/mods/pybtimer.c246
-rw-r--r--cc3200/mods/pybuart.c158
-rw-r--r--cc3200/mods/pybuart.h1
13 files changed, 766 insertions, 621 deletions
diff --git a/cc3200/mods/modutime.c b/cc3200/mods/modutime.c
index 1899565999..05e7b5dca1 100644
--- a/cc3200/mods/modutime.c
+++ b/cc3200/mods/modutime.c
@@ -56,7 +56,7 @@
/// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
/// contains: (year, month, mday, hour, minute, second, weekday, yearday)
/// If secs is not provided or None, then the current time from the RTC is used.
-/// year includes the century (for example 2014)
+/// year includes the century (for example 2015)
/// month is 1-12
/// mday is 1-31
/// hour is 0-23
@@ -67,14 +67,9 @@
STATIC mp_obj_t time_localtime(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0 || args[0] == mp_const_none) {
timeutils_struct_time_t tm;
- uint32_t seconds;
- uint16_t mseconds;
-
- // get the seconds and the milliseconds from the RTC
- MAP_PRCMRTCGet(&seconds, &mseconds);
- mseconds = RTC_CYCLES_U16MS(mseconds);
- timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
+ // get the seconds from the RTC
+ timeutils_seconds_since_2000_to_struct_time(pyb_rtc_get_seconds(), &tm);
mp_obj_t tuple[8] = {
mp_obj_new_int(tm.tm_year),
mp_obj_new_int(tm.tm_mon),
diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c
index 1c3e63710e..b7ff7b5941 100644
--- a/cc3200/mods/modwlan.c
+++ b/cc3200/mods/modwlan.c
@@ -51,7 +51,7 @@
#include "serverstask.h"
#endif
#include "mpexception.h"
-#include "mpcallback.h"
+#include "mpirq.h"
#include "pybsleep.h"
#include "antenna.h"
@@ -88,31 +88,6 @@ typedef enum{
// the ping operation
} e_StatusBits;
-typedef struct _wlan_obj_t {
- mp_obj_base_t base;
- uint32_t status;
-
- uint32_t ip;
-
- int8_t mode;
- uint8_t security;
- uint8_t channel;
- uint8_t antenna;
-
- // my own ssid, key and mac
- uint8_t ssid[33];
- uint8_t key[65];
- uint8_t mac[SL_MAC_ADDR_LEN];
-
- // the sssid (or name) and mac of the other device
- uint8_t ssid_o[33];
- uint8_t bssid[6];
-
-#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
- bool servers_enabled;
-#endif
-} wlan_obj_t;
-
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
@@ -181,7 +156,7 @@ STATIC wlan_obj_t wlan_obj = {
#endif
};
-STATIC const mp_cb_methods_t wlan_cb_methods;
+STATIC const mp_irq_methods_t wlan_irq_methods;
/******************************************************************************
DECLARE PUBLIC DATA
@@ -199,8 +174,8 @@ STATIC void wlan_get_sl_mac (void);
STATIC void wlan_wep_key_unhexlify(const char *key, char *key_out);
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, uint32_t timeout);
-STATIC void wlan_lpds_callback_enable (mp_obj_t self_in);
-STATIC void wlan_lpds_callback_disable (mp_obj_t self_in);
+STATIC void wlan_lpds_irq_enable (mp_obj_t self_in);
+STATIC void wlan_lpds_irq_disable (mp_obj_t self_in);
STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid);
//*****************************************************************************
@@ -793,13 +768,19 @@ arg_error:
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_iwconfig_obj, 1, wlan_iwconfig);
-STATIC void wlan_lpds_callback_enable (mp_obj_t self_in) {
- mp_obj_t _callback = mpcallback_find(self_in);
- pybsleep_set_wlan_lpds_callback (_callback);
+STATIC void wlan_lpds_irq_enable (mp_obj_t self_in) {
+ wlan_obj_t *self = self_in;
+ self->irq_enabled = true;
}
-STATIC void wlan_lpds_callback_disable (mp_obj_t self_in) {
- pybsleep_set_wlan_lpds_callback (NULL);
+STATIC void wlan_lpds_irq_disable (mp_obj_t self_in) {
+ wlan_obj_t *self = self_in;
+ self->irq_enabled = false;
+}
+
+STATIC int wlan_irq_flags (mp_obj_t self_in) {
+ wlan_obj_t *self = self_in;
+ return self->irq_flags;
}
STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid) {
@@ -829,6 +810,7 @@ STATIC mp_obj_t wlan_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
mp_map_init_fixed_table(&kw_args, n_kw, args);
wlan_iwconfig(n_args + 1, (const mp_obj_t *)&wlan_obj, &kw_args);
}
+ pybsleep_set_wlan_obj(&wlan_obj);
return &wlan_obj;
}
@@ -1086,34 +1068,34 @@ STATIC mp_obj_t wlan_scan(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_scan_obj, wlan_scan);
-/// \method callback(handler, pwrmode)
-/// Create a callback object associated with the WLAN subsystem
-/// Only takes one argument (wake_from)
-STATIC mp_obj_t wlan_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
+/// \method irq(trigger, priority, handler, wake)
+STATIC mp_obj_t wlan_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_arg_val_t args[mp_irq_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args);
wlan_obj_t *self = pos_args[0];
- mp_obj_t _callback = mpcallback_find(self);
- // check if any parameters were passed
- if (kw_args->used > 0) {
- // check the power mode
- if (args[4].u_int != PYB_PWR_MODE_LPDS) {
- // throw an exception since WLAN only supports LPDS mode
- nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
- }
- // create the callback
- _callback = mpcallback_new (self, args[1].u_obj, &wlan_cb_methods, true);
+ // check the trigger, only one type is supported
+ if (mp_obj_get_int(args[0].u_obj) != MODWLAN_WIFI_EVENT_ANY) {
+ goto invalid_args;
+ }
- // enable network wakeup
- pybsleep_set_wlan_lpds_callback (_callback);
- } else if (!_callback) {
- _callback = mpcallback_new (self, mp_const_none, &wlan_cb_methods, false);
+ // check the power mode
+ if (mp_obj_get_int(args[3].u_obj) != PYB_PWR_MODE_LPDS) {
+ goto invalid_args;
}
- return _callback;
+
+ // create the callback
+ mp_obj_t _irq = mp_irq_new (self, args[2].u_obj, &wlan_irq_methods);
+ self->irq_obj = _irq;
+
+ return _irq;
+
+invalid_args:
+ // throw an exception since WLAN only supports LPDS mode
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_callback_obj, 1, wlan_callback);
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq);
/// \method mac()
/// returns the MAC address
@@ -1150,7 +1132,7 @@ STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
#if MICROPY_PORT_WLAN_URN
{ MP_OBJ_NEW_QSTR(MP_QSTR_urn), (mp_obj_t)&wlan_urn_obj },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&wlan_callback_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&wlan_irq_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_STA), MP_OBJ_NEW_SMALL_INT(ROLE_STA) },
@@ -1161,6 +1143,7 @@ STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA2), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPA_WPA2) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_INTERNAL), MP_OBJ_NEW_SMALL_INT(ANTENNA_TYPE_INTERNAL) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_EXTERNAL), MP_OBJ_NEW_SMALL_INT(ANTENNA_TYPE_EXTERNAL) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ANY_EVENT), MP_OBJ_NEW_SMALL_INT(MODWLAN_WIFI_EVENT_ANY) },
};
STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table);
@@ -1173,10 +1156,11 @@ const mod_network_nic_type_t mod_network_nic_type_wlan = {
},
};
-STATIC const mp_cb_methods_t wlan_cb_methods = {
- .init = wlan_callback,
- .enable = wlan_lpds_callback_enable,
- .disable = wlan_lpds_callback_disable,
+STATIC const mp_irq_methods_t wlan_irq_methods = {
+ .init = wlan_irq,
+ .enable = wlan_lpds_irq_enable,
+ .disable = wlan_lpds_irq_disable,
+ .flags = wlan_irq_flags,
};
/******************************************************************************/
@@ -1373,7 +1357,7 @@ int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t
tv.tv_usec = 1;
int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv);
- // check for error
+ // check for errors
if (nfds == -1) {
*_errno = nfds;
return -1;
diff --git a/cc3200/mods/modwlan.h b/cc3200/mods/modwlan.h
index 6693209d71..1386d2d191 100644
--- a/cc3200/mods/modwlan.h
+++ b/cc3200/mods/modwlan.h
@@ -35,6 +35,8 @@
#define SL_STOP_TIMEOUT 35
#define SL_STOP_TIMEOUT_LONG 575
+#define MODWLAN_WIFI_EVENT_ANY 0x01
+
/******************************************************************************
DEFINE TYPES
******************************************************************************/
@@ -45,6 +47,34 @@ typedef enum {
MODWLAN_ERROR_UNKNOWN = -3,
} modwlan_Status_t;
+typedef struct _wlan_obj_t {
+ mp_obj_base_t base;
+ mp_obj_t irq_obj;
+ uint32_t status;
+
+ uint32_t ip;
+
+ int8_t mode;
+ uint8_t security;
+ uint8_t channel;
+ uint8_t antenna;
+
+ // my own ssid, key and mac
+ uint8_t ssid[33];
+ uint8_t key[65];
+ uint8_t mac[SL_MAC_ADDR_LEN];
+
+ // the sssid (or name) and mac of the other device
+ uint8_t ssid_o[33];
+ uint8_t bssid[6];
+ uint8_t irq_flags;
+ bool irq_enabled;
+
+#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
+ bool servers_enabled;
+#endif
+} wlan_obj_t;
+
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
diff --git a/cc3200/mods/pybpin.c b/cc3200/mods/pybpin.c
index 82143128e2..02b5fbfd3e 100644
--- a/cc3200/mods/pybpin.c
+++ b/cc3200/mods/pybpin.c
@@ -45,9 +45,9 @@
#include "gpio.h"
#include "interrupt.h"
#include "pybpin.h"
+#include "mpirq.h"
#include "pins.h"
#include "pybsleep.h"
-#include "mpcallback.h"
#include "mpexception.h"
#include "mperror.h"
@@ -66,8 +66,8 @@ STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type);
STATIC void pin_deassign (pin_obj_t* pin);
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);
+STATIC void pin_irq_enable (mp_obj_t self_in);
+STATIC void pin_irq_disable (mp_obj_t self_in);
STATIC void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t priority);
STATIC void pin_validate_mode (uint mode);
STATIC void pin_validate_pull (uint pull);
@@ -88,6 +88,11 @@ DEFINE CONSTANTS
#define GPIO_DIR_MODE_ALT 0x00000002 // Pin is NOT controlled by the PGIO module
#define GPIO_DIR_MODE_ALT_OD 0x00000003 // Pin is NOT controlled by the PGIO module and is in open drain mode
+#define PYB_PIN_FALLING_EDGE 0x01
+#define PYB_PIN_RISING_EDGE 0x02
+#define PYB_PIN_LOW_LEVEL 0x04
+#define PYB_PIN_HIGH_LEVEL 0x08
+
/******************************************************************************
DEFINE TYPES
******************************************************************************/
@@ -100,7 +105,7 @@ typedef struct {
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
-STATIC const mp_cb_methods_t pin_cb_methods;
+STATIC const mp_irq_methods_t pin_irq_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},
@@ -334,7 +339,7 @@ STATIC void pin_get_hibernate_pin_and_idx (const pin_obj_t *self, uint *hib_pin,
}
}
-STATIC void pin_extint_enable (mp_obj_t self_in) {
+STATIC void pin_irq_enable (mp_obj_t self_in) {
const pin_obj_t *self = self_in;
uint hib_pin, idx;
@@ -366,7 +371,7 @@ STATIC void pin_extint_enable (mp_obj_t self_in) {
}
}
-STATIC void pin_extint_disable (mp_obj_t self_in) {
+STATIC void pin_irq_disable (mp_obj_t self_in) {
const pin_obj_t *self = self_in;
uint hib_pin, idx;
@@ -385,6 +390,11 @@ STATIC void pin_extint_disable (mp_obj_t self_in) {
MAP_GPIOIntDisable(self->port, self->bit);
}
+STATIC int pin_irq_flags (mp_obj_t self_in) {
+ const pin_obj_t *self = self_in;
+ return self->irq_flags;
+}
+
STATIC void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t priority) {
void *handler;
uint32_t intnum;
@@ -467,14 +477,22 @@ STATIC void EXTI_Handler(uint port) {
uint32_t bits = MAP_GPIOIntStatus(port, true);
MAP_GPIOIntClear(port, bits);
- // might be that we have more than one Pin interrupt pending
+ // might be that we have more than one pin interrupt pending
// therefore we must loop through all of the 8 possible bits
for (int i = 0; i < 8; i++) {
uint32_t bit = (1 << i);
if (bit & bits) {
pin_obj_t *self = (pin_obj_t *)pin_find_pin_by_port_bit(&pin_board_pins_locals_dict, port, bit);
- mp_obj_t _callback = mpcallback_find(self);
- mpcallback_handler(_callback);
+ if (self->irq_trigger == (PYB_PIN_FALLING_EDGE | PYB_PIN_RISING_EDGE)) {
+ // read the pin value (hoping that the pin level has remained stable)
+ self->irq_flags = MAP_GPIOPinRead(self->port, self->bit) ? PYB_PIN_RISING_EDGE : PYB_PIN_FALLING_EDGE;
+ } else {
+ // same as the triggers
+ self->irq_flags = self->irq_trigger;
+ }
+ mp_irq_handler(mp_irq_find(self));
+ // always clear the flags after leaving the user handler
+ self->irq_flags = 0;
}
}
}
@@ -484,7 +502,7 @@ STATIC void EXTI_Handler(uint port) {
// Micro Python bindings
STATIC const mp_arg_t pin_init_args[] = {
- { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
+ { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PIN_STRENGTH_4MA} },
@@ -498,8 +516,14 @@ STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, mp_uint_t n_args, const mp_
mp_arg_parse_all(n_args, pos_args, kw_args, pin_INIT_NUM_ARGS, pin_init_args, args);
// get the io mode
- uint mode = args[0].u_int;
- pin_validate_mode(mode);
+ uint mode;
+ // default is input
+ if (args[0].u_obj == MP_OBJ_NULL) {
+ mode = GPIO_DIR_MODE_IN;
+ } else {
+ mode = mp_obj_get_int(args[0].u_obj);
+ pin_validate_mode (mode);
+ }
// get the pull type
uint pull;
@@ -609,12 +633,9 @@ STATIC mp_obj_t pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
// Run an argument through the mapper and return the result.
pin_obj_t *pin = (pin_obj_t *)pin_find(args[0]);
- if (n_args > 1 || n_kw > 0) {
- // pin af given, so configure it
- mp_map_t kw_args;
- mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
- pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
- }
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
return (mp_obj_t)pin;
}
@@ -726,136 +747,147 @@ STATIC mp_obj_t pin_alt_list(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_alt_list_obj, pin_alt_list);
-STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
-
+/// \method irq(trigger, priority, handler, wake)
+STATIC mp_obj_t pin_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_arg_val_t args[mp_irq_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args);
pin_obj_t *self = pos_args[0];
- // check if any parameters were passed
- mp_obj_t _callback = mpcallback_find(self);
- if (kw_args->used > 0) {
- // convert the priority to the correct value
- uint priority = mpcallback_translate_priority (args[2].u_int);
- // verify the interrupt mode
- uint intmode = args[0].u_int;
- if (intmode == (GPIO_FALLING_EDGE | GPIO_RISING_EDGE)) {
- intmode = GPIO_BOTH_EDGES;
- }
- else if (intmode != GPIO_FALLING_EDGE && intmode != GPIO_RISING_EDGE &&
- intmode != GPIO_LOW_LEVEL && intmode != GPIO_HIGH_LEVEL) {
- goto invalid_args;
- }
- uint pwrmode = args[4].u_int;
- if (pwrmode > (PYB_PWR_MODE_ACTIVE | PYB_PWR_MODE_LPDS | PYB_PWR_MODE_HIBERNATE)) {
+ // convert the priority to the correct value
+ uint priority = mp_irq_translate_priority (args[1].u_int);
+
+ // verify and translate the interrupt mode
+ uint mp_trigger = mp_obj_get_int(args[0].u_obj);
+ uint trigger;
+ if (mp_trigger == (PYB_PIN_FALLING_EDGE | PYB_PIN_RISING_EDGE)) {
+ trigger = GPIO_BOTH_EDGES;
+ } else {
+ switch (mp_trigger) {
+ case PYB_PIN_FALLING_EDGE:
+ trigger = GPIO_FALLING_EDGE;
+ break;
+ case PYB_PIN_RISING_EDGE:
+ trigger = GPIO_RISING_EDGE;
+ break;
+ case PYB_PIN_LOW_LEVEL:
+ trigger = GPIO_LOW_LEVEL;
+ break;
+ case PYB_PIN_HIGH_LEVEL:
+ trigger = GPIO_HIGH_LEVEL;
+ break;
+ default:
goto invalid_args;
}
+ }
- // 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;
- break;
- case GPIO_RISING_EDGE:
- wake_mode = PRCM_LPDS_RISE_EDGE;
- break;
- case GPIO_LOW_LEVEL:
- wake_mode = PRCM_LPDS_LOW_LEVEL;
- break;
- case GPIO_HIGH_LEVEL:
- wake_mode = PRCM_LPDS_HIGH_LEVEL;
- break;
- default:
- goto invalid_args;
- break;
- }
-
- // 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;
- }
+ uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj);
+ if (pwrmode > (PYB_PWR_MODE_ACTIVE | PYB_PWR_MODE_LPDS | PYB_PWR_MODE_HIBERNATE)) {
+ goto invalid_args;
+ }
- // enable this pin as a wake-up source during LPDS
- pybpin_wake_pin[idx].lpds = wake_mode;
+ // 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;
}
- 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;
+ // wake modes are different in LDPS
+ uint wake_mode;
+ switch (trigger) {
+ case GPIO_FALLING_EDGE:
+ wake_mode = PRCM_LPDS_FALL_EDGE;
+ break;
+ case GPIO_RISING_EDGE:
+ wake_mode = PRCM_LPDS_RISE_EDGE;
+ break;
+ case GPIO_LOW_LEVEL:
+ wake_mode = PRCM_LPDS_LOW_LEVEL;
+ break;
+ case GPIO_HIGH_LEVEL:
+ wake_mode = PRCM_LPDS_HIGH_LEVEL;
+ break;
+ default:
+ goto invalid_args;
+ break;
}
- 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;
- break;
- case GPIO_RISING_EDGE:
- wake_mode = PRCM_HIB_RISE_EDGE;
- break;
- case GPIO_LOW_LEVEL:
- wake_mode = PRCM_HIB_LOW_LEVEL;
- break;
- case GPIO_HIGH_LEVEL:
- wake_mode = PRCM_HIB_HIGH_LEVEL;
- break;
- default:
- goto invalid_args;
- break;
- }
-
- // enable this pin as wake-up source during hibernate
- pybpin_wake_pin[idx].hib = wake_mode;
+ // 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;
}
- else {
- pybpin_wake_pin[idx].hib = PYBPIN_WAKES_NOT;
+
+ // enable this pin as a wake-up source during LPDS
+ pybpin_wake_pin[idx].lpds = wake_mode;
+ } else if (idx < PYBPIN_NUM_WAKE_PINS) {
+ // 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;
+ }
- // we need to update the callback atomically, so we disable the
- // interrupt before we update anything.
- pin_extint_disable(self);
- 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;
- }
+ if (pwrmode & PYB_PWR_MODE_HIBERNATE) {
+ if (idx >= PYBPIN_NUM_WAKE_PINS) {
+ goto invalid_args;
}
- else if (idx < PYBPIN_NUM_WAKE_PINS) {
- pybpin_wake_pin[idx].active = false;
+ // wake modes are different in hibernate
+ uint wake_mode;
+ switch (trigger) {
+ case GPIO_FALLING_EDGE:
+ wake_mode = PRCM_HIB_FALL_EDGE;
+ break;
+ case GPIO_RISING_EDGE:
+ wake_mode = PRCM_HIB_RISE_EDGE;
+ break;
+ case GPIO_LOW_LEVEL:
+ wake_mode = PRCM_HIB_LOW_LEVEL;
+ break;
+ case GPIO_HIGH_LEVEL:
+ wake_mode = PRCM_HIB_HIGH_LEVEL;
+ break;
+ default:
+ goto invalid_args;
+ break;
}
- // all checks have passed, now we can create the callback
- _callback = mpcallback_new (self, args[1].u_obj, &pin_cb_methods, true);
- if (pwrmode & PYB_PWR_MODE_LPDS) {
- pybsleep_set_gpio_lpds_callback (_callback);
+ // enable this pin as wake-up source during hibernate
+ pybpin_wake_pin[idx].hib = wake_mode;
+ } else if (idx < PYBPIN_NUM_WAKE_PINS) {
+ 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_irq_disable(self);
+ if (pwrmode & PYB_PWR_MODE_ACTIVE) {
+ // register the interrupt
+ pin_extint_register((pin_obj_t *)self, trigger, 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;
+ }
- // enable the interrupt just before leaving
- pin_extint_enable(self);
- } else if (!_callback) {
- _callback = mpcallback_new (self, mp_const_none, &pin_cb_methods, false);
+ // all checks have passed, we can create the irq object
+ mp_obj_t _irq = mp_irq_new (self, args[2].u_obj, &pin_irq_methods);
+ if (pwrmode & PYB_PWR_MODE_LPDS) {
+ pybsleep_set_gpio_lpds_callback (_irq);
}
- return _callback;
+
+ // save the mp_trigge for later
+ self->irq_trigger = mp_trigger;
+
+ // enable the interrupt just before leaving
+ pin_irq_enable(self);
+
+ return _irq;
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_irq_obj, 1, pin_irq);
STATIC const mp_map_elem_t pin_locals_dict_table[] = {
// instance methods
@@ -867,7 +899,7 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_pull), (mp_obj_t)&pin_pull_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_drive), (mp_obj_t)&pin_drive_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_alt_list), (mp_obj_t)&pin_alt_list_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pin_callback_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pin_irq_obj },
// class attributes
{ MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&pin_board_pins_obj_type },
@@ -883,10 +915,10 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_LOW_POWER), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_2MA) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MED_POWER), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_4MA) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HIGH_POWER), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_6MA) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_FALLING_EDGE) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING), MP_OBJ_NEW_SMALL_INT(GPIO_RISING_EDGE) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_LOW_LEVEL), MP_OBJ_NEW_SMALL_INT(GPIO_LOW_LEVEL) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_HIGH_LEVEL), MP_OBJ_NEW_SMALL_INT(GPIO_HIGH_LEVEL) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_FALLING), MP_OBJ_NEW_SMALL_INT(PYB_PIN_FALLING_EDGE) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING), MP_OBJ_NEW_SMALL_INT(PYB_PIN_RISING_EDGE) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_LOW_LEVEL), MP_OBJ_NEW_SMALL_INT(PYB_PIN_LOW_LEVEL) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_HIGH_LEVEL), MP_OBJ_NEW_SMALL_INT(PYB_PIN_HIGH_LEVEL) },
};
STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table);
@@ -900,10 +932,11 @@ const mp_obj_type_t pin_type = {
.locals_dict = (mp_obj_t)&pin_locals_dict,
};
-STATIC const mp_cb_methods_t pin_cb_methods = {
- .init = pin_callback,
- .enable = pin_extint_enable,
- .disable = pin_extint_disable,
+STATIC const mp_irq_methods_t pin_irq_methods = {
+ .init = pin_irq,
+ .enable = pin_irq_enable,
+ .disable = pin_irq_disable,
+ .flags = pin_irq_flags,
};
STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
diff --git a/cc3200/mods/pybpin.h b/cc3200/mods/pybpin.h
index 72a90874c4..3e7784926f 100644
--- a/cc3200/mods/pybpin.h
+++ b/cc3200/mods/pybpin.h
@@ -110,9 +110,11 @@ typedef struct {
int8_t af;
uint8_t strength;
uint8_t mode; // this is now a combination of type and mode
- uint8_t num_afs: 6; // up to 63 AFs
- uint8_t value : 1;
- uint8_t used : 1;
+ const uint8_t num_afs; // 255 AFs
+ uint8_t value;
+ uint8_t used;
+ uint8_t irq_trigger;
+ uint8_t irq_flags;
} pin_obj_t;
extern const mp_obj_type_t pin_type;
diff --git a/cc3200/mods/pybrtc.c b/cc3200/mods/pybrtc.c
index cc2e26f3a3..6eb9b76515 100644
--- a/cc3200/mods/pybrtc.c
+++ b/cc3200/mods/pybrtc.c
@@ -37,8 +37,8 @@
#include "rom_map.h"
#include "prcm.h"
#include "pybrtc.h"
+#include "mpirq.h"
#include "pybsleep.h"
-#include "mpcallback.h"
#include "timeutils.h"
#include "simplelink.h"
#include "modnetwork.h"
@@ -49,87 +49,147 @@
/// \class RTC - real time clock
/******************************************************************************
- DEFINE TYPES
+ DECLARE PRIVATE DATA
******************************************************************************/
-typedef struct _pyb_rtc_obj_t {
- mp_obj_base_t base;
- byte prwmode;
- bool alarmset;
- bool repeat;
-} pyb_rtc_obj_t;
+STATIC const mp_irq_methods_t pyb_rtc_irq_methods;
+STATIC pyb_rtc_obj_t pyb_rtc_obj;
/******************************************************************************
- DECLARE PRIVATE DATA
+ FUNCTION-LIKE MACROS
******************************************************************************/
-STATIC const mp_cb_methods_t pybrtc_cb_methods;
-STATIC pyb_rtc_obj_t pyb_rtc_obj = {.prwmode = 0, .alarmset = false, .repeat = false};
+#define RTC_U16MS_CYCLES(msec) ((msec * 1024) / 1000)
+#define RTC_CYCLES_U16MS(cycles) ((cycles * 1000) / 1024)
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
-STATIC uint32_t pyb_rtc_reset (mp_obj_t self_in);
-STATIC void pyb_rtc_callback_enable (mp_obj_t self_in);
-STATIC void pyb_rtc_callback_disable (mp_obj_t self_in);
+STATIC void pyb_rtc_set_time (uint32_t secs, uint16_t msecs);
+STATIC uint32_t pyb_rtc_reset (void);
+STATIC void pyb_rtc_disable_interupt (void);
+STATIC void pyb_rtc_irq_enable (mp_obj_t self_in);
+STATIC void pyb_rtc_irq_disable (mp_obj_t self_in);
+STATIC int pyb_rtc_irq_flags (mp_obj_t self_in);
+STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds);
STATIC mp_obj_t pyb_rtc_datetime(mp_obj_t self, const mp_obj_t datetime);
+STATIC void pyb_rtc_set_alarm (pyb_rtc_obj_t *self, uint32_t seconds, uint16_t mseconds);
+STATIC void rtc_msec_add(uint16_t msecs_1, uint32_t *secs, uint16_t *msecs_2);
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
__attribute__ ((section (".boot")))
void pyb_rtc_pre_init(void) {
- // if the RTC was previously set, leave it alone
+ // only if comming out of a power-on reset
if (MAP_PRCMSysResetCauseGet() == PRCM_POWER_ON) {
// Mark the RTC in use first
MAP_PRCMRTCInUseSet();
// reset the time and date
- pyb_rtc_reset((mp_obj_t)&pyb_rtc_obj);
+ pyb_rtc_reset();
}
}
+void pyb_rtc_get_time (uint32_t *secs, uint16_t *msecs) {
+ uint16_t cycles;
+ MAP_PRCMRTCGet (secs, &cycles);
+ *msecs = RTC_CYCLES_U16MS(cycles);
+}
+
uint32_t pyb_rtc_get_seconds (void) {
uint32_t seconds;
uint16_t mseconds;
- MAP_PRCMRTCGet(&seconds, &mseconds);
+ pyb_rtc_get_time(&seconds, &mseconds);
return seconds;
}
+void pyb_rtc_calc_future_time (uint32_t a_mseconds, uint32_t *f_seconds, uint16_t *f_mseconds) {
+ uint32_t c_seconds;
+ uint16_t c_mseconds;
+ // get the current time
+ pyb_rtc_get_time(&c_seconds, &c_mseconds);
+ // calculate the future seconds
+ *f_seconds = c_seconds + (a_mseconds / 1000);
+ // calculate the "remaining" future mseconds
+ *f_mseconds = a_mseconds % 1000;
+ // add the current milliseconds
+ rtc_msec_add (c_mseconds, f_seconds, f_mseconds);
+}
+
+void pyb_rtc_repeat_alarm (pyb_rtc_obj_t *self) {
+ if (self->repeat) {
+ uint32_t f_seconds, c_seconds;
+ uint16_t f_mseconds, c_mseconds;
+
+ pyb_rtc_get_time(&c_seconds, &c_mseconds);
+
+ // substract the time elapsed between waking up and setting up the alarm again
+ int32_t wake_ms = ((c_seconds * 1000) + c_mseconds) - ((self->alarm_time_s * 1000) + self->alarm_time_ms);
+ int32_t next_alarm = self->alarm_ms - wake_ms;
+ next_alarm = next_alarm > 0 ? next_alarm : PYB_RTC_MIN_ALARM_TIME_MS;
+ pyb_rtc_calc_future_time (next_alarm, &f_seconds, &f_mseconds);
+
+ // now configure the alarm
+ pyb_rtc_set_alarm (self, f_seconds, f_mseconds);
+ }
+}
+
+void pyb_rtc_disable_alarm (void) {
+ pyb_rtc_obj.alarmset = false;
+ pyb_rtc_disable_interupt();
+}
+
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
-STATIC uint32_t pyb_rtc_reset (mp_obj_t self_in) {
+STATIC void pyb_rtc_set_time (uint32_t secs, uint16_t msecs) {
+ // add the RTC access time
+ rtc_msec_add(RTC_ACCESS_TIME_MSEC, &secs, &msecs);
+ // convert from mseconds to cycles
+ msecs = RTC_U16MS_CYCLES(msecs);
+ // now set the time
+ MAP_PRCMRTCSet(secs, msecs);
+}
+
+STATIC uint32_t pyb_rtc_reset (void) {
// fresh reset; configure the RTC Calendar
// set the date to 1st Jan 2015
// set the time to 00:00:00
uint32_t seconds = timeutils_seconds_since_2000(2015, 1, 1, 0, 0, 0);
- // Now set the RTC calendar seconds
- MAP_PRCMRTCSet(seconds, 0);
+ // disable any running alarm
+ pyb_rtc_disable_alarm();
+ // Now set the RTC calendar time
+ pyb_rtc_set_time(seconds, 0);
return seconds;
}
-STATIC void pyb_rtc_callback_enable (mp_obj_t self_in) {
+STATIC void pyb_rtc_disable_interupt (void) {
+ uint primsk = disable_irq();
+ MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
+ (void)MAP_PRCMIntStatus();
+ enable_irq(primsk);
+}
+
+STATIC void pyb_rtc_irq_enable (mp_obj_t self_in) {
pyb_rtc_obj_t *self = self_in;
- // check the wake from param
- if (self->prwmode & PYB_PWR_MODE_ACTIVE) {
- // enable the slow clock interrupt
+ // we always need interrupts if repeat is enabled
+ if ((self->pwrmode & PYB_PWR_MODE_ACTIVE) || self->repeat) {
MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
- } else {
- // just in case it was already enabled before
+ } else { // just in case it was already enabled before
MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
}
- pybsleep_configure_timer_wakeup (self->prwmode);
+ self->irq_enabled = true;
}
-STATIC void pyb_rtc_callback_disable (mp_obj_t self_in) {
+STATIC void pyb_rtc_irq_disable (mp_obj_t self_in) {
pyb_rtc_obj_t *self = self_in;
- // check the wake from param
- if (self->prwmode & PYB_PWR_MODE_ACTIVE) {
- // disable the slow clock interrupt
- MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
+ self->irq_enabled = false;
+ if (!self->repeat) { // we always need interrupts if repeat is enabled
+ pyb_rtc_disable_interupt();
}
- // disable wake from ldps and hibernate
- pybsleep_configure_timer_wakeup (PYB_PWR_MODE_ACTIVE);
- // read the interrupt status to clear any pending interrupt
- (void)MAP_PRCMIntStatus();
+}
+
+STATIC int pyb_rtc_irq_flags (mp_obj_t self_in) {
+ pyb_rtc_obj_t *self = self_in;
+ return self->irq_flags;
}
STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds) {
@@ -177,15 +237,15 @@ STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds) {
///
/// (year, month, day, hours, minutes, seconds, milliseconds, tzinfo=None)
///
-STATIC mp_obj_t pyb_rtc_datetime(mp_obj_t self, const mp_obj_t datetime) {
+STATIC mp_obj_t pyb_rtc_datetime(mp_obj_t self_in, const mp_obj_t datetime) {
uint32_t seconds;
uint32_t useconds;
if (datetime != MP_OBJ_NULL) {
useconds = pyb_rtc_datetime_s_us(datetime, &seconds);
- MAP_PRCMRTCSet(seconds, RTC_U16MS_CYCLES(useconds / 1000));
+ pyb_rtc_set_time (seconds, useconds / 1000);
} else {
- seconds = pyb_rtc_reset(self);
+ seconds = pyb_rtc_reset();
}
// set WLAN time and date, this is needed to verify certificates
@@ -193,6 +253,32 @@ STATIC mp_obj_t pyb_rtc_datetime(mp_obj_t self, const mp_obj_t datetime) {
return mp_const_none;
}
+STATIC void pyb_rtc_set_alarm (pyb_rtc_obj_t *self, uint32_t seconds, uint16_t mseconds) {
+ // disable the interrupt before updating anything
+ if (self->irq_enabled) {
+ MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
+ }
+ // set the match value
+ MAP_PRCMRTCMatchSet(seconds, RTC_U16MS_CYCLES(mseconds));
+ self->alarmset = true;
+ self->alarm_time_s = seconds;
+ self->alarm_time_ms = mseconds;
+ // enabled the interrupts again if applicable
+ if (self->irq_enabled || self->repeat) {
+ MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
+ }
+}
+
+STATIC void rtc_msec_add (uint16_t msecs_1, uint32_t *secs, uint16_t *msecs_2) {
+ if (msecs_1 + *msecs_2 >= 1000) { // larger than one second
+ *msecs_2 = (msecs_1 + *msecs_2) - 1000;
+ *secs += 1; // carry flag
+ } else {
+ // simply add the mseconds
+ *msecs_2 = msecs_1 + *msecs_2;
+ }
+}
+
/******************************************************************************/
// Micro Python bindings
@@ -219,6 +305,9 @@ STATIC mp_obj_t pyb_rtc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
// set the time and date
pyb_rtc_datetime((mp_obj_t)&pyb_rtc_obj, args[1].u_obj);
+ // pass it to the sleep module
+ pybsleep_set_rtc_obj (self);
+
// return constant object
return (mp_obj_t)&pyb_rtc_obj;
}
@@ -236,9 +325,8 @@ STATIC mp_obj_t pyb_rtc_now (mp_obj_t self_in) {
uint32_t seconds;
uint16_t mseconds;
- // get the seconds and the milliseconds from the RTC
- MAP_PRCMRTCGet(&seconds, &mseconds);
- mseconds = RTC_CYCLES_U16MS(mseconds);
+ // get the time from the RTC
+ pyb_rtc_get_time(&seconds, &mseconds);
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
mp_obj_t tuple[8] = {
@@ -256,7 +344,7 @@ STATIC mp_obj_t pyb_rtc_now (mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_now_obj, pyb_rtc_now);
STATIC mp_obj_t pyb_rtc_deinit (mp_obj_t self_in) {
- pyb_rtc_reset (self_in);
+ pyb_rtc_reset();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_deinit_obj, pyb_rtc_deinit);
@@ -264,7 +352,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_deinit_obj, pyb_rtc_deinit);
STATIC mp_obj_t pyb_rtc_alarm (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_time, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_time, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_repeat, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
@@ -278,114 +366,97 @@ STATIC mp_obj_t pyb_rtc_alarm (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
- uint32_t a_seconds;
- uint16_t a_mseconds;
+ uint32_t f_seconds;
+ uint16_t f_mseconds;
+ bool repeat = args[2].u_bool;
if (MP_OBJ_IS_TYPE(args[1].u_obj, &mp_type_tuple)) { // datetime tuple given
- a_mseconds = pyb_rtc_datetime_s_us (args[1].u_obj, &a_seconds) / 1000;
- } else { // then it must be an integer or MP_OBJ_NULL
- uint32_t c_seconds;
- uint16_t c_mseconds;
- if (MP_OBJ_IS_INT(args[1].u_obj)) {
- a_seconds = 0, a_mseconds = mp_obj_get_int(args[1].u_obj);
- } else {
- a_seconds = 1, a_mseconds = 0;
+ // repeat cannot be used with a datetime tuple
+ if (repeat) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
- // get the seconds and the milliseconds from the RTC
- MAP_PRCMRTCGet(&c_seconds, &c_mseconds);
- a_mseconds += RTC_CYCLES_U16MS(c_mseconds);
- // calculate the future time
- a_seconds += c_seconds + (a_mseconds / 1000);
- a_mseconds -= ((a_mseconds / 1000) * 1000);
+ f_mseconds = pyb_rtc_datetime_s_us (args[1].u_obj, &f_seconds) / 1000;
+ } else { // then it must be an integer
+ self->alarm_ms = mp_obj_get_int(args[1].u_obj);
+ pyb_rtc_calc_future_time (self->alarm_ms, &f_seconds, &f_mseconds);
}
- // disable the interrupt before updating anything
- pyb_rtc_callback_disable((mp_obj_t)self);
-
- // set the match value
- MAP_PRCMRTCMatchSet(a_seconds, a_mseconds);
-
- // enabled it again (according to the power mode)
- pyb_rtc_callback_enable((mp_obj_t)self);
+ // store the repepat flag
+ self->repeat = repeat;
- // set the alarmset flag and store the repeat one
- self->alarmset = true;
- self->repeat = args[2].u_bool;
+ // now configure the alarm
+ pyb_rtc_set_alarm (self, f_seconds, f_mseconds);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_alarm_obj, 1, pyb_rtc_alarm);
-STATIC mp_obj_t pyb_rtc_alarm_left (mp_obj_t self_in) {
- pyb_rtc_obj_t *self = self_in;
- uint32_t a_seconds, c_seconds;
- uint16_t a_mseconds, c_mseconds;
+STATIC mp_obj_t pyb_rtc_alarm_left (mp_uint_t n_args, const mp_obj_t *args) {
+ pyb_rtc_obj_t *self = args[0];
int32_t ms_left;
+ uint32_t c_seconds;
+ uint16_t c_mseconds;
+
+ // only alarm id 0 is available
+ if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
+ }
- // get the alarm time
- MAP_PRCMRTCMatchGet(&a_seconds, &a_mseconds);
- a_mseconds = RTC_CYCLES_U16MS(a_mseconds);
// get the current time
- MAP_PRCMRTCGet(&c_seconds, &c_mseconds);
- c_mseconds = RTC_CYCLES_U16MS(c_mseconds);
+ pyb_rtc_get_time(&c_seconds, &c_mseconds);
+
// calculate the ms left
- ms_left = ((a_seconds * 1000) + a_mseconds) - ((c_seconds * 1000) + c_mseconds);
+ ms_left = ((self->alarm_time_s * 1000) + self->alarm_time_ms) - ((c_seconds * 1000) + c_mseconds);
if (!self->alarmset || ms_left < 0) {
ms_left = 0;
}
return mp_obj_new_int(ms_left);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_alarm_left_obj, pyb_rtc_alarm_left);
-
-/// \method callback(handler, value, pwrmode)
-/// Creates a callback object associated with the real time clock
-/// min num of arguments is 1 (value). The value is the alarm time
-/// in the future, in msec
-/// FIXME
-STATIC mp_obj_t pyb_rtc_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
- pyb_rtc_obj_t *self = pos_args[0];
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, pyb_rtc_alarm_left);
- // check if any parameters were passed
- mp_obj_t _callback = mpcallback_find((mp_obj_t)&pyb_rtc_obj);
- if (kw_args->used > 0) {
- uint32_t f_mseconds = MAX(1, mp_obj_get_int(args[3].u_obj));
- uint32_t seconds;
- uint16_t mseconds;
- // get the seconds and the milliseconds from the RTC
- MAP_PRCMRTCGet(&seconds, &mseconds);
- mseconds = RTC_CYCLES_U16MS(mseconds);
-
- // configure the rtc alarm accordingly
- seconds += f_mseconds / 1000;
- mseconds += f_mseconds - ((f_mseconds / 1000) * 1000);
+STATIC mp_obj_t pyb_rtc_alarm_cancel (mp_uint_t n_args, const mp_obj_t *args) {
+ // only alarm id 0 is available
+ if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
+ }
+ // disable the alarm
+ pyb_rtc_disable_alarm();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_cancel_obj, 1, 2, pyb_rtc_alarm_cancel);
- // disable the interrupt before updating anything
- pyb_rtc_callback_disable((mp_obj_t)&pyb_rtc_obj);
+/// \method irq(trigger, priority, handler, wake)
+STATIC mp_obj_t pyb_rtc_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_arg_val_t args[mp_irq_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args);
+ pyb_rtc_obj_t *self = pos_args[0];
- // set the match value
- MAP_PRCMRTCMatchSet(seconds, mseconds);
+ // save the power mode data for later
+ uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj);
+ if (pwrmode > (PYB_PWR_MODE_ACTIVE | PYB_PWR_MODE_LPDS | PYB_PWR_MODE_HIBERNATE)) {
+ goto invalid_args;
+ }
- // save the power mode data for later
- self->prwmode = args[4].u_int;
+ // check the trigger
+ if (mp_obj_get_int(args[0].u_obj) == PYB_RTC_ALARM0) {
+ self->pwrmode = pwrmode;
+ pyb_rtc_irq_enable((mp_obj_t)self);
+ } else {
+ goto invalid_args;
+ }
- // create the callback
- _callback = mpcallback_new ((mp_obj_t)&pyb_rtc_obj, args[1].u_obj, &pybrtc_cb_methods, true);
+ // the interrupt priority is ignored since it's already set to to highest level by the sleep module
+ // to make sure that the wakeup irqs are always called first when resuming from sleep
- // set the lpds callback
- pybsleep_set_timer_lpds_callback(_callback);
+ // create the callback
+ mp_obj_t _irq = mp_irq_new ((mp_obj_t)self, args[2].u_obj, &pyb_rtc_irq_methods);
+ self->irq_obj = _irq;
- // the interrupt priority is ignored since it's already set to to highest level by the sleep module
- // to make sure that the wakeup callbacks are always called first when resuming from sleep
+ return _irq;
- // enable the interrupt
- pyb_rtc_callback_enable((mp_obj_t)&pyb_rtc_obj);
- } else if (!_callback) {
- _callback = mpcallback_new ((mp_obj_t)&pyb_rtc_obj, mp_const_none, &pybrtc_cb_methods, false);
- }
- return _callback;
+invalid_args:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_callback_obj, 1, pyb_rtc_callback);
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_irq_obj, 1, pyb_rtc_irq);
STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_rtc_init_obj },
@@ -393,7 +464,11 @@ STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_now), (mp_obj_t)&pyb_rtc_now_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_alarm), (mp_obj_t)&pyb_rtc_alarm_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_alarm_left), (mp_obj_t)&pyb_rtc_alarm_left_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_rtc_callback_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_alarm_cancel), (mp_obj_t)&pyb_rtc_alarm_cancel_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_rtc_irq_obj },
+
+ // class constants
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ALARM0), MP_OBJ_NEW_SMALL_INT(PYB_RTC_ALARM0) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
@@ -404,8 +479,9 @@ const mp_obj_type_t pyb_rtc_type = {
.locals_dict = (mp_obj_t)&pyb_rtc_locals_dict,
};
-STATIC const mp_cb_methods_t pybrtc_cb_methods = {
- .init = pyb_rtc_callback,
- .enable = pyb_rtc_callback_enable,
- .disable = pyb_rtc_callback_disable,
+STATIC const mp_irq_methods_t pyb_rtc_irq_methods = {
+ .init = pyb_rtc_irq,
+ .enable = pyb_rtc_irq_enable,
+ .disable = pyb_rtc_irq_disable,
+ .flags = pyb_rtc_irq_flags
};
diff --git a/cc3200/mods/pybrtc.h b/cc3200/mods/pybrtc.h
index 06c4868db7..5111b78f7c 100644
--- a/cc3200/mods/pybrtc.h
+++ b/cc3200/mods/pybrtc.h
@@ -28,12 +28,32 @@
#ifndef PYBRTC_H_
#define PYBRTC_H_
-#define RTC_U16MS_CYCLES(msec) ((msec * 1024) / 1000)
-#define RTC_CYCLES_U16MS(cycles) ((cycles * 1000) / 1024)
+// RTC triggers
+#define PYB_RTC_ALARM0 (0x01)
+
+#define RTC_ACCESS_TIME_MSEC (5)
+#define PYB_RTC_MIN_ALARM_TIME_MS (RTC_ACCESS_TIME_MSEC * 2)
+
+typedef struct _pyb_rtc_obj_t {
+ mp_obj_base_t base;
+ mp_obj_t irq_obj;
+ uint32_t irq_flags;
+ uint32_t alarm_ms;
+ uint32_t alarm_time_s;
+ uint16_t alarm_time_ms;
+ byte pwrmode;
+ bool alarmset;
+ bool repeat;
+ bool irq_enabled;
+} pyb_rtc_obj_t;
extern const mp_obj_type_t pyb_rtc_type;
extern void pyb_rtc_pre_init(void);
+extern void pyb_rtc_get_time (uint32_t *secs, uint16_t *msecs);
extern uint32_t pyb_rtc_get_seconds (void);
+extern void pyb_rtc_calc_future_time (uint32_t a_mseconds, uint32_t *f_seconds, uint16_t *f_mseconds);
+extern void pyb_rtc_repeat_alarm (pyb_rtc_obj_t *self);
+extern void pyb_rtc_disable_alarm (void);
#endif // PYBRTC_H_
diff --git a/cc3200/mods/pybsd.c b/cc3200/mods/pybsd.c
index 864db513bc..55dc98ae80 100644
--- a/cc3200/mods/pybsd.c
+++ b/cc3200/mods/pybsd.c
@@ -54,7 +54,7 @@
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
-pybsd_obj_t pybsd_obj = {.pin_clk = MP_OBJ_NULL, .enabled = false};
+pybsd_obj_t pybsd_obj;
/******************************************************************************
DECLARE PRIVATE DATA
diff --git a/cc3200/mods/pybsleep.c b/cc3200/mods/pybsleep.c
index 0b6a29b3f5..d7a8e439df 100644
--- a/cc3200/mods/pybsleep.c
+++ b/cc3200/mods/pybsleep.c
@@ -43,6 +43,7 @@
#include "spi.h"
#include "pin.h"
#include "pybsleep.h"
+#include "mpirq.h"
#include "pybpin.h"
#include "simplelink.h"
#include "modnetwork.h"
@@ -50,12 +51,12 @@
#include "osi.h"
#include "debug.h"
#include "mpexception.h"
-#include "mpcallback.h"
#include "mperror.h"
#include "sleeprestore.h"
#include "serverstask.h"
#include "antenna.h"
#include "cryptohash.h"
+#include "pybrtc.h"
/******************************************************************************
DECLARE PRIVATE CONSTANTS
@@ -70,8 +71,8 @@
#define WAKEUP_TIME_LPDS (LPDS_UP_TIME + LPDS_DOWN_TIME + USER_OFFSET) // 20 msec
#define WAKEUP_TIME_HIB (32768) // 1 s
-#define FORCED_TIMER_INTERRUPT_MS (1)
-#define FAILED_SLEEP_DELAY_MS (FORCED_TIMER_INTERRUPT_MS * 3)
+#define FORCED_TIMER_INTERRUPT_MS (PYB_RTC_MIN_ALARM_TIME_MS)
+#define FAILED_SLEEP_DELAY_MS (FORCED_TIMER_INTERRUPT_MS * 2)
/******************************************************************************
DECLARE PRIVATE TYPES
@@ -113,10 +114,9 @@ typedef struct {
} pybsleep_obj_t;
typedef struct {
- mp_obj_t wlan_lpds_wake_cb;
- mp_obj_t timer_lpds_wake_cb;
- mp_obj_t gpio_lpds_wake_cb;
- uint timer_wake_pwrmode;
+ mp_obj_t gpio_lpds_wake_cb;
+ wlan_obj_t *wlan_obj;
+ pyb_rtc_obj_t *rtc_obj;
} pybsleep_data_t;
/******************************************************************************
@@ -124,7 +124,7 @@ typedef struct {
******************************************************************************/
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, 0};
+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;
@@ -224,20 +224,16 @@ void pybsleep_remove (const mp_obj_t obj) {
}
}
-void pybsleep_set_wlan_lpds_callback (mp_obj_t cb_obj) {
- pybsleep_data.wlan_lpds_wake_cb = cb_obj;
-}
-
void pybsleep_set_gpio_lpds_callback (mp_obj_t cb_obj) {
pybsleep_data.gpio_lpds_wake_cb = cb_obj;
}
-void pybsleep_set_timer_lpds_callback (mp_obj_t cb_obj) {
- pybsleep_data.timer_lpds_wake_cb = cb_obj;
+void pybsleep_set_wlan_obj (mp_obj_t wlan_obj) {
+ pybsleep_data.wlan_obj = (wlan_obj_t *)wlan_obj;
}
-void pybsleep_configure_timer_wakeup (uint pwrmode) {
- pybsleep_data.timer_wake_pwrmode = pwrmode;
+void pybsleep_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) {
@@ -410,7 +406,7 @@ void pybsleep_suspend_exit (void) {
pybsleep_obj_wakeup();
// reconfigure all the previously enabled interrupts
- mpcallback_wake_all();
+ mp_irq_wake_all();
// we need to init the crypto hash engine again
CRYPTOHASH_Init();
@@ -425,25 +421,35 @@ void pybsleep_suspend_exit (void) {
STATIC void PRCMInterruptHandler (void) {
// reading the interrupt status automatically clears the interrupt
if (PRCM_INT_SLOW_CLK_CTR == MAP_PRCMIntStatus()) {
- // this interrupt is triggered during active mode
- mpcallback_handler(pybsleep_data.timer_lpds_wake_cb);
- }
- else {
+ // reconfigure it again (if repeat is true)
+ pyb_rtc_repeat_alarm (pybsleep_data.rtc_obj);
+ pybsleep_data.rtc_obj->irq_flags = PYB_RTC_ALARM0;
+ // need to check if irq's are enabled from the user point of view
+ if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_ACTIVE)) {
+ mp_irq_handler(pybsleep_data.rtc_obj->irq_obj);
+ }
+ pybsleep_data.rtc_obj->irq_flags = 0;
+ } else {
// interrupt has been triggered while waking up from LPDS
switch (MAP_PRCMLPDSWakeupCauseGet()) {
case PRCM_LPDS_HOST_IRQ:
- mpcallback_handler(pybsleep_data.wlan_lpds_wake_cb);
+ pybsleep_data.wlan_obj->irq_flags = MODWLAN_WIFI_EVENT_ANY;
+ mp_irq_handler(pybsleep_data.wlan_obj->irq_obj);
pybsleep_wake_reason = PYB_SLP_WAKED_BY_WLAN;
+ pybsleep_data.wlan_obj->irq_flags = 0;
break;
case PRCM_LPDS_GPIO:
- mpcallback_handler(pybsleep_data.gpio_lpds_wake_cb);
+ mp_irq_handler(pybsleep_data.gpio_lpds_wake_cb);
pybsleep_wake_reason = PYB_SLP_WAKED_BY_GPIO;
break;
case PRCM_LPDS_TIMER:
- // disable the timer as wake-up source
- pybsleep_data.timer_wake_pwrmode &= ~PYB_PWR_MODE_LPDS;
+ // reconfigure it again if repeat is true
+ pyb_rtc_repeat_alarm (pybsleep_data.rtc_obj);
+ pybsleep_data.rtc_obj->irq_flags = PYB_RTC_ALARM0;
+ // next one clears the wake cause flag
MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER);
- mpcallback_handler(pybsleep_data.timer_lpds_wake_cb);
+ mp_irq_handler(pybsleep_data.rtc_obj->irq_obj);
+ pybsleep_data.rtc_obj->irq_flags = 0;
pybsleep_wake_reason = PYB_SLP_WAKED_BY_RTC;
break;
default:
@@ -473,9 +479,9 @@ STATIC void pybsleep_iopark (bool hibernate) {
break;
#endif
default:
- // enable a weak pull-down if the pin is unused
+ // enable a weak pull-up if the pin is unused
if (!pin->used) {
- MAP_PinConfigSet(pin->pin_num, pin->strength, PIN_TYPE_STD_PD);
+ MAP_PinConfigSet(pin->pin_num, pin->strength, PIN_TYPE_STD_PU);
}
if (hibernate) {
// make it an input
@@ -517,71 +523,70 @@ STATIC void pybsleep_iopark (bool hibernate) {
}
STATIC bool setup_timer_lpds_wake (void) {
- uint64_t t_match, t_curr, t_remaining;
+ uint64_t t_match, t_curr;
+ int64_t t_remaining;
// get the time remaining for the RTC timer to expire
t_match = MAP_PRCMSlowClkCtrMatchGet();
t_curr = MAP_PRCMSlowClkCtrGet();
- if (t_match > t_curr) {
- // get the time remaining in terms of slow clocks
- t_remaining = (t_match - t_curr);
- if (t_remaining > WAKEUP_TIME_LPDS) {
- // subtract the time it takes for wakeup from lpds
- t_remaining -= WAKEUP_TIME_LPDS;
- t_remaining = (t_remaining > 0xFFFFFFFF) ? 0xFFFFFFFF: t_remaining;
- // setup the LPDS wake time
- MAP_PRCMLPDSIntervalSet((uint32_t)t_remaining);
- // enable the wake source
- MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_TIMER);
- return true;
- }
- }
- else {
- // setup a timer interrupt immediately
- MAP_PRCMRTCMatchSet(0, FORCED_TIMER_INTERRUPT_MS);
+ // get the time remaining in terms of slow clocks
+ t_remaining = (t_match - t_curr);
+ if (t_remaining > WAKEUP_TIME_LPDS) {
+ // subtract the time it takes to wakeup from lpds
+ t_remaining -= WAKEUP_TIME_LPDS;
+ t_remaining = (t_remaining > 0xFFFFFFFF) ? 0xFFFFFFFF: t_remaining;
+ // setup the LPDS wake time
+ MAP_PRCMLPDSIntervalSet((uint32_t)t_remaining);
+ // enable the wake source
+ MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_TIMER);
+ return true;
}
// disable the timer as wake source
MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER);
- // LPDS wake by timer was not possible, force
- // an interrupt in active mode instead
+ uint32_t f_seconds;
+ uint16_t f_mseconds;
+ // setup a timer interrupt immediately
+ pyb_rtc_calc_future_time (FORCED_TIMER_INTERRUPT_MS, &f_seconds, &f_mseconds);
+ MAP_PRCMRTCMatchSet(f_seconds, f_mseconds);
+ // LPDS wake by timer was not possible, force an interrupt in active mode instead
MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
return false;
}
STATIC bool setup_timer_hibernate_wake (void) {
- uint64_t t_match, t_curr, t_remaining;
+ uint64_t t_match, t_curr;
+ int64_t t_remaining;
// get the time remaining for the RTC timer to expire
t_match = MAP_PRCMSlowClkCtrMatchGet();
t_curr = MAP_PRCMSlowClkCtrGet();
- if (t_match > t_curr) {
- // get the time remaining in terms of slow clocks
- t_remaining = (t_match - t_curr);
- if (t_remaining > WAKEUP_TIME_HIB) {
- // subtract the time it takes for wakeup from hibernate
- t_remaining -= WAKEUP_TIME_HIB;
- // setup the LPDS wake time
- MAP_PRCMHibernateIntervalSet((uint32_t)t_remaining);
- // enable the wake source
- MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
- return true;
- }
- }
- else {
- // setup a timer interrupt immediately
- MAP_PRCMRTCMatchSet(0, FORCED_TIMER_INTERRUPT_MS);
+ // get the time remaining in terms of slow clocks
+ t_remaining = (t_match - t_curr);
+ if (t_remaining > WAKEUP_TIME_HIB) {
+ // subtract the time it takes for wakeup from hibernate
+ t_remaining -= WAKEUP_TIME_HIB;
+ // setup the LPDS wake time
+ MAP_PRCMHibernateIntervalSet((uint32_t)t_remaining);
+ // enable the wake source
+ MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
+ return true;
}
+
// disable the timer as wake source
MAP_PRCMLPDSWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR);
- // hibernate wake by timer was not possible, force
- // an interrupt in active mode instead
+ uint32_t f_seconds;
+ uint16_t f_mseconds;
+ // setup a timer interrupt immediately
+ pyb_rtc_calc_future_time (FORCED_TIMER_INTERRUPT_MS, &f_seconds, &f_mseconds);
+ MAP_PRCMRTCMatchSet(f_seconds, f_mseconds);
+ // LPDS wake by timer was not possible, force an interrupt in active mode instead
MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
return false;
@@ -605,21 +610,22 @@ 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.timer_wake_pwrmode & PYB_PWR_MODE_LPDS) {
+ 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
- pybsleep_data.timer_wake_pwrmode &= ~PYB_PWR_MODE_LPDS;
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_lpds_wake_cb) {
+ if (pybsleep_data.wlan_obj->irq_enabled) {
MAP_PRCMLPDSWakeupSourceEnable (PRCM_LPDS_HOST_IRQ);
server_sleep_sockets();
- }
- else {
+ } else {
MAP_PRCMLPDSWakeupSourceDisable (PRCM_LPDS_HOST_IRQ);
}
@@ -643,14 +649,17 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_suspend_obj, pyb_sleep_suspend);
/// 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.timer_wake_pwrmode & PYB_PWR_MODE_HIBERNATE) {
+ 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
- pybsleep_data.timer_wake_pwrmode &= ~PYB_PWR_MODE_HIBERNATE;
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
diff --git a/cc3200/mods/pybsleep.h b/cc3200/mods/pybsleep.h
index c27cf39c52..6deb09ba66 100644
--- a/cc3200/mods/pybsleep.h
+++ b/cc3200/mods/pybsleep.h
@@ -67,10 +67,9 @@ void pybsleep_init0 (void);
void pybsleep_signal_soft_reset (void);
void pybsleep_add (const mp_obj_t obj, WakeUpCB_t wakeup);
void pybsleep_remove (const mp_obj_t 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);
-void pybsleep_configure_timer_wakeup (uint pwrmode);
+void pybsleep_set_wlan_obj (mp_obj_t wlan_obj);
+void pybsleep_set_rtc_obj (mp_obj_t rtc_obj);
pybsleep_reset_cause_t pybsleep_get_reset_cause (void);
#endif /* PYBSLEEP_H_ */
diff --git a/cc3200/mods/pybtimer.c b/cc3200/mods/pybtimer.c
index bd3a935654..e599345336 100644
--- a/cc3200/mods/pybtimer.c
+++ b/cc3200/mods/pybtimer.c
@@ -44,8 +44,8 @@
#include "prcm.h"
#include "timer.h"
#include "pybtimer.h"
+#include "mpirq.h"
#include "pybsleep.h"
-#include "mpcallback.h"
#include "mpexception.h"
@@ -96,7 +96,8 @@ typedef struct _pyb_timer_obj_t {
mp_obj_base_t base;
uint32_t timer;
uint32_t config;
- uint16_t intflags;
+ uint16_t irq_trigger;
+ uint16_t irq_flags;
uint8_t peripheral;
uint8_t id;
} pyb_timer_obj_t;
@@ -114,7 +115,7 @@ typedef struct _pyb_timer_channel_obj_t {
/******************************************************************************
DEFINE PRIVATE DATA
******************************************************************************/
-STATIC const mp_cb_methods_t pyb_timer_channel_cb_methods;
+STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods;
STATIC pyb_timer_obj_t pyb_timer_obj[PYBTIMER_NUM_TIMERS] = {{.timer = TIMERA0_BASE, .peripheral = PRCM_TIMERA0},
{.timer = TIMERA1_BASE, .peripheral = PRCM_TIMERA1},
{.timer = TIMERA2_BASE, .peripheral = PRCM_TIMERA2},
@@ -124,7 +125,7 @@ STATIC const mp_obj_type_t pyb_timer_channel_type;
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
-STATIC mp_obj_t pyb_timer_channel_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
+STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
STATIC void timer_disable (pyb_timer_obj_t *tim);
STATIC void TIMER0AIntHandler(void);
STATIC void TIMER0BIntHandler(void);
@@ -142,18 +143,26 @@ void timer_init0 (void) {
mp_obj_list_init(&MP_STATE_PORT(pyb_timer_channel_obj_list), 0);
}
-void pyb_timer_channel_callback_enable (mp_obj_t self_in) {
+/******************************************************************************
+ DEFINE PRIVATE FUNCTIONS
+ ******************************************************************************/
+STATIC void pyb_timer_channel_irq_enable (mp_obj_t self_in) {
+ pyb_timer_channel_obj_t *self = self_in;
+ MAP_TimerIntClear(self->timer->timer, self->timer->irq_trigger & self->channel);
+ MAP_TimerIntEnable(self->timer->timer, self->timer->irq_trigger & self->channel);
+}
+
+STATIC void pyb_timer_channel_irq_disable (mp_obj_t self_in) {
pyb_timer_channel_obj_t *self = self_in;
- MAP_TimerIntClear(self->timer->timer, self->timer->intflags & self->channel);
- MAP_TimerIntEnable(self->timer->timer, self->timer->intflags & self->channel);
+ MAP_TimerIntDisable(self->timer->timer, self->timer->irq_trigger & self->channel);
}
-void pyb_timer_channel_callback_disable (mp_obj_t self_in) {
+STATIC int pyb_timer_channel_irq_flags (mp_obj_t self_in) {
pyb_timer_channel_obj_t *self = self_in;
- MAP_TimerIntDisable(self->timer->timer, self->timer->intflags & self->channel);
+ return self->timer->irq_flags;
}
-pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channel_n) {
+STATIC pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channel_n) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_timer_channel_obj_list).len; i++) {
pyb_timer_channel_obj_t *ch = ((pyb_timer_channel_obj_t *)(MP_STATE_PORT(pyb_timer_channel_obj_list).items[i]));
// any 32-bit timer must be matched by any of its 16-bit versions
@@ -164,14 +173,14 @@ pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channe
return MP_OBJ_NULL;
}
-void pyb_timer_channel_remove (pyb_timer_channel_obj_t *ch) {
+STATIC void pyb_timer_channel_remove (pyb_timer_channel_obj_t *ch) {
pyb_timer_channel_obj_t *channel;
if ((channel = pyb_timer_channel_find(ch->timer->timer, ch->channel))) {
mp_obj_list_remove(&MP_STATE_PORT(pyb_timer_channel_obj_list), channel);
}
}
-void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) {
+STATIC void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) {
// remove it in case it already exists
pyb_timer_channel_remove(ch);
mp_obj_list_append(&MP_STATE_PORT(pyb_timer_channel_obj_list), ch);
@@ -180,8 +189,8 @@ void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) {
STATIC void timer_disable (pyb_timer_obj_t *tim) {
// disable all timers and it's interrupts
MAP_TimerDisable(tim->timer, TIMER_A | TIMER_B);
- MAP_TimerIntDisable(tim->timer, tim->intflags);
- MAP_TimerIntClear(tim->timer, tim->intflags);
+ MAP_TimerIntDisable(tim->timer, tim->irq_trigger);
+ MAP_TimerIntClear(tim->timer, tim->irq_trigger);
MAP_PRCMPeripheralClkDisable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
memset(&pyb_timer_obj[tim->id], 0, sizeof(pyb_timer_obj_t));
}
@@ -509,10 +518,11 @@ const mp_obj_type_t pyb_timer_type = {
.locals_dict = (mp_obj_t)&pyb_timer_locals_dict,
};
-STATIC const mp_cb_methods_t pyb_timer_channel_cb_methods = {
- .init = pyb_timer_channel_callback,
- .enable = pyb_timer_channel_callback_enable,
- .disable = pyb_timer_channel_callback_disable,
+STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = {
+ .init = pyb_timer_channel_irq,
+ .enable = pyb_timer_channel_irq_enable,
+ .disable = pyb_timer_channel_irq_disable,
+ .flags = pyb_timer_channel_irq_flags,
};
STATIC void TIMERGenericIntHandler(uint32_t timer, uint16_t channel) {
@@ -522,8 +532,7 @@ STATIC void TIMERGenericIntHandler(uint32_t timer, uint16_t channel) {
if ((self = pyb_timer_channel_find(timer, channel))) {
status = MAP_TimerIntStatus(self->timer->timer, true) & self->channel;
MAP_TimerIntClear(self->timer->timer, status);
- mp_obj_t _callback = mpcallback_find(self);
- mpcallback_handler(_callback);
+ mp_irq_handler(mp_irq_find(self));
}
}
@@ -716,130 +725,107 @@ STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *a
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_duty_cycle_obj, 1, 3, pyb_timer_channel_duty_cycle);
-/// \method callback(handler, priority, value)
-/// create a callback object associated with the timer channel
-STATIC mp_obj_t pyb_timer_channel_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
-
+/// \method irq(trigger, priority, handler, wake)
+/// FIXME triggers!!
+STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_arg_val_t args[mp_irq_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args);
pyb_timer_channel_obj_t *ch = pos_args[0];
- mp_obj_t _callback = mpcallback_find(ch);
- if (kw_args->used > 0) {
- // convert the priority to the correct value
- uint priority = mpcallback_translate_priority (args[2].u_int);
-
- // validate the power mode
- uint pwrmode = args[4].u_int;
- if (pwrmode != PYB_PWR_MODE_ACTIVE) {
- goto invalid_args;
- }
- uint32_t _config = (ch->channel == TIMER_B) ? ((ch->timer->config & TIMER_B) >> 8) : (ch->timer->config & TIMER_A);
- uint32_t c_value = mp_obj_get_int(args[3].u_obj);
+ // convert the priority to the correct value
+ uint priority = mp_irq_translate_priority (args[1].u_int);
- // validate and set the value if we are in edge count mode
- if (_config == TIMER_CFG_A_CAP_COUNT) {
- if (!c_value || c_value > 0xFFFF) {
- // zero or exceeds the maximum value of a 16-bit timer
- goto invalid_args;
- }
- MAP_TimerMatchSet(ch->timer->timer, ch->channel, c_value);
- }
+ // validate the power mode
+ uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj);
+ if (pwrmode != PYB_PWR_MODE_ACTIVE) {
+ goto invalid_args;
+ }
- // disable the callback first
- pyb_timer_channel_callback_disable(ch);
-
- uint8_t shift = (ch->channel == TIMER_B) ? 8 : 0;
- switch (_config) {
- case TIMER_CFG_A_ONE_SHOT:
- case TIMER_CFG_A_PERIODIC:
- ch->timer->intflags |= TIMER_TIMA_TIMEOUT << shift;
- break;
- case TIMER_CFG_A_CAP_COUNT:
- ch->timer->intflags |= TIMER_CAPA_MATCH << shift;
- // set the match value and make 1 the minimum
- MAP_TimerMatchSet(ch->timer->timer, ch->channel, MAX(1, c_value));
- break;
- case TIMER_CFG_A_CAP_TIME:
- ch->timer->intflags |= TIMER_CAPA_EVENT << shift;
- break;
- case TIMER_CFG_A_PWM:
- // special case for the PWM match interrupt
- ch->timer->intflags |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH;
- break;
- default:
- break;
+ // disable the callback first
+ pyb_timer_channel_irq_disable(ch);
+
+ uint8_t shift = (ch->channel == TIMER_B) ? 8 : 0;
+ uint32_t _config = (ch->channel == TIMER_B) ? ((ch->timer->config & TIMER_B) >> 8) : (ch->timer->config & TIMER_A);
+ switch (_config) {
+ case TIMER_CFG_A_ONE_SHOT:
+ case TIMER_CFG_A_PERIODIC:
+ ch->timer->irq_trigger |= TIMER_TIMA_TIMEOUT << shift;
+ break;
+ case TIMER_CFG_A_CAP_COUNT:
+ ch->timer->irq_trigger |= TIMER_CAPA_MATCH << shift;
+ break;
+ case TIMER_CFG_A_CAP_TIME:
+ ch->timer->irq_trigger |= TIMER_CAPA_EVENT << shift;
+ break;
+ case TIMER_CFG_A_PWM:
+ // special case for the PWM match interrupt
+ ch->timer->irq_trigger |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH;
+ break;
+ default:
+ break;
+ }
+ // special case for a 32-bit timer
+ if (ch->channel == (TIMER_A | TIMER_B)) {
+ ch->timer->irq_trigger |= (ch->timer->irq_trigger << 8);
+ }
+
+ void (*pfnHandler)(void);
+ uint32_t intregister;
+ switch (ch->timer->timer) {
+ case TIMERA0_BASE:
+ if (ch->channel == TIMER_B) {
+ pfnHandler = &TIMER0BIntHandler;
+ intregister = INT_TIMERA0B;
+ } else {
+ pfnHandler = &TIMER0AIntHandler;
+ intregister = INT_TIMERA0A;
}
- // special case for a 32-bit timer
- if (ch->channel == (TIMER_A | TIMER_B)) {
- ch->timer->intflags |= (ch->timer->intflags << 8);
+ break;
+ case TIMERA1_BASE:
+ if (ch->channel == TIMER_B) {
+ pfnHandler = &TIMER1BIntHandler;
+ intregister = INT_TIMERA1B;
+ } else {
+ pfnHandler = &TIMER1AIntHandler;
+ intregister = INT_TIMERA1A;
}
-
- void (*pfnHandler)(void);
- uint32_t intregister;
- switch (ch->timer->timer) {
- case TIMERA0_BASE:
- if (ch->channel == TIMER_B) {
- pfnHandler = &TIMER0BIntHandler;
- intregister = INT_TIMERA0B;
- } else {
- pfnHandler = &TIMER0AIntHandler;
- intregister = INT_TIMERA0A;
- }
- break;
- case TIMERA1_BASE:
- if (ch->channel == TIMER_B) {
- pfnHandler = &TIMER1BIntHandler;
- intregister = INT_TIMERA1B;
- } else {
- pfnHandler = &TIMER1AIntHandler;
- intregister = INT_TIMERA1A;
- }
- break;
- case TIMERA2_BASE:
- if (ch->channel == TIMER_B) {
- pfnHandler = &TIMER2BIntHandler;
- intregister = INT_TIMERA2B;
- } else {
- pfnHandler = &TIMER2AIntHandler;
- intregister = INT_TIMERA2A;
- }
- break;
- default:
- if (ch->channel == TIMER_B) {
- pfnHandler = &TIMER3BIntHandler;
- intregister = INT_TIMERA3B;
- } else {
- pfnHandler = &TIMER3AIntHandler;
- intregister = INT_TIMERA3A;
- }
- break;
+ break;
+ case TIMERA2_BASE:
+ if (ch->channel == TIMER_B) {
+ pfnHandler = &TIMER2BIntHandler;
+ intregister = INT_TIMERA2B;
+ } else {
+ pfnHandler = &TIMER2AIntHandler;
+ intregister = INT_TIMERA2A;
+ }
+ break;
+ default:
+ if (ch->channel == TIMER_B) {
+ pfnHandler = &TIMER3BIntHandler;
+ intregister = INT_TIMERA3B;
+ } else {
+ pfnHandler = &TIMER3AIntHandler;
+ intregister = INT_TIMERA3A;
}
+ break;
+ }
- // register the interrupt and configure the priority
- MAP_IntPrioritySet(intregister, priority);
- MAP_TimerIntRegister(ch->timer->timer, ch->channel, pfnHandler);
+ // register the interrupt and configure the priority
+ MAP_IntPrioritySet(intregister, priority);
+ MAP_TimerIntRegister(ch->timer->timer, ch->channel, pfnHandler);
- // create the callback
- _callback = mpcallback_new (ch, args[1].u_obj, &pyb_timer_channel_cb_methods, true);
+ // create the callback
+ mp_obj_t _irq = mp_irq_new (ch, args[2].u_obj, &pyb_timer_channel_irq_methods);
- // reload the timer
- uint32_t period_c;
- uint32_t match;
- compute_prescaler_period_and_match_value(ch, &period_c, &match);
- MAP_TimerLoadSet(ch->timer->timer, ch->channel, period_c);
+ // enable the callback before returning
+ pyb_timer_channel_irq_enable(ch);
- // enable the callback before returning
- pyb_timer_channel_callback_enable(ch);
- } else if (!_callback) {
- _callback = mpcallback_new (ch, mp_const_none, &pyb_timer_channel_cb_methods, false);
- }
- return _callback;
+ return _irq;
invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_callback_obj, 1, pyb_timer_channel_callback);
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_irq_obj, 1, pyb_timer_channel_irq);
STATIC const mp_map_elem_t pyb_timer_channel_locals_dict_table[] = {
// instance methods
@@ -849,7 +835,7 @@ STATIC const mp_map_elem_t pyb_timer_channel_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_event_count), (mp_obj_t)&pyb_timer_channel_event_count_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_event_time), (mp_obj_t)&pyb_timer_channel_event_time_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_duty_cycle), (mp_obj_t)&pyb_timer_channel_duty_cycle_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_timer_channel_callback_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_timer_channel_irq_obj },
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);
diff --git a/cc3200/mods/pybuart.c b/cc3200/mods/pybuart.c
index 73cf661bcc..fca534458a 100644
--- a/cc3200/mods/pybuart.c
+++ b/cc3200/mods/pybuart.c
@@ -45,9 +45,9 @@
#include "prcm.h"
#include "uart.h"
#include "pybuart.h"
+#include "mpirq.h"
#include "pybioctl.h"
#include "pybsleep.h"
-#include "mpcallback.h"
#include "mpexception.h"
#include "py/mpstate.h"
#include "osi.h"
@@ -69,13 +69,13 @@
#define PYBUART_TX_WAIT_US(baud) ((PYBUART_FRAME_TIME_US(baud)) + 1)
#define PYBUART_TX_MAX_TIMEOUT_MS (5)
-#define PYBUART_RX_BUFFER_LEN (128)
+#define PYBUART_RX_BUFFER_LEN (256)
// interrupt triggers
-#define E_UART_TRIGGER_RX_ANY (0x01)
-#define E_UART_TRIGGER_RX_HALF (0x02)
-#define E_UART_TRIGGER_RX_FULL (0x04)
-#define E_UART_TRIGGER_TX_DONE (0x08)
+#define UART_TRIGGER_RX_ANY (0x01)
+#define UART_TRIGGER_RX_HALF (0x02)
+#define UART_TRIGGER_RX_FULL (0x04)
+#define UART_TRIGGER_TX_DONE (0x08)
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
@@ -83,12 +83,12 @@
STATIC void uart_init (pyb_uart_obj_t *self);
STATIC bool uart_rx_wait (pyb_uart_obj_t *self);
STATIC void uart_check_init(pyb_uart_obj_t *self);
+STATIC mp_obj_t uart_irq_new (pyb_uart_obj_t *self, byte trigger, mp_int_t priority, mp_obj_t handler);
STATIC void UARTGenericIntHandler(uint32_t uart_id);
STATIC void UART0IntHandler(void);
STATIC void UART1IntHandler(void);
-STATIC void uart_callback_enable (mp_obj_t self_in);
-STATIC void uart_callback_disable (mp_obj_t self_in);
-STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in);
+STATIC void uart_irq_enable (mp_obj_t self_in);
+STATIC void uart_irq_disable (mp_obj_t self_in);
/******************************************************************************
DEFINE PRIVATE TYPES
@@ -105,7 +105,8 @@ struct _pyb_uart_obj_t {
uint16_t read_buf_tail; // indexes first full slot (not full if equals head)
byte peripheral;
byte irq_trigger;
- bool callback_enabled;
+ bool irq_enabled;
+ byte irq_flags;
};
/******************************************************************************
@@ -113,7 +114,7 @@ struct _pyb_uart_obj_t {
******************************************************************************/
STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS] = { {.reg = UARTA0_BASE, .baudrate = 0, .read_buf = NULL, .peripheral = PRCM_UARTA0},
{.reg = UARTA1_BASE, .baudrate = 0, .read_buf = NULL, .peripheral = PRCM_UARTA1} };
-STATIC const mp_cb_methods_t uart_cb_methods;
+STATIC const mp_irq_methods_t uart_irq_methods;
STATIC const mp_obj_t pyb_uart_def_pin[PYB_NUM_UARTS][2] = { {&pin_GP1, &pin_GP2}, {&pin_GP3, &pin_GP4} };
@@ -176,28 +177,6 @@ void uart_tx_strn_cooked(pyb_uart_obj_t *self, const char *str, uint len) {
}
}
-mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, mp_int_t priority, byte trigger) {
- // disable the uart interrupts before updating anything
- uart_callback_disable (self);
-
- if (self->uart_id == PYB_UART_0) {
- MAP_IntPrioritySet(INT_UARTA0, priority);
- MAP_UARTIntRegister(self->reg, UART0IntHandler);
- } else {
- MAP_IntPrioritySet(INT_UARTA1, priority);
- MAP_UARTIntRegister(self->reg, UART1IntHandler);
- }
-
- // create the callback
- mp_obj_t _callback = mpcallback_new ((mp_obj_t)self, handler, &uart_cb_methods, true);
-
- // enable the interrupts now
- self->irq_trigger = trigger;
- uart_callback_enable (self);
-
- return _callback;
-}
-
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
@@ -248,15 +227,37 @@ STATIC bool uart_rx_wait (pyb_uart_obj_t *self) {
}
}
+STATIC mp_obj_t uart_irq_new (pyb_uart_obj_t *self, byte trigger, mp_int_t priority, mp_obj_t handler) {
+ // disable the uart interrupts before updating anything
+ uart_irq_disable (self);
+
+ if (self->uart_id == PYB_UART_0) {
+ MAP_IntPrioritySet(INT_UARTA0, priority);
+ MAP_UARTIntRegister(self->reg, UART0IntHandler);
+ } else {
+ MAP_IntPrioritySet(INT_UARTA1, priority);
+ MAP_UARTIntRegister(self->reg, UART1IntHandler);
+ }
+
+ // create the callback
+ mp_obj_t _irq = mp_irq_new ((mp_obj_t)self, handler, &uart_irq_methods);
+
+ // enable the interrupts now
+ self->irq_trigger = trigger;
+ uart_irq_enable (self);
+ return _irq;
+}
+
STATIC void UARTGenericIntHandler(uint32_t uart_id) {
pyb_uart_obj_t *self;
uint32_t status;
- bool exec_callback = false;
self = &pyb_uart_obj[uart_id];
status = MAP_UARTIntStatus(self->reg, true);
// receive interrupt
if (status & (UART_INT_RX | UART_INT_RT)) {
+ // set the flags
+ self->irq_flags = UART_TRIGGER_RX_ANY;
MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT);
while (UARTCharsAvail(self->reg)) {
int data = MAP_UARTCharGetNonBlocking(self->reg);
@@ -274,17 +275,16 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) {
}
}
}
+ }
- if (self->irq_trigger & E_UART_TRIGGER_RX_ANY) {
- exec_callback = true;
- }
-
- if (exec_callback && self->callback_enabled) {
- // call the user defined handler
- mp_obj_t _callback = mpcallback_find(self);
- mpcallback_handler(_callback);
- }
+ // check the flags to see if the user handler should be called
+ if ((self->irq_trigger & self->irq_flags) && self->irq_enabled) {
+ // call the user defined handler
+ mp_irq_handler(mp_irq_find(self));
}
+
+ // clear the flags
+ self->irq_flags = 0;
}
STATIC void uart_check_init(pyb_uart_obj_t *self) {
@@ -302,19 +302,24 @@ STATIC void UART1IntHandler(void) {
UARTGenericIntHandler(1);
}
-STATIC void uart_callback_enable (mp_obj_t self_in) {
+STATIC void uart_irq_enable (mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
// check for any of the rx interrupt types
- if (self->irq_trigger & (E_UART_TRIGGER_RX_ANY | E_UART_TRIGGER_RX_HALF | E_UART_TRIGGER_RX_FULL)) {
+ if (self->irq_trigger & (UART_TRIGGER_RX_ANY | UART_TRIGGER_RX_HALF | UART_TRIGGER_RX_FULL)) {
MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT);
MAP_UARTIntEnable(self->reg, UART_INT_RX | UART_INT_RT);
}
- self->callback_enabled = true;
+ self->irq_enabled = true;
+}
+
+STATIC void uart_irq_disable (mp_obj_t self_in) {
+ pyb_uart_obj_t *self = self_in;
+ self->irq_enabled = false;
}
-STATIC void uart_callback_disable (mp_obj_t self_in) {
+STATIC int uart_irq_flags (mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
- self->callback_enabled = false;
+ return self->irq_flags;
}
/******************************************************************************/
@@ -430,7 +435,9 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, const mp_arg_val_t *a
// register it with the sleep module
pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)uart_init);
// enable the callback
- uart_callback_new (self, mp_const_none, INT_PRIORITY_LVL_3, E_UART_TRIGGER_RX_ANY);
+ uart_irq_new (self, UART_TRIGGER_RX_ANY, INT_PRIORITY_LVL_3, mp_const_none);
+ // disable the irq (from the user point of view)
+ uart_irq_disable(self);
return mp_const_none;
@@ -531,33 +538,37 @@ STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_sendbreak_obj, pyb_uart_sendbreak);
-STATIC mp_obj_t pyb_uart_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
+/// \method irq(trigger, priority, handler, wake)
+STATIC mp_obj_t pyb_uart_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_arg_val_t args[mp_irq_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args);
// check if any parameters were passed
pyb_uart_obj_t *self = pos_args[0];
uart_check_init(self);
- mp_obj_t _callback = mpcallback_find((mp_obj_t)self);
- if (kw_args->used > 0) {
- // convert the priority to the correct value
- uint priority = mpcallback_translate_priority (args[2].u_int);
+ // convert the priority to the correct value
+ uint priority = mp_irq_translate_priority (args[1].u_int);
- // check the power mode
- if (PYB_PWR_MODE_ACTIVE != args[4].u_int) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
- }
+ // check the power mode
+ uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj);
+ if (PYB_PWR_MODE_ACTIVE != pwrmode) {
+ goto invalid_args;
+ }
- // register a new callback
- // FIXME triggers!!
- return uart_callback_new (self, args[1].u_obj, mp_obj_get_int(args[3].u_obj), priority);
- } else if (!_callback) {
- _callback = mpcallback_new (self, mp_const_none, &uart_cb_methods, false);
+ // check the trigger
+ uint trigger = mp_obj_get_int(args[0].u_obj);
+ if (!trigger || trigger > (UART_TRIGGER_RX_ANY | UART_TRIGGER_RX_HALF | UART_TRIGGER_RX_FULL | UART_TRIGGER_TX_DONE)) {
+ goto invalid_args;
}
- return _callback;
+
+ // register a new callback
+ return uart_irq_new (self, trigger, priority, args[2].u_obj);
+
+invalid_args:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_callback_obj, 1, pyb_uart_callback);
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_callback_obj, 1, pyb_uart_irq);
STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
// instance methods
@@ -565,7 +576,7 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_uart_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_uart_any_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendbreak), (mp_obj_t)&pyb_uart_sendbreak_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_uart_callback_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_uart_callback_obj },
/// \method read([nbytes])
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
@@ -581,7 +592,7 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_EVEN), MP_OBJ_NEW_SMALL_INT(UART_CONFIG_PAR_EVEN) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ODD), MP_OBJ_NEW_SMALL_INT(UART_CONFIG_PAR_ODD) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_RX_ANY), MP_OBJ_NEW_SMALL_INT(E_UART_TRIGGER_RX_ANY) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RX_ANY), MP_OBJ_NEW_SMALL_INT(UART_TRIGGER_RX_ANY) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
@@ -654,10 +665,11 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
-STATIC const mp_cb_methods_t uart_cb_methods = {
- .init = pyb_uart_callback,
- .enable = uart_callback_enable,
- .disable = uart_callback_disable,
+STATIC const mp_irq_methods_t uart_irq_methods = {
+ .init = pyb_uart_irq,
+ .enable = uart_irq_enable,
+ .disable = uart_irq_disable,
+ .flags = uart_irq_flags
};
const mp_obj_type_t pyb_uart_type = {
diff --git a/cc3200/mods/pybuart.h b/cc3200/mods/pybuart.h
index 89f3edc0ed..74871cbab0 100644
--- a/cc3200/mods/pybuart.h
+++ b/cc3200/mods/pybuart.h
@@ -43,6 +43,5 @@ int uart_rx_char(pyb_uart_obj_t *uart_obj);
bool uart_tx_char(pyb_uart_obj_t *self, int c);
bool uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len);
void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len);
-mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, mp_int_t priority, byte trigger);
#endif // PYBUART_H_