cc3200: New irq API, affects all classes that provide the irq method.

pull/1480/merge
Daniel Campora 2015-09-22 23:20:29 +02:00
rodzic 81d64ab939
commit dbdcb58d64
31 zmienionych plików z 1437 dodań i 790 usunięć

Wyświetl plik

@ -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 \

Wyświetl plik

@ -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, \
}

Wyświetl plik

@ -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)
@ -208,6 +208,39 @@ static void RTCU32SecRegWrite(unsigned long u32Msec)
MAP_PRCMHIBRegWrite(RTC_SECS_U32_REG_ADDR, 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
//*****************************************************************************
@ -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;
}
//*****************************************************************************
//

Wyświetl plik

@ -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);

Wyświetl plik

@ -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);
/// \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_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);
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,
};

Wyświetl plik

@ -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_ */

Wyświetl plik

@ -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),

Wyświetl plik

@ -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);
// 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 trigger, only one type is supported
if (mp_obj_get_int(args[0].u_obj) != MODWLAN_WIFI_EVENT_ANY) {
goto invalid_args;
}
return _callback;
// check the power mode
if (mp_obj_get_int(args[3].u_obj) != PYB_PWR_MODE_LPDS) {
goto invalid_args;
}
// 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;

Wyświetl plik

@ -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
******************************************************************************/

Wyświetl plik

@ -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) {
// 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;
}
uint pwrmode = args[4].u_int;
if (pwrmode > (PYB_PWR_MODE_ACTIVE | PYB_PWR_MODE_LPDS | PYB_PWR_MODE_HIBERNATE)) {
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;
}
// enable this pin as a wake-up source during LPDS
pybpin_wake_pin[idx].lpds = wake_mode;
}
else {
// this pin was the previous LPDS wake source, so disable it completely
if (pybpin_wake_pin[idx].lpds != PYBPIN_WAKES_NOT) {
MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_GPIO);
}
pybpin_wake_pin[idx].lpds = PYBPIN_WAKES_NOT;
}
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;
}
else {
pybpin_wake_pin[idx].hib = PYBPIN_WAKES_NOT;
}
// we need to update the callback atomically, so we disable the
// interrupt before we update anything.
pin_extint_disable(self);
if (pwrmode & PYB_PWR_MODE_ACTIVE) {
// register the interrupt
pin_extint_register((pin_obj_t *)self, intmode, priority);
if (idx < PYBPIN_NUM_WAKE_PINS) {
pybpin_wake_pin[idx].active = true;
}
}
else if (idx < PYBPIN_NUM_WAKE_PINS) {
pybpin_wake_pin[idx].active = false;
}
// all checks have passed, now we can create the callback
_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 the interrupt just before leaving
pin_extint_enable(self);
} else if (!_callback) {
_callback = mpcallback_new (self, mp_const_none, &pin_cb_methods, false);
}
return _callback;
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;
}
// 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 (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;
}
// 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;
}
// 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;
}
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 (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;
}
// 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;
}
// 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);
}
// 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) {

Wyświetl plik

@ -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;

Wyświetl plik

@ -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"
@ -48,88 +48,148 @@
/// \moduleref pyb
/// \class RTC - real time clock
/******************************************************************************
DEFINE TYPES
******************************************************************************/
typedef struct _pyb_rtc_obj_t {
mp_obj_base_t base;
byte prwmode;
bool alarmset;
bool repeat;
} pyb_rtc_obj_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC const mp_cb_methods_t pybrtc_cb_methods;
STATIC pyb_rtc_obj_t pyb_rtc_obj = {.prwmode = 0, .alarmset = false, .repeat = false};
STATIC const mp_irq_methods_t pyb_rtc_irq_methods;
STATIC pyb_rtc_obj_t pyb_rtc_obj;
/******************************************************************************
FUNCTION-LIKE MACROS
******************************************************************************/
#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) {
pyb_rtc_obj_t *self = self_in;
// check the wake from param
if (self->prwmode & PYB_PWR_MODE_ACTIVE) {
// enable the slow clock interrupt
MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
} else {
// just in case it was already enabled before
MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
}
pybsleep_configure_timer_wakeup (self->prwmode);
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_callback_disable (mp_obj_t self_in) {
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) {
// disable 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
MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
}
// 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();
self->irq_enabled = true;
}
STATIC void pyb_rtc_irq_disable (mp_obj_t self_in) {
pyb_rtc_obj_t *self = self_in;
self->irq_enabled = false;
if (!self->repeat) { // we always need interrupts if repeat is enabled
pyb_rtc_disable_interupt();
}
}
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);
// store the repepat flag
self->repeat = repeat;
// 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);
// 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);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, 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);
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);
/// \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];
// 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);
// disable the interrupt before updating anything
pyb_rtc_callback_disable((mp_obj_t)&pyb_rtc_obj);
// set the match value
MAP_PRCMRTCMatchSet(seconds, mseconds);
// save the power mode data for later
self->prwmode = args[4].u_int;
// create the callback
_callback = mpcallback_new ((mp_obj_t)&pyb_rtc_obj, args[1].u_obj, &pybrtc_cb_methods, true);
// set the lpds callback
pybsleep_set_timer_lpds_callback(_callback);
// 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
// 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);
// 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;
}
return _callback;
// 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;
}
// 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
// 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;
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_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
};

