summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--bare-arm/main.c2
-rw-r--r--py/argcheck.c2
-rw-r--r--py/builtin.c10
-rw-r--r--py/builtinevex.c2
-rw-r--r--py/builtinimport.c8
-rw-r--r--py/makeqstrdata.py34
-rw-r--r--py/modcmath.c2
-rw-r--r--py/mpconfig.h11
-rw-r--r--py/nlr.h1
-rw-r--r--py/nlrsetjmp.c1
-rw-r--r--py/obj.c2
-rw-r--r--py/obj.h11
-rw-r--r--py/objarray.c2
-rw-r--r--py/objbool.c2
-rw-r--r--py/objboundmeth.c2
-rw-r--r--py/objcell.c13
-rw-r--r--py/objclosure.c10
-rw-r--r--py/objcomplex.c2
-rw-r--r--py/objdict.c2
-rw-r--r--py/objexcept.c67
-rw-r--r--py/objfilter.c2
-rw-r--r--py/objfloat.c2
-rw-r--r--py/objfun.c49
-rw-r--r--py/objgenerator.c5
-rw-r--r--py/objgetitemiter.c2
-rw-r--r--py/objint.c2
-rw-r--r--py/objint_longlong.c2
-rw-r--r--py/objint_mpz.c2
-rw-r--r--py/objlist.c2
-rw-r--r--py/objmap.c2
-rw-r--r--py/objmodule.c2
-rw-r--r--py/objnamedtuple.c2
-rw-r--r--py/objnone.c2
-rw-r--r--py/objobject.c2
-rw-r--r--py/objproperty.c2
-rw-r--r--py/objrange.c2
-rw-r--r--py/objset.c2
-rw-r--r--py/objslice.c2
-rw-r--r--py/objstr.c2
-rw-r--r--py/objstringio.c2
-rw-r--r--py/objtuple.c2
-rw-r--r--py/objtype.c107
-rw-r--r--py/objtype.h8
-rw-r--r--py/objzip.c2
-rw-r--r--py/opmethods.c2
-rwxr-xr-xpy/py-version.sh2
-rw-r--r--py/qstrdefs.h1
-rw-r--r--py/runtime.c7
-rw-r--r--py/sequence.c2
-rw-r--r--py/showbc.c2
-rw-r--r--py/stream.c30
-rw-r--r--py/stream.h9
-rw-r--r--py/vm.c2
-rw-r--r--qemu-arm/main.c2
-rw-r--r--stmhal/.gitignore5
-rw-r--r--stmhal/Makefile37
-rw-r--r--stmhal/accel.c2
-rw-r--r--stmhal/adc.c2
-rwxr-xr-xstmhal/autoflash3
-rw-r--r--stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h2
-rw-r--r--stmhal/boards/PYBV10/mpconfigboard.h2
-rw-r--r--stmhal/boards/PYBV3/mpconfigboard.h4
-rw-r--r--stmhal/boards/PYBV4/mpconfigboard.h2
-rw-r--r--stmhal/boards/STM32F4DISC/mpconfigboard.h2
-rw-r--r--stmhal/boards/stm32f4xx-af.csv10
-rw-r--r--stmhal/bufhelper.c2
-rw-r--r--stmhal/bufhelper.h2
-rw-r--r--stmhal/cc3k/cc3000_common.c5
-rw-r--r--stmhal/cc3k/ccspi.c5
-rw-r--r--stmhal/cc3k/evnt_handler.c5
-rw-r--r--stmhal/cc3k/hci.c5
-rw-r--r--stmhal/cc3k/netapp.c5
-rw-r--r--stmhal/cc3k/nvmem.c4
-rw-r--r--stmhal/cc3k/pybcc3k.c6
-rw-r--r--stmhal/cc3k/security.c5
-rw-r--r--stmhal/cc3k/socket.c5
-rw-r--r--stmhal/cc3k/wlan.c5
-rw-r--r--stmhal/dac.c52
-rw-r--r--stmhal/extint.c2
-rw-r--r--stmhal/file.c1
-rw-r--r--stmhal/gccollect.c6
-rw-r--r--stmhal/gendoc.py2
-rw-r--r--stmhal/help.c2
-rw-r--r--stmhal/i2c.c4
-rw-r--r--stmhal/input.c4
-rw-r--r--stmhal/lcd.c2
-rw-r--r--stmhal/led.c2
-rw-r--r--stmhal/main.c6
-rw-r--r--stmhal/modos.c3
-rw-r--r--stmhal/modpyb.c26
-rw-r--r--stmhal/modstm.c2
-rw-r--r--stmhal/modtime.c2
-rw-r--r--stmhal/mpconfigport.h11
-rw-r--r--stmhal/pin.c5
-rw-r--r--stmhal/pybwlan.c6
-rw-r--r--stmhal/pyexec.c10
-rw-r--r--stmhal/rtc.c41
-rw-r--r--stmhal/servo.c3
-rw-r--r--stmhal/spi.c4
-rw-r--r--stmhal/timer.c68
-rw-r--r--stmhal/uart.c2
-rw-r--r--tests/basics/builtin-minmax.py15
-rw-r--r--tests/basics/subclass-native3.py18
-rw-r--r--tests/float/builtin-float-minmax.py26
-rw-r--r--tests/io/file1.py2
-rw-r--r--tests/pyb/accel.py7
-rw-r--r--tests/pyb/accel.py.exp1
-rw-r--r--tests/pyb/adc.py10
-rw-r--r--tests/pyb/adc.py.exp1
-rw-r--r--tests/pyb/dac.py8
-rw-r--r--tests/pyb/dac.py.exp1
-rw-r--r--tests/pyb/extint.py6
-rw-r--r--tests/pyb/extint.py.exp2
-rw-r--r--tests/pyb/i2c.py23
-rw-r--r--tests/pyb/i2c.py.exp4
-rw-r--r--tests/pyb/led.py28
-rw-r--r--tests/pyb/led.py.exp4
-rw-r--r--tests/pyb/pin.py29
-rw-r--r--tests/pyb/pin.py.exp12
-rw-r--r--tests/pyb/pyb1.py42
-rw-r--r--tests/pyb/pyb1.py.exp5
-rw-r--r--tests/pyb/rtc.py6
-rw-r--r--tests/pyb/rtc.py.exp2
-rw-r--r--tests/pyb/servo.py16
-rw-r--r--tests/pyb/servo.py.exp3
-rw-r--r--tests/pyb/spi.py17
-rw-r--r--tests/pyb/spi.py.exp5
-rw-r--r--tests/pyb/switch.py6
-rw-r--r--tests/pyb/switch.py.exp1
-rw-r--r--tests/pyb/timer.py28
-rw-r--r--tests/pyb/timer.py.exp6
-rw-r--r--tests/pyb/uart.py12
-rw-r--r--tests/pyb/uart.py.exp2
l---------tests/pyboard.py1
-rwxr-xr-xtests/run-tests172
-rwxr-xr-xtools/build-stm-latest.sh31
-rw-r--r--tools/pyboard.py38
-rw-r--r--unix-cpy/main.c2
-rw-r--r--unix/file.c19
-rw-r--r--unix/main.c8
-rw-r--r--unix/modffi.c2
-rw-r--r--unix/modsocket.c2
-rw-r--r--unix/mpconfigport.h3
-rw-r--r--windows/Makefile2
-rw-r--r--windows/alloca.h3
-rw-r--r--windows/init.c5
-rw-r--r--windows/init.h1
-rw-r--r--windows/mpconfigport.h7
-rw-r--r--windows/realpath.c42
-rw-r--r--windows/realpath.h2
151 files changed, 1148 insertions, 386 deletions
diff --git a/.gitignore b/.gitignore
index ce2e45af97..4c0191f692 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
*.map
*.hex
*.dis
+*.exe
# Packages
############
diff --git a/bare-arm/main.c b/bare-arm/main.c
index 8ad9b15870..bdaded4362 100644
--- a/bare-arm/main.c
+++ b/bare-arm/main.c
@@ -2,9 +2,9 @@
#include <stdio.h>
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
diff --git a/py/argcheck.c b/py/argcheck.c
index 6738bb9813..1b6d3a7ec4 100644
--- a/py/argcheck.c
+++ b/py/argcheck.c
@@ -26,9 +26,9 @@
#include <stdlib.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/builtin.c b/py/builtin.c
index 250a3558e8..5ff40be0c2 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -1,9 +1,9 @@
#include <stdio.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "objstr.h"
@@ -245,7 +245,7 @@ STATIC mp_obj_t mp_builtin_max(uint n_args, const mp_obj_t *args) {
mp_obj_t max_obj = NULL;
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
- if (max_obj == NULL || mp_binary_op(MP_BINARY_OP_LESS, max_obj, item)) {
+ if (max_obj == NULL || (mp_binary_op(MP_BINARY_OP_LESS, max_obj, item) == mp_const_true)) {
max_obj = item;
}
}
@@ -257,7 +257,7 @@ STATIC mp_obj_t mp_builtin_max(uint n_args, const mp_obj_t *args) {
// given many args
mp_obj_t max_obj = args[0];
for (int i = 1; i < n_args; i++) {
- if (mp_binary_op(MP_BINARY_OP_LESS, max_obj, args[i])) {
+ if (mp_binary_op(MP_BINARY_OP_LESS, max_obj, args[i]) == mp_const_true) {
max_obj = args[i];
}
}
@@ -274,7 +274,7 @@ STATIC mp_obj_t mp_builtin_min(uint n_args, const mp_obj_t *args) {
mp_obj_t min_obj = NULL;
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
- if (min_obj == NULL || mp_binary_op(MP_BINARY_OP_LESS, item, min_obj)) {
+ if (min_obj == NULL || (mp_binary_op(MP_BINARY_OP_LESS, item, min_obj) == mp_const_true)) {
min_obj = item;
}
}
@@ -286,7 +286,7 @@ STATIC mp_obj_t mp_builtin_min(uint n_args, const mp_obj_t *args) {
// given many args
mp_obj_t min_obj = args[0];
for (int i = 1; i < n_args; i++) {
- if (mp_binary_op(MP_BINARY_OP_LESS, args[i], min_obj)) {
+ if (mp_binary_op(MP_BINARY_OP_LESS, args[i], min_obj) == mp_const_true) {
min_obj = args[i];
}
}
diff --git a/py/builtinevex.c b/py/builtinevex.c
index ae82537374..bc3adb6256 100644
--- a/py/builtinevex.c
+++ b/py/builtinevex.c
@@ -1,8 +1,8 @@
#include <stdint.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "lexer.h"
#include "lexerunix.h"
diff --git a/py/builtinimport.c b/py/builtinimport.c
index 07978e61d7..f4e089b5d8 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -1,16 +1,12 @@
#include <stdint.h>
-#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
-#ifdef __MINGW32__
-// For alloca()
-#include <malloc.h>
-#endif
+#include <alloca.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "lexer.h"
#include "lexerunix.h"
diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py
index 34413f0beb..2ec5a1fb69 100644
--- a/py/makeqstrdata.py
+++ b/py/makeqstrdata.py
@@ -29,43 +29,15 @@ def compute_hash(qstr):
hash = (hash * 33) ^ ord(char)
return hash & 0xffff
-# given a list of (name,regex) pairs, find the first one that matches the given line
-def re_match_first(regexs, line):
- for name, regex in regexs:
- match = re.match(regex, line)
- if match:
- return name, match
- return None, None
-
-# regexs to recognise lines that the CPP emits
-# use a list so that matching order is honoured
-cpp_regexs = [
- ('qstr', r'Q\((.+)\)$'),
- ('cdecl', r'(typedef|extern) [A-Za-z0-9_* ]+;$')
-]
-
def do_work(infiles):
# read the qstrs in from the input files
qstrs = {}
for infile in infiles:
with open(infile, 'rt') as f:
- line_number = 0
for line in f:
- line_number += 1
- line = line.strip()
-
- # ignore blank lines, comments and preprocessor directives
- if len(line) == 0 or line.startswith('//') or line.startswith('#'):
- continue
-
- # work out what kind of line it is
- match_kind, match = re_match_first(cpp_regexs, line)
- if match_kind is None:
- # unknown line format
- print('({}:{}) bad qstr format, got {}'.format(infile, line_number, line), file=sys.stderr)
- return False
- elif match_kind != 'qstr':
- # not a line with a qstr
+ # is this a QSTR line?
+ match = re.match(r'^Q\((.+)\)$', line.strip())
+ if not match:
continue
# get the qstr value
diff --git a/py/modcmath.c b/py/modcmath.c
index 80dc0c8860..cfafdf84e8 100644
--- a/py/modcmath.c
+++ b/py/modcmath.c
@@ -65,7 +65,7 @@ mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) {
mp_obj_get_complex(z_obj, &real, &imag);
mp_float_t sqrt_abs = MICROPY_FLOAT_C_FUN(pow)(real*real + imag*imag, 0.25);
mp_float_t theta = 0.5 * MICROPY_FLOAT_C_FUN(atan2)(imag, real);
- return mp_obj_new_complex(sqrt_abs * cos(theta), sqrt_abs * sin(theta));
+ return mp_obj_new_complex(sqrt_abs * MICROPY_FLOAT_C_FUN(cos)(theta), sqrt_abs * MICROPY_FLOAT_C_FUN(sin)(theta));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt);
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 04d4a7ddc9..8a2e96cc4a 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -94,6 +94,17 @@ typedef long long mp_longint_impl_t;
#define MICROPY_ENABLE_DOC_STRING (0)
#endif
+// Exception messages are short static strings (TODO)
+#define MICROPY_ERROR_REPORTING_TERSE (1)
+// Exception messages provide basic error details
+#define MICROPY_ERROR_REPORTING_NORMAL (2)
+// Exception messages provide full info, e.g. object names
+#define MICROPY_ERROR_REPORTING_DETAILED (3)
+
+#ifndef MICROPY_ERROR_REPORTING
+#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL)
+#endif
+
// Float and complex implementation
#define MICROPY_FLOAT_IMPL_NONE (0)
#define MICROPY_FLOAT_IMPL_FLOAT (1)
diff --git a/py/nlr.h b/py/nlr.h
index c7b5928430..757ae61b2f 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -3,7 +3,6 @@
#include <limits.h>
#include <setjmp.h>
-#include "mpconfig.h"
typedef struct _nlr_buf_t nlr_buf_t;
struct _nlr_buf_t {
diff --git a/py/nlrsetjmp.c b/py/nlrsetjmp.c
index a97c8634b2..a8756d9d87 100644
--- a/py/nlrsetjmp.c
+++ b/py/nlrsetjmp.c
@@ -1,5 +1,6 @@
#include <setjmp.h>
#include <stdio.h>
+#include "mpconfig.h"
#include "nlr.h"
#if MICROPY_NLR_SETJMP
diff --git a/py/obj.c b/py/obj.c
index 4b72514476..e1cee3c234 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -2,9 +2,9 @@
#include <stdarg.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/obj.h b/py/obj.h
index 35c98d3714..0ecc2fe782 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -169,9 +169,10 @@ typedef mp_obj_t (*mp_fun_var_t)(uint n, const mp_obj_t *);
typedef mp_obj_t (*mp_fun_kw_t)(uint n, const mp_obj_t *, mp_map_t *);
typedef enum {
- PRINT_STR,
- PRINT_REPR,
- PRINT_EXC, // Special format for printing exception in unhandled exception message
+ PRINT_STR = 0,
+ PRINT_REPR = 1,
+ PRINT_EXC = 2, // Special format for printing exception in unhandled exception message
+ PRINT_EXC_SUBCLASS = 4, // Internal flag for printing exception subclasses
} mp_print_kind_t;
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind);
@@ -424,6 +425,7 @@ mp_float_t mp_obj_int_as_float(mp_obj_t self_in);
machine_int_t mp_obj_int_get_checked(mp_obj_t self_in);
// exception
+#define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new)
bool mp_obj_is_exception_type(mp_obj_t self_in);
bool mp_obj_is_exception_instance(mp_obj_t self_in);
bool mp_obj_exception_match(mp_obj_t exc, const mp_obj_type_t *exc_type);
@@ -431,6 +433,7 @@ void mp_obj_exception_clear_traceback(mp_obj_t self_in);
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block);
void mp_obj_exception_get_traceback(mp_obj_t self_in, machine_uint_t *n, machine_uint_t **values);
mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in);
+mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args);
// str
mp_obj_t mp_obj_str_builder_start(const mp_obj_type_t *type, uint len, byte **data);
@@ -508,6 +511,8 @@ typedef struct _mp_obj_fun_native_t { // need this so we can define const object
bool mp_obj_fun_prepare_simple_args(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args,
uint *out_args1_len, const mp_obj_t **out_args1, uint *out_args2_len, const mp_obj_t **out_args2);
+const char *mp_obj_fun_get_name(mp_obj_t fun);
+const char *mp_obj_code_get_name(const byte *code_info);
mp_obj_t mp_identity(mp_obj_t self);
MP_DECLARE_CONST_FUN_OBJ(mp_identity_obj);
diff --git a/py/objarray.c b/py/objarray.c
index ea37655762..428e619723 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -1,9 +1,9 @@
#include <string.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/objbool.c b/py/objbool.c
index 56020914d0..c479fd3629 100644
--- a/py/objbool.c
+++ b/py/objbool.c
@@ -1,8 +1,8 @@
#include <stdlib.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/objboundmeth.c b/py/objboundmeth.c
index 55b75e42cd..346118d518 100644
--- a/py/objboundmeth.c
+++ b/py/objboundmeth.c
@@ -1,8 +1,8 @@
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/objcell.c b/py/objcell.c
index 7fdf07b046..35b44e996d 100644
--- a/py/objcell.c
+++ b/py/objcell.c
@@ -1,6 +1,6 @@
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -20,14 +20,13 @@ void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) {
self->obj = obj;
}
-#if 0
+#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
STATIC void cell_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_cell_t *o = o_in;
- print(env, "<cell ");
+ print(env, "<cell %p ", o->obj);
if (o->obj == MP_OBJ_NULL) {
print(env, "(nil)");
} else {
- //print(env, "%p", o->obj);
mp_obj_print_helper(print, env, o->obj, PRINT_REPR);
}
print(env, ">");
@@ -36,8 +35,10 @@ STATIC void cell_print(void (*print)(void *env, const char *fmt, ...), void *env
const mp_obj_type_t cell_type = {
{ &mp_type_type },
- .name = MP_QSTR_, // should never need to print cell type
- //.print = cell_print,
+ .name = MP_QSTR_, // cell representation is just value in < >
+#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
+ .print = cell_print,
+#endif
};
mp_obj_t mp_obj_new_cell(mp_obj_t obj) {
diff --git a/py/objclosure.c b/py/objclosure.c
index 09371b0348..2b83cab71a 100644
--- a/py/objclosure.c
+++ b/py/objclosure.c
@@ -1,8 +1,8 @@
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "objtuple.h"
@@ -38,10 +38,10 @@ mp_obj_t closure_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *
}
}
-#if 0
+#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
STATIC void closure_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_closure_t *o = o_in;
- print(env, "<closure %p, n_closed=%u ", o, o->n_closed);
+ print(env, "<closure %s at %p, n_closed=%u ", mp_obj_fun_get_name(o->fun), o, o->n_closed);
for (int i = 0; i < o->n_closed; i++) {
if (o->closed[i] == MP_OBJ_NULL) {
print(env, "(nil)");
@@ -57,7 +57,9 @@ STATIC void closure_print(void (*print)(void *env, const char *fmt, ...), void *
const mp_obj_type_t closure_type = {
{ &mp_type_type },
.name = MP_QSTR_closure,
- //.print = closure_print,
+#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
+ .print = closure_print,
+#endif
.call = closure_call,
};
diff --git a/py/objcomplex.c b/py/objcomplex.c
index 9244209647..45cff6a184 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -1,9 +1,9 @@
#include <stdlib.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "parsenum.h"
diff --git a/py/objdict.c b/py/objdict.c
index 0654a198ea..334798c372 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -2,9 +2,9 @@
#include <string.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "objtuple.h"
diff --git a/py/objexcept.c b/py/objexcept.c
index 160cf09fd4..abf56ab036 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -2,12 +2,13 @@
#include <stdarg.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "objtuple.h"
+#include "objtype.h"
#include "runtime.h"
#include "runtime0.h"
@@ -30,12 +31,17 @@ const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit},
STATIC void mp_obj_exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_exception_t *o = o_in;
- if (kind == PRINT_REPR) {
+ mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS;
+ bool is_subclass = kind & PRINT_EXC_SUBCLASS;
+ if (!is_subclass && (k == PRINT_REPR || k == PRINT_EXC)) {
print(env, "%s", qstr_str(o->base.type->name));
- } else if (kind == PRINT_EXC) {
- print(env, "%s: ", qstr_str(o->base.type->name));
}
- if (kind == PRINT_STR || kind == PRINT_EXC) {
+
+ if (k == PRINT_EXC) {
+ print(env, ": ");
+ }
+
+ if (k == PRINT_STR || k == PRINT_EXC) {
if (o->args == NULL || o->args->len == 0) {
print(env, "");
return;
@@ -47,7 +53,7 @@ STATIC void mp_obj_exception_print(void (*print)(void *env, const char *fmt, ...
tuple_print(print, env, o->args, kind);
}
-STATIC mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_type_t *type = type_in;
if (n_kw != 0) {
@@ -266,38 +272,39 @@ bool mp_obj_exception_match(mp_obj_t exc, const mp_obj_type_t *exc_type) {
return mp_binary_op(MP_BINARY_OP_EXCEPTION_MATCH, exc, (mp_obj_t)exc_type) == mp_const_true;
}
-void mp_obj_exception_clear_traceback(mp_obj_t self_in) {
- // make sure self_in is an exception instance
- // TODO add traceback information to user-defined exceptions (need proper builtin subclassing for that)
- if (mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new) {
- mp_obj_exception_t *self = self_in;
-
- // just set the traceback to the null object
- // we don't want to call any memory management functions here
- self->traceback = MP_OBJ_NULL;
+// traceback handling functions
+
+#define GET_NATIVE_EXCEPTION(self, self_in) \
+ /* make sure self_in is an exception instance */ \
+ assert(mp_obj_is_exception_instance(self_in)); \
+ mp_obj_exception_t *self; \
+ if (mp_obj_is_native_exception_instance(self_in)) { \
+ self = self_in; \
+ } else { \
+ self = ((mp_obj_instance_t*)self_in)->subobj[0]; \
}
+
+void mp_obj_exception_clear_traceback(mp_obj_t self_in) {
+ GET_NATIVE_EXCEPTION(self, self_in);
+ // just set the traceback to the null object
+ // we don't want to call any memory management functions here
+ self->traceback = MP_OBJ_NULL;
}
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block) {
- // make sure self_in is an exception instance
- // TODO add traceback information to user-defined exceptions (need proper builtin subclassing for that)
- if (mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new && self_in != &mp_emergency_exception_obj) {
- mp_obj_exception_t *self = self_in;
-
- // for traceback, we are just using the list object for convenience, it's not really a list of Python objects
- if (self->traceback == MP_OBJ_NULL) {
- self->traceback = mp_obj_new_list(0, NULL);
- }
- mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)file);
- mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)line);
- mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)block);
+ GET_NATIVE_EXCEPTION(self, self_in);
+
+ // for traceback, we are just using the list object for convenience, it's not really a list of Python objects
+ if (self->traceback == MP_OBJ_NULL) {
+ self->traceback = mp_obj_new_list(0, NULL);
}
+ mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)file);
+ mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)line);
+ mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)block);
}
void mp_obj_exception_get_traceback(mp_obj_t self_in, machine_uint_t *n, machine_uint_t **values) {
- // make sure self_in is an exception instance
- assert(mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new);
- mp_obj_exception_t *self = self_in;
+ GET_NATIVE_EXCEPTION(self, self_in);
if (self->traceback == MP_OBJ_NULL) {
*n = 0;
diff --git a/py/objfilter.c b/py/objfilter.c
index 3eacdfc9b7..37cb269adc 100644
--- a/py/objfilter.c
+++ b/py/objfilter.c
@@ -1,9 +1,9 @@
#include <stdlib.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/objfloat.c b/py/objfloat.c
index 9249160579..14d861b66f 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -4,9 +4,9 @@
#include <assert.h>
#include <math.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "parsenum.h"
diff --git a/py/objfun.c b/py/objfun.c
index d828b6d084..4690dc6c88 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -1,15 +1,11 @@
#include <stdbool.h>
-#include <stdlib.h>
#include <string.h>
#include <assert.h>
-#ifdef __MINGW32__
-// For alloca()
-#include <malloc.h>
-#endif
+#include <alloca.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "objtuple.h"
@@ -126,6 +122,24 @@ mp_obj_t mp_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var
/******************************************************************************/
/* byte code functions */
+const char *mp_obj_code_get_name(const byte *code_info) {
+ qstr block_name = code_info[8] | (code_info[9] << 8) | (code_info[10] << 16) | (code_info[11] << 24);
+ return qstr_str(block_name);
+}
+
+const char *mp_obj_fun_get_name(mp_obj_t fun_in) {
+ mp_obj_fun_bc_t *fun = fun_in;
+ const byte *code_info = fun->bytecode;
+ return mp_obj_code_get_name(code_info);
+}
+
+#if MICROPY_CPYTHON_COMPAT
+STATIC void fun_bc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+ mp_obj_fun_bc_t *o = o_in;
+ print(env, "<function %s at 0x%x>", mp_obj_fun_get_name(o), o);
+}
+#endif
+
#if DEBUG_PRINT
STATIC void dump_args(const mp_obj_t *a, int sz) {
DEBUG_printf("%p: ", a);
@@ -139,8 +153,18 @@ STATIC void dump_args(const mp_obj_t *a, int sz) {
#endif
STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, uint expected, uint given) {
+#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
+ // Generic message, to be reused for other argument issues
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+ "argument num/types mismatch"));
+#elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"function takes %d positional arguments but %d were given", expected, given));
+#elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ "%s() takes %d positional arguments but %d were given",
+ mp_obj_fun_get_name(f), expected, given));
+#endif
}
// If it's possible to call a function without allocating new argument array,
@@ -155,6 +179,8 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, uint expected, ui
bool mp_obj_fun_prepare_simple_args(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args,
uint *out_args1_len, const mp_obj_t **out_args1, uint *out_args2_len, const mp_obj_t **out_args2) {
mp_obj_fun_bc_t *self = self_in;
+ DEBUG_printf("mp_obj_fun_prepare_simple_args: given: %d pos, %d kw, expected: %d pos (%d default)\n",
+ n_args, n_kw, self->n_pos_args, self->n_def_args);
assert(n_kw == 0);
assert(self->n_kwonly_args == 0);
@@ -167,8 +193,12 @@ bool mp_obj_fun_prepare_simple_args(mp_obj_t self_in, uint n_args, uint n_kw, co
if (n_args > self->n_pos_args) {
goto arg_error;
} else {
- extra_args -= self->n_pos_args - n_args;
- n_extra_args += self->n_pos_args - n_args;
+ if (n_args >= self->n_pos_args - self->n_def_args) {
+ extra_args -= self->n_pos_args - n_args;
+ n_extra_args += self->n_pos_args - n_args;
+ } else {
+ fun_pos_args_mismatch(self, self->n_pos_args - self->n_def_args, n_args);
+ }
}
*out_args1 = args;
*out_args1_len = n_args;
@@ -335,6 +365,9 @@ continue2:;
const mp_obj_type_t mp_type_fun_bc = {
{ &mp_type_type },
.name = MP_QSTR_function,
+#if MICROPY_CPYTHON_COMPAT
+ .print = fun_bc_print,
+#endif
.call = fun_bc_call,
.binary_op = fun_binary_op,
};
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 895c03cc23..d7d6dcaaf4 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -1,9 +1,9 @@
#include <stdlib.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -68,7 +68,8 @@ typedef struct _mp_obj_gen_instance_t {
} mp_obj_gen_instance_t;
void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
- print(env, "<generator object 'fun-name' at %p>", self_in);
+ mp_obj_gen_instance_t *self = self_in;
+ print(env, "<generator object '%s' at %p>", mp_obj_code_get_name(self->code_info), self_in);
}
mp_obj_t gen_instance_getiter(mp_obj_t self_in) {
diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c
index faa8321c34..15676b452b 100644
--- a/py/objgetitemiter.c
+++ b/py/objgetitemiter.c
@@ -1,8 +1,8 @@
#include <stdlib.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/objint.c b/py/objint.c
index 110876e003..bec4e920fd 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -3,9 +3,9 @@
#include <assert.h>
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "parsenum.h"
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 7d71c5a691..d319e27463 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -2,9 +2,9 @@
#include <stdint.h>
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "mpz.h"
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index b94dcfee37..bfc7def357 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -3,9 +3,9 @@
#include <stdio.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "parsenumbase.h"
#include "obj.h"
diff --git a/py/objlist.c b/py/objlist.c
index 0c55f524da..d886affff8 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -1,9 +1,9 @@
#include <string.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/objmap.c b/py/objmap.c
index 45e65549da..c6f8f16572 100644
--- a/py/objmap.c
+++ b/py/objmap.c
@@ -1,9 +1,9 @@
#include <stdlib.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/objmodule.c b/py/objmodule.c
index 15ccd68ac2..d4a45b84a5 100644
--- a/py/objmodule.c
+++ b/py/objmodule.c
@@ -1,9 +1,9 @@
#include <stdlib.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "objmodule.h"
diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c
index 4239983589..99a1d7bb9d 100644
--- a/py/objnamedtuple.c
+++ b/py/objnamedtuple.c
@@ -1,7 +1,7 @@
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "nlr.h"
#include "qstr.h"
#include "obj.h"
diff --git a/py/objnone.c b/py/objnone.c
index fc55132f39..49b726bdde 100644
--- a/py/objnone.c
+++ b/py/objnone.c
@@ -1,8 +1,8 @@
#include <stdlib.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/objobject.c b/py/objobject.c
index 74a4926b34..62fd0c4c9a 100644
--- a/py/objobject.c
+++ b/py/objobject.c
@@ -1,8 +1,8 @@
#include <stdlib.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/objproperty.c b/py/objproperty.c
index dd4eedebdb..220388df0a 100644
--- a/py/objproperty.c
+++ b/py/objproperty.c
@@ -1,9 +1,9 @@
#include <stdlib.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/objrange.c b/py/objrange.c
index 8c0eadd32e..acfeed7d9c 100644
--- a/py/objrange.c
+++ b/py/objrange.c
@@ -1,8 +1,8 @@
#include <stdlib.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/objset.c b/py/objset.c
index db3683f608..1d10f94e81 100644
--- a/py/objset.c
+++ b/py/objset.c
@@ -2,9 +2,9 @@
#include <string.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/objslice.c b/py/objslice.c
index 924927db5f..0488eb4220 100644
--- a/py/objslice.c
+++ b/py/objslice.c
@@ -1,9 +1,9 @@
#include <stdlib.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/objstr.c b/py/objstr.c
index aab1a4492c..fc7415fe15 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -2,9 +2,9 @@
#include <string.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/objstringio.c b/py/objstringio.c
index a3a7566300..8b3dfaf61e 100644
--- a/py/objstringio.c
+++ b/py/objstringio.c
@@ -1,9 +1,9 @@
#include <stdio.h>
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/objtuple.c b/py/objtuple.c
index e6b902d74f..792c65193c 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -1,9 +1,9 @@
#include <string.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/objtype.c b/py/objtype.c
index 56a5dd937d..fd187147a0 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -3,13 +3,14 @@
#include <string.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
+#include "objtype.h"
#if 0 // print debugging info
#define DEBUG_PRINT (1)
@@ -19,28 +20,20 @@
#endif
/******************************************************************************/
-// class object
-// creating an instance of a class makes one of these objects
-
-typedef struct _mp_obj_class_t {
- mp_obj_base_t base;
- mp_map_t members;
- mp_obj_t subobj[];
- // TODO maybe cache __getattr__ and __setattr__ for efficient lookup of them
-} mp_obj_class_t;
+// instance object
-#define is_native_type(type) ((type)->make_new != class_make_new)
-STATIC mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args);
+#define is_native_type(type) ((type)->make_new != instance_make_new)
+STATIC mp_obj_t instance_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args);
-STATIC mp_obj_t mp_obj_new_class(mp_obj_t class, uint subobjs) {
- mp_obj_class_t *o = m_new_obj_var(mp_obj_class_t, mp_obj_t, subobjs);
+STATIC mp_obj_t mp_obj_new_instance(mp_obj_t class, uint subobjs) {
+ mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, subobjs);
o->base.type = class;
mp_map_init(&o->members, 0);
mp_seq_clear(o->subobj, 0, subobjs, sizeof(*o->subobj));
return o;
}
-STATIC int class_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
+STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
uint len;
mp_obj_t *items;
mp_obj_tuple_get(type->bases_tuple, &len, &items);
@@ -52,7 +45,7 @@ STATIC int class_count_native_bases(const mp_obj_type_t *type, const mp_obj_type
*last_native_base = items[i];
count++;
} else {
- count += class_count_native_bases(items[i], last_native_base);
+ count += instance_count_native_bases(items[i], last_native_base);
}
}
@@ -70,8 +63,8 @@ STATIC int class_count_native_bases(const mp_obj_type_t *type, const mp_obj_type
// applies to instance->subobj[0]. In most cases, we also don't need to know which type
// it was - because instance->subobj[0] is of that type. The only exception is when
// object is not yet constructed, then we need to know base native type to construct
-// instance->subobj[0]. This case is handled via class_count_native_bases() though.
-STATIC void mp_obj_class_lookup(mp_obj_class_t *o, const mp_obj_type_t *type, qstr attr, machine_uint_t meth_offset, mp_obj_t *dest) {
+// instance->subobj[0]. This case is handled via instance_count_native_bases() though.
+STATIC void mp_obj_class_lookup(mp_obj_instance_t *o, const mp_obj_type_t *type, qstr attr, machine_uint_t meth_offset, mp_obj_t *dest) {
assert(dest[0] == NULL);
assert(dest[1] == NULL);
for (;;) {
@@ -137,8 +130,8 @@ STATIC void mp_obj_class_lookup(mp_obj_class_t *o, const mp_obj_type_t *type, qs
}
}
-STATIC void class_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
- mp_obj_class_t *self = self_in;
+STATIC void instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ mp_obj_instance_t *self = self_in;
qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__;
mp_obj_t member[2] = {MP_OBJ_NULL};
mp_obj_class_lookup(self, self->base.type, meth, offsetof(mp_obj_type_t, print), member);
@@ -148,7 +141,15 @@ STATIC void class_print(void (*print)(void *env, const char *fmt, ...), void *en
}
if (member[0] == MP_OBJ_SENTINEL) {
- mp_obj_print_helper(print, env, self->subobj[0], kind);
+ // Handle Exception subclasses specially
+ if (mp_obj_is_native_exception_instance(self->subobj[0])) {
+ if (kind != PRINT_STR) {
+ print(env, "%s", qstr_str(self->base.type->name));
+ }
+ mp_obj_print_helper(print, env, self->subobj[0], kind | PRINT_EXC_SUBCLASS);
+ } else {
+ mp_obj_print_helper(print, env, self->subobj[0], kind);
+ }
return;
}
@@ -162,15 +163,15 @@ STATIC void class_print(void (*print)(void *env, const char *fmt, ...), void *en
print(env, "<%s object at %p>", mp_obj_get_type_str(self_in), self_in);
}
-STATIC mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+STATIC mp_obj_t instance_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
mp_obj_type_t *self = self_in;
const mp_obj_type_t *native_base;
- uint num_native_bases = class_count_native_bases(self, &native_base);
+ uint num_native_bases = instance_count_native_bases(self, &native_base);
assert(num_native_bases < 2);
- mp_obj_class_t *o = mp_obj_new_class(self_in, num_native_bases);
+ mp_obj_instance_t *o = mp_obj_new_instance(self_in, num_native_bases);
// look for __init__ function
mp_obj_t init_fn[2] = {MP_OBJ_NULL};
@@ -188,7 +189,7 @@ STATIC mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const m
// now call Python class __init__ function with all args
mp_obj_t init_ret;
if (n_args == 0 && n_kw == 0) {
- init_ret = mp_call_function_n_kw(init_fn[0], 1, 0, (mp_obj_t*)&o);
+ init_ret = mp_call_function_n_kw(init_fn[0], 1, 0, (mp_obj_t*)(void*)&o);
} else {
mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw);
args2[0] = o;
@@ -218,8 +219,8 @@ STATIC const qstr unary_op_method_name[] = {
[MP_UNARY_OP_NOT] = MP_QSTR_, // don't need to implement this, used to make sure array has full size
};
-STATIC mp_obj_t class_unary_op(int op, mp_obj_t self_in) {
- mp_obj_class_t *self = self_in;
+STATIC mp_obj_t instance_unary_op(int op, mp_obj_t self_in) {
+ mp_obj_instance_t *self = self_in;
qstr op_name = unary_op_method_name[op];
/* Still try to lookup native slot
if (op_name == 0) {
@@ -281,7 +282,7 @@ STATIC const qstr binary_op_method_name[] = {
// and put the result in the dest[] array for a possible method call.
// Conversion means dealing with static/class methods, callables, and values.
// see http://docs.python.org/3.3/howto/descriptor.html
-STATIC void class_convert_return_attr(mp_obj_t self, mp_obj_t member, mp_obj_t *dest) {
+STATIC void instance_convert_return_attr(mp_obj_t self, mp_obj_t member, mp_obj_t *dest) {
assert(dest[1] == NULL);
if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
// return just the function
@@ -300,10 +301,10 @@ STATIC void class_convert_return_attr(mp_obj_t self, mp_obj_t member, mp_obj_t *
}
}
-STATIC mp_obj_t class_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+STATIC mp_obj_t instance_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// Note: For ducktyping, CPython does not look in the instance members or use
// __getattr__ or __getattribute__. It only looks in the class dictionary.
- mp_obj_class_t *lhs = lhs_in;
+ mp_obj_instance_t *lhs = lhs_in;
qstr op_name = binary_op_method_name[op];
/* Still try to lookup native slot
if (op_name == 0) {
@@ -317,7 +318,7 @@ STATIC mp_obj_t class_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
} else if (member[0] != MP_OBJ_NULL) {
mp_obj_t dest[3];
dest[1] = MP_OBJ_NULL;
- class_convert_return_attr(lhs_in, member[0], dest);
+ instance_convert_return_attr(lhs_in, member[0], dest);
dest[2] = rhs_in;
return mp_call_method_n_kw(1, 0, dest);
} else {
@@ -325,9 +326,9 @@ STATIC mp_obj_t class_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
}
}
-STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
+STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
// logic: look in obj members then class locals (TODO check this against CPython)
- mp_obj_class_t *self = self_in;
+ mp_obj_instance_t *self = self_in;
mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
if (elem != NULL) {
@@ -345,13 +346,13 @@ STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
} else if (MP_OBJ_IS_TYPE(member, &mp_type_property)) {
// object member is a property
// delegate the store to the property
- // TODO should this be part of class_convert_return_attr?
+ // TODO should this be part of instance_convert_return_attr?
const mp_obj_t *proxy = mp_obj_property_get(member);
if (proxy[0] == mp_const_none) {
// TODO
} else {
dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in);
- // TODO should we convert the returned value using class_convert_return_attr?
+ // TODO should we convert the returned value using instance_convert_return_attr?
}
#endif
} else {
@@ -359,7 +360,7 @@ STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
// if we don't yet have bound method (supposedly from native base), go
// try to convert own attrs.
if (dest[1] == MP_OBJ_NULL) {
- class_convert_return_attr(self_in, member, dest);
+ instance_convert_return_attr(self_in, member, dest);
}
}
return;
@@ -379,8 +380,8 @@ STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
}
}
-STATIC bool class_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
- mp_obj_class_t *self = self_in;
+STATIC bool instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
+ mp_obj_instance_t *self = self_in;
#if MICROPY_ENABLE_PROPERTY
// for property, we need to do a lookup first in the class dict
@@ -413,8 +414,8 @@ STATIC bool class_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
}
}
-STATIC mp_obj_t class_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
- mp_obj_class_t *self = self_in;
+STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
+ mp_obj_instance_t *self = self_in;
mp_obj_t member[2] = {MP_OBJ_NULL};
uint meth_args;
if (value == MP_OBJ_NULL) {
@@ -434,7 +435,7 @@ STATIC mp_obj_t class_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return mp_obj_subscr(self->subobj[0], index, value);
} else if (member[0] != MP_OBJ_NULL) {
mp_obj_t args[3] = {self_in, index, value};
- // TODO probably need to call class_convert_return_attr, and use mp_call_method_n_kw
+ // TODO probably need to call instance_convert_return_attr, and use mp_call_method_n_kw
mp_obj_t ret = mp_call_function_n_kw(member[0], meth_args, 0, args);
if (value == MP_OBJ_SENTINEL) {
return ret;
@@ -446,8 +447,8 @@ STATIC mp_obj_t class_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
}
}
-STATIC mp_obj_t class_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
- mp_obj_class_t *self = self_in;
+STATIC mp_obj_t instance_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+ mp_obj_instance_t *self = self_in;
mp_obj_t member[2] = {MP_OBJ_NULL};
mp_obj_class_lookup(self, self->base.type, MP_QSTR___call__, offsetof(mp_obj_type_t, call), member);
if (member[0] == MP_OBJ_NULL) {
@@ -604,19 +605,19 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
mp_obj_type_t *o = m_new0(mp_obj_type_t, 1);
o->base.type = &mp_type_type;
o->name = name;
- o->print = class_print;
- o->make_new = class_make_new;
- o->unary_op = class_unary_op;
- o->binary_op = class_binary_op;
- o->load_attr = class_load_attr;
- o->store_attr = class_store_attr;
- o->subscr = class_subscr;
- o->call = class_call;
+ o->print = instance_print;
+ o->make_new = instance_make_new;
+ o->unary_op = instance_unary_op;
+ o->binary_op = instance_binary_op;
+ o->load_attr = instance_load_attr;
+ o->store_attr = instance_store_attr;
+ o->subscr = instance_subscr;
+ o->call = instance_call;
o->bases_tuple = bases_tuple;
o->locals_dict = locals_dict;
const mp_obj_type_t *native_base;
- uint num_native_bases = class_count_native_bases(o, &native_base);
+ uint num_native_bases = instance_count_native_bases(o, &native_base);
if (num_native_bases > 1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict"));
}
@@ -673,7 +674,7 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_t member[2] = {MP_OBJ_NULL};
mp_obj_class_lookup(self->obj, (mp_obj_type_t*)items[i], attr, 0, member);
if (member[0] != MP_OBJ_NULL) {
- class_convert_return_attr(self->obj, member[0], dest);
+ instance_convert_return_attr(self->obj, member[0], dest);
return;
}
}
diff --git a/py/objtype.h b/py/objtype.h
new file mode 100644
index 0000000000..c3176c3282
--- /dev/null
+++ b/py/objtype.h
@@ -0,0 +1,8 @@
+// instance object
+// creating an instance of a class makes one of these objects
+typedef struct _mp_obj_instance_t {
+ mp_obj_base_t base;
+ mp_map_t members;
+ mp_obj_t subobj[];
+ // TODO maybe cache __getattr__ and __setattr__ for efficient lookup of them
+} mp_obj_instance_t;
diff --git a/py/objzip.c b/py/objzip.c
index 4c7070b7c7..c3bffd830d 100644
--- a/py/objzip.c
+++ b/py/objzip.c
@@ -1,8 +1,8 @@
#include <stdlib.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/opmethods.c b/py/opmethods.c
index a745ec1227..b029eef7c5 100644
--- a/py/opmethods.c
+++ b/py/opmethods.c
@@ -1,6 +1,6 @@
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/py/py-version.sh b/py/py-version.sh
index f574b574f4..42474ef6a5 100755
--- a/py/py-version.sh
+++ b/py/py-version.sh
@@ -1,5 +1,6 @@
#!/bin/bash
+git_tag="$(git describe --dirty || echo unknown)"
git_hash="$(git rev-parse --short HEAD 2> /dev/null || echo unknown)"
git_files_are_clean=1
# Check if there are any modified files.
@@ -11,6 +12,7 @@ if [ "${git_files_are_clean}" != "1" ]; then
fi
cat <<EOF
// This file was generated by py/py-version.sh
+#define MICROPY_GIT_TAG "${git_tag}"
#define MICROPY_GIT_HASH "${git_hash}"
#define MICROPY_BUILD_DATE "$(date '+%Y-%m-%d')"
EOF
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 6960bd06cb..bcaed02d8b 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -314,6 +314,7 @@ Q(unpack)
Q(io)
Q(readall)
Q(readline)
+Q(readlines)
Q(StringIO)
Q(BytesIO)
Q(getvalue)
diff --git a/py/runtime.c b/py/runtime.c
index b56740a022..ba78ec40f3 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -2,9 +2,9 @@
#include <string.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "objtuple.h"
@@ -42,6 +42,11 @@ const mp_obj_module_t mp_module___main__ = {
};
void mp_init(void) {
+ // call port specific initialization if any
+#ifdef MICROPY_PORT_INIT_FUNC
+ MICROPY_PORT_INIT_FUNC;
+#endif
+
mp_emit_glue_init();
// init global module stuff
diff --git a/py/sequence.c b/py/sequence.c
index f91bf43c74..9fce1c51ad 100644
--- a/py/sequence.c
+++ b/py/sequence.c
@@ -2,9 +2,9 @@
#include <stdbool.h>
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/showbc.c b/py/showbc.c
index e3032e8d98..b5b5ce44aa 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -1,8 +1,8 @@
#include <stdio.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "bc0.h"
diff --git a/py/stream.c b/py/stream.c
index 72e6ab509d..f20ee0f5e8 100644
--- a/py/stream.c
+++ b/py/stream.c
@@ -1,8 +1,8 @@
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "stream.h"
@@ -123,8 +123,7 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
while (max_size == -1 || max_size-- != 0) {
char *p = vstr_add_len(vstr, 1);
if (p == NULL) {
- // TODO
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError/*&mp_type_RuntimeError*/, "Out of memory"));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory"));
}
machine_int_t out_sz = o->type->stream_p->read(o, p, 1, &error);
@@ -143,16 +142,29 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
break;
}
}
- // TODO don't intern this string
- vstr_shrink(vstr);
- return MP_OBJ_NEW_QSTR(qstr_from_strn_take(vstr_str(vstr), vstr->alloc, vstr_len(vstr)));
+ // TODO need a string creation API that doesn't copy the given data
+ mp_obj_t ret = mp_obj_new_str((byte*)vstr->buf, vstr->len, false);
+ vstr_free(vstr);
+ return ret;
+}
+
+// TODO take an optional extra argument (what does it do exactly?)
+STATIC mp_obj_t stream_unbuffered_readlines(mp_obj_t self) {
+ mp_obj_t lines = mp_obj_new_list(0, NULL);
+ for (;;) {
+ mp_obj_t line = stream_unbuffered_readline(1, &self);
+ if (mp_obj_str_get_len(line) == 0) {
+ break;
+ }
+ mp_obj_list_append(lines, line);
+ }
+ return lines;
}
+MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj, stream_unbuffered_readlines);
mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
mp_obj_t l_in = stream_unbuffered_readline(1, &self);
- uint sz;
- mp_obj_str_get_data(l_in, &sz);
- if (sz != 0) {
+ if (mp_obj_str_get_len(l_in) != 0) {
return l_in;
}
return MP_OBJ_STOP_ITERATION;
diff --git a/py/stream.h b/py/stream.h
index a0cc34797b..cb70a3d914 100644
--- a/py/stream.h
+++ b/py/stream.h
@@ -1,7 +1,8 @@
-extern const mp_obj_fun_native_t mp_stream_read_obj;
-extern const mp_obj_fun_native_t mp_stream_readall_obj;
-extern const mp_obj_fun_native_t mp_stream_unbuffered_readline_obj;
-extern const mp_obj_fun_native_t mp_stream_write_obj;
+MP_DECLARE_CONST_FUN_OBJ(mp_stream_read_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_stream_readall_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_stream_unbuffered_readline_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_stream_unbuffered_readlines_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_stream_write_obj);
// Iterator which uses mp_stream_unbuffered_readline_obj
mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self);
diff --git a/py/vm.c b/py/vm.c
index d3eb970427..f2ca91be52 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -2,9 +2,9 @@
#include <string.h>
#include <assert.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "emitglue.h"
diff --git a/qemu-arm/main.c b/qemu-arm/main.c
index 6ecc9a4b2e..91c096289e 100644
--- a/qemu-arm/main.c
+++ b/qemu-arm/main.c
@@ -2,9 +2,9 @@
#include <stdio.h>
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
diff --git a/stmhal/.gitignore b/stmhal/.gitignore
new file mode 100644
index 0000000000..61ad25738f
--- /dev/null
+++ b/stmhal/.gitignore
@@ -0,0 +1,5 @@
+build-PYBV3/
+build-PYBV4/
+build-PYBV10/
+build-STM32F4DISC/
+build-NETDUINO_PLUS_2/
diff --git a/stmhal/Makefile b/stmhal/Makefile
index a32d9afbba..e27dd7b6ce 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -1,3 +1,13 @@
+# Select the board to build for: if not given on the command line,
+# then default to PYBV10.
+BOARD ?= PYBV10
+ifeq ($(wildcard boards/$(BOARD)/.),)
+$(error Invalid BOARD specified)
+endif
+
+# If the build directory is not given, make it reflect the board name.
+BUILD ?= build-$(BOARD)
+
include ../py/mkenv.mk
# qstr definitions (must come before including py.mk)
@@ -13,6 +23,9 @@ USBDEV_DIR=usbdev
FATFS_DIR=fatfs
CC3K_DIR=cc3k
DFU=../tools/dfu.py
+# may need to prefix dfu-util with sudo
+DFU_UTIL=dfu-util
+DEVICE=0483:df11
CROSS_COMPILE = arm-none-eabi-
@@ -30,10 +43,6 @@ INC += -I$(CC3K_DIR)
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) $(COPT)
-BOARD ?= PYBV10
-ifeq ($(wildcard boards/$(BOARD)/.),)
-$(error Invalid BOARD specified)
-endif
CFLAGS += -Iboards/$(BOARD)
#Debugging/Optimization
@@ -187,19 +196,21 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_FATFS:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_CC3K:.c=.o))
OBJ += $(BUILD)/pins_$(BOARD).o
-all: $(BUILD)/flash.dfu
+all: $(BUILD)/firmware.dfu
-$(BUILD)/flash.dfu: $(BUILD)/flash0.bin $(BUILD)/flash1.bin
- $(ECHO) "Create $@"
- $(Q)$(PYTHON) $(DFU) -b 0x08000000:$(BUILD)/flash0.bin -b 0x08020000:$(BUILD)/flash1.bin $@
+.PHONY: deploy
-$(BUILD)/flash0.bin: $(BUILD)/flash.elf
- $(Q)$(OBJCOPY) -O binary -j .isr_vector $^ $@
+deploy: $(BUILD)/firmware.dfu
+ $(ECHO) "Writing $< to the board"
+ $(Q)$(DFU_UTIL) -a 0 -d $(DEVICE) -D $<
-$(BUILD)/flash1.bin: $(BUILD)/flash.elf
- $(Q)$(OBJCOPY) -O binary -j .text -j .data $^ $@
+$(BUILD)/firmware.dfu: $(BUILD)/firmware.elf
+ $(ECHO) "Create $@"
+ $(Q)$(OBJCOPY) -O binary -j .isr_vector $^ $(BUILD)/firmware0.bin
+ $(Q)$(OBJCOPY) -O binary -j .text -j .data $^ $(BUILD)/firmware1.bin
+ $(Q)$(PYTHON) $(DFU) -b 0x08000000:$(BUILD)/firmware0.bin -b 0x08020000:$(BUILD)/firmware1.bin $@
-$(BUILD)/flash.elf: $(OBJ)
+$(BUILD)/firmware.elf: $(OBJ)
$(ECHO) "LINK $@"
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
$(Q)$(SIZE) $@
diff --git a/stmhal/accel.c b/stmhal/accel.c
index d3373f1ebd..64ed8b2f1d 100644
--- a/stmhal/accel.c
+++ b/stmhal/accel.c
@@ -3,9 +3,9 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/stmhal/adc.c b/stmhal/adc.c
index 0cc2a9a904..e04571abee 100644
--- a/stmhal/adc.c
+++ b/stmhal/adc.c
@@ -2,9 +2,9 @@
#include <stm32f4xx_hal.h>
#include <string.h>
+#include "mpconfig.h"
#include "misc.h"
#include "nlr.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/stmhal/autoflash b/stmhal/autoflash
index dc28a97e29..d2240ccb55 100755
--- a/stmhal/autoflash
+++ b/stmhal/autoflash
@@ -8,6 +8,7 @@
# - run a terminal
SERIAL=/dev/ttyACM0
+DEVICE=0483:df11
while true; do
echo "waiting for DFU device..."
@@ -19,7 +20,7 @@ while true; do
done
echo "found DFU device, flashing"
- dfu-util -a 0 -D build/flash.dfu
+ dfu-util -a 0 -d $DEVICE -D build/flash.dfu
echo "waiting for DFU to exit..."
while true; do
diff --git a/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h b/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h
index b70b56d9ce..0e40545253 100644
--- a/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h
+++ b/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h
@@ -11,7 +11,6 @@
#define MICROPY_HW_HAS_MMA7660 (0)
#define MICROPY_HW_HAS_LIS3DSH (0)
#define MICROPY_HW_HAS_LCD (0)
-#define MICROPY_HW_HAS_WLAN (0)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (0)
#define MICROPY_HW_ENABLE_TIMER (1)
@@ -20,6 +19,7 @@
#define MICROPY_HW_ENABLE_I2C1 (0)
#define MICROPY_HW_ENABLE_SPI1 (0)
#define MICROPY_HW_ENABLE_SPI3 (0)
+#define MICROPY_HW_ENABLE_CC3K (0)
// USRSW is pulled low. Pressing the button makes the input go high.
#define MICROPY_HW_USRSW_PIN (pin_B11)
diff --git a/stmhal/boards/PYBV10/mpconfigboard.h b/stmhal/boards/PYBV10/mpconfigboard.h
index fc22f63341..3def531232 100644
--- a/stmhal/boards/PYBV10/mpconfigboard.h
+++ b/stmhal/boards/PYBV10/mpconfigboard.h
@@ -7,7 +7,6 @@
#define MICROPY_HW_HAS_MMA7660 (1)
#define MICROPY_HW_HAS_LIS3DSH (0)
#define MICROPY_HW_HAS_LCD (1)
-#define MICROPY_HW_HAS_WLAN (1)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_TIMER (1)
@@ -16,6 +15,7 @@
#define MICROPY_HW_ENABLE_I2C1 (1)
#define MICROPY_HW_ENABLE_SPI1 (1)
#define MICROPY_HW_ENABLE_SPI3 (0)
+#define MICROPY_HW_ENABLE_CC3K (0)
// USRSW has no pullup or pulldown, and pressing the switch makes the input go low
#define MICROPY_HW_USRSW_PIN (pin_B3)
diff --git a/stmhal/boards/PYBV3/mpconfigboard.h b/stmhal/boards/PYBV3/mpconfigboard.h
index 02ad78a64c..ac0d84ca29 100644
--- a/stmhal/boards/PYBV3/mpconfigboard.h
+++ b/stmhal/boards/PYBV3/mpconfigboard.h
@@ -7,15 +7,15 @@
#define MICROPY_HW_HAS_MMA7660 (1)
#define MICROPY_HW_HAS_LIS3DSH (0)
#define MICROPY_HW_HAS_LCD (0)
-#define MICROPY_HW_HAS_WLAN (0)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_TIMER (1)
#define MICROPY_HW_ENABLE_SERVO (1)
-#define MICROPY_HW_ENABLE_DAC (0)
+#define MICROPY_HW_ENABLE_DAC (1)
#define MICROPY_HW_ENABLE_I2C1 (1)
#define MICROPY_HW_ENABLE_SPI1 (1)
#define MICROPY_HW_ENABLE_SPI3 (0)
+#define MICROPY_HW_ENABLE_CC3K (0)
// USRSW has no pullup or pulldown, and pressing the switch makes the input go low
#define MICROPY_HW_USRSW_PIN (pin_A13)
diff --git a/stmhal/boards/PYBV4/mpconfigboard.h b/stmhal/boards/PYBV4/mpconfigboard.h
index 550f1633f9..9fedb70136 100644
--- a/stmhal/boards/PYBV4/mpconfigboard.h
+++ b/stmhal/boards/PYBV4/mpconfigboard.h
@@ -7,7 +7,6 @@
#define MICROPY_HW_HAS_MMA7660 (1)
#define MICROPY_HW_HAS_LIS3DSH (0)
#define MICROPY_HW_HAS_LCD (1)
-#define MICROPY_HW_HAS_WLAN (0)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_TIMER (1)
@@ -16,6 +15,7 @@
#define MICROPY_HW_ENABLE_I2C1 (1)
#define MICROPY_HW_ENABLE_SPI1 (1)
#define MICROPY_HW_ENABLE_SPI3 (0)
+#define MICROPY_HW_ENABLE_CC3K (0)
// USRSW has no pullup or pulldown, and pressing the switch makes the input go low
#define MICROPY_HW_USRSW_PIN (pin_B3)
diff --git a/stmhal/boards/STM32F4DISC/mpconfigboard.h b/stmhal/boards/STM32F4DISC/mpconfigboard.h
index c83bb162bb..e6780eacbd 100644
--- a/stmhal/boards/STM32F4DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32F4DISC/mpconfigboard.h
@@ -7,7 +7,6 @@
#define MICROPY_HW_HAS_MMA7660 (0)
#define MICROPY_HW_HAS_LIS3DSH (1)
#define MICROPY_HW_HAS_LCD (0)
-#define MICROPY_HW_HAS_WLAN (0)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_TIMER (1)
@@ -16,6 +15,7 @@
#define MICROPY_HW_ENABLE_I2C1 (1)
#define MICROPY_HW_ENABLE_SPI1 (1)
#define MICROPY_HW_ENABLE_SPI3 (0)
+#define MICROPY_HW_ENABLE_CC3K (0)
// USRSW is pulled low. Pressing the button makes the input go high.
#define MICROPY_HW_USRSW_PIN (pin_A0)
diff --git a/stmhal/boards/stm32f4xx-af.csv b/stmhal/boards/stm32f4xx-af.csv
index 0a21fc87d6..5746ac8cc9 100644
--- a/stmhal/boards/stm32f4xx-af.csv
+++ b/stmhal/boards/stm32f4xx-af.csv
@@ -16,20 +16,20 @@ PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT
PortA,PA13,JTMS-SWDIO,,,,,,,,,,,,,,,EVENTOUT
PortA,PA14,JTCK-SWCLK,,,,,,,,,,,,,,,EVENTOUT
PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT
-PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,,,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT,AC12_IN8
+PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,,,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT,ADC12_IN8
PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT,ADC12_IN9
PortB,PB2,,,,,,,,,,,,,,,,EVENTOUT
-PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCKI2S3_CK,,,,,,,,,EVENTOUT
+PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT
PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,,,,,,,,EVENTOUT
PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,,DCMI_D10,,EVENTOUT
PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,CAN2_TX,,,,DCMI_D5,,EVENTOUT
PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FSMC_NL,DCMI_VSYNC,,EVENTOUT
PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,ETH_MII_TXD3,SDIO_D4,DCMI_D6,,EVENTOUT
PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,,,SDIO_D5,DCMI_D7,,EVENTOUT
-PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCKI2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,,EVENTOUT
+PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,,EVENTOUT
PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,,EVENTOUT
PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT
-PortB,PB13,,TIM1_CH1N,,,,SPI2_SCKI2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT
+PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT
PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,I2S2ext_SD,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT
PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT
PortC,PC0,,,,,,,,,,,OTG_HS_ULPI_STP,,,,,EVENTOUT,ADC123_IN10
@@ -129,7 +129,7 @@ PortH,PH13,,,,TIM8_CH1N,,,,,,CAN1_TX,,,,,,EVENTOUT
PortH,PH14,,,,TIM8_CH2N,,,,,,,,,,DCMI_D4,,EVENTOUT
PortH,PH15,,,,TIM8_CH3N,,,,,,,,,,DCMI_D11,,EVENTOUT
PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,,DCMI_D13,,EVENTOUT
-PortI,PI1,,,,,,SPI2_SCKI2S2_CK,,,,,,,,DCMI_D8,,EVENTOUT
+PortI,PI1,,,,,,SPI2_SCK/I2S2_CK,,,,,,,,DCMI_D8,,EVENTOUT
PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,I2S2ext_SD,,,,,,,DCMI_D9,,EVENTOUT
PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,,DCMI_D10,,EVENTOUT
PortI,PI4,,,,TIM8_BKIN,,,,,,,,,,DCMI_D5,,EVENTOUT
diff --git a/stmhal/bufhelper.c b/stmhal/bufhelper.c
index 5612a048dc..c5dcd6c1d2 100644
--- a/stmhal/bufhelper.c
+++ b/stmhal/bufhelper.c
@@ -4,7 +4,7 @@
#include "obj.h"
#include "bufhelper.h"
-void pyb_buf_get_for_send(mp_obj_t o, mp_buffer_info_t *bufinfo, uint8_t *tmp_data) {
+void pyb_buf_get_for_send(mp_obj_t o, mp_buffer_info_t *bufinfo, byte *tmp_data) {
if (MP_OBJ_IS_INT(o)) {
tmp_data[0] = mp_obj_get_int(o);
bufinfo->buf = tmp_data;
diff --git a/stmhal/bufhelper.h b/stmhal/bufhelper.h
index 9b58e817c8..53ab7ab3e0 100644
--- a/stmhal/bufhelper.h
+++ b/stmhal/bufhelper.h
@@ -1,2 +1,2 @@
-void pyb_buf_get_for_send(mp_obj_t o, mp_buffer_info_t *bufinfo, uint8_t *tmp_data);
+void pyb_buf_get_for_send(mp_obj_t o, mp_buffer_info_t *bufinfo, byte *tmp_data);
mp_obj_t pyb_buf_get_for_recv(mp_obj_t o, mp_buffer_info_t *bufinfo);
diff --git a/stmhal/cc3k/cc3000_common.c b/stmhal/cc3k/cc3000_common.c
index 48eda26760..8d9bd7d03a 100644
--- a/stmhal/cc3k/cc3000_common.c
+++ b/stmhal/cc3k/cc3000_common.c
@@ -52,6 +52,9 @@
*
*****************************************************************************/
#include <stdint.h>
+#include "mpconfigport.h"
+
+#if MICROPY_HW_ENABLE_CC3K
#include "cc3000_common.h"
#include "socket.h"
@@ -194,3 +197,5 @@ uint32_t STREAM_TO_UINT32_f(char * cp, uint16_t offset)
//! @}
//
//*****************************************************************************
+
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/cc3k/ccspi.c b/stmhal/cc3k/ccspi.c
index 4785897e13..133b17d030 100644
--- a/stmhal/cc3k/ccspi.c
+++ b/stmhal/cc3k/ccspi.c
@@ -42,6 +42,9 @@
*****************************************************************************/
#include <stdint.h>
#include <string.h> // for memset
+#include "mpconfigport.h"
+
+#if MICROPY_HW_ENABLE_CC3K
#include "ccspi.h"
#include "hci.h"
@@ -735,3 +738,5 @@ void cc3k_int_poll()
SpiIntGPIOHandler();
}
}
+
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/cc3k/evnt_handler.c b/stmhal/cc3k/evnt_handler.c
index 5a75fadcc0..cca2e796d7 100644
--- a/stmhal/cc3k/evnt_handler.c
+++ b/stmhal/cc3k/evnt_handler.c
@@ -52,6 +52,9 @@
//******************************************************************************
#include <stdint.h>
+#include "mpconfigport.h"
+
+#if MICROPY_HW_ENABLE_CC3K
#include "cc3000_common.h"
#include "string.h"
@@ -871,3 +874,5 @@ SimpleLinkWaitData(unsigned char *pBuf, unsigned char *from,
//! @}
//
//*****************************************************************************
+
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/cc3k/hci.c b/stmhal/cc3k/hci.c
index ef77db95f9..533311f175 100644
--- a/stmhal/cc3k/hci.c
+++ b/stmhal/cc3k/hci.c
@@ -50,6 +50,9 @@
#include <stdint.h>
#include <string.h> // for memcpy
+#include "mpconfigport.h"
+
+#if MICROPY_HW_ENABLE_CC3K
#include "cc3000_common.h"
#include "hci.h"
@@ -240,3 +243,5 @@ hci_patch_send(unsigned char ucOpcode, unsigned char *pucBuff, char *patch, unsi
//
//
//*****************************************************************************
+
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/cc3k/netapp.c b/stmhal/cc3k/netapp.c
index 4b3efb24df..cdeccefc46 100644
--- a/stmhal/cc3k/netapp.c
+++ b/stmhal/cc3k/netapp.c
@@ -41,6 +41,9 @@
*
*****************************************************************************/
#include <stdint.h>
+#include "mpconfigport.h"
+
+#if MICROPY_HW_ENABLE_CC3K
#include "netapp.h"
#include "hci.h"
@@ -475,3 +478,5 @@ long netapp_set_debug_level(unsigned long ulLevel)
}
#endif
+
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/cc3k/nvmem.c b/stmhal/cc3k/nvmem.c
index 4113620086..774759c41f 100644
--- a/stmhal/cc3k/nvmem.c
+++ b/stmhal/cc3k/nvmem.c
@@ -50,6 +50,9 @@
#include <stdint.h>
#include <string.h>
+#include "mpconfigport.h"
+
+#if MICROPY_HW_ENABLE_CC3K
#include "nvmem.h"
#include "hci.h"
@@ -364,3 +367,4 @@ nvmem_create_entry(unsigned long ulFileId, unsigned long ulNewLen)
//
//*****************************************************************************
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/cc3k/pybcc3k.c b/stmhal/cc3k/pybcc3k.c
index 17b205b949..d43f42f0ba 100644
--- a/stmhal/cc3k/pybcc3k.c
+++ b/stmhal/cc3k/pybcc3k.c
@@ -2,9 +2,9 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -17,6 +17,8 @@
#include "ccdebug.h"
#include "pybcc3k.h"
+#if MICROPY_HW_ENABLE_CC3K
+
// IRQ on PA14, input, pulled up, active low
// EN on PC7, output, active high
// CS on PC6, output, active low
@@ -165,3 +167,5 @@ uint8_t pyb_cc3000_spi_send(uint8_t val) {
HAL_SPI_TransmitReceive(&SPI_HANDLE, data, data, 1, 1000);
return data[0];
}
+
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/cc3k/security.c b/stmhal/cc3k/security.c
index c12aee370d..c52d7f67e6 100644
--- a/stmhal/cc3k/security.c
+++ b/stmhal/cc3k/security.c
@@ -41,6 +41,9 @@
//*****************************************************************************
#include <stdint.h>
+#include "mpconfigport.h"
+
+#if MICROPY_HW_ENABLE_CC3K
#include "security.h"
@@ -533,3 +536,5 @@ signed long aes_write_key(unsigned char *key)
//! @}
//
//*****************************************************************************
+
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/cc3k/socket.c b/stmhal/cc3k/socket.c
index cfccbd7831..86a4549ecf 100644
--- a/stmhal/cc3k/socket.c
+++ b/stmhal/cc3k/socket.c
@@ -50,6 +50,9 @@
#include <stdint.h>
#include <string.h> // for memcpy
+#include "mpconfigport.h"
+
+#if MICROPY_HW_ENABLE_CC3K
#include "hci.h"
#include "socket.h"
@@ -1188,3 +1191,5 @@ mdnsAdvertiser(unsigned short mdnsEnabled, char * deviceServiceName, unsigned sh
return ret;
}
+
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/cc3k/wlan.c b/stmhal/cc3k/wlan.c
index be6b3242ce..b22796a7c8 100644
--- a/stmhal/cc3k/wlan.c
+++ b/stmhal/cc3k/wlan.c
@@ -49,6 +49,9 @@
//*****************************************************************************
#include <stdlib.h>
#include <stdint.h>
+#include "mpconfigport.h"
+
+#if MICROPY_HW_ENABLE_CC3K
#include "wlan.h"
#include "hci.h"
@@ -1262,3 +1265,5 @@ wlan_smart_config_process()
//! @}
//
//*****************************************************************************
+
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/dac.c b/stmhal/dac.c
index cd62f017fb..56674c4313 100644
--- a/stmhal/dac.c
+++ b/stmhal/dac.c
@@ -3,9 +3,9 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "parse.h"
#include "obj.h"
@@ -16,6 +16,31 @@
/// \moduleref pyb
/// \class DAC - digital to analog conversion
///
+/// The DAC is used to output analog values (a specific voltage) on pin X5 or pin X6.
+/// The voltage will be between 0 and 3.3V.
+///
+/// *This module will undergo changes to the API.*
+///
+/// Example usage:
+///
+/// from pyb import DAC
+///
+/// dac = DAC(1) # create DAC 1 on pin X5
+/// dac.write(128) # write a value to the DAC (makes X5 1.65V)
+///
+/// To output a continuous sine-wave:
+///
+/// import math
+/// from pyb import DAC
+///
+/// # create a buffer containing a sine-wave
+/// buf = bytearray(100)
+/// for i in range(len(buf)):
+/// buf[i] = 128 + 127 * math.sin(2 * math.pi * i / len(buf))
+///
+/// # output the sine-wave at 400Hz
+/// dac = DAC(1)
+/// dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR)
STATIC DAC_HandleTypeDef DAC_Handle;
@@ -52,6 +77,10 @@ typedef struct _pyb_dac_obj_t {
// create the dac object
// currently support either DAC1 on X5 (id = 1) or DAC2 on X6 (id = 2)
+/// \classmethod \constructor(id)
+/// Construct a new DAC object.
+///
+/// `id` can be 1 or 2: DAC 1 is on pin X5 and DAC 2 is on pin X6.
STATIC mp_obj_t pyb_dac_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, 1, false);
@@ -93,6 +122,9 @@ STATIC mp_obj_t pyb_dac_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
return dac;
}
+/// \method noise(freq)
+/// Generate a pseudo-random noise signal. A new random sample is written
+/// to the DAC output at the given frequency.
STATIC mp_obj_t pyb_dac_noise(mp_obj_t self_in, mp_obj_t freq) {
pyb_dac_obj_t *self = self_in;
@@ -117,6 +149,10 @@ STATIC mp_obj_t pyb_dac_noise(mp_obj_t self_in, mp_obj_t freq) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_noise_obj, pyb_dac_noise);
+/// \method triangle(freq)
+/// Generate a triangle wave. The value on the DAC output changes at
+/// the given frequency, and the frequence of the repeating triangle wave
+/// itself is 256 (or 1024, need to check) times smaller.
STATIC mp_obj_t pyb_dac_triangle(mp_obj_t self_in, mp_obj_t freq) {
pyb_dac_obj_t *self = self_in;
@@ -141,7 +177,8 @@ STATIC mp_obj_t pyb_dac_triangle(mp_obj_t self_in, mp_obj_t freq) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_triangle_obj, pyb_dac_triangle);
-// direct access to DAC (8 bit only at the moment)
+/// \method write(value)
+/// Direct access to the DAC output (8 bit only at the moment).
STATIC mp_obj_t pyb_dac_write(mp_obj_t self_in, mp_obj_t val) {
pyb_dac_obj_t *self = self_in;
@@ -160,12 +197,15 @@ STATIC mp_obj_t pyb_dac_write(mp_obj_t self_in, mp_obj_t val) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_write_obj, pyb_dac_write);
-// initiates a burst of RAM->DAC using DMA
-// input data is treated as an array of bytes (8 bit data)
-// TIM6 is used to set the frequency of the transfer
+/// \method write_timed(data, freq, *, mode=DAC.NORMAL)
+/// Initiates a burst of RAM to DAC using a DMA transfer.
+/// The input data is treated as an array of bytes (8 bit data).
+///
+/// `mode` can be `DAC.NORMAL` or `DAC.CIRCULAR`.
+///
+/// TIM6 is used to control the frequency of the transfer.
// TODO add callback argument, to call when transfer is finished
// TODO add double buffer argument
-
STATIC const mp_arg_t pyb_dac_write_timed_args[] = {
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
diff --git a/stmhal/extint.c b/stmhal/extint.c
index 61469e0a17..90016d19a9 100644
--- a/stmhal/extint.c
+++ b/stmhal/extint.c
@@ -4,9 +4,9 @@
#include <stm32f4xx_hal.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "gc.h"
#include "obj.h"
diff --git a/stmhal/file.c b/stmhal/file.c
index 978ba65fc6..f78709b9f5 100644
--- a/stmhal/file.c
+++ b/stmhal/file.c
@@ -51,6 +51,7 @@ STATIC const mp_map_elem_t file_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readlines), (mp_obj_t)&mp_stream_unbuffered_readlines_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&file_obj_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&file_obj_close_obj },
diff --git a/stmhal/gccollect.c b/stmhal/gccollect.c
index d40460d70c..8be531416f 100644
--- a/stmhal/gccollect.c
+++ b/stmhal/gccollect.c
@@ -41,9 +41,9 @@ void gc_collect(void) {
gc_info_t info;
gc_info(&info);
printf("GC@%lu %lums\n", start, ticks);
- printf(" %lu total\n", info.total);
- printf(" %lu : %lu\n", info.used, info.free);
- printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
+ printf(" " UINT_FMT " total\n", info.total);
+ printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free);
+ printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block);
}
}
diff --git a/stmhal/gendoc.py b/stmhal/gendoc.py
index 42882ad277..0122579ab8 100644
--- a/stmhal/gendoc.py
+++ b/stmhal/gendoc.py
@@ -343,7 +343,7 @@ def main():
args = cmd_parser.parse_args()
if len(args.files) == 0:
- args.files = ['modpyb.c', 'accel.c', 'adc.c', 'dac.c', 'extint.c', 'i2c.c', 'led.c', 'pin.c', 'rng.c', 'servo.c', 'spi.c', 'uart.c', 'usrsw.c']
+ args.files = ['modpyb.c', 'accel.c', 'adc.c', 'dac.c', 'extint.c', 'i2c.c', 'led.c', 'pin.c', 'rng.c', 'servo.c', 'spi.c', 'uart.c', 'usrsw.c', 'timer.c', 'rtc.c']
doc = Doc()
for file in args.files:
diff --git a/stmhal/help.c b/stmhal/help.c
index 975a102445..084d708e6e 100644
--- a/stmhal/help.c
+++ b/stmhal/help.c
@@ -1,8 +1,8 @@
#include <stdio.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index ef9da496d0..96222bf336 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -3,9 +3,9 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -367,7 +367,7 @@ STATIC mp_obj_t pyb_i2c_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_arg
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_send_obj, 1, pyb_i2c_send);
-/// \method recv(send, addr=0x00, timeout=5000)
+/// \method recv(recv, addr=0x00, timeout=5000)
///
/// Receive data on the bus:
///
diff --git a/stmhal/input.c b/stmhal/input.c
index 0ded898667..6e98ea960c 100644
--- a/stmhal/input.c
+++ b/stmhal/input.c
@@ -1,6 +1,8 @@
+#include <stdint.h>
+
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "readline.h"
diff --git a/stmhal/lcd.c b/stmhal/lcd.c
index efee13d233..f121a93d7a 100644
--- a/stmhal/lcd.c
+++ b/stmhal/lcd.c
@@ -2,9 +2,9 @@
#include <string.h>
#include <stm32f4xx_hal.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#if MICROPY_HW_HAS_LCD
diff --git a/stmhal/led.c b/stmhal/led.c
index 9e32c52483..264a475484 100644
--- a/stmhal/led.c
+++ b/stmhal/led.c
@@ -1,9 +1,9 @@
#include <stdio.h>
#include <stm32f4xx_hal.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/stmhal/main.c b/stmhal/main.c
index 603bf31889..5faa70e657 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -495,13 +495,11 @@ soft_reset:
vstr_free(vstr);
}
-#if 0
-#if MICROPY_HW_HAS_WLAN
- // wifi
+#if MICROPY_HW_ENABLE_CC3K
+ // wifi using the CC3000 driver
pyb_wlan_init();
pyb_wlan_start();
#endif
-#endif
// enter REPL
// REPL mode can change, or it can request a soft reset
diff --git a/stmhal/modos.c b/stmhal/modos.c
index 33b4ff73e0..3594cbc3a6 100644
--- a/stmhal/modos.c
+++ b/stmhal/modos.c
@@ -1,8 +1,9 @@
+#include <stdint.h>
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "systick.h"
diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c
index 2f53bb5234..1ffff1d17a 100644
--- a/stmhal/modpyb.c
+++ b/stmhal/modpyb.c
@@ -82,9 +82,9 @@ STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) {
gc_info_t info;
gc_info(&info);
printf("GC:\n");
- printf(" %lu total\n", info.total);
- printf(" %lu : %lu\n", info.used, info.free);
- printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
+ printf(" " UINT_FMT " total\n", info.total);
+ printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free);
+ printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block);
}
// free space on flash
@@ -143,22 +143,26 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis);
/// \function delay(ms)
/// Delay for the given number of milliseconds.
-STATIC mp_obj_t pyb_delay(mp_obj_t count) {
- HAL_Delay(mp_obj_get_int(count));
+STATIC mp_obj_t pyb_delay(mp_obj_t ms_in) {
+ machine_int_t ms = mp_obj_get_int(ms_in);
+ if (ms >= 0) {
+ HAL_Delay(ms);
+ }
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_delay_obj, pyb_delay);
/// \function udelay(us)
/// Delay for the given number of microseconds.
-STATIC mp_obj_t pyb_udelay(mp_obj_t usec) {
- uint32_t count = 0;
- const uint32_t utime = (168 * mp_obj_get_int(usec) / 5);
- for (;;) {
- if (++count > utime) {
- return mp_const_none;
+STATIC mp_obj_t pyb_udelay(mp_obj_t usec_in) {
+ machine_int_t usec = mp_obj_get_int(usec_in);
+ if (usec > 0) {
+ uint32_t count = 0;
+ const uint32_t utime = (168 * usec / 4);
+ while (++count <= utime) {
}
}
+ return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay);
diff --git a/stmhal/modstm.c b/stmhal/modstm.c
index 078f590ece..a2b72995ae 100644
--- a/stmhal/modstm.c
+++ b/stmhal/modstm.c
@@ -3,9 +3,9 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "modstm.h"
diff --git a/stmhal/modtime.c b/stmhal/modtime.c
index 83be2deaa1..410c6391e2 100644
--- a/stmhal/modtime.c
+++ b/stmhal/modtime.c
@@ -1,8 +1,8 @@
#include <stm32f4xx_hal.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "modtime.h"
diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h
index 24ab20b16b..faa1c806a4 100644
--- a/stmhal/mpconfigport.h
+++ b/stmhal/mpconfigport.h
@@ -1,5 +1,3 @@
-#include <stdint.h>
-
// options to control how Micro Python is built
#define MICROPY_EMIT_THUMB (1)
@@ -21,6 +19,7 @@
#define MICROPY_ENABLE_LFN (1)
#define MICROPY_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
#define MICROPY_MOD_SYS_STDFILES (1)
+#define MICROPY_ENABLE_MOD_CMATH (1)
// extra built in names to add to the global namespace
extern const struct _mp_obj_fun_native_t mp_builtin_help_obj;
@@ -51,11 +50,11 @@ extern const struct _mp_obj_module_t time_module;
#define BYTES_PER_WORD (4)
-#define UINT_FMT "%lu"
-#define INT_FMT "%ld"
+#define UINT_FMT "%u"
+#define INT_FMT "%d"
-typedef int32_t machine_int_t; // must be pointer size
-typedef uint32_t machine_uint_t; // must be pointer size
+typedef int machine_int_t; // must be pointer size
+typedef unsigned int machine_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
diff --git a/stmhal/pin.c b/stmhal/pin.c
index 06923a492d..d390926360 100644
--- a/stmhal/pin.c
+++ b/stmhal/pin.c
@@ -4,9 +4,9 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -179,7 +179,7 @@ STATIC mp_obj_t pin_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_
if (n_args >= 2) {
// pin mode given, so configure this GPIO
- mp_obj_t args2[3] = {(mp_obj_t)pin, args2[1], MP_OBJ_NULL};
+ mp_obj_t args2[3] = {(mp_obj_t)pin, args[1], MP_OBJ_NULL};
if (n_args == 3) {
args2[2] = args[2];
}
@@ -241,6 +241,7 @@ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_debug_obj, (mp_obj_t)&pin_debug_fun_o
/// - `Pin.PULL_DOWN` - enable the pull-down resistor.
///
/// Returns: `None`.
+// TODO allow keyword args
STATIC mp_obj_t pin_obj_init(uint n_args, mp_obj_t *args) {
pin_obj_t *self = args[0];
diff --git a/stmhal/pybwlan.c b/stmhal/pybwlan.c
index 72cb9bfd98..fb214209c2 100644
--- a/stmhal/pybwlan.c
+++ b/stmhal/pybwlan.c
@@ -5,13 +5,15 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
+#if MICROPY_HW_ENABLE_CC3K
+
#include "cc3k/ccspi.h"
#include "cc3k/hci.h"
#include "cc3k/socket.h"
@@ -377,3 +379,5 @@ void pyb_wlan_start(void) {
printf("nvmem_read_sp_version=%d; %02x %02x\n", ret, ver[0], ver[1]);
*/
}
+
+#endif // MICROPY_HW_ENABLE_CC3K
diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c
index 3f9482ec58..00025c8c6f 100644
--- a/stmhal/pyexec.c
+++ b/stmhal/pyexec.c
@@ -3,9 +3,9 @@
#include <stm32f4xx_hal.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "misc.h"
#include "lexer.h"
@@ -84,9 +84,9 @@ bool parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bo
gc_info_t info;
gc_info(&info);
printf("GC:\n");
- printf(" %lu total\n", info.total);
- printf(" %lu : %lu\n", info.used, info.free);
- printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
+ printf(" " UINT_FMT " total\n", info.total);
+ printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free);
+ printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block);
}
}
@@ -155,7 +155,7 @@ int pyexec_friendly_repl(void) {
#endif
friendly_repl_reset:
- stdout_tx_str("Micro Python build " MICROPY_GIT_HASH " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with STM32F405RG\r\n");
+ stdout_tx_str("Micro Python " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with STM32F405RG\r\n");
stdout_tx_str("Type \"help()\" for more information.\r\n");
// to test ctrl-C
diff --git a/stmhal/rtc.c b/stmhal/rtc.c
index 79e524cab2..ea7aa789ec 100644
--- a/stmhal/rtc.c
+++ b/stmhal/rtc.c
@@ -9,6 +9,18 @@
#include "runtime.h"
#include "rtc.h"
+/// \moduleref pyb
+/// \class RTC - real time clock
+///
+/// The RTC is and independent clock that keeps track of the date
+/// and time.
+///
+/// Example usage:
+///
+/// rtc = pyb.RTC()
+/// rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0))
+/// print(rtc.datetime())
+
RTC_HandleTypeDef RTCHandle;
// rtc_info indicates various things about RTC startup
@@ -159,13 +171,13 @@ void rtc_init(void) {
// fresh reset; configure RTC Calendar
RTC_CalendarConfig();
} else {
- // RTC was previously set, so leave it alon
+ // RTC was previously set, so leave it alone
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) {
- // power on reset occured
+ // power on reset occurred
rtc_info |= 0x10000;
}
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET) {
- // external reset occured
+ // external reset occurred
rtc_info |= 0x20000;
}
// Clear source Reset Flag
@@ -213,6 +225,8 @@ typedef struct _pyb_rtc_obj_t {
STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}};
+/// \classmethod \constructor()
+/// Create an RTC object.
STATIC mp_obj_t pyb_rtc_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
@@ -221,11 +235,32 @@ STATIC mp_obj_t pyb_rtc_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
return (mp_obj_t)&pyb_rtc_obj;
}
+/// \method info()
+/// Get information about the startup time and reset source.
+///
+/// - The lower 0xffff are the number of milliseconds the RTC took to
+/// start up.
+/// - Bit 0x10000 is set if a power-on reset occurred.
+/// - Bit 0x20000 is set if an external reset occurred
mp_obj_t pyb_rtc_info(mp_obj_t self_in) {
return mp_obj_new_int(rtc_info);
}
MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_info_obj, pyb_rtc_info);
+/// \method datetime([datetimetuple])
+/// Get or set the date and time of the RTC.
+///
+/// With no arguments, this method returns an 8-tuple with the current
+/// date and time. With 1 argument (being an 8-tuple) it sets the date
+/// and time.
+///
+/// The 8-tuple has the following format:
+///
+/// (year, month, day, weekday, hours, minutes, seconds, subseconds)
+///
+/// `weekday` is 1-7 for Monday through Sunday.
+///
+/// `subseconds` counts down from 255 to 0
mp_obj_t pyb_rtc_datetime(uint n_args, const mp_obj_t *args) {
if (n_args == 1) {
// get date and time
diff --git a/stmhal/servo.c b/stmhal/servo.c
index 2ebe64376f..6f87197bd2 100644
--- a/stmhal/servo.c
+++ b/stmhal/servo.c
@@ -2,9 +2,9 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -203,6 +203,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_servo_pulse_width_obj, 1, 2, pyb_
/// \method calibration([pulse_min, pulse_max, pulse_centre, [pulse_angle_90, pulse_speed_100]])
/// Get or set the calibration of the servo timing.
+// TODO should accept 1 arg, a 5-tuple of values to set
STATIC mp_obj_t pyb_servo_calibration(uint n_args, const mp_obj_t *args) {
pyb_servo_obj_t *self = args[0];
if (n_args == 1) {
diff --git a/stmhal/spi.c b/stmhal/spi.c
index ba550f9799..a07ebd21a9 100644
--- a/stmhal/spi.c
+++ b/stmhal/spi.c
@@ -3,9 +3,9 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -198,7 +198,7 @@ STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *
}
}
-/// \method init(mode, baudrate=328125, *, polarity=1, phase=1, bits=8, firstbit=SPI.MSB, ti=false, crc=None)
+/// \method init(mode, baudrate=328125, *, polarity=1, phase=1, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
///
/// Initialise the SPI bus with the given parameters:
///
diff --git a/stmhal/timer.c b/stmhal/timer.c
index 1578e9b1d9..e92a9988f7 100644
--- a/stmhal/timer.c
+++ b/stmhal/timer.c
@@ -16,6 +16,38 @@
#include "timer.h"
#include "servo.h"
+/// \moduleref pyb
+/// \class Timer - periodically call a function
+///
+/// Timers can be used for a great variety of tasks. At the moment, only
+/// the simplest case is implemented: that of calling a function periodically.
+///
+/// Each timer consists of a counter that counts up at a certain rate. The rate
+/// at which it counts is the peripheral clock frequency (in Hz) divided by the
+/// timer prescaler. When the counter reaches the timer period it triggers an
+/// event, and the counter resets back to zero. By using the callback method,
+/// the timer event can call a Python function.
+///
+/// Example usage to toggle an LED at a fixed frequency:
+///
+/// tim = pyb.Timer(4) # create a timer object using timer 4
+/// tim.init(freq=2) # trigger at 2Hz
+/// tim.callback(lambda t:pyb.LED(1).toggle())
+///
+/// Further examples:
+///
+/// tim = pyb.Timer(4, freq=100) # freq in Hz
+/// tim = pyb.Timer(4, prescaler=1, period=100)
+/// tim.counter() # get counter (can also set)
+/// tim.prescaler(2) # set prescaler (can also get)
+/// tim.period(200) # set period (can also get)
+/// tim.callback(lambda t: ...) # set callback for update interrupt (t=tim instance)
+/// tim.callback(None) # clear callback
+///
+/// *Note:* Timer 3 is reserved for internal use. Timer 5 controls
+/// the servo driver, and Timer 6 is used for timed ADC/DAC reading/writing.
+/// It is recommended to use the other timers in your programs.
+
// The timers can be used by multiple drivers, and need a common point for
// the interrupts to be dispatched, so they are all collected here.
//
@@ -29,16 +61,6 @@
//
// TIM6:
// - ADC, DAC for read_timed and write_timed
-//
-// Python usage model:
-//
-// tim = pyb.Timer(4, freq=100) # freq in Hz
-// tim = pyb.Timer(4, prescaler=1, period=100)
-// tim.counter() # get counter (can also set)
-// tim.prescaler(2) # set prescaler (can also get)
-// tim.period(200) # set period (can also get)
-// tim.callback(lambda t: ...) # set callback for update interrupt (t=tim instance)
-// tim.callback(None) # clear callback
typedef struct _pyb_timer_obj_t {
mp_obj_base_t base;
@@ -173,6 +195,12 @@ STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void
}
}
+/// \method init(*, freq, prescaler, period)
+/// Initialise the timer. Initialisation must be either by frequency (in Hz)
+/// or by prescaler and period:
+///
+/// tim.init(freq=100) # set the timer to trigger at 100Hz
+/// tim.init(prescaler=100, period=300) # set the prescaler and period directly
STATIC const mp_arg_t pyb_timer_init_args[] = {
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
{ MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
@@ -257,6 +285,10 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, uint n_args, const
return mp_const_none;
}
+/// \classmethod \constructor(id, ...)
+/// Construct a new timer object of the given id. If additional
+/// arguments are given, then the timer is initialised by `init(...)`.
+/// `id` can be 1 to 14, excluding 3.
STATIC mp_obj_t pyb_timer_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
@@ -308,6 +340,10 @@ STATIC mp_obj_t pyb_timer_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_a
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_init_obj, 1, pyb_timer_init);
+/// \method deinit()
+/// Deinitialises the timer.
+///
+/// *This function is not yet implemented.*
STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) {
//pyb_timer_obj_t *self = self_in;
// TODO implement me
@@ -315,6 +351,8 @@ STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit);
+/// \method counter([value])
+/// Get or set the timer counter.
mp_obj_t pyb_timer_counter(uint n_args, const mp_obj_t *args) {
pyb_timer_obj_t *self = args[0];
if (n_args == 1) {
@@ -328,6 +366,8 @@ mp_obj_t pyb_timer_counter(uint n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_counter_obj, 1, 2, pyb_timer_counter);
+/// \method prescaler([value])
+/// Get or set the prescaler for the timer.
mp_obj_t pyb_timer_prescaler(uint n_args, const mp_obj_t *args) {
pyb_timer_obj_t *self = args[0];
if (n_args == 1) {
@@ -341,6 +381,8 @@ mp_obj_t pyb_timer_prescaler(uint n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_prescaler_obj, 1, 2, pyb_timer_prescaler);
+/// \method period([value])
+/// Get or set the period of the timer.
mp_obj_t pyb_timer_period(uint n_args, const mp_obj_t *args) {
pyb_timer_obj_t *self = args[0];
if (n_args == 1) {
@@ -354,6 +396,10 @@ mp_obj_t pyb_timer_period(uint n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_period_obj, 1, 2, pyb_timer_period);
+/// \method callback(fun)
+/// Set the function to be called when the timer triggers.
+/// `fun` is passed 1 argument, the timer object.
+/// If `fun` is `None` then the callback will be disabled.
STATIC mp_obj_t pyb_timer_callback(mp_obj_t self_in, mp_obj_t callback) {
pyb_timer_obj_t *self = self_in;
if (callback == mp_const_none) {
@@ -421,7 +467,7 @@ void timer_irq_handler(uint tim_id) {
// Uncaught exception; disable the callback so it doesn't run again.
tim->callback = mp_const_none;
__HAL_TIM_DISABLE_IT(&tim->tim, TIM_IT_UPDATE);
- printf("Uncaught exception in Timer(%lu) interrupt handler\n", tim->tim_id);
+ printf("Uncaught exception in Timer(" UINT_FMT ") interrupt handler\n", tim->tim_id);
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
}
gc_unlock();
diff --git a/stmhal/uart.c b/stmhal/uart.c
index 6dc60ca084..04373a8840 100644
--- a/stmhal/uart.c
+++ b/stmhal/uart.c
@@ -3,9 +3,9 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/tests/basics/builtin-minmax.py b/tests/basics/builtin-minmax.py
new file mode 100644
index 0000000000..8ee4bbca7d
--- /dev/null
+++ b/tests/basics/builtin-minmax.py
@@ -0,0 +1,15 @@
+# test builtin min and max functions
+
+print(min(0,1))
+print(min(1,0))
+print(min(0,-1))
+print(min(-1,0))
+
+print(max(0,1))
+print(max(1,0))
+print(max(0,-1))
+print(max(-1,0))
+
+print(min([1,2,4,0,-1,2]))
+print(max([1,2,4,0,-1,2]))
+
diff --git a/tests/basics/subclass-native3.py b/tests/basics/subclass-native3.py
index 5d443cf5cd..bd99ab0d6a 100644
--- a/tests/basics/subclass-native3.py
+++ b/tests/basics/subclass-native3.py
@@ -3,6 +3,20 @@ class MyExc(Exception):
e = MyExc(100, "Some error")
print(e)
-# TODO: Prints native base class name
-#print(repr(e))
+print(repr(e))
print(e.args)
+
+try:
+ raise MyExc("Some error")
+except MyExc as e:
+ print("Caught exception:", repr(e))
+
+try:
+ raise MyExc("Some error2")
+except Exception as e:
+ print("Caught exception:", repr(e))
+
+try:
+ raise MyExc("Some error2")
+except:
+ print("Caught user exception")
diff --git a/tests/float/builtin-float-minmax.py b/tests/float/builtin-float-minmax.py
new file mode 100644
index 0000000000..ce45a768a5
--- /dev/null
+++ b/tests/float/builtin-float-minmax.py
@@ -0,0 +1,26 @@
+# test builtin min and max functions with float args
+
+print(min(0,1.0))
+print(min(1.0,0))
+print(min(0,-1.0))
+print(min(-1.0,0))
+
+print(max(0,1.0))
+print(max(1.0,0))
+print(max(0,-1.0))
+print(max(-1.0,0))
+
+print(min(1.5,-1.5))
+print(min(-1.5,1.5))
+
+print(max(1.5,-1.5))
+print(max(-1.5,1.5))
+
+print(min([1,2.9,4,0,-1,2]))
+print(max([1,2.9,4,0,-1,2]))
+
+print(min([1,2.9,4,6.5,-1,2]))
+print(max([1,2.9,4,6.5,-1,2]))
+print(min([1,2.9,4,-6.5,-1,2]))
+print(max([1,2.9,4,-6.5,-1,2]))
+
diff --git a/tests/io/file1.py b/tests/io/file1.py
index 8552f535bd..7d5154a4f8 100644
--- a/tests/io/file1.py
+++ b/tests/io/file1.py
@@ -2,3 +2,5 @@ f = open("io/data/file1")
print(f.read(5))
print(f.readline())
print(f.read())
+f = open("io/data/file1")
+print(f.readlines())
diff --git a/tests/pyb/accel.py b/tests/pyb/accel.py
new file mode 100644
index 0000000000..13f53b33c0
--- /dev/null
+++ b/tests/pyb/accel.py
@@ -0,0 +1,7 @@
+accel = pyb.Accel()
+print(accel)
+accel.x()
+accel.y()
+accel.z()
+accel.tilt()
+accel.filtered_xyz()
diff --git a/tests/pyb/accel.py.exp b/tests/pyb/accel.py.exp
new file mode 100644
index 0000000000..28070be177
--- /dev/null
+++ b/tests/pyb/accel.py.exp
@@ -0,0 +1 @@
+<Accel>
diff --git a/tests/pyb/adc.py b/tests/pyb/adc.py
new file mode 100644
index 0000000000..7bed54e9f8
--- /dev/null
+++ b/tests/pyb/adc.py
@@ -0,0 +1,10 @@
+from pyb import ADC
+from pyb import Pin
+
+adc = ADC('X22')
+print(adc)
+
+adc.read()
+
+buf = bytearray(100)
+adc.read_timed(buf, 500)
diff --git a/tests/pyb/adc.py.exp b/tests/pyb/adc.py.exp
new file mode 100644
index 0000000000..bbc6af7379
--- /dev/null
+++ b/tests/pyb/adc.py.exp
@@ -0,0 +1 @@
+<ADC on X22 channel=13>
diff --git a/tests/pyb/dac.py b/tests/pyb/dac.py
new file mode 100644
index 0000000000..61ab7bd6e6
--- /dev/null
+++ b/tests/pyb/dac.py
@@ -0,0 +1,8 @@
+dac = pyb.DAC(1)
+print(dac)
+dac.noise(100)
+dac.triangle(100)
+dac.write(0)
+dac.write_timed(bytearray(10), 100, mode=pyb.DAC.NORMAL)
+pyb.delay(20)
+dac.write(0)
diff --git a/tests/pyb/dac.py.exp b/tests/pyb/dac.py.exp
new file mode 100644
index 0000000000..ae245f2e61
--- /dev/null
+++ b/tests/pyb/dac.py.exp
@@ -0,0 +1 @@
+<DAC>
diff --git a/tests/pyb/extint.py b/tests/pyb/extint.py
new file mode 100644
index 0000000000..20648995bc
--- /dev/null
+++ b/tests/pyb/extint.py
@@ -0,0 +1,6 @@
+ext = pyb.ExtInt('X1', pyb.ExtInt.IRQ_RISING, pyb.Pin.PULL_DOWN, lambda l:print('line:', l))
+ext.disable()
+ext.enable()
+print(ext.line())
+ext.swint()
+ext.disable()
diff --git a/tests/pyb/extint.py.exp b/tests/pyb/extint.py.exp
new file mode 100644
index 0000000000..28019d75c6
--- /dev/null
+++ b/tests/pyb/extint.py.exp
@@ -0,0 +1,2 @@
+0
+line: 0
diff --git a/tests/pyb/i2c.py b/tests/pyb/i2c.py
new file mode 100644
index 0000000000..79169d0553
--- /dev/null
+++ b/tests/pyb/i2c.py
@@ -0,0 +1,23 @@
+from pyb import I2C
+
+i2c = I2C(1)
+i2c2 = I2C(2)
+
+i2c.init(I2C.MASTER, baudrate=400000)
+print(i2c.scan())
+i2c.deinit()
+
+# use accelerometer to test i2c bus
+
+accel_addr = 76
+
+pyb.Accel() # this will init the bus for us
+
+print(i2c.scan())
+print(i2c.is_ready(accel_addr))
+
+print(i2c.mem_read(1, accel_addr, 7, timeout=500))
+i2c.mem_write(0, accel_addr, 0, timeout=500)
+
+i2c.send(7, addr=accel_addr)
+i2c.recv(1, addr=accel_addr)
diff --git a/tests/pyb/i2c.py.exp b/tests/pyb/i2c.py.exp
new file mode 100644
index 0000000000..c2b982f0fe
--- /dev/null
+++ b/tests/pyb/i2c.py.exp
@@ -0,0 +1,4 @@
+[]
+[76]
+True
+b'\x01'
diff --git a/tests/pyb/led.py b/tests/pyb/led.py
new file mode 100644
index 0000000000..a727c90dfa
--- /dev/null
+++ b/tests/pyb/led.py
@@ -0,0 +1,28 @@
+from pyb import LED
+
+for i in range(4):
+ print(LED(i+1))
+
+for i in range(4):
+ LED(i+1).on()
+pyb.delay(10)
+for i in range(4):
+ LED(i+1).off()
+pyb.delay(10)
+for i in range(4):
+ LED(i+1).toggle()
+pyb.delay(10)
+for i in range(4):
+ LED(i+1).intensity(0)
+
+for i in range(256):
+ LED(4).intensity(i)
+ if LED(4).intensity() != i:
+ print('fail', i)
+ pyb.delay(1)
+for i in range(256):
+ LED(4).intensity(255 - i)
+ pyb.delay(1)
+
+for i in range(4):
+ LED(i+1).off()
diff --git a/tests/pyb/led.py.exp b/tests/pyb/led.py.exp
new file mode 100644
index 0000000000..b528706694
--- /dev/null
+++ b/tests/pyb/led.py.exp
@@ -0,0 +1,4 @@
+<LED 1>
+<LED 2>
+<LED 3>
+<LED 4>
diff --git a/tests/pyb/pin.py b/tests/pyb/pin.py
new file mode 100644
index 0000000000..448ce53998
--- /dev/null
+++ b/tests/pyb/pin.py
@@ -0,0 +1,29 @@
+from pyb import Pin
+
+p = Pin('X1')
+print(p)
+print(p.name())
+print(p.pin())
+print(p.port())
+
+p = Pin('X1', Pin.IN, Pin.PULL_UP)
+#p = Pin('X1', Pin.IN, pull=Pin.PULL_UP)
+print(p.value())
+
+p.init(p.IN, p.PULL_DOWN)
+#p.init(p.IN, pull=p.PULL_DOWN)
+print(p.value())
+
+p.init(p.OUT_PP)
+p.low()
+print(p.value())
+p.high()
+print(p.value())
+p.value(0)
+print(p.value())
+p.value(1)
+print(p.value())
+p.value(False)
+print(p.value())
+p.value(True)
+print(p.value())
diff --git a/tests/pyb/pin.py.exp b/tests/pyb/pin.py.exp
new file mode 100644
index 0000000000..4856f5b8e7
--- /dev/null
+++ b/tests/pyb/pin.py.exp
@@ -0,0 +1,12 @@
+<Pin A0>
+A0
+0
+0
+1
+0
+0
+1
+0
+1
+0
+1
diff --git a/tests/pyb/pyb1.py b/tests/pyb/pyb1.py
new file mode 100644
index 0000000000..0087ec0507
--- /dev/null
+++ b/tests/pyb/pyb1.py
@@ -0,0 +1,42 @@
+# basic tests of pyb module
+
+import pyb
+
+# test delay
+
+pyb.delay(-1)
+pyb.delay(0)
+pyb.delay(1)
+
+start = pyb.millis()
+pyb.delay(17)
+print((pyb.millis() - start) // 5) # should print 3
+
+# test udelay
+
+pyb.udelay(-1)
+pyb.udelay(0)
+pyb.udelay(1)
+
+start = pyb.millis()
+pyb.udelay(17000)
+print((pyb.millis() - start) // 5) # should print 3
+
+# other
+
+pyb.disable_irq()
+pyb.enable_irq()
+
+print(pyb.freq())
+
+print(pyb.have_cdc())
+
+pyb.hid((0, 0, 0, 0)) # won't do anything
+
+pyb.rng()
+
+pyb.sync()
+
+print(len(pyb.unique_id()))
+
+pyb.wfi()
diff --git a/tests/pyb/pyb1.py.exp b/tests/pyb/pyb1.py.exp
new file mode 100644
index 0000000000..84034d683c
--- /dev/null
+++ b/tests/pyb/pyb1.py.exp
@@ -0,0 +1,5 @@
+3
+3
+(168000000, 168000000, 42000000, 84000000)
+True
+12
diff --git a/tests/pyb/rtc.py b/tests/pyb/rtc.py
new file mode 100644
index 0000000000..ac716b27fc
--- /dev/null
+++ b/tests/pyb/rtc.py
@@ -0,0 +1,6 @@
+from pyb import RTC
+rtc = RTC()
+print(rtc)
+rtc.datetime((2014, 1, 1, 1, 0, 0, 0, 0))
+pyb.delay(1000)
+print(rtc.datetime()[:7])
diff --git a/tests/pyb/rtc.py.exp b/tests/pyb/rtc.py.exp
new file mode 100644
index 0000000000..d1ea2d9590
--- /dev/null
+++ b/tests/pyb/rtc.py.exp
@@ -0,0 +1,2 @@
+<RTC>
+(2014, 1, 1, 1, 0, 0, 1)
diff --git a/tests/pyb/servo.py b/tests/pyb/servo.py
new file mode 100644
index 0000000000..d15cafe483
--- /dev/null
+++ b/tests/pyb/servo.py
@@ -0,0 +1,16 @@
+from pyb import Servo
+
+servo = Servo(1)
+print(servo)
+
+servo.angle(0)
+servo.angle(10, 100)
+
+servo.speed(-10)
+servo.speed(10, 100)
+
+servo.pulse_width(1500)
+print(servo.pulse_width())
+
+servo.calibration(630, 2410, 1490, 2460, 2190)
+print(servo.calibration())
diff --git a/tests/pyb/servo.py.exp b/tests/pyb/servo.py.exp
new file mode 100644
index 0000000000..ac6032ba5f
--- /dev/null
+++ b/tests/pyb/servo.py.exp
@@ -0,0 +1,3 @@
+<Servo 1 at 1500us>
+1500
+(630, 2410, 1490, 2460, 2190)
diff --git a/tests/pyb/spi.py b/tests/pyb/spi.py
new file mode 100644
index 0000000000..90dfb441a3
--- /dev/null
+++ b/tests/pyb/spi.py
@@ -0,0 +1,17 @@
+from pyb import SPI
+
+spi = SPI(1)
+print(spi)
+
+spi = SPI(1, SPI.MASTER)
+spi = SPI(1, SPI.MASTER, baudrate=500000)
+spi = SPI(1, SPI.MASTER, 500000, polarity=1, phase=1, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
+print(spi)
+
+spi.init(SPI.SLAVE)
+print(spi)
+
+spi.init(SPI.MASTER)
+spi.send(1, timeout=100)
+print(spi.recv(1, timeout=100))
+print(spi.send_recv(1, timeout=100))
diff --git a/tests/pyb/spi.py.exp b/tests/pyb/spi.py.exp
new file mode 100644
index 0000000000..030dfe1b34
--- /dev/null
+++ b/tests/pyb/spi.py.exp
@@ -0,0 +1,5 @@
+SPI(1)
+SPI(1, SPI.MASTER, baudrate=328125, polarity=1, phase=1, bits=8)
+SPI(1, SPI.SLAVE, polarity=1, phase=1, bits=8)
+b'\xff'
+b'\xff'
diff --git a/tests/pyb/switch.py b/tests/pyb/switch.py
new file mode 100644
index 0000000000..4b74e0fd73
--- /dev/null
+++ b/tests/pyb/switch.py
@@ -0,0 +1,6 @@
+from pyb import Switch
+
+sw = pyb.Switch()
+print(sw())
+sw.callback(print)
+sw.callback(None)
diff --git a/tests/pyb/switch.py.exp b/tests/pyb/switch.py.exp
new file mode 100644
index 0000000000..bc59c12aa1
--- /dev/null
+++ b/tests/pyb/switch.py.exp
@@ -0,0 +1 @@
+False
diff --git a/tests/pyb/timer.py b/tests/pyb/timer.py
new file mode 100644
index 0000000000..ff1bda0f23
--- /dev/null
+++ b/tests/pyb/timer.py
@@ -0,0 +1,28 @@
+from pyb import Timer
+
+tim = Timer(4)
+tim = Timer(4, prescaler=100, period=200)
+print(tim.prescaler())
+print(tim.period())
+tim.prescaler(300)
+print(tim.prescaler())
+tim.period(400)
+print(tim.period())
+
+tim = Timer(4, freq=1)
+tim.init(freq=2000)
+def f(t):
+ print(1)
+ t.callback(None)
+tim.callback(f)
+pyb.delay(10)
+
+# f3 closes over f2.y
+def f2(x):
+ y = x
+ def f3(t):
+ print(2, y)
+ t.callback(None)
+ return f3
+tim.callback(f2(3))
+pyb.delay(10)
diff --git a/tests/pyb/timer.py.exp b/tests/pyb/timer.py.exp
new file mode 100644
index 0000000000..58b81e2af1
--- /dev/null
+++ b/tests/pyb/timer.py.exp
@@ -0,0 +1,6 @@
+100
+200
+300
+400
+1
+2 3
diff --git a/tests/pyb/uart.py b/tests/pyb/uart.py
new file mode 100644
index 0000000000..6e0118d155
--- /dev/null
+++ b/tests/pyb/uart.py
@@ -0,0 +1,12 @@
+from pyb import UART
+
+uart = UART(1)
+uart = UART(1, 9600)
+uart = UART(1, 9600, bits=8, stop=1, parity=None)
+print(uart)
+
+uart.init(1200)
+print(uart)
+
+uart.any()
+uart.send(1, timeout=500)
diff --git a/tests/pyb/uart.py.exp b/tests/pyb/uart.py.exp
new file mode 100644
index 0000000000..58ded4d848
--- /dev/null
+++ b/tests/pyb/uart.py.exp
@@ -0,0 +1,2 @@
+UART(1, baudrate=9600, bits=8, stop=1, parity=None)
+UART(1, baudrate=1200, bits=8, stop=1, parity=None)
diff --git a/tests/pyboard.py b/tests/pyboard.py
new file mode 120000
index 0000000000..3a82f6a6a3
--- /dev/null
+++ b/tests/pyboard.py
@@ -0,0 +1 @@
+../tools/pyboard.py \ No newline at end of file
diff --git a/tests/run-tests b/tests/run-tests
index 9e94026fa2..c1eee59eaa 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -3,6 +3,7 @@
import os
import subprocess
import sys
+import argparse
from glob import glob
# Tests require at least CPython 3.3. If your default python3 executable
@@ -15,82 +16,113 @@ else:
CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3')
MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../unix/micropython')
-# Set of tests that we shouldn't run under Travis CI
-skip_travis_tests = set(['basics/memoryerror.py'])
-
def rm_f(fname):
if os.path.exists(fname):
os.remove(fname)
-test_count = 0
-testcase_count = 0
-passed_count = 0
-failed_tests = []
-tests = []
-
-if not sys.argv[1:]:
- test_dirs = ('basics', 'float', 'import', 'io', 'misc')
- tests = sorted(test_file for test_files in (glob('{}/*.py'.format(dir)) for dir in test_dirs) for test_file in test_files)
-else:
- tests = sys.argv[1:]
-
-test_on_pyboard = False
-if test_on_pyboard:
- import pyboard
- pyb = pyboard.Pyboard('/dev/ttyACM0')
- pyb.enter_raw_repl()
-
-running_under_travis = os.getenv('TRAVIS') == 'true'
-
-for test_file in tests:
- if running_under_travis and test_file in skip_travis_tests:
- print("skip ", test_file)
- continue
-
- # run CPython
- try:
- output_expected = subprocess.check_output([CPYTHON3, '-B', test_file])
- except subprocess.CalledProcessError:
- output_expected = b'CPYTHON3 CRASH'
-
- # run Micro Python
- if test_on_pyboard:
+def run_tests(pyb, tests):
+ test_count = 0
+ testcase_count = 0
+ passed_count = 0
+ failed_tests = []
+
+ running_under_travis = os.getenv('TRAVIS') == 'true'
+
+ # Set of tests that we shouldn't run under Travis CI
+ skip_travis_tests = set(['basics/memoryerror.py'])
+
+ for test_file in tests:
+ if running_under_travis and test_file in skip_travis_tests:
+ print("skip ", test_file)
+ continue
+
+ # get expected output
+ test_file_expected = test_file + '.exp'
+ if os.path.isfile(test_file_expected):
+ # expected output given by a file, so read that in
+ with open(test_file_expected, 'rb') as f:
+ output_expected = f.read()
+ else:
+ # run CPython to work out expeceted output
+ try:
+ output_expected = subprocess.check_output([CPYTHON3, '-B', test_file])
+ except subprocess.CalledProcessError:
+ output_expected = b'CPYTHON3 CRASH'
+
+ # run Micro Python
+ if pyb is None:
+ # run on PC
+ try:
+ output_mupy = subprocess.check_output([MICROPYTHON, '-X', 'emit=bytecode', test_file])
+ except subprocess.CalledProcessError:
+ output_mupy = b'CRASH'
+ else:
+ # run on pyboard
+ pyb.enter_raw_repl()
+ try:
+ output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n')
+ except pyboard.PyboardError:
+ output_mupy = b'CRASH'
+
+ testcase_count += len(output_expected.splitlines())
+
+ test_basename = os.path.basename(test_file)
+ test_name = os.path.splitext(test_basename)[0]
+ filename_expected = test_basename + ".exp"
+ filename_mupy = test_basename + ".out"
+
+ if output_expected == output_mupy:
+ print("pass ", test_file)
+ passed_count += 1
+ rm_f(filename_expected)
+ rm_f(filename_mupy)
+ else:
+ with open(filename_expected, "w") as f:
+ f.write(str(output_expected, "ascii"))
+ with open(filename_mupy, "w") as f:
+ f.write(str(output_mupy, "ascii"))
+ print("FAIL ", test_file)
+ failed_tests.append(test_name)
+
+ test_count += 1
+
+ print("{} tests performed ({} individual testcases)".format(test_count, testcase_count))
+ print("{} tests passed".format(passed_count))
+
+ if len(failed_tests) > 0:
+ print("{} tests failed: {}".format(len(failed_tests), ' '.join(failed_tests)))
+ return False
+
+ # all tests succeeded
+ return True
+
+def main():
+ cmd_parser = argparse.ArgumentParser(description='Run tests for Micro Python.')
+ cmd_parser.add_argument('--pyboard', action='store_true', help='run the tests on the pyboard')
+ cmd_parser.add_argument('files', nargs='*', help='input test files')
+ args = cmd_parser.parse_args()
+
+ if args.pyboard:
+ import pyboard
+ pyb = pyboard.Pyboard('/dev/ttyACM0')
pyb.enter_raw_repl()
- try:
- output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n')
- except pyboard.PyboardError:
- output_mupy = b'CRASH'
else:
- try:
- output_mupy = subprocess.check_output([MICROPYTHON, '-X', 'emit=bytecode', test_file])
- except subprocess.CalledProcessError:
- output_mupy = b'CRASH'
-
- testcase_count += len(output_expected.splitlines())
-
- test_basename = os.path.basename(test_file)
- test_name = os.path.splitext(test_basename)[0]
- filename_expected = test_basename + ".exp"
- filename_mupy = test_basename + ".out"
-
- if output_expected == output_mupy:
- print("pass ", test_file)
- passed_count += 1
- rm_f(filename_expected)
- rm_f(filename_mupy)
+ pyb = None
+
+ if len(args.files) == 0:
+ if pyb is None:
+ # run PC tests
+ test_dirs = ('basics', 'float', 'import', 'io', 'misc')
+ else:
+ # run pyboard tests
+ test_dirs = ('basics', 'float', 'pyb')
+ tests = sorted(test_file for test_files in (glob('{}/*.py'.format(dir)) for dir in test_dirs) for test_file in test_files)
else:
- with open(filename_expected, "w") as f:
- f.write(str(output_expected, "ascii"))
- with open(filename_mupy, "w") as f:
- f.write(str(output_mupy, "ascii"))
- print("FAIL ", test_file)
- failed_tests.append(test_name)
-
- test_count += 1
+ # tests explicitly given
+ tests = args.files
-print("{} tests performed ({} individual testcases)".format(test_count, testcase_count))
-print("{} tests passed".format(passed_count))
+ if not run_tests(pyb, tests):
+ sys.exit(1)
-if len(failed_tests) > 0:
- print("{} tests failed: {}".format(len(failed_tests), ' '.join(failed_tests)))
- sys.exit(1)
+if __name__ == "__main__":
+ main()
diff --git a/tools/build-stm-latest.sh b/tools/build-stm-latest.sh
new file mode 100755
index 0000000000..f0d639d10f
--- /dev/null
+++ b/tools/build-stm-latest.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# check/get parameters
+if [ $# != 1 ]; then
+ echo "usage: $0 <dest-dir>"
+ exit 1
+fi
+
+dest_dir=$1
+
+# check we are in the correct directory
+if [ ! -r modpyb.c ]; then
+ echo "must be in stm directory"
+ exit 1
+fi
+
+# get the date
+date=$(date '+%Y-%m-%d')
+
+# get the git hash
+git_hash="$(git rev-parse --short HEAD 2> /dev/null || echo unknown)"
+
+# build the versions
+for board in PYBV3 PYBV10; do
+ echo $board
+ lower_board=$(echo $board | tr A-Z a-z)
+ build_dir=/tmp/stm-build-$board
+ make -B BOARD=$board BUILD=$build_dir || exit 1
+ mv $build_dir/firmware.dfu $dest_dir/$lower_board-$date-$git_hash.dfu
+ rm -rf $build_dir
+done
diff --git a/tools/pyboard.py b/tools/pyboard.py
index a44710914e..dce60350d0 100644
--- a/tools/pyboard.py
+++ b/tools/pyboard.py
@@ -9,7 +9,7 @@ Example usage:
import pyboard
pyb = pyboard.Pyboard('/dev/ttyACM0')
pyb.enter_raw_repl()
- pyb.exec('pyb.Led(1).on()')
+ pyb.exec('pyb.LED(1).on()')
pyb.exit_raw_repl()
To run a script from the local machine on the board and print out the results:
@@ -17,6 +17,10 @@ To run a script from the local machine on the board and print out the results:
import pyboard
pyboard.execfile('test.py', device='/dev/ttyACM0')
+This script can also be run directly. To execute a local script, use:
+
+ python pyboard.py test.py
+
"""
import time
@@ -50,6 +54,7 @@ class Pyboard:
return data
def enter_raw_repl(self):
+ self.serial.write(b'\r\x03') # ctrl-C: interrupt any running program
self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL
self.serial.write(b'\x04') # ctrl-D: soft reset
data = self.read_until(1, b'to exit\r\n>')
@@ -110,18 +115,19 @@ def run_test():
pyb.exec('def apply(l, f):\r\n for item in l:\r\n f(item)\r\n')
- pyb.exec('leds=[pyb.Led(l) for l in range(1, 5)]')
+ pyb.exec('leds=[pyb.LED(l) for l in range(1, 5)]')
pyb.exec('apply(leds, lambda l:l.off())')
## USR switch test
- if True:
- for i in range(2):
- print("press USR button")
- pyb.exec('while pyb.switch(): pyb.delay(10)')
- pyb.exec('while not pyb.switch(): pyb.delay(10)')
+ pyb.exec('switch = pyb.Switch()')
+
+ for i in range(2):
+ print("press USR button")
+ pyb.exec('while switch(): pyb.delay(10)')
+ pyb.exec('while not switch(): pyb.delay(10)')
- print('USR switch passed')
+ print('USR switch passed')
## accel test
@@ -155,5 +161,19 @@ def run_test():
pyb.exit_raw_repl()
pyb.close()
+def main():
+ import argparse
+ cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.')
+ cmd_parser.add_argument('--device', default='/dev/ttyACM0', help='the serial device of the pyboard')
+ cmd_parser.add_argument('--test', action='store_true', help='run a small test suite on the pyboard')
+ cmd_parser.add_argument('files', nargs='*', help='input files')
+ args = cmd_parser.parse_args()
+
+ if args.test:
+ run_test()
+
+ for file in args.files:
+ execfile(file, device=args.device)
+
if __name__ == "__main__":
- run_test()
+ main()
diff --git a/unix-cpy/main.c b/unix-cpy/main.c
index 6cdd72c5da..3f42398f59 100644
--- a/unix-cpy/main.c
+++ b/unix-cpy/main.c
@@ -3,9 +3,9 @@
#include <stdio.h>
#include <string.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "lexer.h"
#include "lexerunix.h"
diff --git a/unix/file.c b/unix/file.c
index 041e28e956..2b7e1a04f1 100644
--- a/unix/file.c
+++ b/unix/file.c
@@ -5,9 +5,9 @@
#include <sys/stat.h>
#include <sys/types.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -18,6 +18,16 @@ typedef struct _mp_obj_fdfile_t {
int fd;
} mp_obj_fdfile_t;
+#ifdef MICROPY_CPYTHON_COMPAT
+void check_fd_is_open(const mp_obj_fdfile_t *o) {
+ if (o->fd < 0) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "I/O operation on closed file"));
+ }
+}
+#else
+#define check_fd_is_open(o)
+#endif
+
STATIC const mp_obj_type_t rawfile_type;
STATIC void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
@@ -27,6 +37,7 @@ STATIC void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *e
STATIC machine_int_t fdfile_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) {
mp_obj_fdfile_t *o = o_in;
+ check_fd_is_open(o);
machine_int_t r = read(o->fd, buf, size);
if (r == -1) {
*errcode = errno;
@@ -36,6 +47,7 @@ STATIC machine_int_t fdfile_read(mp_obj_t o_in, void *buf, machine_uint_t size,
STATIC machine_int_t fdfile_write(mp_obj_t o_in, const void *buf, machine_uint_t size, int *errcode) {
mp_obj_fdfile_t *o = o_in;
+ check_fd_is_open(o);
machine_int_t r = write(o->fd, buf, size);
if (r == -1) {
*errcode = errno;
@@ -46,6 +58,9 @@ STATIC machine_int_t fdfile_write(mp_obj_t o_in, const void *buf, machine_uint_t
STATIC mp_obj_t fdfile_close(mp_obj_t self_in) {
mp_obj_fdfile_t *self = self_in;
close(self->fd);
+#ifdef MICROPY_CPYTHON_COMPAT
+ self->fd = -1;
+#endif
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_close_obj, fdfile_close);
@@ -57,6 +72,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fdfile___exit___obj, 4, 4, fdfile___e
STATIC mp_obj_t fdfile_fileno(mp_obj_t self_in) {
mp_obj_fdfile_t *self = self_in;
+ check_fd_is_open(self);
return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->fd);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno);
@@ -116,6 +132,7 @@ STATIC const mp_map_elem_t rawfile_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readlines), (mp_obj_t)&mp_stream_unbuffered_readlines_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&fdfile_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },
diff --git a/unix/main.c b/unix/main.c
index 4c86edeae5..6354184fdc 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -8,9 +8,9 @@
#include <sys/types.h>
#include <errno.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "lexer.h"
#include "lexerunix.h"
@@ -142,7 +142,7 @@ STATIC char *prompt(char *p) {
}
STATIC void do_repl(void) {
- printf("Micro Python build " MICROPY_GIT_HASH " on " MICROPY_BUILD_DATE "; UNIX version\n");
+ printf("Micro Python " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; UNIX version\n");
for (;;) {
char *line = prompt(">>> ");
@@ -394,11 +394,7 @@ int main(int argc, char **argv) {
return usage(argv);
}
} else {
-#ifdef __MINGW32__
- char *basedir = _fullpath(NULL, argv[a], _MAX_PATH);
-#else
char *basedir = realpath(argv[a], NULL);
-#endif
if (basedir == NULL) {
fprintf(stderr, "%s: can't open file '%s': [Errno %d] ", argv[0], argv[1], errno);
perror("");
diff --git a/unix/modffi.c b/unix/modffi.c
index be542625ed..39551c264f 100644
--- a/unix/modffi.c
+++ b/unix/modffi.c
@@ -4,9 +4,9 @@
#include <dlfcn.h>
#include <ffi.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/unix/modsocket.c b/unix/modsocket.c
index e52f5d92a9..898d5bfe9f 100644
--- a/unix/modsocket.c
+++ b/unix/modsocket.c
@@ -11,9 +11,9 @@
#include <netdb.h>
#include <errno.h>
+#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "objtuple.h"
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index 2d252427f0..b777cfbe31 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -16,6 +16,9 @@
#define MICROPY_USE_COMPUTED_GOTO (1)
#define MICROPY_MOD_SYS_STDFILES (1)
#define MICROPY_ENABLE_MOD_CMATH (1)
+// Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc.
+// names in exception messages (may require more RAM).
+#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED)
extern const struct _mp_obj_module_t mp_module_time;
extern const struct _mp_obj_module_t mp_module_socket;
diff --git a/windows/Makefile b/windows/Makefile
index 2f5418886f..ce75a60985 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -30,6 +30,8 @@ endif
SRC_C = \
unix/main.c \
unix/file.c \
+ realpath.c \
+ init.c \
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
diff --git a/windows/alloca.h b/windows/alloca.h
new file mode 100644
index 0000000000..1cf7722669
--- /dev/null
+++ b/windows/alloca.h
@@ -0,0 +1,3 @@
+// Compatibility header to workaround lack of native alloca.h in some
+// Windows toolchains.
+#include <malloc.h>
diff --git a/windows/init.c b/windows/init.c
new file mode 100644
index 0000000000..78b8738f77
--- /dev/null
+++ b/windows/init.c
@@ -0,0 +1,5 @@
+#include <stdlib.h>
+
+void init() {
+ putenv("PRINTF_EXPONENT_DIGITS=2");
+}
diff --git a/windows/init.h b/windows/init.h
new file mode 100644
index 0000000000..70e535e495
--- /dev/null
+++ b/windows/init.h
@@ -0,0 +1 @@
+void init(void);
diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h
index 993fef9d59..94b3334007 100644
--- a/windows/mpconfigport.h
+++ b/windows/mpconfigport.h
@@ -12,8 +12,10 @@
#define MICROPY_DEBUG_PRINTERS (1)
#define MICROPY_ENABLE_REPL_HELPERS (1)
#define MICROPY_ENABLE_LEXER_UNIX (1)
+#define MICROPY_MOD_SYS_STDFILES (1)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
+#define MICROPY_PORT_INIT_FUNC init()
// type definitions for the specific machine
@@ -33,3 +35,8 @@ typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
extern const struct _mp_obj_fun_native_t mp_builtin_open_obj;
+#define MICROPY_EXTRA_BUILTINS \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
+
+#include "realpath.h"
+#include "init.h"
diff --git a/windows/realpath.c b/windows/realpath.c
new file mode 100644
index 0000000000..550298a7d5
--- /dev/null
+++ b/windows/realpath.c
@@ -0,0 +1,42 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <io.h>
+
+#ifndef R_OK
+ #define R_OK 4
+#endif
+
+// Make sure a path only has forward slashes.
+char *to_unix_path(char *p) {
+ if (p != NULL) {
+ char *pp = p;
+ while (*pp != 0) {
+ if (*pp == '\\')
+ *pp = '/';
+ ++pp;
+ }
+ }
+ return p;
+}
+
+// Implement realpath() using _fullpath and make it use the same error codes as realpath() on unix.
+// Also have it return a path with forward slashes only as some code relies on this,
+// but _fullpath() returns backward slashes no matter what.
+char *realpath(const char *path, char *resolved_path) {
+ char *ret = NULL;
+ if (path == NULL) {
+ errno = EINVAL;
+ } else if (access(path, R_OK) == 0) {
+ ret = resolved_path;
+ if (ret == NULL)
+ ret = malloc(_MAX_PATH);
+ if (ret == NULL) {
+ errno = ENOMEM;
+ } else {
+ ret = _fullpath(ret, path, _MAX_PATH);
+ if (ret == NULL)
+ errno = EIO;
+ }
+ }
+ return to_unix_path(ret);
+}
diff --git a/windows/realpath.h b/windows/realpath.h
new file mode 100644
index 0000000000..77798acd57
--- /dev/null
+++ b/windows/realpath.h
@@ -0,0 +1,2 @@
+
+extern char *realpath(const char *path, char *resolved_path);