summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--cc3200/application.mk2
-rw-r--r--cc3200/boards/cc3200_prefix.c26
-rw-r--r--cc3200/hal/prcm.c68
-rw-r--r--cc3200/hal/prcm.h1
-rw-r--r--cc3200/misc/mpirq.c (renamed from cc3200/misc/mpcallback.c)147
-rw-r--r--cc3200/misc/mpirq.h (renamed from cc3200/misc/mpcallback.h)46
-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
-rw-r--r--cc3200/mpconfigport.h2
-rw-r--r--cc3200/mptask.c9
-rw-r--r--cc3200/qstrdefsport.h13
-rw-r--r--cc3200/util/random.c12
-rw-r--r--tests/wipy/pin_irq.py116
-rw-r--r--tests/wipy/pin_irq.py.exp19
-rw-r--r--tests/wipy/rtc.py21
-rw-r--r--tests/wipy/rtc.py.exp3
-rw-r--r--tests/wipy/rtc_irq.py89
-rw-r--r--tests/wipy/rtc_irq.py.exp18
-rw-r--r--tests/wipy/uart_irq.py149
-rw-r--r--tests/wipy/uart_irq.py.exp33
31 files changed, 1404 insertions, 757 deletions
diff --git a/cc3200/application.mk b/cc3200/application.mk
index 6663a61859..4d4e03da1c 100644
--- a/cc3200/application.mk
+++ b/cc3200/application.mk
@@ -78,7 +78,7 @@ APP_MISC_SRC_C = $(addprefix misc/,\
antenna.c \
FreeRTOSHooks.c \
help.c \
- mpcallback.c \
+ mpirq.c \
mperror.c \
mpexception.c \
mpsystick.c \
diff --git a/cc3200/boards/cc3200_prefix.c b/cc3200/boards/cc3200_prefix.c
index 520ea2c5d9..9712857453 100644
--- a/cc3200/boards/cc3200_prefix.c
+++ b/cc3200/boards/cc3200_prefix.c
@@ -52,16 +52,18 @@
#define PIN(p_pin_name, p_port, p_bit, p_pin_num, p_af_list, p_num_afs) \
{ \
{ &pin_type }, \
- .name = MP_QSTR_ ## p_pin_name, \
- .port = PORT_A ## p_port, \
- .af_list = (p_af_list), \
- .pull = PIN_TYPE_STD, \
- .bit = (p_bit), \
- .pin_num = (p_pin_num), \
- .af = PIN_MODE_0, \
- .strength = PIN_STRENGTH_4MA, \
- .mode = GPIO_DIR_MODE_IN, \
- .num_afs = (p_num_afs), \
- .value = 0, \
- .used = false, \
+ .name = MP_QSTR_ ## p_pin_name, \
+ .port = PORT_A ## p_port, \
+ .af_list = (p_af_list), \
+ .pull = PIN_TYPE_STD, \
+ .bit = (p_bit), \
+ .pin_num = (p_pin_num), \
+ .af = PIN_MODE_0, \
+ .strength = PIN_STRENGTH_4MA, \
+ .mode = GPIO_DIR_MODE_IN, \
+ .num_afs = (p_num_afs), \
+ .value = 0, \
+ .used = false, \
+ .irq_trigger = 0, \
+ .irq_flags = 0, \
}
diff --git a/cc3200/hal/prcm.c b/cc3200/hal/prcm.c
index 773fc90fb0..4b66c0ff1e 100644
--- a/cc3200/hal/prcm.c
+++ b/cc3200/hal/prcm.c
@@ -112,17 +112,17 @@
// following wrapper can be used to convert the value from cycles to
// millisecond:
//
-// CYCLES_U16MS(cycles) ((cycles *1000)/ 1024),
+// CYCLES_U16MS(cycles) ((cycles * 1000) / 1024),
//
// Similarly, before setting the value, it must be first converted (from ms to
// cycles).
//
-// U16MS_CYCLES(msec) ((msec *1024)/1000)
+// U16MS_CYCLES(msec) ((msec * 1024) / 1000)
//
// Note: There is a precision loss of 1 ms with the above scheme.
//
//
-#define SCC_U64MSEC_GET() (MAP_PRCMSlowClkCtrGet() >> 5)
+#define SCC_U64MSEC_GET() (RTCFastDomainCounterGet() >> 5)
#define SCC_U64MSEC_MATCH_SET(u64Msec) (MAP_PRCMSlowClkCtrMatchSet(u64Msec << 5))
#define SCC_U64MSEC_MATCH_GET() (MAP_PRCMSlowClkCtrMatchGet() >> 5)
@@ -209,6 +209,39 @@ static void RTCU32SecRegWrite(unsigned long u32Msec)
}
//*****************************************************************************
+// Fast function to get the most accurate RTC counter value
+//*****************************************************************************
+static unsigned long long RTCFastDomainCounterGet (void) {
+
+ #define BRK_IF_RTC_CTRS_ALIGN(c2, c1) if (c2 - c1 <= 1) { \
+ itr++; \
+ break; \
+ }
+
+ unsigned long long rtc_count1, rtc_count2, rtc_count3;
+ unsigned int itr;
+
+ do {
+ rtc_count1 = PRCMSlowClkCtrFastGet();
+ rtc_count2 = PRCMSlowClkCtrFastGet();
+ rtc_count3 = PRCMSlowClkCtrFastGet();
+ itr = 0;
+
+ BRK_IF_RTC_CTRS_ALIGN(rtc_count2, rtc_count1);
+ BRK_IF_RTC_CTRS_ALIGN(rtc_count3, rtc_count2);
+ BRK_IF_RTC_CTRS_ALIGN(rtc_count3, rtc_count1);
+
+ // Consistent values in two consecutive reads implies a correct
+ // value of the counter. Do note, the counter does not give the
+ // calendar time but a hardware that ticks upwards continuously.
+ // The 48-bit counter operates at 32,768 HZ.
+
+ } while (true);
+
+ return (1 == itr) ? rtc_count2 : rtc_count3;
+}
+
+//*****************************************************************************
// Macros
//*****************************************************************************
#define IS_RTC_USED() IsRTCUsed()
@@ -1245,6 +1278,35 @@ unsigned long long PRCMSlowClkCtrGet(void)
return ullRTCVal;
}
+//*****************************************************************************
+//
+//! Gets the current value of the internal slow clock counter
+//!
+//! This function is similar to \sa PRCMSlowClkCtrGet() but reads the counter
+//! value from a relatively faster interface using an auto-latch mechainsm.
+//!
+//! \note Due to the nature of implemetation of auto latching, when using this
+//! API, the recommendation is to read the value thrice and identify the right
+//! value (as 2 out the 3 read values will always be correct and with a max. of
+//! 1 LSB change)
+//!
+//! \return 64-bit current counter vlaue.
+//
+//*****************************************************************************
+unsigned long long PRCMSlowClkCtrFastGet(void)
+{
+ unsigned long long ullRTCVal;
+
+ //
+ // Read as 2 32-bit values
+ //
+ ullRTCVal = HWREG(HIB1P2_BASE + HIB1P2_O_HIB_RTC_TIMER_MSW_1P2);
+ ullRTCVal = ullRTCVal << 32;
+ ullRTCVal |= HWREG(HIB1P2_BASE + HIB1P2_O_HIB_RTC_TIMER_LSW_1P2);
+
+ return ullRTCVal;
+
+}
//*****************************************************************************
//
diff --git a/cc3200/hal/prcm.h b/cc3200/hal/prcm.h
index 110d8326ea..2f700ae2c6 100644
--- a/cc3200/hal/prcm.h
+++ b/cc3200/hal/prcm.h
@@ -247,6 +247,7 @@ extern void PRCMHibernateWakeupSourceDisable(unsigned long ulHIBWakupSrc);
extern void PRCMHibernateIntervalSet(unsigned long long ullTicks);
extern unsigned long long PRCMSlowClkCtrGet(void);
+extern unsigned long long PRCMSlowClkCtrFastGet(void);
extern void PRCMSlowClkCtrMatchSet(unsigned long long ullTicks);
extern unsigned long long PRCMSlowClkCtrMatchGet(void);
diff --git a/cc3200/misc/mpcallback.c b/cc3200/misc/mpirq.c
index 8e7a9f740a..e780c78b6d 100644
--- a/cc3200/misc/mpcallback.c
+++ b/cc3200/misc/mpirq.c
@@ -34,46 +34,51 @@
#include "inc/hw_types.h"
#include "interrupt.h"
#include "pybsleep.h"
-#include "mpcallback.h"
#include "mpexception.h"
#include "mperror.h"
+#include "mpirq.h"
/******************************************************************************
- DEFINE PUBLIC DATA
+ DECLARE PUBLIC DATA
******************************************************************************/
-const mp_arg_t mpcallback_init_args[] = {
- { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+const mp_arg_t mp_irq_init_args[] = {
+ { MP_QSTR_trigger, 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} }, // the lowest priority
{ MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_priority, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
- { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_wake_from, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYB_PWR_MODE_ACTIVE} },
+ { MP_QSTR_wake, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
/******************************************************************************
+ DECLARE PRIVATE DATA
+ ******************************************************************************/
+STATIC uint8_t mp_irq_priorities[] = { INT_PRIORITY_LVL_7, INT_PRIORITY_LVL_6, INT_PRIORITY_LVL_5, INT_PRIORITY_LVL_4,
+ INT_PRIORITY_LVL_3, INT_PRIORITY_LVL_2, INT_PRIORITY_LVL_1 };
+
+/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
-void mpcallback_init0 (void) {
+void mp_irq_init0 (void) {
// initialize the callback objects list
- mp_obj_list_init(&MP_STATE_PORT(mpcallback_obj_list), 0);
+ mp_obj_list_init(&MP_STATE_PORT(mp_irq_obj_list), 0);
}
-mp_obj_t mpcallback_new (mp_obj_t parent, mp_obj_t handler, const mp_cb_methods_t *methods, bool enable) {
- mpcallback_obj_t *self = m_new_obj(mpcallback_obj_t);
- self->base.type = &pyb_callback_type;
+mp_obj_t mp_irq_new (mp_obj_t parent, mp_obj_t handler, const mp_irq_methods_t *methods) {
+ mp_irq_obj_t *self = m_new_obj(mp_irq_obj_t);
+ self->base.type = &mp_irq_type;
self->handler = handler;
self->parent = parent;
- self->methods = (mp_cb_methods_t *)methods;
- self->isenabled = enable;
+ self->methods = (mp_irq_methods_t *)methods;
+ self->isenabled = true;
// remove it in case it was already registered
- mpcallback_remove(parent);
- mp_obj_list_append(&MP_STATE_PORT(mpcallback_obj_list), self);
+ mp_irq_remove(parent);
+ mp_obj_list_append(&MP_STATE_PORT(mp_irq_obj_list), self);
return self;
}
-mpcallback_obj_t *mpcallback_find (mp_obj_t parent) {
- for (mp_uint_t i = 0; i < MP_STATE_PORT(mpcallback_obj_list).len; i++) {
- mpcallback_obj_t *callback_obj = ((mpcallback_obj_t *)(MP_STATE_PORT(mpcallback_obj_list).items[i]));
+mp_irq_obj_t *mp_irq_find (mp_obj_t parent) {
+ for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_irq_obj_list).len; i++) {
+ mp_irq_obj_t *callback_obj = ((mp_irq_obj_t *)(MP_STATE_PORT(mp_irq_obj_list).items[i]));
if (callback_obj->parent == parent) {
return callback_obj;
}
@@ -81,58 +86,40 @@ mpcallback_obj_t *mpcallback_find (mp_obj_t parent) {
return NULL;
}
-void mpcallback_wake_all (void) {
+void mp_irq_wake_all (void) {
// re-enable all active callback objects one by one
- for (mp_uint_t i = 0; i < MP_STATE_PORT(mpcallback_obj_list).len; i++) {
- mpcallback_obj_t *callback_obj = ((mpcallback_obj_t *)(MP_STATE_PORT(mpcallback_obj_list).items[i]));
+ for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_irq_obj_list).len; i++) {
+ mp_irq_obj_t *callback_obj = ((mp_irq_obj_t *)(MP_STATE_PORT(mp_irq_obj_list).items[i]));
if (callback_obj->isenabled) {
callback_obj->methods->enable(callback_obj->parent);
}
}
}
-void mpcallback_disable_all (void) {
+void mp_irq_disable_all (void) {
// re-enable all active callback objects one by one
- for (mp_uint_t i = 0; i < MP_STATE_PORT(mpcallback_obj_list).len; i++) {
- mpcallback_obj_t *callback_obj = ((mpcallback_obj_t *)(MP_STATE_PORT(mpcallback_obj_list).items[i]));
+ for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_irq_obj_list).len; i++) {
+ mp_irq_obj_t *callback_obj = ((mp_irq_obj_t *)(MP_STATE_PORT(mp_irq_obj_list).items[i]));
callback_obj->methods->disable(callback_obj->parent);
}
}
-void mpcallback_remove (const mp_obj_t parent) {
- mpcallback_obj_t *callback_obj;
- if ((callback_obj = mpcallback_find(parent))) {
- mp_obj_list_remove(&MP_STATE_PORT(mpcallback_obj_list), callback_obj);
+void mp_irq_remove (const mp_obj_t parent) {
+ mp_irq_obj_t *callback_obj;
+ if ((callback_obj = mp_irq_find(parent))) {
+ mp_obj_list_remove(&MP_STATE_PORT(mp_irq_obj_list), callback_obj);
}
}
-uint mpcallback_translate_priority (uint priority) {
- if (priority < 1 || priority > 7) {
+uint mp_irq_translate_priority (uint priority) {
+ if (priority < 1 || priority > MP_ARRAY_SIZE(mp_irq_priorities)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
-
- switch (priority) {
- case 1:
- return INT_PRIORITY_LVL_7;
- case 2:
- return INT_PRIORITY_LVL_6;
- case 3:
- return INT_PRIORITY_LVL_5;
- case 4:
- return INT_PRIORITY_LVL_4;
- case 5:
- return INT_PRIORITY_LVL_3;
- case 6:
- return INT_PRIORITY_LVL_2;
- case 7:
- return INT_PRIORITY_LVL_1;
- default:
- return INT_PRIORITY_LVL_7;
- }
+ return mp_irq_priorities[priority - 1];
}
-void mpcallback_handler (mp_obj_t self_in) {
- mpcallback_obj_t *self = self_in;
+void mp_irq_handler (mp_obj_t self_in) {
+ mp_irq_obj_t *self = self_in;
if (self && self->handler != mp_const_none) {
// when executing code within a handler we must lock the GC to prevent
// any memory allocations.
@@ -159,59 +146,57 @@ void mpcallback_handler (mp_obj_t self_in) {
/******************************************************************************/
// Micro Python bindings
-/// \method init()
-/// Initializes the interrupt callback. With no parameters passed, everything will default
-/// to the values assigned to mpcallback_init_args[].
-STATIC mp_obj_t callback_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mpcallback_obj_t *self = pos_args[0];
+STATIC mp_obj_t mp_irq_init (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_irq_obj_t *self = pos_args[0];
// this is a bit of a hack, but it let us reuse the callback_create method from our parent
((mp_obj_t *)pos_args)[0] = self->parent;
self->methods->init (n_args, pos_args, kw_args);
return mp_const_none;
}
-MP_DEFINE_CONST_FUN_OBJ_KW(callback_init_obj, 1, callback_init);
+MP_DEFINE_CONST_FUN_OBJ_KW(mp_irq_init_obj, 1, mp_irq_init);
-/// \method enable()
-/// Enables the interrupt callback
-STATIC mp_obj_t callback_enable (mp_obj_t self_in) {
- mpcallback_obj_t *self = self_in;
+STATIC mp_obj_t mp_irq_enable (mp_obj_t self_in) {
+ mp_irq_obj_t *self = self_in;
self->methods->enable(self->parent);
self->isenabled = true;
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(callback_enable_obj, callback_enable);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_enable_obj, mp_irq_enable);
-/// \method disable()
-/// Disables the interrupt callback
-STATIC mp_obj_t callback_disable (mp_obj_t self_in) {
- mpcallback_obj_t *self = self_in;
+STATIC mp_obj_t mp_irq_disable (mp_obj_t self_in) {
+ mp_irq_obj_t *self = self_in;
self->methods->disable(self->parent);
self->isenabled = false;
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(callback_disable_obj, callback_disable);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_disable_obj, mp_irq_disable);
+
+STATIC mp_obj_t mp_irq_flags (mp_obj_t self_in) {
+ mp_irq_obj_t *self = self_in;
+ return mp_obj_new_int(self->methods->flags(self->parent));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_flags_obj, mp_irq_flags);
-/// \method \call()
-/// Triggers the interrupt callback
-STATIC mp_obj_t callback_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+STATIC mp_obj_t mp_irq_call (mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 0, false);
- mpcallback_handler (self_in);
+ mp_irq_handler (self_in);
return mp_const_none;
}
-STATIC const mp_map_elem_t callback_locals_dict_table[] = {
+STATIC const mp_map_elem_t mp_irq_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&callback_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&callback_enable_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&callback_disable_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&mp_irq_init_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&mp_irq_enable_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&mp_irq_disable_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_flags), (mp_obj_t)&mp_irq_flags_obj },
};
-STATIC MP_DEFINE_CONST_DICT(callback_locals_dict, callback_locals_dict_table);
+STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table);
-const mp_obj_type_t pyb_callback_type = {
+const mp_obj_type_t mp_irq_type = {
{ &mp_type_type },
- .name = MP_QSTR_callback,
- .call = callback_call,
- .locals_dict = (mp_obj_t)&callback_locals_dict,
+ .name = MP_QSTR_irq,
+ .call = mp_irq_call,
+ .locals_dict = (mp_obj_t)&mp_irq_locals_dict,
};
diff --git a/cc3200/misc/mpcallback.h b/cc3200/misc/mpirq.h
index cc15a3ac65..3fd21ee094 100644
--- a/cc3200/misc/mpcallback.h
+++ b/cc3200/misc/mpirq.h
@@ -24,50 +24,52 @@
* THE SOFTWARE.
*/
-#ifndef MPCALLBACK_H_
-#define MPCALLBACK_H_
+#ifndef MPIRQ_H_
+#define MPIRQ_H_
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
-#define mpcallback_INIT_NUM_ARGS 5
+#define mp_irq_INIT_NUM_ARGS 4
/******************************************************************************
DEFINE TYPES
******************************************************************************/
-typedef void (*mp_cb_method_t) (mp_obj_t self);
-typedef mp_obj_t (*mp_cb_init_t) (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
+typedef mp_obj_t (*mp_irq_init_t) (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
+typedef void (*mp_irq_void_method_t) (mp_obj_t self);
+typedef int (*mp_irq_int_method_t) (mp_obj_t self);
typedef struct {
- mp_cb_init_t init;
- mp_cb_method_t enable;
- mp_cb_method_t disable;
-} mp_cb_methods_t;
+ mp_irq_init_t init;
+ mp_irq_void_method_t enable;
+ mp_irq_void_method_t disable;
+ mp_irq_int_method_t flags;
+} mp_irq_methods_t;
typedef struct {
mp_obj_base_t base;
mp_obj_t parent;
mp_obj_t handler;
- mp_cb_methods_t *methods;
+ mp_irq_methods_t *methods;
bool isenabled;
-} mpcallback_obj_t;
+} mp_irq_obj_t;
/******************************************************************************
DECLARE EXPORTED DATA
******************************************************************************/
-extern const mp_arg_t mpcallback_init_args[];
-extern const mp_obj_type_t pyb_callback_type;
+extern const mp_arg_t mp_irq_init_args[];
+extern const mp_obj_type_t mp_irq_type;
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
-void mpcallback_init0 (void);
-mp_obj_t mpcallback_new (mp_obj_t parent, mp_obj_t handler, const mp_cb_methods_t *methods, bool enable);
-mpcallback_obj_t *mpcallback_find (mp_obj_t parent);
-void mpcallback_wake_all (void);
-void mpcallback_disable_all (void);
-void mpcallback_remove (const mp_obj_t parent);
-void mpcallback_handler (mp_obj_t self_in);
-uint mpcallback_translate_priority (uint priority);
+void mp_irq_init0 (void);
+mp_obj_t mp_irq_new (mp_obj_t parent, mp_obj_t handler, const mp_irq_methods_t *methods);
+mp_irq_obj_t *mp_irq_find (mp_obj_t parent);
+void mp_irq_wake_all (void);
+void mp_irq_disable_all (void);
+void mp_irq_remove (const mp_obj_t parent);
+void mp_irq_handler (mp_obj_t self_in);
+uint mp_irq_translate_priority (uint priority);
-#endif /* MPCALLBACK_H_ */
+#endif /* MPIRQ_H_ */
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_
diff --git a/cc3200/mpconfigport.h b/cc3200/mpconfigport.h
index aed07bdcae..7c0a693279 100644
--- a/cc3200/mpconfigport.h
+++ b/cc3200/mpconfigport.h
@@ -160,7 +160,7 @@ extern const struct _mp_obj_module_t mp_module_ussl;
mp_obj_t mp_const_user_interrupt; \
mp_obj_t pyb_config_main; \
mp_obj_list_t pybsleep_obj_list; \
- mp_obj_list_t mpcallback_obj_list; \
+ mp_obj_list_t mp_irq_obj_list; \
mp_obj_list_t pyb_timer_channel_obj_list; \
mp_obj_list_t mount_obj_list; \
struct _pyb_uart_obj_t *pyb_uart_objs[2]; \
diff --git a/cc3200/mptask.c b/cc3200/mptask.c
index ec342e2d09..4f01a66eb6 100644
--- a/cc3200/mptask.c
+++ b/cc3200/mptask.c
@@ -64,8 +64,8 @@
#include "pins.h"
#include "pybsleep.h"
#include "pybtimer.h"
-#include "mpcallback.h"
#include "cryptohash.h"
+#include "mpirq.h"
#include "updater.h"
#include "moduos.h"
@@ -126,7 +126,7 @@ soft_reset:
// execute all basic initializations
mpexception_init0();
- mpcallback_init0();
+ mp_irq_init0();
pybsleep_init0();
pin_init0();
mperror_init0();
@@ -234,7 +234,10 @@ soft_reset_exit:
// disable all callbacks to avoid undefined behaviour
// when coming out of a soft reset
- mpcallback_disable_all();
+ mp_irq_disable_all();
+
+ // cancel the RTC alarm which might be running independent of the irq state
+ pyb_rtc_disable_alarm();
// flush the serial flash buffer
sflash_disk_flush();
diff --git a/cc3200/qstrdefsport.h b/cc3200/qstrdefsport.h
index 9ccdf829fd..5c619e1cdc 100644
--- a/cc3200/qstrdefsport.h
+++ b/cc3200/qstrdefsport.h
@@ -179,10 +179,12 @@ Q(RTC)
Q(init)
Q(alarm)
Q(alarm_left)
+Q(alarm_cancel)
Q(now)
Q(deinit)
Q(datetime)
Q(repeat)
+Q(ALARM0)
// for time class
Q(time)
@@ -292,6 +294,7 @@ Q(WPA)
Q(WPA2)
Q(INTERNAL)
Q(EXTERNAL)
+Q(ANY_EVENT)
// for WDT class
Q(WDT)
@@ -303,16 +306,16 @@ Q(HeartBeat)
Q(enable)
Q(disable)
-// for callback class
+// for irq class
+Q(irq)
Q(init)
Q(enable)
Q(disable)
-Q(callback)
+Q(flags)
+Q(trigger)
Q(handler)
-Q(mode)
-Q(value)
Q(priority)
-Q(wake_from)
+Q(wake)
// for Sleep class
Q(Sleep)
diff --git a/cc3200/util/random.c b/cc3200/util/random.c
index 470d95d3a8..baa2db62ee 100644
--- a/cc3200/util/random.c
+++ b/cc3200/util/random.c
@@ -32,14 +32,13 @@
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "rom_map.h"
-#include "prcm.h"
+#include "pybrtc.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "random.h"
#include "debug.h"
-
/******************************************************************************
* LOCAL TYPES
******************************************************************************/
@@ -57,16 +56,19 @@ static uint32_t s_seed;
/******************************************************************************
* LOCAL FUNCTION DECLARATIONS
******************************************************************************/
-static uint32_t lfsr (uint32_t input);
+STATIC uint32_t lfsr (uint32_t input);
/******************************************************************************
* PRIVATE FUNCTIONS
******************************************************************************/
-static uint32_t lfsr (uint32_t input) {
+STATIC uint32_t lfsr (uint32_t input) {
assert( input != 0 );
return (input >> 1) ^ (-(input & 0x01) & 0x00E10000);
}
+/******************************************************************************/
+// Micro Python bindings;
+
STATIC mp_obj_t pyb_rng_get(void) {
return mp_obj_new_int(rng_get());
}
@@ -81,7 +83,7 @@ void rng_init0 (void) {
uint16_t mseconds;
// get the seconds and the milliseconds from the RTC
- MAP_PRCMRTCGet(&seconds, &mseconds);
+ pyb_rtc_get_time(&seconds, &mseconds);
wlan_get_mac (juggler.id8);
diff --git a/tests/wipy/pin_irq.py b/tests/wipy/pin_irq.py
new file mode 100644
index 0000000000..75a7f090d8
--- /dev/null
+++ b/tests/wipy/pin_irq.py
@@ -0,0 +1,116 @@
+'''
+Pin IRQ test for the CC3200 based boards.
+'''
+
+from pyb import Pin
+from pyb import Sleep
+import os
+import time
+
+machine = os.uname().machine
+if 'LaunchPad' in machine:
+ pins = ['GP16', 'GP13']
+elif 'WiPy' in machine:
+ pins = ['GP16', 'GP13']
+else:
+ raise Exception('Board not supported!')
+
+pin0 = Pin(pins[0], mode=Pin.OUT, value=1)
+pin1 = Pin(pins[1], mode=Pin.IN, pull=Pin.PULL_UP)
+
+def pin_handler (pin_o):
+ global pin_irq_count_trigger
+ global pin_irq_count_total
+ global _trigger
+ if _trigger & pin1_irq.flags():
+ pin_irq_count_trigger += 1
+ pin_irq_count_total += 1
+
+pin_irq_count_trigger = 0
+pin_irq_count_total = 0
+_trigger = Pin.IRQ_FALLING
+pin1_irq = pin1.irq(trigger=_trigger, handler=pin_handler)
+for i in range (0, 10):
+ pin0.toggle()
+ time.sleep_ms(5)
+print(pin_irq_count_trigger == 5)
+print(pin_irq_count_total == 5)
+
+pin_irq_count_trigger = 0
+pin_irq_count_total = 0
+_trigger = Pin.IRQ_RISING
+pin1_irq = pin1.irq(trigger=_trigger, handler=pin_handler)
+for i in range (0, 200):
+ pin0.toggle()
+ time.sleep_ms(5)
+print(pin_irq_count_trigger == 100)
+print(pin_irq_count_total == 100)
+
+pin1_irq.disable()
+pin0(1)
+pin_irq_count_trigger = 0
+pin_irq_count_total = 0
+_trigger = Pin.IRQ_FALLING
+pin1_irq.init(trigger=_trigger, handler=pin_handler)
+pin0(0)
+time.sleep_us(50)
+print(pin_irq_count_trigger == 1)
+print(pin_irq_count_total == 1)
+pin0(1)
+time.sleep_us(50)
+print(pin_irq_count_trigger == 1)
+print(pin_irq_count_total == 1)
+
+# check the call method
+pin1_irq()
+print(pin_irq_count_trigger == 1) # no flags since the irq was manually triggered
+print(pin_irq_count_total == 2)
+
+pin1_irq.disable()
+pin_irq_count_trigger = 0
+pin_irq_count_total = 0
+for i in range (0, 10):
+ pin0.toggle()
+ time.sleep_ms(5)
+print(pin_irq_count_trigger == 0)
+print(pin_irq_count_total == 0)
+
+# test waking up from suspended mode on low level
+pin0(0)
+t0 = time.ticks_ms()
+pin1_irq.init(trigger=Pin.IRQ_LOW_LEVEL, wake=Sleep.SUSPENDED)
+Sleep.suspend()
+print(time.ticks_ms() - t0 < 10)
+print('Awake')
+
+# test waking up from suspended mode on high level
+pin0(1)
+t0 = time.ticks_ms()
+pin1_irq.init(trigger=Pin.IRQ_HIGH_LEVEL, wake=Sleep.SUSPENDED)
+Sleep.suspend()
+print(time.ticks_ms() - t0 < 10)
+print('Awake')
+
+# check for memory leaks
+for i in range(0, 1000):
+ pin0_irq = pin0.irq(trigger=_trigger, handler=pin_handler)
+ pin1_irq = pin1.irq(trigger=_trigger, handler=pin_handler)
+
+# next ones must raise
+try:
+ pin1_irq.init(trigger=123456, handler=pin_handler)
+except:
+ print('Exception')
+
+try:
+ pin1_irq.init(trigger=Pin.IRQ_LOW_LEVEL, wake=1789456)
+except:
+ print('Exception')
+
+try:
+ pin0_irq = pin0.irq(trigger=Pin.IRQ_RISING, wake=Sleep.SUSPENDED) # GP16 can't wake up from DEEPSLEEP
+except:
+ print('Exception')
+
+pin0_irq.disable()
+pin1_irq.disable()
diff --git a/tests/wipy/pin_irq.py.exp b/tests/wipy/pin_irq.py.exp
new file mode 100644
index 0000000000..458bd95668
--- /dev/null
+++ b/tests/wipy/pin_irq.py.exp
@@ -0,0 +1,19 @@
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+Awake
+True
+Awake
+Exception
+Exception
+Exception
diff --git a/tests/wipy/rtc.py b/tests/wipy/rtc.py
index 4114796db1..9f4a0f673e 100644
--- a/tests/wipy/rtc.py
+++ b/tests/wipy/rtc.py
@@ -66,17 +66,22 @@ rtc.alarm(0, 5000)
rtc.alarm(time=2000)
time.sleep_ms(1000)
left = rtc.alarm_left()
-print(abs(left-1000) < 20)
+print(abs(left-1000) <= 10)
time.sleep_ms(1000)
print(rtc.alarm_left() == 0)
time.sleep_ms(100)
-print(rtc.alarm_left() == 0)
+print(rtc.alarm_left(0) == 0)
+
+rtc.alarm(time=1000, repeat=True)
+time.sleep_ms(1500)
+left = rtc.alarm_left()
+print(abs(left-500) <= 15)
rtc.init((2015, 8, 29, 9, 0, 0, 0, None))
rtc.alarm(time=(2015, 8, 29, 9, 0, 45))
time.sleep_ms(1000)
left = rtc.alarm_left()
-print(abs(left-44000) < 100)
+print(abs(left-44000) <= 90)
# next ones must raise
try:
@@ -85,6 +90,16 @@ except:
print('Exception')
try:
+ rtc.alarm_left(1)
+except:
+ print('Exception')
+
+try:
+ rtc.alarm_cancel(1)
+except:
+ print('Exception')
+
+try:
rtc.alarm(5000)
except:
print('Exception')
diff --git a/tests/wipy/rtc.py.exp b/tests/wipy/rtc.py.exp
index 8225f4602f..44f8f8b81c 100644
--- a/tests/wipy/rtc.py.exp
+++ b/tests/wipy/rtc.py.exp
@@ -28,6 +28,9 @@ True
True
True
True
+True
+Exception
+Exception
Exception
Exception
Exception
diff --git a/tests/wipy/rtc_irq.py b/tests/wipy/rtc_irq.py
new file mode 100644
index 0000000000..1c9ea93f1d
--- /dev/null
+++ b/tests/wipy/rtc_irq.py
@@ -0,0 +1,89 @@
+'''
+RTC IRQ test for the CC3200 based boards.
+'''
+
+from pyb import RTC
+from pyb import Sleep
+import os
+import time
+
+machine = os.uname().machine
+if not 'LaunchPad' in machine and not 'WiPy' in machine:
+ raise Exception('Board not supported!')
+
+def rtc_ticks_ms(rtc):
+ timedate = rtc.now()
+ return (timedate[5] * 1000) + (timedate[6] // 1000)
+
+rtc_irq_count = 0
+
+def alarm_handler (rtc_o):
+ global rtc_irq
+ global rtc_irq_count
+ if rtc_irq.flags() & RTC.ALARM0:
+ rtc_irq_count += 1
+
+rtc = RTC()
+rtc.alarm(time=500, repeat=True)
+rtc_irq = rtc.irq(trigger=RTC.ALARM0, handler=alarm_handler)
+
+# active mode
+time.sleep_ms(1000)
+rtc.alarm_cancel()
+print(rtc_irq_count == 2)
+rtc_irq_count = 0
+rtc.alarm(time=200, repeat=True)
+time.sleep_ms(1000)
+rtc.alarm_cancel()
+print(rtc_irq_count == 5)
+
+rtc_irq_count = 0
+rtc.alarm(time=100, repeat=True)
+time.sleep_ms(1000)
+rtc.alarm_cancel()
+print(rtc_irq_count == 10)
+
+# deep sleep mode
+rtc.alarm_cancel()
+rtc_irq_count = 0
+rtc.alarm(time=50, repeat=True)
+rtc_irq.init(trigger=RTC.ALARM0, handler=alarm_handler, wake=Sleep.SUSPENDED | Sleep.ACTIVE)
+while rtc_irq_count < 3:
+ Sleep.suspend()
+print(rtc_irq_count == 3)
+
+# no repetition
+rtc.alarm_cancel()
+rtc_irq_count = 0
+rtc.alarm(time=100, repeat=False)
+time.sleep_ms(250)
+print(rtc_irq_count == 1)
+
+rtc.alarm_cancel()
+t0 = rtc_ticks_ms(rtc)
+rtc.alarm(time=500, repeat=False)
+Sleep.suspend()
+t1 = rtc_ticks_ms(rtc)
+print(abs(t1 - t0 - 500) < 20)
+
+# deep sleep repeated mode
+rtc.alarm_cancel()
+rtc_irq_count = 0
+rtc.alarm(time=250, repeat=True)
+t0 = rtc_ticks_ms(rtc)
+rtc_irq = rtc.irq(trigger=RTC.ALARM0, handler=alarm_handler, wake=Sleep.SUSPENDED)
+while rtc_irq_count < 10:
+ Sleep.suspend()
+ t1 = rtc_ticks_ms(rtc)
+ print(abs(t1 - t0 - (250 * rtc_irq_count)) < 25)
+
+# next ones must raise
+try:
+ rtc_irq = rtc.irq(trigger=10, handler=alarm_handler)
+except:
+ print('Exception')
+
+try:
+ rtc_irq = rtc.irq(trigger=RTC.ALARM0, wake=1789456)
+except:
+ print('Exception')
diff --git a/tests/wipy/rtc_irq.py.exp b/tests/wipy/rtc_irq.py.exp
new file mode 100644
index 0000000000..a9ef48c7a7
--- /dev/null
+++ b/tests/wipy/rtc_irq.py.exp
@@ -0,0 +1,18 @@
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+Exception
+Exception
diff --git a/tests/wipy/uart_irq.py b/tests/wipy/uart_irq.py
new file mode 100644
index 0000000000..3f1084cce3
--- /dev/null
+++ b/tests/wipy/uart_irq.py
@@ -0,0 +1,149 @@
+'''
+UART IRQ test for the CC3200 based boards.
+'''
+
+from pyb import UART
+import os
+import pyb
+import time
+
+machine = os.uname().machine
+if 'LaunchPad' in machine:
+ uart_pins = [[('GP12', 'GP13'), ('GP12', 'GP13', 'GP7', 'GP6')], [('GP16', 'GP17'), ('GP16', 'GP17', 'GP7', 'GP6')]]
+elif 'WiPy' in machine:
+ uart_pins = [[('GP12', 'GP13'), ('GP12', 'GP13', 'GP7', 'GP6')], [('GP16', 'GP17'), ('GP16', 'GP17', 'GP7', 'GP6')]]
+else:
+ raise Exception('Board not supported!')
+
+# just in case we have stdio duplicated on any of the uarts
+pyb.repl_uart(None)
+
+uart0 = UART(0, 1000000, pins=uart_pins[0][0])
+uart1 = UART(1, 1000000, pins=uart_pins[1][0])
+
+uart0_int_count = 0
+uart1_int_count = 0
+
+def uart0_handler (uart_o):
+ global uart0_irq
+ global uart0_int_count
+ if (uart0_irq.flags() & UART.RX_ANY):
+ uart0_int_count += 1
+
+def uart1_handler (uart_o):
+ global uart1_irq
+ global uart1_int_count
+ if (uart1_irq.flags() & UART.RX_ANY):
+ uart1_int_count += 1
+
+uart0_irq = uart0.irq(trigger=UART.RX_ANY, handler=uart0_handler)
+uart1_irq = uart1.irq(trigger=UART.RX_ANY, handler=uart1_handler)
+
+uart0.write(b'123')
+# wait for the characters to be received
+while not uart1.any():
+ pass
+
+time.sleep_us(100)
+print(uart1.any() == 3)
+print(uart1_int_count > 0)
+print(uart1_irq.flags() == 0)
+print(uart0_irq.flags() == 0)
+print(uart1.read() == b'123')
+
+uart1.write(b'12345')
+# wait for the characters to be received
+while not uart0.any():
+ pass
+
+time.sleep_us(100)
+print(uart0.any() == 5)
+print(uart0_int_count > 0)
+print(uart0_irq.flags() == 0)
+print(uart1_irq.flags() == 0)
+print(uart0.read() == b'12345')
+
+# do it again
+uart1_int_count = 0
+uart0.write(b'123')
+# wait for the characters to be received
+while not uart1.any():
+ pass
+
+time.sleep_us(100)
+print(uart1.any() == 3)
+print(uart1_int_count > 0)
+print(uart1_irq.flags() == 0)
+print(uart0_irq.flags() == 0)
+print(uart1.read() == b'123')
+
+# disable the interrupt
+uart1_irq.disable()
+# do it again
+uart1_int_count = 0
+uart0.write(b'123')
+# wait for the characters to be received
+while not uart1.any():
+ pass
+
+time.sleep_us(100)
+print(uart1.any() == 3)
+print(uart1_int_count == 0) # no interrupt triggered this time
+print(uart1_irq.flags() == 0)
+print(uart0_irq.flags() == 0)
+print(uart1.read() == b'123')
+
+# enable the interrupt
+uart1_irq.enable()
+# do it again
+uart1_int_count = 0
+uart0.write(b'123')
+# wait for the characters to be received
+while not uart1.any():
+ pass
+
+time.sleep_us(100)
+print(uart1.any() == 3)
+print(uart1_int_count > 0)
+print(uart1_irq.flags() == 0)
+print(uart0_irq.flags() == 0)
+print(uart1.read() == b'123')
+
+uart1_irq.init(trigger=UART.RX_ANY, handler=None) # No handler
+# do it again
+uart1_int_count = 0
+uart0.write(b'123')
+# wait for the characters to be received
+while not uart1.any():
+ pass
+
+time.sleep_us(100)
+print(uart1.any() == 3)
+print(uart1_int_count == 0) # no interrupt handler called
+print(uart1_irq.flags() == 0)
+print(uart0_irq.flags() == 0)
+print(uart1.read() == b'123')
+
+# check for memory leaks
+for i in range(0, 1000):
+ uart0_irq = uart0.irq(trigger=UART.RX_ANY, handler=uart0_handler)
+ uart1_irq = uart1.irq(trigger=UART.RX_ANY, handler=uart1_handler)
+
+# next ones must raise
+try:
+ uart0_irq = uart0.irq(trigger=100, handler=uart0_handler)
+except:
+ print('Exception')
+
+try:
+ uart0_irq = uart0.irq(trigger=0)
+except:
+ print('Exception')
+
+try:
+ uart0_irq = uart0.irq(trigger=UART.RX_ANY, wake=Sleep.SUSPENDED)
+except:
+ print('Exception')
+
+uart0_irq.disable()
+uart1_irq.disable()
diff --git a/tests/wipy/uart_irq.py.exp b/tests/wipy/uart_irq.py.exp
new file mode 100644
index 0000000000..b165e824a0
--- /dev/null
+++ b/tests/wipy/uart_irq.py.exp
@@ -0,0 +1,33 @@
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+True
+Exception
+Exception
+Exception