Wyświetl plik

@ -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_

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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_ */

Wyświetl plik

@ -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->intflags & self->channel);
MAP_TimerIntEnable(self->timer->timer, self->timer->intflags & self->channel);
MAP_TimerIntClear(self->timer->timer, self->timer->irq_trigger & self->channel);
MAP_TimerIntEnable(self->timer->timer, self->timer->irq_trigger & self->channel);
}
void pyb_timer_channel_callback_disable (mp_obj_t self_in) {
STATIC void pyb_timer_channel_irq_disable (mp_obj_t self_in) {
pyb_timer_channel_obj_t *self = self_in;
MAP_TimerIntDisable(self->timer->timer, self->timer->intflags & self->channel);
MAP_TimerIntDisable(self->timer->timer, self->timer->irq_trigger & self->channel);
}
pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channel_n) {
STATIC int pyb_timer_channel_irq_flags (mp_obj_t self_in) {
pyb_timer_channel_obj_t *self = self_in;
return self->timer->irq_flags;
}
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;
}
// convert the priority to the correct value
uint priority = mp_irq_translate_priority (args[1].u_int);
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);
// 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);
}
// 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;
}
// special case for a 32-bit timer
if (ch->channel == (TIMER_A | TIMER_B)) {
ch->timer->intflags |= (ch->timer->intflags << 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;
}
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;
}
// 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);
// 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_callback_enable(ch);
} else if (!_callback) {
_callback = mpcallback_new (ch, mp_const_none, &pyb_timer_channel_cb_methods, false);
// 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;
}
return _callback;
// 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;
}
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;
}
// register the interrupt and configure the priority
MAP_IntPrioritySet(intregister, priority);
MAP_TimerIntRegister(ch->timer->timer, ch->channel, pfnHandler);
// create the callback
mp_obj_t _irq = mp_irq_new (ch, args[2].u_obj, &pyb_timer_channel_irq_methods);
// enable the callback before returning
pyb_timer_channel_irq_enable(ch);
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);

Wyświetl plik

@ -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_callback_disable (mp_obj_t self_in) {
STATIC void uart_irq_disable (mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
self->callback_enabled = false;
self->irq_enabled = false;
}
STATIC int uart_irq_flags (mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
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));
}
// 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 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;
}
return _callback;
// 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;
}
// 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 = {

Wyświetl plik

@ -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_

Wyświetl plik

@ -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]; \

Wyświetl plik

@ -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();

Wyświetl plik

@ -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)

Wyświetl plik

@ -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);

Wyświetl plik

@ -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()

Wyświetl plik

@ -0,0 +1,19 @@
True
True
True
True
True
True
True
True
True
True
True
True
True
Awake
True
Awake
Exception
Exception
Exception

Wyświetl plik

@ -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:
@ -84,6 +89,16 @@ try:
except:
print('Exception')
try:
rtc.alarm_left(1)
except:
print('Exception')
try:
rtc.alarm_cancel(1)
except:
print('Exception')
try:
rtc.alarm(5000)
except:

Wyświetl plik

@ -28,6 +28,9 @@ True
True
True
True
True
Exception
Exception
Exception
Exception
Exception

Wyświetl plik

@ -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')

Wyświetl plik

@ -0,0 +1,18 @@
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
Exception
Exception

Wyświetl plik

@ -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()

Wyświetl plik

@ -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