summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/builtin.h1
-rw-r--r--py/builtintables.c3
-rw-r--r--py/mkenv.mk2
-rw-r--r--py/modcmath.c131
-rw-r--r--py/modmath.c9
-rw-r--r--py/mpconfig.h12
-rw-r--r--py/nlr.h20
-rw-r--r--py/nlrsetjmp.c16
-rw-r--r--py/py.mk2
-rw-r--r--py/qstrdefs.h9
-rw-r--r--py/runtime.c5
-rw-r--r--py/vm.c66
-rw-r--r--stmhal/Makefile2
-rw-r--r--stmhal/flash.c77
-rw-r--r--stmhal/flash.h1
-rw-r--r--stmhal/main.c36
-rw-r--r--stmhal/malloc0.c37
-rw-r--r--stmhal/math.c81
-rw-r--r--stmhal/mathsincos.c601
-rw-r--r--stmhal/pybstdio.c4
-rw-r--r--stmhal/pyexec.c1
-rw-r--r--stmhal/std.h2
-rw-r--r--stmhal/stm32f4xx_it.c48
-rw-r--r--stmhal/storage.c77
-rw-r--r--stmhal/storage.h2
-rw-r--r--stmhal/timer.c15
-rw-r--r--stmhal/usbd_cdc_interface.c26
-rw-r--r--stmhal/usbd_desc_cdc_msc.c18
-rw-r--r--stmhal/usbd_msc_storage.c16
-rw-r--r--stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h6
-rw-r--r--stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c3
-rw-r--r--stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c1
-rw-r--r--tests/README4
-rw-r--r--tests/basics/fun-callstar.py2
-rw-r--r--tests/basics/fun-defargs.py2
-rw-r--r--tests/basics/int-divzero.py5
-rw-r--r--tests/basics/list1.py5
-rw-r--r--tests/basics/modulo.py17
-rw-r--r--tests/basics/string-format-modulo.py14
-rw-r--r--tests/basics/string-format.py87
-rw-r--r--tests/basics/true-value.py6
-rw-r--r--tests/basics/types1.py6
-rw-r--r--tests/basics/types2.py4
-rw-r--r--tests/float/float1.py (renamed from tests/basics/float1.py)0
-rw-r--r--tests/float/int-divzero.py4
-rw-r--r--tests/float/list-index.py8
-rw-r--r--tests/float/math-fun-bool.py (renamed from tests/basics/math-fun-bool.py)0
-rw-r--r--tests/float/math-fun.py (renamed from tests/basics/math-fun.py)0
-rw-r--r--tests/float/modulo.py14
-rw-r--r--tests/float/string-format-modulo.py16
-rw-r--r--tests/float/string-format.py123
-rw-r--r--tests/float/true-value.py7
-rw-r--r--tests/float/types.py17
-rw-r--r--tests/import/import-pkg1.py (renamed from tests/basics/import-pkg1.py)0
-rw-r--r--tests/import/import-pkg2.py (renamed from tests/basics/import-pkg2.py)0
-rw-r--r--tests/import/import-pkg3.py (renamed from tests/basics/import-pkg3.py)0
-rw-r--r--tests/import/import-pkg4.py (renamed from tests/basics/import-pkg4.py)0
-rw-r--r--tests/import/import-pkg5.py (renamed from tests/basics/import-pkg5.py)0
-rw-r--r--tests/import/import1a.py (renamed from tests/basics/import1a.py)0
-rw-r--r--tests/import/import1b.py (renamed from tests/basics/import1b.py)0
-rw-r--r--tests/import/import2a.py (renamed from tests/basics/import2a.py)0
-rw-r--r--tests/import/import3a.py (renamed from tests/basics/import3a.py)0
-rw-r--r--tests/import/pkg/__init__.py (renamed from tests/basics/pkg/__init__.py)0
-rw-r--r--tests/import/pkg/mod.py (renamed from tests/basics/pkg/mod.py)0
-rw-r--r--tests/import/pkg2/__init__.py (renamed from tests/basics/pkg2/__init__.py)0
-rw-r--r--tests/import/pkg2/mod1.py (renamed from tests/basics/pkg2/mod1.py)0
-rw-r--r--tests/import/pkg2/mod2.py (renamed from tests/basics/pkg2/mod2.py)0
-rw-r--r--tests/import/pkg3/__init__.py (renamed from tests/basics/pkg3/__init__.py)0
-rw-r--r--tests/import/pkg3/mod1.py (renamed from tests/basics/pkg3/mod1.py)0
-rw-r--r--tests/import/pkg3/mod2.py (renamed from tests/basics/pkg3/mod2.py)0
-rw-r--r--tests/import/pkg3/subpkg1/__init__.py (renamed from tests/basics/pkg3/subpkg1/__init__.py)0
-rw-r--r--tests/import/pkg3/subpkg1/mod1.py (renamed from tests/basics/pkg3/subpkg1/mod1.py)0
-rw-r--r--tests/import/try-module.py (renamed from tests/basics/try-module.py)0
-rwxr-xr-xtests/run-tests19
-rw-r--r--unix/Makefile5
-rw-r--r--unix/modffi.c10
-rw-r--r--unix/mpconfigport.h2
77 files changed, 1394 insertions, 313 deletions
diff --git a/py/builtin.h b/py/builtin.h
index 36b9f38814..9b2b9c9424 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -48,6 +48,7 @@ extern const mp_obj_module_t mp_module_array;
extern const mp_obj_module_t mp_module_collections;
extern const mp_obj_module_t mp_module_io;
extern const mp_obj_module_t mp_module_math;
+extern const mp_obj_module_t mp_module_cmath;
extern const mp_obj_module_t mp_module_micropython;
extern const mp_obj_module_t mp_module_struct;
extern const mp_obj_module_t mp_module_sys;
diff --git a/py/builtintables.c b/py/builtintables.c
index 6bdae24002..c4c96ed35a 100644
--- a/py/builtintables.c
+++ b/py/builtintables.c
@@ -139,6 +139,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
#if MICROPY_ENABLE_FLOAT
{ MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&mp_module_math },
+#if MICROPY_ENABLE_MOD_CMATH
+ { MP_OBJ_NEW_QSTR(MP_QSTR_cmath), (mp_obj_t)&mp_module_cmath },
+#endif
#endif
#if MICROPY_ENABLE_MOD_SYS
{ MP_OBJ_NEW_QSTR(MP_QSTR_sys), (mp_obj_t)&mp_module_sys },
diff --git a/py/mkenv.mk b/py/mkenv.mk
index 8ae54f06bb..4bc71edd78 100644
--- a/py/mkenv.mk
+++ b/py/mkenv.mk
@@ -54,4 +54,6 @@ STRIP = $(CROSS_COMPILE)strip
all:
.PHONY: all
+.DELETE_ON_ERROR:
+
MKENV_INCLUDED = 1
diff --git a/py/modcmath.c b/py/modcmath.c
new file mode 100644
index 0000000000..3f561e7f30
--- /dev/null
+++ b/py/modcmath.c
@@ -0,0 +1,131 @@
+#include <math.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "builtin.h"
+
+#if MICROPY_ENABLE_FLOAT && MICROPY_ENABLE_MOD_CMATH
+
+// These are defined in modmath.c
+extern const mp_obj_float_t mp_math_e_obj;
+extern const mp_obj_float_t mp_math_pi_obj;
+
+mp_obj_t mp_cmath_phase(mp_obj_t z_obj) {
+ mp_float_t real, imag;
+ mp_obj_get_complex(z_obj, &real, &imag);
+ return mp_obj_new_float(MICROPY_FLOAT_C_FUN(atan2)(imag, real));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_phase_obj, mp_cmath_phase);
+
+mp_obj_t mp_cmath_polar(mp_obj_t z_obj) {
+ mp_float_t real, imag;
+ mp_obj_get_complex(z_obj, &real, &imag);
+ mp_obj_t tuple[2] = {
+ mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag)),
+ mp_obj_new_float(MICROPY_FLOAT_C_FUN(atan2)(imag, real)),
+ };
+ return mp_obj_new_tuple(2, tuple);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_polar_obj, mp_cmath_polar);
+
+mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) {
+ mp_float_t r = mp_obj_get_float(r_obj);
+ mp_float_t phi = mp_obj_get_float(phi_obj);
+ return mp_obj_new_complex(r * MICROPY_FLOAT_C_FUN(cos)(phi), r * MICROPY_FLOAT_C_FUN(sin)(phi));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_cmath_rect_obj, mp_cmath_rect);
+
+mp_obj_t mp_cmath_exp(mp_obj_t z_obj) {
+ mp_float_t real, imag;
+ mp_obj_get_complex(z_obj, &real, &imag);
+ mp_float_t exp_real = MICROPY_FLOAT_C_FUN(exp)(real);
+ return mp_obj_new_complex(exp_real * MICROPY_FLOAT_C_FUN(cos)(imag), exp_real * MICROPY_FLOAT_C_FUN(sin)(imag));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_exp_obj, mp_cmath_exp);
+
+// TODO can take second argument, being the base
+mp_obj_t mp_cmath_log(mp_obj_t z_obj) {
+ mp_float_t real, imag;
+ mp_obj_get_complex(z_obj, &real, &imag);
+ return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log)(real*real + imag*imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log);
+
+mp_obj_t mp_cmath_log10(mp_obj_t z_obj) {
+ mp_float_t real, imag;
+ mp_obj_get_complex(z_obj, &real, &imag);
+ return mp_obj_new_complex(0.5 * MICROPY_FLOAT_C_FUN(log10)(real*real + imag*imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10);
+
+mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) {
+ mp_float_t real, imag;
+ 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));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt);
+
+mp_obj_t mp_cmath_cos(mp_obj_t z_obj) {
+ mp_float_t real, imag;
+ mp_obj_get_complex(z_obj, &real, &imag);
+ return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), -MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_cos_obj, mp_cmath_cos);
+
+mp_obj_t mp_cmath_sin(mp_obj_t z_obj) {
+ mp_float_t real, imag;
+ mp_obj_get_complex(z_obj, &real, &imag);
+ return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sin_obj, mp_cmath_sin);
+
+STATIC const mp_map_elem_t mp_module_cmath_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_cmath) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_e), (mp_obj_t)&mp_math_e_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pi), (mp_obj_t)&mp_math_pi_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_phase), (mp_obj_t)&mp_cmath_phase_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_polar), (mp_obj_t)&mp_cmath_polar_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rect), (mp_obj_t)&mp_cmath_rect_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_exp), (mp_obj_t)&mp_cmath_exp_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_log), (mp_obj_t)&mp_cmath_log_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_log10), (mp_obj_t)&mp_cmath_log10_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sqrt), (mp_obj_t)&mp_cmath_sqrt_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_acos), (mp_obj_t)&mp_cmath_acos_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_asin), (mp_obj_t)&mp_cmath_asin_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_atan), (mp_obj_t)&mp_cmath_atan_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_cos), (mp_obj_t)&mp_cmath_cos_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sin), (mp_obj_t)&mp_cmath_sin_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_tan), (mp_obj_t)&mp_cmath_tan_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_acosh), (mp_obj_t)&mp_cmath_acosh_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_asinh), (mp_obj_t)&mp_cmath_asinh_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_atanh), (mp_obj_t)&mp_cmath_atanh_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_cosh), (mp_obj_t)&mp_cmath_cosh_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_sinh), (mp_obj_t)&mp_cmath_sinh_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_tanh), (mp_obj_t)&mp_cmath_tanh_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_isfinite), (mp_obj_t)&mp_cmath_isfinite_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_isinf), (mp_obj_t)&mp_cmath_isinf_obj },
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_isnan), (mp_obj_t)&mp_cmath_isnan_obj },
+};
+
+STATIC const mp_obj_dict_t mp_module_cmath_globals = {
+ .base = {&mp_type_dict},
+ .map = {
+ .all_keys_are_qstrs = 1,
+ .table_is_fixed_array = 1,
+ .used = sizeof(mp_module_cmath_globals_table) / sizeof(mp_map_elem_t),
+ .alloc = sizeof(mp_module_cmath_globals_table) / sizeof(mp_map_elem_t),
+ .table = (mp_map_elem_t*)mp_module_cmath_globals_table,
+ },
+};
+
+const mp_obj_module_t mp_module_cmath = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_cmath,
+ .globals = (mp_obj_dict_t*)&mp_module_cmath_globals,
+};
+
+#endif // MICROPY_ENABLE_FLOAT && MICROPY_ENABLE_MOD_CMATH
diff --git a/py/modmath.c b/py/modmath.c
index c26ba16189..09bb4ce3aa 100644
--- a/py/modmath.c
+++ b/py/modmath.c
@@ -6,7 +6,7 @@
#include "obj.h"
#include "builtin.h"
-#if MICROPY_ENABLE_FLOAT
+#if MICROPY_ENABLE_FLOAT && MICROPY_ENABLE_MOD_MATH
//TODO: Change macros to check for overflow and raise OverflowError or RangeError
#define MATH_FUN_1(py_name, c_name) \
@@ -25,8 +25,9 @@
mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int((machine_int_t)MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
-STATIC const mp_obj_float_t mp_math_e_obj = {{&mp_type_float}, M_E};
-STATIC const mp_obj_float_t mp_math_pi_obj = {{&mp_type_float}, M_PI};
+// These are also used by cmath.c
+const mp_obj_float_t mp_math_e_obj = {{&mp_type_float}, M_E};
+const mp_obj_float_t mp_math_pi_obj = {{&mp_type_float}, M_PI};
MATH_FUN_1(sqrt, sqrt)
MATH_FUN_2(pow, pow)
@@ -156,4 +157,4 @@ const mp_obj_module_t mp_module_math = {
.globals = (mp_obj_dict_t*)&mp_module_math_globals,
};
-#endif // MICROPY_ENABLE_FLOAT
+#endif // MICROPY_ENABLE_FLOAT && MICROPY_ENABLE_MOD_MATH
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 7fd7067953..43c931cd66 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -110,6 +110,16 @@ typedef double mp_float_t;
#define MICROPY_ENABLE_FLOAT (0)
#endif
+// Whether to provide "math" module
+#ifndef MICROPY_ENABLE_MOD_MATH
+#define MICROPY_ENABLE_MOD_MATH (1)
+#endif
+
+// Whether to provide "cmath" module
+#ifndef MICROPY_ENABLE_MOD_CMATH
+#define MICROPY_ENABLE_MOD_CMATH (0)
+#endif
+
// Whether to provide "io" module
#ifndef MICROPY_ENABLE_MOD_IO
#define MICROPY_ENABLE_MOD_IO (1)
@@ -137,7 +147,7 @@ typedef double mp_float_t;
// Whether to support the property object
#ifndef MICROPY_ENABLE_PROPERTY
-#define MICROPY_ENABLE_PROPERTY (0)
+#define MICROPY_ENABLE_PROPERTY (1)
#endif
// Enable features which improve CPython compatibility
diff --git a/py/nlr.h b/py/nlr.h
index 4e931919db..05fe63d22d 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -2,12 +2,14 @@
// exception handling, basically a stack of setjmp/longjmp buffers
#include <limits.h>
+#include <setjmp.h>
typedef struct _nlr_buf_t nlr_buf_t;
struct _nlr_buf_t {
// the entries here must all be machine word size
nlr_buf_t *prev;
void *ret_val;
+#if !MICROPY_NLR_SETJMP
#if defined(__i386__)
void *regs[6];
#elif defined(__x86_64__)
@@ -19,13 +21,29 @@ struct _nlr_buf_t {
#elif defined(__thumb2__)
void *regs[10];
#else
-#error Unknown arch in nlr.h
+ #define MICROPY_NLR_SETJMP (1)
+ #warning "No native NLR support for this arch, using setjmp implementation"
+#endif
+#endif
+
+#if MICROPY_NLR_SETJMP
+ jmp_buf jmpbuf;
#endif
};
+#if MICROPY_NLR_SETJMP
+extern nlr_buf_t *nlr_setjmp_top;
+void nlr_setjmp_jump(void *val) __attribute__((noreturn));
+// nlr_push() must be defined as a macro, because "The stack context will be
+// invalidated if the function which called setjmp() returns."
+#define nlr_push(buf) ((buf)->prev = nlr_setjmp_top, nlr_setjmp_top = (buf), setjmp((buf)->jmpbuf))
+#define nlr_pop() { nlr_setjmp_top = nlr_setjmp_top->prev; }
+#define nlr_jump(val) nlr_setjmp_jump(val)
+#else
unsigned int nlr_push(nlr_buf_t *);
void nlr_pop(void);
void nlr_jump(void *val) __attribute__((noreturn));
+#endif
// This must be implemented by a port. It's called by nlr_jump
// if no nlr buf has been pushed. It must not return, but rather
diff --git a/py/nlrsetjmp.c b/py/nlrsetjmp.c
new file mode 100644
index 0000000000..a97c8634b2
--- /dev/null
+++ b/py/nlrsetjmp.c
@@ -0,0 +1,16 @@
+#include <setjmp.h>
+#include <stdio.h>
+#include "nlr.h"
+
+#if MICROPY_NLR_SETJMP
+
+nlr_buf_t *nlr_setjmp_top;
+
+void nlr_setjmp_jump(void *val) {
+ nlr_buf_t *buf = nlr_setjmp_top;
+ nlr_setjmp_top = buf->prev;
+ buf->ret_val = val;
+ longjmp(buf->jmpbuf, 1);
+}
+
+#endif
diff --git a/py/py.mk b/py/py.mk
index c86f84910d..01a5fd1c2b 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -15,6 +15,7 @@ PY_O_BASENAME = \
nlrx86.o \
nlrx64.o \
nlrthumb.o \
+ nlrsetjmp.o \
malloc.o \
gc.o \
qstr.o \
@@ -87,6 +88,7 @@ PY_O_BASENAME = \
modcollections.o \
modio.o \
modmath.o \
+ modcmath.o \
modmicropython.o \
modstruct.o \
modsys.o \
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 20c4db75f0..a4df86fda7 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -217,6 +217,7 @@ Q(iterator)
Q(module)
Q(slice)
+#if MICROPY_ENABLE_MOD_MATH || MICROPY_ENABLE_MOD_CMATH
Q(math)
Q(e)
Q(pi)
@@ -258,6 +259,14 @@ Q(erf)
Q(erfc)
Q(gamma)
Q(lgamma)
+#endif
+
+#if MICROPY_ENABLE_MOD_CMATH
+Q(cmath)
+Q(phase)
+Q(polar)
+Q(rect)
+#endif
Q(mem_total)
Q(mem_current)
diff --git a/py/runtime.c b/py/runtime.c
index a507f97f36..98b2d076ec 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -365,7 +365,8 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
case MP_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); break;
case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); break;
- default: assert(0);
+ default:
+ goto unsupported_op;
}
// TODO: We just should make mp_obj_new_int() inline and use that
if (MP_OBJ_FITS_SMALL_INT(lhs_val)) {
@@ -437,9 +438,7 @@ generic_binary_op:
// TODO implement dispatch for reverse binary ops
// TODO specify in error message what the operator is
-#if MICROPY_ENABLE_FLOAT
unsupported_op:
-#endif
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"unsupported operand types for binary operator: '%s', '%s'",
mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));
diff --git a/py/vm.c b/py/vm.c
index 1c154007ca..e42e54941e 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -165,8 +165,6 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
mp_obj_t *fastn, mp_obj_t **sp_in_out,
mp_exc_stack_t *exc_stack, mp_exc_stack_t **exc_sp_in_out,
volatile mp_obj_t inject_exc) {
- // careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
-
#if MICROPY_USE_COMPUTED_GOTOS
#include "vmentrytable.h"
#define DISPATCH() do { \
@@ -182,32 +180,43 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
#define ENTRY_DEFAULT default
#endif
- int op = 0;
- const byte *ip = *ip_in_out;
- mp_obj_t *sp = *sp_in_out;
- machine_uint_t unum;
- qstr qst;
- mp_obj_t obj1, obj2;
- nlr_buf_t nlr;
+ // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
+ // sees that it's possible for us to jump from the dispatch loop to the exception
+ // handler. Without this, the code may have a different stack layout in the dispatch
+ // loop and the exception handler, leading to very obscure bugs.
+ #define RAISE(o) do { nlr_pop(); nlr.ret_val = o; goto exception_handler; } while(0)
+ // variables that are visible to the exception handler (declared volatile)
volatile bool currently_in_except_block = MP_TAGPTR_TAG(*exc_sp_in_out); // 0 or 1, to detect nested exceptions
mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(*exc_sp_in_out); // stack grows up, exc_sp points to top of stack
- const byte *volatile save_ip = ip; // this is so we can access ip in the exception handler without making ip volatile (which means the compiler can't keep it in a register in the main loop)
+ const byte *volatile save_ip = *ip_in_out; // this is so we can access ip in the exception handler without making ip volatile (which means the compiler can't keep it in a register in the main loop)
+ mp_obj_t *volatile save_sp = *sp_in_out; // this is so we can access sp in the exception handler when needed
// outer exception handling loop
for (;;) {
+ nlr_buf_t nlr;
outer_dispatch_loop:
if (nlr_push(&nlr) == 0) {
+ // local variables that are not visible to the exception handler
+ byte op = 0;
+ const byte *ip = *ip_in_out;
+ mp_obj_t *sp = *sp_in_out;
+ machine_uint_t unum;
+ qstr qst;
+ mp_obj_t obj1, obj2;
+
// If we have exception to inject, now that we finish setting up
// execution context, raise it. This works as if RAISE_VARARGS
// bytecode was executed.
// Injecting exc into yield from generator is a special case,
// handled by MP_BC_YIELD_FROM itself
if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
- mp_obj_t t = inject_exc;
+ obj1 = inject_exc;
inject_exc = MP_OBJ_NULL;
- nlr_raise(mp_make_raise_obj(t));
+ obj1 = mp_make_raise_obj(obj1);
+ RAISE(obj1);
}
+
// loop to execute byte code
for (;;) {
dispatch_loop:
@@ -297,7 +306,8 @@ dispatch_loop:
load_check:
if (obj1 == MP_OBJ_NULL) {
local_name_error:
- nlr_raise(mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment"));
+ obj1 = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
+ RAISE(obj1);
}
PUSH(obj1);
DISPATCH();
@@ -580,7 +590,7 @@ unwind_jump:
// if TOS is an integer, does something else
// else error
if (mp_obj_is_exception_type(TOP())) {
- nlr_raise(sp[-1]);
+ RAISE(sp[-1]);
}
if (TOP() == mp_const_none) {
sp--;
@@ -606,6 +616,7 @@ unwind_jump:
ENTRY(MP_BC_FOR_ITER):
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
+ save_sp = sp;
obj1 = mp_iternext_allow_raise(TOP());
if (obj1 == MP_OBJ_NULL) {
--sp; // pop the exhausted iterator
@@ -829,12 +840,14 @@ unwind_return:
}
}
if (obj1 == MP_OBJ_NULL) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise"));
+ obj1 = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
+ RAISE(obj1);
}
} else {
obj1 = POP();
}
- nlr_raise(mp_make_raise_obj(obj1));
+ obj1 = mp_make_raise_obj(obj1);
+ RAISE(obj1);
ENTRY(MP_BC_YIELD_VALUE):
yield:
@@ -847,7 +860,7 @@ yield:
ENTRY(MP_BC_YIELD_FROM): {
//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
-#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { nlr_raise(t); }
+#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { RAISE(t); }
mp_vm_return_kind_t ret_kind;
obj1 = POP();
mp_obj_t t_exc = MP_OBJ_NULL;
@@ -890,7 +903,7 @@ yield:
GENERATOR_EXIT_IF_NEEDED(t_exc);
DISPATCH();
} else {
- nlr_raise(obj2);
+ RAISE(obj2);
}
}
}
@@ -912,25 +925,27 @@ yield:
DISPATCH();
ENTRY_DEFAULT:
- printf("code %p, byte code 0x%02x not implemented\n", ip, op);
obj1 = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
nlr_pop();
fastn[0] = obj1;
return MP_VM_RETURN_EXCEPTION;
+
#if !MICROPY_USE_COMPUTED_GOTOS
} // switch
#endif
- }
+ } // for loop
} else {
+exception_handler:
// exception occurred
// check if it's a StopIteration within a for block
if (*save_ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
- ip = save_ip + 1;
+ const byte *ip = save_ip + 1;
+ machine_uint_t unum;
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
- --sp; // pop the exhausted iterator
- ip += unum; // jump to after for-block
+ *ip_in_out = ip + unum; // jump to after for-block
+ *sp_in_out = save_sp - 1; // pop the exhausted iterator
goto outer_dispatch_loop; // continue with dispatch loop
}
@@ -969,14 +984,15 @@ yield:
currently_in_except_block = 1;
// catch exception and pass to byte code
- sp = MP_TAGPTR_PTR(exc_sp->val_sp);
- ip = exc_sp->handler;
+ *ip_in_out = exc_sp->handler;
+ mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
// save this exception in the stack so it can be used in a reraise, if needed
exc_sp->prev_exc = nlr.ret_val;
// push(traceback, exc-val, exc-type)
PUSH(mp_const_none);
PUSH(nlr.ret_val);
PUSH(mp_obj_get_type(nlr.ret_val));
+ *sp_in_out = sp;
} else {
// propagate exception to higher level
diff --git a/stmhal/Makefile b/stmhal/Makefile
index aa4f4f3e8d..27caaca016 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -71,7 +71,7 @@ SRC_C = \
usb.c \
printf.c \
math.c \
- malloc0.c \
+ mathsincos.c \
gccollect.c \
pybstdio.c \
readline.c \
diff --git a/stmhal/flash.c b/stmhal/flash.c
index 6ed3b04324..ce16fe271b 100644
--- a/stmhal/flash.c
+++ b/stmhal/flash.c
@@ -49,7 +49,81 @@ uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *si
return 0;
}
+void flash_erase(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
+ // check there is something to write
+ if (num_word32 == 0) {
+ return;
+ }
+
+ // unlock
+ HAL_FLASH_Unlock();
+
+ // Clear pending flags (if any)
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
+ FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
+
+ // erase the sector(s)
+ FLASH_EraseInitTypeDef EraseInitStruct;
+ EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
+ EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V
+ EraseInitStruct.Sector = flash_get_sector_info(flash_dest, NULL, NULL);
+ EraseInitStruct.NbSectors = flash_get_sector_info(flash_dest + 4 * num_word32 - 1, NULL, NULL) - EraseInitStruct.Sector + 1;
+ uint32_t SectorError = 0;
+ if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
+ // error occurred during sector erase
+ HAL_FLASH_Lock(); // lock the flash
+ return;
+ }
+}
+
+/*
+// erase the sector using an interrupt
+void flash_erase_it(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
+ // check there is something to write
+ if (num_word32 == 0) {
+ return;
+ }
+
+ // unlock
+ HAL_FLASH_Unlock();
+
+ // Clear pending flags (if any)
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
+ FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
+
+ // erase the sector(s)
+ FLASH_EraseInitTypeDef EraseInitStruct;
+ EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
+ EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V
+ EraseInitStruct.Sector = flash_get_sector_info(flash_dest, NULL, NULL);
+ EraseInitStruct.NbSectors = flash_get_sector_info(flash_dest + 4 * num_word32 - 1, NULL, NULL) - EraseInitStruct.Sector + 1;
+ if (HAL_FLASHEx_Erase_IT(&EraseInitStruct) != HAL_OK) {
+ // error occurred during sector erase
+ HAL_FLASH_Lock(); // lock the flash
+ return;
+ }
+}
+*/
+
void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
+ // program the flash word by word
+ for (int i = 0; i < num_word32; i++) {
+ if (HAL_FLASH_Program(TYPEPROGRAM_WORD, flash_dest, *src) != HAL_OK) {
+ // error occurred during flash write
+ HAL_FLASH_Lock(); // lock the flash
+ return;
+ }
+ flash_dest += 4;
+ src += 1;
+ }
+
+ // lock the flash
+ HAL_FLASH_Lock();
+}
+
+/*
+ use erase, then write
+void flash_erase_and_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
// check there is something to write
if (num_word32 == 0) {
return;
@@ -71,6 +145,7 @@ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32)
uint32_t SectorError = 0;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
// error occurred during sector erase
+ HAL_FLASH_Lock(); // lock the flash
return;
}
@@ -78,6 +153,7 @@ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32)
for (int i = 0; i < num_word32; i++) {
if (HAL_FLASH_Program(TYPEPROGRAM_WORD, flash_dest, *src) != HAL_OK) {
// error occurred during flash write
+ HAL_FLASH_Lock(); // lock the flash
return;
}
flash_dest += 4;
@@ -87,3 +163,4 @@ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32)
// lock the flash
HAL_FLASH_Lock();
}
+*/
diff --git a/stmhal/flash.h b/stmhal/flash.h
index 33d31df7a6..7900d2c1ae 100644
--- a/stmhal/flash.h
+++ b/stmhal/flash.h
@@ -1,2 +1,3 @@
uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size);
+void flash_erase(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32);
void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32);
diff --git a/stmhal/main.c b/stmhal/main.c
index c5633fb68b..2d7e76172f 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -1,9 +1,7 @@
#include <stdio.h>
#include <string.h>
-#include <stm32f4xx_hal.h>
-#include <stm32f4xx_hal_gpio.h>
-#include "std.h"
+#include "stm32f4xx_hal.h"
#include "misc.h"
#include "systick.h"
@@ -14,11 +12,10 @@
#include "lexer.h"
#include "parse.h"
#include "obj.h"
-#include "parsehelper.h"
-#include "compile.h"
#include "runtime.h"
#include "gc.h"
#include "gccollect.h"
+#include "pybstdio.h"
#include "readline.h"
#include "pyexec.h"
#include "usart.h"
@@ -64,12 +61,25 @@ void flash_error(int n) {
}
void __fatal_error(const char *msg) {
-#if MICROPY_HW_HAS_LCD
+ for (volatile uint delay = 0; delay < 10000000; delay++) {
+ }
+ led_state(1, 1);
+ led_state(2, 1);
+ led_state(3, 1);
+ led_state(4, 1);
+ stdout_tx_strn("\nFATAL ERROR:\n", 14);
+ stdout_tx_strn(msg, strlen(msg));
+#if 0 && MICROPY_HW_HAS_LCD
lcd_print_strn("\nFATAL ERROR:\n", 14);
lcd_print_strn(msg, strlen(msg));
#endif
- for (;;) {
- flash_error(1);
+ for (uint i = 0;;) {
+ led_toggle(((i++) & 3) + 1);
+ for (volatile uint delay = 0; delay < 10000000; delay++) {
+ }
+ if (i >= 8) {
+ __WFI();
+ }
}
}
@@ -109,16 +119,6 @@ STATIC mp_obj_t pyb_usb_mode(mp_obj_t usb_mode) {
MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_mode_obj, pyb_usb_mode);
-void fatality(void) {
- led_state(PYB_LED_R1, 1);
- led_state(PYB_LED_G1, 1);
- led_state(PYB_LED_R2, 1);
- led_state(PYB_LED_G2, 1);
- for (;;) {
- flash_error(1);
- }
-}
-
static const char fresh_boot_py[] =
"# boot.py -- run on boot-up\n"
"# can run arbitrary Python, but best to keep it minimal\n"
diff --git a/stmhal/malloc0.c b/stmhal/malloc0.c
deleted file mode 100644
index 510fa0d740..0000000000
--- a/stmhal/malloc0.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <stdio.h>
-#include <stdint.h>
-#include "misc.h"
-#include "mpconfig.h"
-#include "gc.h"
-
-#if 0
-static uint32_t mem = 0;
-
-void *malloc(size_t n) {
- if (mem == 0) {
- extern uint32_t _heap_start;
- mem = (uint32_t)&_heap_start; // need to use big ram block so we can execute code from it (is it true that we can't execute from CCM?)
- }
- void *ptr = (void*)mem;
- mem = (mem + n + 3) & (~3);
- if (mem > 0x20000000 + 0x18000) {
- void __fatal_error(const char*);
- __fatal_error("out of memory");
- }
- return ptr;
-}
-
-void free(void *ptr) {
-}
-
-void *realloc(void *ptr, size_t n) {
- return malloc(n);
-}
-
-#endif
-
-void __assert_func(void) {
- printf("\nASSERT FAIL!");
- for (;;) {
- }
-}
diff --git a/stmhal/math.c b/stmhal/math.c
index 9b815f1180..75a5aeb2ee 100644
--- a/stmhal/math.c
+++ b/stmhal/math.c
@@ -70,16 +70,11 @@ float tanhf(float x) { return sinhf(x) / coshf(x); }
float acoshf(float x) { return 0.0; }
float asinhf(float x) { return 0.0; }
float atanhf(float x) { return 0.0; }
-float cosf(float x) { return 0.0; }
-float sinf(float x) { return 0.0; }
float tanf(float x) { return 0.0; }
float acosf(float x) { return 0.0; }
float asinf(float x) { return 0.0; }
float atanf(float x) { return 0.0; }
float atan2f(float x, float y) { return 0.0; }
-float ceilf(float x) { return 0.0; }
-float floorf(float x) { return 0.0; }
-float truncf(float x) { return 0.0; }
float fmodf(float x, float y) { return 0.0; }
float tgammaf(float x) { return 0.0; }
float lgammaf(float x) { return 0.0; }
@@ -820,3 +815,79 @@ float sinhf(float x)
t = 2*h*__expo2f(absx);
return t;
}
+
+/*****************************************************************************/
+/*****************************************************************************/
+// ceilf, floorf and truncf from musl-0.9.15
+/*****************************************************************************/
+/*****************************************************************************/
+
+float ceilf(float x)
+{
+ union {float f; uint32_t i;} u = {x};
+ int e = (int)(u.i >> 23 & 0xff) - 0x7f;
+ uint32_t m;
+
+ if (e >= 23)
+ return x;
+ if (e >= 0) {
+ m = 0x007fffff >> e;
+ if ((u.i & m) == 0)
+ return x;
+ FORCE_EVAL(x + 0x1p120f);
+ if (u.i >> 31 == 0)
+ u.i += m;
+ u.i &= ~m;
+ } else {
+ FORCE_EVAL(x + 0x1p120f);
+ if (u.i >> 31)
+ u.f = -0.0;
+ else if (u.i << 1)
+ u.f = 1.0;
+ }
+ return u.f;
+}
+
+float floorf(float x)
+{
+ union {float f; uint32_t i;} u = {x};
+ int e = (int)(u.i >> 23 & 0xff) - 0x7f;
+ uint32_t m;
+
+ if (e >= 23)
+ return x;
+ if (e >= 0) {
+ m = 0x007fffff >> e;
+ if ((u.i & m) == 0)
+ return x;
+ FORCE_EVAL(x + 0x1p120f);
+ if (u.i >> 31)
+ u.i += m;
+ u.i &= ~m;
+ } else {
+ FORCE_EVAL(x + 0x1p120f);
+ if (u.i >> 31 == 0)
+ u.i = 0;
+ else if (u.i << 1)
+ u.f = -1.0;
+ }
+ return u.f;
+}
+
+float truncf(float x)
+{
+ union {float f; uint32_t i;} u = {x};
+ int e = (int)(u.i >> 23 & 0xff) - 0x7f + 9;
+ uint32_t m;
+
+ if (e >= 23 + 9)
+ return x;
+ if (e < 9)
+ e = 1;
+ m = -1U >> e;
+ if ((u.i & m) == 0)
+ return x;
+ FORCE_EVAL(x + 0x1p120f);
+ u.i &= ~m;
+ return u.f;
+}
diff --git a/stmhal/mathsincos.c b/stmhal/mathsincos.c
new file mode 100644
index 0000000000..420c8bba10
--- /dev/null
+++ b/stmhal/mathsincos.c
@@ -0,0 +1,601 @@
+// These math functions are taken from newlib 2.1.0, the newlib/libm directory.
+
+#include <stdint.h>
+#include <math.h>
+
+
+/* @(#)fdlibm.h 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#define FLT_UWORD_IS_FINITE(x) ((x)<0x7f800000L)
+
+/* A union which permits us to convert between a float and a 32 bit
+ int. */
+
+typedef union
+{
+ float value;
+ __uint32_t word;
+} ieee_float_shape_type;
+
+
+/* Get a 32 bit int from a float. */
+
+#define GET_FLOAT_WORD(i,d) \
+do { \
+ ieee_float_shape_type gf_u; \
+ gf_u.value = (d); \
+ (i) = gf_u.word; \
+} while (0)
+
+/* Set a float from a 32 bit int. */
+
+#define SET_FLOAT_WORD(d,i) \
+do { \
+ ieee_float_shape_type sf_u; \
+ sf_u.word = (i); \
+ (d) = sf_u.value; \
+} while (0)
+
+
+
+/* kf_rem_pio2.c -- float version of k_rem_pio2.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* In the float version, the input parameter x contains 8 bit
+ integers, not 24 bit integers. 113 bit precision is not supported. */
+
+#ifdef __STDC__
+static const int init_jk[] = {4,7,9}; /* initial value for jk */
+#else
+static int init_jk[] = {4,7,9};
+#endif
+
+#ifdef __STDC__
+static const float PIo2[] = {
+#else
+static float PIo2[] = {
+#endif
+ 1.5703125000e+00, /* 0x3fc90000 */
+ 4.5776367188e-04, /* 0x39f00000 */
+ 2.5987625122e-05, /* 0x37da0000 */
+ 7.5437128544e-08, /* 0x33a20000 */
+ 6.0026650317e-11, /* 0x2e840000 */
+ 7.3896444519e-13, /* 0x2b500000 */
+ 5.3845816694e-15, /* 0x27c20000 */
+ 5.6378512969e-18, /* 0x22d00000 */
+ 8.3009228831e-20, /* 0x1fc40000 */
+ 3.2756352257e-22, /* 0x1bc60000 */
+ 6.3331015649e-25, /* 0x17440000 */
+};
+
+static const float
+zero = 0.0000000000e+00, /* 0x00000000 */
+one = 1.0000000000e+00, /* 0x3f800000 */
+two8 = 2.5600000000e+02, /* 0x43800000 */
+twon8 = 3.9062500000e-03; /* 0x3b800000 */
+
+int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const __int32_t *ipio2)
+{
+ __int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+ float z,fw,f[20],fq[20],q[20];
+
+ /* initialize jk*/
+ jk = init_jk[prec];
+ jp = jk;
+
+ /* determine jx,jv,q0, note that 3>q0 */
+ jx = nx-1;
+ jv = (e0-3)/8; if(jv<0) jv=0;
+ q0 = e0-8*(jv+1);
+
+ /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+ j = jv-jx; m = jx+jk;
+ for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j];
+
+ /* compute q[0],q[1],...q[jk] */
+ for (i=0;i<=jk;i++) {
+ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+ }
+
+ jz = jk;
+recompute:
+ /* distill q[] into iq[] reversingly */
+ for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+ fw = (float)((__int32_t)(twon8* z));
+ iq[i] = (__int32_t)(z-two8*fw);
+ z = q[j-1]+fw;
+ }
+
+ /* compute n */
+ z = scalbnf(z,(int)q0); /* actual value of z */
+ z -= (float)8.0*floorf(z*(float)0.125); /* trim off integer >= 8 */
+ n = (__int32_t) z;
+ z -= (float)n;
+ ih = 0;
+ if(q0>0) { /* need iq[jz-1] to determine n */
+ i = (iq[jz-1]>>(8-q0)); n += i;
+ iq[jz-1] -= i<<(8-q0);
+ ih = iq[jz-1]>>(7-q0);
+ }
+ else if(q0==0) ih = iq[jz-1]>>8;
+ else if(z>=(float)0.5) ih=2;
+
+ if(ih>0) { /* q > 0.5 */
+ n += 1; carry = 0;
+ for(i=0;i<jz ;i++) { /* compute 1-q */
+ j = iq[i];
+ if(carry==0) {
+ if(j!=0) {
+ carry = 1; iq[i] = 0x100- j;
+ }
+ } else iq[i] = 0xff - j;
+ }
+ if(q0>0) { /* rare case: chance is 1 in 12 */
+ switch(q0) {
+ case 1:
+ iq[jz-1] &= 0x7f; break;
+ case 2:
+ iq[jz-1] &= 0x3f; break;
+ }
+ }
+ if(ih==2) {
+ z = one - z;
+ if(carry!=0) z -= scalbnf(one,(int)q0);
+ }
+ }
+
+ /* check if recomputation is needed */
+ if(z==zero) {
+ j = 0;
+ for (i=jz-1;i>=jk;i--) j |= iq[i];
+ if(j==0) { /* need recomputation */
+ for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
+
+ for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
+ f[jx+i] = (float) ipio2[jv+i];
+ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+ q[i] = fw;
+ }
+ jz += k;
+ goto recompute;
+ }
+ }
+
+ /* chop off zero terms */
+ if(z==(float)0.0) {
+ jz -= 1; q0 -= 8;
+ while(iq[jz]==0) { jz--; q0-=8;}
+ } else { /* break z into 8-bit if necessary */
+ z = scalbnf(z,-(int)q0);
+ if(z>=two8) {
+ fw = (float)((__int32_t)(twon8*z));
+ iq[jz] = (__int32_t)(z-two8*fw);
+ jz += 1; q0 += 8;
+ iq[jz] = (__int32_t) fw;
+ } else iq[jz] = (__int32_t) z ;
+ }
+
+ /* convert integer "bit" chunk to floating-point value */
+ fw = scalbnf(one,(int)q0);
+ for(i=jz;i>=0;i--) {
+ q[i] = fw*(float)iq[i]; fw*=twon8;
+ }
+
+ /* compute PIo2[0,...,jp]*q[jz,...,0] */
+ for(i=jz;i>=0;i--) {
+ for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+ fq[jz-i] = fw;
+ }
+
+ /* compress fq[] into y[] */
+ switch(prec) {
+ case 0:
+ fw = 0.0;
+ for (i=jz;i>=0;i--) fw += fq[i];
+ y[0] = (ih==0)? fw: -fw;
+ break;
+ case 1:
+ case 2:
+ fw = 0.0;
+ for (i=jz;i>=0;i--) fw += fq[i];
+ y[0] = (ih==0)? fw: -fw;
+ fw = fq[0]-fw;
+ for (i=1;i<=jz;i++) fw += fq[i];
+ y[1] = (ih==0)? fw: -fw;
+ break;
+ case 3: /* painful */
+ for (i=jz;i>0;i--) {
+ fw = fq[i-1]+fq[i];
+ fq[i] += fq[i-1]-fw;
+ fq[i-1] = fw;
+ }
+ for (i=jz;i>1;i--) {
+ fw = fq[i-1]+fq[i];
+ fq[i] += fq[i-1]-fw;
+ fq[i-1] = fw;
+ }
+ for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
+ if(ih==0) {
+ y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
+ } else {
+ y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+ }
+ }
+ return n&7;
+}
+
+
+/* ef_rem_pio2.c -- float version of e_rem_pio2.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/* __ieee754_rem_pio2f(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2f()
+ */
+
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ */
+static const __int32_t two_over_pi[] = {
+0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
+0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
+0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
+0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
+0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
+0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
+0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
+0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
+0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
+0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
+0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
+0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
+0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
+0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
+0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
+0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
+0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
+0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
+0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
+0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
+0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
+0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
+};
+
+/* This array is like the one in e_rem_pio2.c, but the numbers are
+ single precision and the last 8 bits are forced to 0. */
+static const __int32_t npio2_hw[] = {
+0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
+0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
+0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
+0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
+0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
+0x4242c700, 0x42490f00
+};
+
+/*
+ * invpio2: 24 bits of 2/pi
+ * pio2_1: first 17 bit of pi/2
+ * pio2_1t: pi/2 - pio2_1
+ * pio2_2: second 17 bit of pi/2
+ * pio2_2t: pi/2 - (pio2_1+pio2_2)
+ * pio2_3: third 17 bit of pi/2
+ * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static const float
+half = 5.0000000000e-01, /* 0x3f000000 */
+invpio2 = 6.3661980629e-01, /* 0x3f22f984 */
+pio2_1 = 1.5707855225e+00, /* 0x3fc90f80 */
+pio2_1t = 1.0804334124e-05, /* 0x37354443 */
+pio2_2 = 1.0804273188e-05, /* 0x37354400 */
+pio2_2t = 6.0770999344e-11, /* 0x2e85a308 */
+pio2_3 = 6.0770943833e-11, /* 0x2e85a300 */
+pio2_3t = 6.1232342629e-17; /* 0x248d3132 */
+
+__int32_t __ieee754_rem_pio2f(float x, float *y)
+{
+ float z,w,t,r,fn;
+ float tx[3];
+ __int32_t i,j,n,ix,hx;
+ int e0,nx;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix<=0x3f490fd8) /* |x| ~<= pi/4 , no need for reduction */
+ {y[0] = x; y[1] = 0; return 0;}
+ if(ix<0x4016cbe4) { /* |x| < 3pi/4, special case with n=+-1 */
+ if(hx>0) {
+ z = x - pio2_1;
+ if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
+ y[0] = z - pio2_1t;
+ y[1] = (z-y[0])-pio2_1t;
+ } else { /* near pi/2, use 24+24+24 bit pi */
+ z -= pio2_2;
+ y[0] = z - pio2_2t;
+ y[1] = (z-y[0])-pio2_2t;
+ }
+ return 1;
+ } else { /* negative x */
+ z = x + pio2_1;
+ if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
+ y[0] = z + pio2_1t;
+ y[1] = (z-y[0])+pio2_1t;
+ } else { /* near pi/2, use 24+24+24 bit pi */
+ z += pio2_2;
+ y[0] = z + pio2_2t;
+ y[1] = (z-y[0])+pio2_2t;
+ }
+ return -1;
+ }
+ }
+ if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
+ t = fabsf(x);
+ n = (__int32_t) (t*invpio2+half);
+ fn = (float)n;
+ r = t-fn*pio2_1;
+ w = fn*pio2_1t; /* 1st round good to 40 bit */
+ if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) {
+ y[0] = r-w; /* quick check no cancellation */
+ } else {
+ __uint32_t high;
+ j = ix>>23;
+ y[0] = r-w;
+ GET_FLOAT_WORD(high,y[0]);
+ i = j-((high>>23)&0xff);
+ if(i>8) { /* 2nd iteration needed, good to 57 */
+ t = r;
+ w = fn*pio2_2;
+ r = t-w;
+ w = fn*pio2_2t-((t-r)-w);
+ y[0] = r-w;
+ GET_FLOAT_WORD(high,y[0]);
+ i = j-((high>>23)&0xff);
+ if(i>25) { /* 3rd iteration need, 74 bits acc */
+ t = r; /* will cover all possible cases */
+ w = fn*pio2_3;
+ r = t-w;
+ w = fn*pio2_3t-((t-r)-w);
+ y[0] = r-w;
+ }
+ }
+ }
+ y[1] = (r-y[0])-w;
+ if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+ else return n;
+ }
+ /*
+ * all other (large) arguments
+ */
+ if(!FLT_UWORD_IS_FINITE(ix)) {
+ y[0]=y[1]=x-x; return 0;
+ }
+ /* set z = scalbn(|x|,ilogb(x)-7) */
+ e0 = (int)((ix>>23)-134); /* e0 = ilogb(z)-7; */
+ SET_FLOAT_WORD(z, ix - ((__int32_t)e0<<23));
+ for(i=0;i<2;i++) {
+ tx[i] = (float)((__int32_t)(z));
+ z = (z-tx[i])*two8;
+ }
+ tx[2] = z;
+ nx = 3;
+ while(tx[nx-1]==zero) nx--; /* skip zero term */
+ n = __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi);
+ if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+ return n;
+}
+
+
+/* kf_sin.c -- float version of k_sin.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+
+static const float
+S1 = -1.6666667163e-01, /* 0xbe2aaaab */
+S2 = 8.3333337680e-03, /* 0x3c088889 */
+S3 = -1.9841270114e-04, /* 0xb9500d01 */
+S4 = 2.7557314297e-06, /* 0x3638ef1b */
+S5 = -2.5050759689e-08, /* 0xb2d72f34 */
+S6 = 1.5896910177e-10; /* 0x2f2ec9d3 */
+
+float __kernel_sinf(float x, float y, int iy) /* iy=0 if y is zero */
+{
+ float z,r,v;
+ __int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff; /* high word of x */
+ if(ix<0x32000000) /* |x| < 2**-27 */
+ {if((int)x==0) return x;} /* generate inexact */
+ z = x*x;
+ v = z*x;
+ r = S2+z*(S3+z*(S4+z*(S5+z*S6)));
+ if(iy==0) return x+v*(S1+z*r);
+ else return x-((z*(half*y-v*r)-y)-v*S1);
+}
+
+
+
+/* kf_cos.c -- float version of k_cos.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+
+static const float
+C1 = 4.1666667908e-02, /* 0x3d2aaaab */
+C2 = -1.3888889225e-03, /* 0xbab60b61 */
+C3 = 2.4801587642e-05, /* 0x37d00d01 */
+C4 = -2.7557314297e-07, /* 0xb493f27c */
+C5 = 2.0875723372e-09, /* 0x310f74f6 */
+C6 = -1.1359647598e-11; /* 0xad47d74e */
+
+float __kernel_cosf(float x, float y)
+{
+ float a,hz,z,r,qx;
+ __int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff; /* ix = |x|'s high word*/
+ if(ix<0x32000000) { /* if x < 2**27 */
+ if(((int)x)==0) return one; /* generate inexact */
+ }
+ z = x*x;
+ r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
+ if(ix < 0x3e99999a) /* if |x| < 0.3 */
+ return one - ((float)0.5*z - (z*r - x*y));
+ else {
+ if(ix > 0x3f480000) { /* x > 0.78125 */
+ qx = (float)0.28125;
+ } else {
+ SET_FLOAT_WORD(qx,ix-0x01000000); /* x/4 */
+ }
+ hz = (float)0.5*z-qx;
+ a = one-qx;
+ return a - (hz - (z*r-x*y));
+ }
+}
+
+
+/* sf_sin.c -- float version of s_sin.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+
+float sinf(float x)
+{
+ float y[2],z=0.0;
+ __int32_t n,ix;
+
+ GET_FLOAT_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0);
+
+ /* sin(Inf or NaN) is NaN */
+ else if (!FLT_UWORD_IS_FINITE(ix)) return x-x;
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2f(x,y);
+ switch(n&3) {
+ case 0: return __kernel_sinf(y[0],y[1],1);
+ case 1: return __kernel_cosf(y[0],y[1]);
+ case 2: return -__kernel_sinf(y[0],y[1],1);
+ default:
+ return -__kernel_cosf(y[0],y[1]);
+ }
+ }
+}
+
+
+/* sf_cos.c -- float version of s_cos.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+
+float cosf(float x)
+{
+ float y[2],z=0.0;
+ __int32_t n,ix;
+
+ GET_FLOAT_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3f490fd8) return __kernel_cosf(x,z);
+
+ /* cos(Inf or NaN) is NaN */
+ else if (!FLT_UWORD_IS_FINITE(ix)) return x-x;
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2f(x,y);
+ switch(n&3) {
+ case 0: return __kernel_cosf(y[0],y[1]);
+ case 1: return -__kernel_sinf(y[0],y[1],1);
+ case 2: return -__kernel_cosf(y[0],y[1]);
+ default:
+ return __kernel_sinf(y[0],y[1],1);
+ }
+ }
+}
diff --git a/stmhal/pybstdio.c b/stmhal/pybstdio.c
index d40cebf947..baabfd120c 100644
--- a/stmhal/pybstdio.c
+++ b/stmhal/pybstdio.c
@@ -9,7 +9,6 @@
#include "obj.h"
#include "stream.h"
#include "pybstdio.h"
-#include "storage.h"
#include "usb.h"
#include "usart.h"
@@ -50,9 +49,6 @@ int stdin_rx_chr(void) {
return usart_rx_char(pyb_usart_global_debug);
}
__WFI();
- if (storage_needs_flush()) {
- storage_flush();
- }
}
}
diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c
index 298e58a5fd..9821e6a929 100644
--- a/stmhal/pyexec.c
+++ b/stmhal/pyexec.c
@@ -21,7 +21,6 @@
#include "pybstdio.h"
#include "readline.h"
#include "pyexec.h"
-#include "storage.h"
#include "usb.h"
#include "build/py/py-version.h"
diff --git a/stmhal/std.h b/stmhal/std.h
index 843ddd8270..6982b715d0 100644
--- a/stmhal/std.h
+++ b/stmhal/std.h
@@ -1,7 +1,5 @@
typedef unsigned int size_t;
-void __assert_func(void);
-
void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
diff --git a/stmhal/stm32f4xx_it.c b/stmhal/stm32f4xx_it.c
index aee689d7e2..df69f52b8e 100644
--- a/stmhal/stm32f4xx_it.c
+++ b/stmhal/stm32f4xx_it.c
@@ -49,6 +49,7 @@
#include "obj.h"
#include "exti.h"
#include "timer.h"
+#include "storage.h"
/** @addtogroup STM32F4xx_HAL_Examples
* @{
@@ -63,7 +64,7 @@
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
-extern void fatality();
+extern void __fatal_error(const char*);
extern PCD_HandleTypeDef hpcd;
/* Private function prototypes -----------------------------------------------*/
@@ -87,12 +88,10 @@ void NMI_Handler(void)
* @param None
* @retval None
*/
-void HardFault_Handler(void)
-{
+void HardFault_Handler(void) {
/* Go to infinite loop when Hard Fault exception occurs */
- while (1)
- {
- fatality();
+ while (1) {
+ __fatal_error("HardFault");
}
}
@@ -101,12 +100,10 @@ void HardFault_Handler(void)
* @param None
* @retval None
*/
-void MemManage_Handler(void)
-{
+void MemManage_Handler(void) {
/* Go to infinite loop when Memory Manage exception occurs */
- while (1)
- {
- fatality();
+ while (1) {
+ __fatal_error("MemManage");
}
}
@@ -115,12 +112,10 @@ void MemManage_Handler(void)
* @param None
* @retval None
*/
-void BusFault_Handler(void)
-{
+void BusFault_Handler(void) {
/* Go to infinite loop when Bus Fault exception occurs */
- while (1)
- {
- fatality();
+ while (1) {
+ __fatal_error("BusFault");
}
}
@@ -129,12 +124,10 @@ void BusFault_Handler(void)
* @param None
* @retval None
*/
-void UsageFault_Handler(void)
-{
+void UsageFault_Handler(void) {
/* Go to infinite loop when Usage Fault exception occurs */
- while (1)
- {
- fatality();
+ while (1) {
+ __fatal_error("UsageFault");
}
}
@@ -263,6 +256,19 @@ void OTG_XX_WKUP_IRQHandler(void)
{
}*/
+// Handle a flash (erase/program) interrupt.
+void FLASH_IRQHandler(void) {
+ // This calls the real flash IRQ handler, if needed
+ /*
+ uint32_t flash_cr = FLASH->CR;
+ if ((flash_cr & FLASH_IT_EOP) || (flash_cr & FLASH_IT_ERR)) {
+ HAL_FLASH_IRQHandler();
+ }
+ */
+ // This call the storage IRQ handler, to check if the flash cache needs flushing
+ storage_irq_handler();
+}
+
/**
* @brief These functions handle the EXTI interrupt requests.
* @param None
diff --git a/stmhal/storage.c b/stmhal/storage.c
index 98d5ee7e70..0348986f26 100644
--- a/stmhal/storage.c
+++ b/stmhal/storage.c
@@ -16,20 +16,22 @@
#define FLASH_PART1_NUM_BLOCKS (224) // 16k+16k+16k+64k=112k
#define FLASH_MEM_START_ADDR (0x08004000) // sector 1, 16k
+#define FLASH_FLAG_DIRTY (1)
+#define FLASH_FLAG_FORCE_WRITE (2)
+#define FLASH_FLAG_ERASED (4)
static bool flash_is_initialised = false;
-static bool flash_cache_dirty;
+static __IO uint8_t flash_flags = 0;
static uint32_t flash_cache_sector_id;
static uint32_t flash_cache_sector_start;
static uint32_t flash_cache_sector_size;
static uint32_t flash_tick_counter_last_write;
static void flash_cache_flush(void) {
- if (flash_cache_dirty) {
- // sync the cache RAM buffer by writing it to the flash page
- flash_write(flash_cache_sector_start, (const uint32_t*)CACHE_MEM_START_ADDR, flash_cache_sector_size / 4);
- flash_cache_dirty = false;
- // indicate a clean cache with LED off
- led_state(PYB_LED_R1, 0);
+ if (flash_flags & FLASH_FLAG_DIRTY) {
+ flash_flags |= FLASH_FLAG_FORCE_WRITE;
+ while (flash_flags & FLASH_FLAG_DIRTY) {
+ NVIC->STIR = FLASH_IRQn;
+ }
}
}
@@ -44,9 +46,9 @@ static uint8_t *flash_cache_get_addr_for_write(uint32_t flash_addr) {
flash_cache_sector_start = flash_sector_start;
flash_cache_sector_size = flash_sector_size;
}
- flash_cache_dirty = true;
- // indicate a dirty cache with LED on
- led_state(PYB_LED_R1, 1);
+ flash_flags |= FLASH_FLAG_DIRTY;
+ led_state(PYB_LED_R1, 1); // indicate a dirty cache with LED on
+ flash_tick_counter_last_write = HAL_GetTick();
return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start;
}
@@ -64,11 +66,17 @@ static uint8_t *flash_cache_get_addr_for_read(uint32_t flash_addr) {
void storage_init(void) {
if (!flash_is_initialised) {
- flash_cache_dirty = false;
+ flash_flags = 0;
flash_cache_sector_id = 0;
- flash_is_initialised = true;
flash_tick_counter_last_write = 0;
+ flash_is_initialised = true;
}
+
+ // Enable the flash IRQ, which is used to also call our storage IRQ handler
+ // It needs to go at a higher priority than all those components that rely on
+ // the flash storage (eg higher than USB MSC).
+ HAL_NVIC_SetPriority(FLASH_IRQn, 1, 1);
+ HAL_NVIC_EnableIRQ(FLASH_IRQn);
}
uint32_t storage_get_block_size(void) {
@@ -79,9 +87,47 @@ uint32_t storage_get_block_count(void) {
return FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS;
}
-bool storage_needs_flush(void) {
- // wait 2 seconds after last write to flush
- return flash_cache_dirty && sys_tick_has_passed(flash_tick_counter_last_write, 2000);
+void storage_irq_handler(void) {
+ if (!(flash_flags & FLASH_FLAG_DIRTY)) {
+ return;
+ }
+
+ // This code uses interrupts to erase the flash
+ /*
+ if (flash_erase_state == 0) {
+ flash_erase_it(flash_cache_sector_start, (const uint32_t*)CACHE_MEM_START_ADDR, flash_cache_sector_size / 4);
+ flash_erase_state = 1;
+ return;
+ }
+
+ if (flash_erase_state == 1) {
+ // wait for erase
+ // TODO add timeout
+ #define flash_erase_done() (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) == RESET)
+ if (!flash_erase_done()) {
+ return;
+ }
+ flash_erase_state = 2;
+ }
+ */
+
+ // This code erases the flash directly, waiting for it to finish
+ if (!(flash_flags & FLASH_FLAG_ERASED)) {
+ flash_erase(flash_cache_sector_start, (const uint32_t*)CACHE_MEM_START_ADDR, flash_cache_sector_size / 4);
+ flash_flags |= FLASH_FLAG_ERASED;
+ return;
+ }
+
+ // If not a forced write, wait at least 5 seconds after last write to flush
+ // On file close and flash unmount we get a forced write, so we can afford to wait a while
+ if ((flash_flags & FLASH_FLAG_FORCE_WRITE) || sys_tick_has_passed(flash_tick_counter_last_write, 5000)) {
+ // sync the cache RAM buffer by writing it to the flash page
+ flash_write(flash_cache_sector_start, (const uint32_t*)CACHE_MEM_START_ADDR, flash_cache_sector_size / 4);
+ // clear the flash flags now that we have a clean cache
+ flash_flags = 0;
+ // indicate a clean cache with LED off
+ led_state(PYB_LED_R1, 0);
+ }
}
void storage_flush(void) {
@@ -167,7 +213,6 @@ bool storage_write_block(const uint8_t *src, uint32_t block) {
uint32_t flash_addr = FLASH_MEM_START_ADDR + (block - FLASH_PART1_START_BLOCK) * FLASH_BLOCK_SIZE;
uint8_t *dest = flash_cache_get_addr_for_write(flash_addr);
memcpy(dest, src, FLASH_BLOCK_SIZE);
- flash_tick_counter_last_write = HAL_GetTick();
return true;
} else {
diff --git a/stmhal/storage.h b/stmhal/storage.h
index 4d153d2f69..ae6c832281 100644
--- a/stmhal/storage.h
+++ b/stmhal/storage.h
@@ -3,7 +3,7 @@
void storage_init(void);
uint32_t storage_get_block_size(void);
uint32_t storage_get_block_count(void);
-bool storage_needs_flush(void);
+void storage_irq_handler(void);
void storage_flush(void);
bool storage_read_block(uint8_t *dest, uint32_t block);
bool storage_write_block(const uint8_t *src, uint32_t block);
diff --git a/stmhal/timer.c b/stmhal/timer.c
index 5ea605039d..26524fbdd9 100644
--- a/stmhal/timer.c
+++ b/stmhal/timer.c
@@ -19,6 +19,7 @@
// the interrupts to be dispatched, so they are all collected here.
//
// TIM3:
+// - flash storage controller, to flush the cache
// - USB CDC interface, interval, to check for new data
// - LED 4, PWM to set the LED intensity
//
@@ -29,14 +30,17 @@ TIM_HandleTypeDef TIM3_Handle;
TIM_HandleTypeDef TIM5_Handle;
TIM_HandleTypeDef TIM6_Handle;
+// Used to divide down TIM3 and periodically call the flash storage IRQ
+static uint32_t tim3_counter = 0;
+
// TIM3 is set-up for the USB CDC interface
void timer_tim3_init(void) {
// set up the timer for USBD CDC
__TIM3_CLK_ENABLE();
TIM3_Handle.Instance = TIM3;
- TIM3_Handle.Init.Period = (USBD_CDC_POLLING_INTERVAL*1000) - 1;
- TIM3_Handle.Init.Prescaler = 84-1;
+ TIM3_Handle.Init.Period = (USBD_CDC_POLLING_INTERVAL*1000) - 1; // TIM3 fires every USBD_CDC_POLLING_INTERVAL ms
+ TIM3_Handle.Init.Prescaler = 84-1; // for System clock at 168MHz, TIM3 runs at 1MHz
TIM3_Handle.Init.ClockDivision = 0;
TIM3_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_Base_Init(&TIM3_Handle);
@@ -105,6 +109,13 @@ void timer_tim6_init(uint freq) {
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim == &TIM3_Handle) {
USBD_CDC_HAL_TIM_PeriodElapsedCallback();
+
+ // Periodically raise a flash IRQ for the flash storage controller
+ if (tim3_counter++ >= 500 / USBD_CDC_POLLING_INTERVAL) {
+ tim3_counter = 0;
+ NVIC->STIR = FLASH_IRQn;
+ }
+
} else if (htim == &TIM5_Handle) {
servo_timer_irq_callback();
}
diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c
index 552f7cc9ec..b2c85fa4f3 100644
--- a/stmhal/usbd_cdc_interface.c
+++ b/stmhal/usbd_cdc_interface.c
@@ -63,6 +63,7 @@ static uint16_t UserTxBufPtrIn = 0; // increment this pointer modulo APP_TX_DATA
static __IO uint16_t UserTxBufPtrOut = 0; // increment this pointer modulo APP_TX_DATA_SIZE when data is drained
static uint16_t UserTxBufPtrOutShadow = 0; // shadow of above
static uint8_t UserTxBufPtrWaitCount = 0; // used to implement a timeout waiting for low-level USB driver
+static uint8_t UserTxNeedEmptyPacket = 0; // used to flush the USB IN endpoint if the last packet was exactly the endpoint packet size
static int user_interrupt_char = VCP_CHAR_NONE;
static void *user_interrupt_data = NULL;
@@ -257,7 +258,7 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
return;
}
- if (UserTxBufPtrOut == UserTxBufPtrIn) {
+ if (UserTxBufPtrOut == UserTxBufPtrIn && !UserTxNeedEmptyPacket) {
// No outstanding data to send
return;
}
@@ -265,10 +266,11 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
if (UserTxBufPtrOut != UserTxBufPtrOutShadow) {
// We have sent data and are waiting for the low-level USB driver to
// finish sending it over the USB in-endpoint.
- if (UserTxBufPtrWaitCount < 10) {
+ // We have a 15 * 10ms = 150ms timeout
+ if (UserTxBufPtrWaitCount < 15) {
PCD_HandleTypeDef *hpcd = hUSBDDevice.pData;
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
- if (USBx_INEP(3)->DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ) {
+ if (USBx_INEP(CDC_IN_EP & 0x7f)->DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ) {
// USB in-endpoint is still reading the data
UserTxBufPtrWaitCount++;
return;
@@ -277,7 +279,7 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
UserTxBufPtrOut = UserTxBufPtrOutShadow;
}
- if (UserTxBufPtrOutShadow != UserTxBufPtrIn) {
+ if (UserTxBufPtrOutShadow != UserTxBufPtrIn || UserTxNeedEmptyPacket) {
uint32_t buffptr;
uint32_t buffsize;
@@ -289,14 +291,6 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
buffptr = UserTxBufPtrOutShadow;
- // dpgeorge: For some reason that I don't understand, a packet size of 64 bytes
- // (CDC_DATA_FS_MAX_PACKET_SIZE) does not get through to the USB host until the
- // next packet is sent. To work around this, we just make sure that we never
- // send a packet 64 bytes in length.
- if (buffsize == CDC_DATA_FS_MAX_PACKET_SIZE) {
- buffsize -= 1;
- }
-
USBD_CDC_SetTxBuffer(&hUSBDDevice, (uint8_t*)&UserTxBuffer[buffptr], buffsize);
if (USBD_CDC_TransmitPacket(&hUSBDDevice) == USBD_OK) {
@@ -305,6 +299,14 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
UserTxBufPtrOutShadow = 0;
}
UserTxBufPtrWaitCount = 0;
+
+ // According to the USB specification, a packet size of 64 bytes (CDC_DATA_FS_MAX_PACKET_SIZE)
+ // gets held at the USB host until the next packet is sent. This is because a
+ // packet of maximum size is considered to be part of a longer chunk of data, and
+ // the host waits for all data to arrive (ie, waits for a packet < max packet size).
+ // To flush a packet of exactly max packet size, we need to send a zero-size packet.
+ // See eg http://www.cypress.com/?id=4&rID=92719
+ UserTxNeedEmptyPacket = (buffsize == CDC_DATA_FS_MAX_PACKET_SIZE && UserTxBufPtrOutShadow == UserTxBufPtrIn);
}
}
}
diff --git a/stmhal/usbd_desc_cdc_msc.c b/stmhal/usbd_desc_cdc_msc.c
index 137e0bed99..1af99d0b90 100644
--- a/stmhal/usbd_desc_cdc_msc.c
+++ b/stmhal/usbd_desc_cdc_msc.c
@@ -32,6 +32,23 @@
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
+
+// So we don't clash with existing ST boards, we use the unofficial FOSS VID.
+// This needs a proper solution.
+#define USBD_VID 0xf055
+#define USBD_PID 0x9800
+#define USBD_LANGID_STRING 0x409
+#define USBD_MANUFACTURER_STRING "Micro Python"
+#define USBD_PRODUCT_HS_STRING "Pyboard Virtual Comm Port in HS Mode"
+#define USBD_SERIALNUMBER_HS_STRING "000000000010"
+#define USBD_PRODUCT_FS_STRING "Pyboard Virtual Comm Port in FS Mode"
+#define USBD_SERIALNUMBER_FS_STRING "000000000011"
+#define USBD_CONFIGURATION_HS_STRING "VCP Config"
+#define USBD_INTERFACE_HS_STRING "VCP Interface"
+#define USBD_CONFIGURATION_FS_STRING "VCP Config"
+#define USBD_INTERFACE_FS_STRING "VCP Interface"
+
+/*
#define USBD_VID 0x0483
#define USBD_PID 0x5740
#define USBD_LANGID_STRING 0x409
@@ -44,6 +61,7 @@
#define USBD_INTERFACE_HS_STRING "VCP Interface"
#define USBD_CONFIGURATION_FS_STRING "VCP Config"
#define USBD_INTERFACE_FS_STRING "VCP Interface"
+*/
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
diff --git a/stmhal/usbd_msc_storage.c b/stmhal/usbd_msc_storage.c
index 0225a2a23c..6ec9abc3d1 100644
--- a/stmhal/usbd_msc_storage.c
+++ b/stmhal/usbd_msc_storage.c
@@ -38,7 +38,10 @@
// These are needed to support removal of the medium, so that the USB drive
// can be unmounted, and won't be remounted automatically.
static uint8_t flash_removed = 0;
+
+#if MICROPY_HW_HAS_SDCARD
static uint8_t sdcard_removed = 0;
+#endif
/******************************************************************************/
// Callback functions for when the internal flash is the mass storage device
@@ -109,6 +112,12 @@ int8_t FLASH_STORAGE_StopUnit(uint8_t lun) {
return 0;
}
+int8_t FLASH_STORAGE_PreventAllowMediumRemoval(uint8_t lun, uint8_t param) {
+ // sync the flash so that the cache is cleared and the device can be unplugged/turned off
+ disk_ioctl(0, CTRL_SYNC, NULL);
+ return 0;
+}
+
/**
* @brief Read data from the medium
* @param lun : logical unit number
@@ -146,7 +155,6 @@ int8_t FLASH_STORAGE_Write (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16
}
}
*/
- storage_flush(); // XXX hack for now so that the cache is always flushed
return 0;
}
@@ -165,6 +173,7 @@ const USBD_StorageTypeDef USBD_FLASH_STORAGE_fops = {
FLASH_STORAGE_IsReady,
FLASH_STORAGE_IsWriteProtected,
FLASH_STORAGE_StopUnit,
+ FLASH_STORAGE_PreventAllowMediumRemoval,
FLASH_STORAGE_Read,
FLASH_STORAGE_Write,
FLASH_STORAGE_GetMaxLun,
@@ -295,6 +304,10 @@ int8_t SDCARD_STORAGE_StopUnit(uint8_t lun) {
return 0;
}
+int8_t SDCARD_STORAGE_PreventAllowMediumRemoval(uint8_t lun, uint8_t param) {
+ return 0;
+}
+
/**
* @brief Read data from the medium
* @param lun : logical unit number
@@ -340,6 +353,7 @@ const USBD_StorageTypeDef USBD_SDCARD_STORAGE_fops = {
SDCARD_STORAGE_IsReady,
SDCARD_STORAGE_IsWriteProtected,
SDCARD_STORAGE_StopUnit,
+ SDCARD_STORAGE_PreventAllowMediumRemoval,
SDCARD_STORAGE_Read,
SDCARD_STORAGE_Write,
SDCARD_STORAGE_GetMaxLun,
diff --git a/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h
index 9343994931..798bdc99db 100644
--- a/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h
+++ b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h
@@ -13,6 +13,11 @@
#define MSC_IN_EP (0x81)
#define MSC_OUT_EP (0x01)
+// Need to define here for usbd_cdc_interface.c (it needs CDC_IN_EP)
+#define CDC_IN_EP (0x83)
+#define CDC_OUT_EP (0x03)
+#define CDC_CMD_EP (0x82)
+
// only CDC_MSC and CDC_HID are available
#define USBD_MODE_CDC (0x01)
#define USBD_MODE_MSC (0x02)
@@ -54,6 +59,7 @@ typedef struct _USBD_STORAGE {
int8_t (* IsReady) (uint8_t lun);
int8_t (* IsWriteProtected) (uint8_t lun);
int8_t (* StopUnit)(uint8_t lun);
+ int8_t (* PreventAllowMediumRemoval)(uint8_t lun, uint8_t param0);
int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t (* GetMaxLun)(void);
diff --git a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c
index 6dc0af0e65..aa8c0c80cf 100644
--- a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c
+++ b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c
@@ -4,9 +4,6 @@
#define USB_CDC_MSC_CONFIG_DESC_SIZ (98)
#define USB_CDC_HID_CONFIG_DESC_SIZ (100)
#define CDC_IFACE_NUM (1)
-#define CDC_IN_EP (0x83)
-#define CDC_OUT_EP (0x03)
-#define CDC_CMD_EP (0x82)
#define MSC_IFACE_NUM (0)
#define HID_IFACE_NUM_WITH_CDC (0)
#define HID_IFACE_NUM_WITH_MSC (1)
diff --git a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c
index b00d1ae2ce..60258d64d9 100644
--- a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c
+++ b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c
@@ -472,6 +472,7 @@ static int8_t SCSI_AllowMediumRemoval(USBD_HandleTypeDef *pdev, uint8_t lun, ui
{
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
hmsc->bot_data_length = 0;
+ ((USBD_StorageTypeDef *)pdev->pUserData)->PreventAllowMediumRemoval(lun, params[0]);
return 0;
}
diff --git a/tests/README b/tests/README
index ef00705712..0cb526c3b4 100644
--- a/tests/README
+++ b/tests/README
@@ -2,3 +2,7 @@ This directory contains tests for various functionality areas of MicroPython.
To run all stable tests, run "run-tests" script in this directory. Note
that bytecode tests are not yet stable and should be run separately in
"bytecode" subdirectory.
+
+When creating new tests, anything that relies on float support should go in the
+float/ subdirectory. Anything that relies on import x, where x is not a built-in
+module, should go in the import/ subdirectory.
diff --git a/tests/basics/fun-callstar.py b/tests/basics/fun-callstar.py
index e19acb3491..255563b26b 100644
--- a/tests/basics/fun-callstar.py
+++ b/tests/basics/fun-callstar.py
@@ -31,5 +31,3 @@ a.foo(1, 2, *[100])
# Iterator
a.foo(*range(3))
-
-print('flush') # so that it works on pyboard...
diff --git a/tests/basics/fun-defargs.py b/tests/basics/fun-defargs.py
index 51516c7363..0666b8c494 100644
--- a/tests/basics/fun-defargs.py
+++ b/tests/basics/fun-defargs.py
@@ -18,5 +18,3 @@ try:
fun2(1, 2, 3, 4)
except TypeError:
print("TypeError")
-
-print('flush') # so that it works on pyboard...
diff --git a/tests/basics/int-divzero.py b/tests/basics/int-divzero.py
index d1fc579321..28ec2a6995 100644
--- a/tests/basics/int-divzero.py
+++ b/tests/basics/int-divzero.py
@@ -1,9 +1,4 @@
try:
- 1 / 0
-except ZeroDivisionError:
- print("ZeroDivisionError")
-
-try:
1 // 0
except ZeroDivisionError:
print("ZeroDivisionError")
diff --git a/tests/basics/list1.py b/tests/basics/list1.py
index a0c8afc4f8..c8317baa3d 100644
--- a/tests/basics/list1.py
+++ b/tests/basics/list1.py
@@ -22,8 +22,3 @@ print(x)
print(x[1:])
print(x[:-1])
print(x[2:3])
-
-try:
- print(x[1.0])
-except TypeError:
- print("TypeError")
diff --git a/tests/basics/modulo.py b/tests/basics/modulo.py
index 4d83db6ec8..c95305d13d 100644
--- a/tests/basics/modulo.py
+++ b/tests/basics/modulo.py
@@ -1,5 +1,6 @@
# check modulo matches python definition
-# This test compiler version
+
+# this tests compiler constant folding
print(123 % 7)
print(-123 % 7)
print(123 % -7)
@@ -20,17 +21,3 @@ print(a % b)
print(a % -b)
print(-a % b)
print(-a % -b)
-
-if False:
- print(1.23456 % 0.7)
- print(-1.23456 % 0.7)
- print(1.23456 % -0.7)
- print(-1.23456 % -0.7)
-
- a = 1.23456
- b = 0.7
- print(a % b)
- print(a % -b)
- print(-a % b)
- print(-a % -b)
-
diff --git a/tests/basics/string-format-modulo.py b/tests/basics/string-format-modulo.py
index 8e58be18c8..0e2c1d1096 100644
--- a/tests/basics/string-format-modulo.py
+++ b/tests/basics/string-format-modulo.py
@@ -23,11 +23,9 @@ except TypeError:
print("%s" % True)
print("%s" % 1)
-print("%s" % 1.0)
print("%r" % True)
print("%r" % 1)
-print("%r" % 1.0)
print("%c" % 48)
print("%c" % 'a')
@@ -37,28 +35,16 @@ print("%d" % 10)
print("%+d" % 10)
print("% d" % 10)
print("%d" % -10)
-print("%d" % 1.0)
print("%d" % True)
print("%i" % -10)
-print("%i" % 1.0)
print("%i" % True)
print("%u" % -10)
-print("%u" % 1.0)
print("%u" % True)
print("%x" % 18)
-print("%x" % 18.0)
print("%o" % 18)
-print("%o" % 18.0)
print("%X" % 18)
-print("%X" % 18.0)
print("%#x" % 18)
print("%#X" % 18)
print("%#6o" % 18)
print("%#6x" % 18)
print("%#06x" % 18)
-print("%e" % 1.23456)
-print("%E" % 1.23456)
-print("%f" % 1.23456)
-print("%F" % 1.23456)
-print("%g" % 1.23456)
-print("%G" % 1.23456)
diff --git a/tests/basics/string-format.py b/tests/basics/string-format.py
index 2d6d0cc721..84ea054758 100644
--- a/tests/basics/string-format.py
+++ b/tests/basics/string-format.py
@@ -60,26 +60,6 @@ test("{:@<6d}", -123)
test("{:@=6d}", -123)
test("{:06d}", -123)
-test("{:10.4e}", 123.456)
-test("{:10.4e}", -123.456)
-test("{:10.4f}", 123.456)
-test("{:10.4f}", -123.456)
-test("{:10.4g}", 123.456)
-test("{:10.4g}", -123.456)
-test("{:e}", 100)
-test("{:f}", 200)
-test("{:g}", 300)
-
-test("{:10.4E}", 123.456)
-test("{:10.4E}", -123.456)
-test("{:10.4F}", 123.456)
-test("{:10.4F}", -123.456)
-test("{:10.4G}", 123.456)
-test("{:10.4G}", -123.456)
-
-# The following fails right now
-#test("{:10.1}", 0.0)
-
def test_fmt(conv, fill, alignment, sign, prefix, width, precision, type, arg):
fmt = '{'
if conv:
@@ -137,71 +117,4 @@ if full_tests:
for str in ('', 'a', 'bcd', 'This is a test with a longer string'):
test_fmt(conv, fill, alignment, '', '', width, '', 's', str)
-eg_nums = (0.0, -0.0, 0.1, 1.234, 12.3459, 1.23456789, 123456789.0, -0.0,
- -0.1, -1.234, -12.3459, 1e4, 1e-4, 1e5, 1e-5, 1e6, 1e-6, 1e10,
- 1e37, -1e37, 1e-37, -1e-37,
- 1.23456e8, 1.23456e7, 1.23456e6, 1.23456e5, 1.23456e4, 1.23456e3, 1.23456e2, 1.23456e1, 1.23456e0,
- 1.23456e-1, 1.23456e-2, 1.23456e-3, 1.23456e-4, 1.23456e-5, 1.23456e-6, 1.23456e-7, 1.23456e-8,
- -1.23456e8, -1.23456e7, -1.23456e6, -1.23456e5, -1.23456e4, -1.23456e3, -1.23456e2, -1.23456e1, -1.23456e0,
- -1.23456e-1, -1.23456e-2, -1.23456e-3, -1.23456e-4, -1.23456e-5, -1.23456e-6, -1.23456e-7, -1.23456e-8)
-
-if full_tests:
- for type in ('e', 'E', 'g', 'G', 'n'):
- for width in ('', '4', '6', '8', '10'):
- for alignment in ('', '<', '>', '=', '^'):
- for fill in ('', '@', '0', ' '):
- for sign in ('', '+', '-', ' '):
- for prec in ('', '1', '3', '6'):
- for num in eg_nums:
- test_fmt('', fill, alignment, sign, '', width, prec, type, num)
-
-# Note: We use 1.23459 rather than 1.2345 because '{:3f}'.format(1.2345)
-# rounds differently than print("%.3f", 1.2345);
-
-f_nums = (0.0, -0.0, 0.0001, 0.001, 0.01, 0.1, 1.0, 10.0,
- 0.0012, 0.0123, 0.1234, 1.23459, 12.3456,
- -0.0001, -0.001, -0.01, -0.1, -1.0, -10.0,
- -0.0012, -0.0123, -0.1234, -1.23459, -12.3456)
-
-if full_tests:
- for type in ('f', 'F'):
- for width in ('', '4', '6', '8', '10'):
- for alignment in ('', '<', '>', '=', '^'):
- for fill in ('', ' ', '0', '@'):
- for sign in ('', '+', '-', ' '):
- # An empty precision defaults to 6, but when uPy is
- # configured to use a float, we can only use a
- # precision of 6 with numbers less than 10 and still
- # get results that compare to CPython (which uses
- # long doubles).
- for prec in ('1', '2', '3'):
- for num in f_nums:
- test_fmt('', fill, alignment, sign, '', width, prec, type, num)
- for num in int_nums2:
- test_fmt('', fill, alignment, sign, '', width, '', type, num)
-
-pct_nums1 = (0.1, 0.58, 0.99, -0.1, -0.58, -0.99)
-pct_nums2 = (True, False, 1, 0, -1)
-
-if full_tests:
- type = '%'
- for width in ('', '4', '6', '8', '10'):
- for alignment in ('', '<', '>', '=', '^'):
- for fill in ('', ' ', '0', '@'):
- for sign in ('', '+', '-', ' '):
- # An empty precision defaults to 6, but when uPy is
- # configured to use a float, we can only use a
- # precision of 6 with numbers less than 10 and still
- # get results that compare to CPython (which uses
- # long doubles).
- for prec in ('1', '2', '3'):
- for num in pct_nums1:
- test_fmt('', fill, alignment, sign, '', width, prec, type, num)
- for num in pct_nums2:
- test_fmt('', fill, alignment, sign, '', width, '', type, num)
-
-# We don't currently test a type of '' with floats (see the detailed comment
-# in objstr.c)
-
# TODO Add tests for erroneous format strings.
-
diff --git a/tests/basics/true-value.py b/tests/basics/true-value.py
index 1dd547f326..9ec209fe82 100644
--- a/tests/basics/true-value.py
+++ b/tests/basics/true-value.py
@@ -9,12 +9,6 @@ if not None:
if not 0:
print("0")
-if not 0.0:
- print("float 0")
-
-if not 0+0j:
- print("complex 0")
-
if not "":
print("Empty string")
if "foo":
diff --git a/tests/basics/types1.py b/tests/basics/types1.py
index 57b33b842b..38a20d6803 100644
--- a/tests/basics/types1.py
+++ b/tests/basics/types1.py
@@ -2,8 +2,6 @@
print(bool)
print(int)
-print(float)
-print(complex)
print(tuple)
print(list)
print(set)
@@ -11,8 +9,6 @@ print(dict)
print(type(bool()) == bool)
print(type(int()) == int)
-print(type(float()) == float)
-print(type(complex()) == complex)
print(type(tuple()) == tuple)
print(type(list()) == list)
print(type(set()) == set)
@@ -20,8 +16,6 @@ print(type(dict()) == dict)
print(type(False) == bool)
print(type(0) == int)
-print(type(0.0) == float)
-print(type(1j) == complex)
print(type(()) == tuple)
print(type([]) == list)
print(type({None}) == set)
diff --git a/tests/basics/types2.py b/tests/basics/types2.py
index 83a69c918f..ba7be6b154 100644
--- a/tests/basics/types2.py
+++ b/tests/basics/types2.py
@@ -9,4 +9,6 @@ print(int == int)
print(int != list)
d = {}
-d[int] = float
+d[int] = list
+d[list] = int
+print(len(d))
diff --git a/tests/basics/float1.py b/tests/float/float1.py
index bf1305c3d5..bf1305c3d5 100644
--- a/tests/basics/float1.py
+++ b/tests/float/float1.py
diff --git a/tests/float/int-divzero.py b/tests/float/int-divzero.py
new file mode 100644
index 0000000000..b037dd8c7b
--- /dev/null
+++ b/tests/float/int-divzero.py
@@ -0,0 +1,4 @@
+try:
+ 1 / 0
+except ZeroDivisionError:
+ print("ZeroDivisionError")
diff --git a/tests/float/list-index.py b/tests/float/list-index.py
new file mode 100644
index 0000000000..13e4557af7
--- /dev/null
+++ b/tests/float/list-index.py
@@ -0,0 +1,8 @@
+x = [1, 2]
+
+print(x[1])
+
+try:
+ print(x[1.0])
+except TypeError:
+ print("TypeError")
diff --git a/tests/basics/math-fun-bool.py b/tests/float/math-fun-bool.py
index cf718d4b80..cf718d4b80 100644
--- a/tests/basics/math-fun-bool.py
+++ b/tests/float/math-fun-bool.py
diff --git a/tests/basics/math-fun.py b/tests/float/math-fun.py
index 7a37c58454..7a37c58454 100644
--- a/tests/basics/math-fun.py
+++ b/tests/float/math-fun.py
diff --git a/tests/float/modulo.py b/tests/float/modulo.py
new file mode 100644
index 0000000000..911268513a
--- /dev/null
+++ b/tests/float/modulo.py
@@ -0,0 +1,14 @@
+# check modulo matches python definition
+# TODO we currenty fail with this
+if False:
+ print(1.23456 % 0.7)
+ print(-1.23456 % 0.7)
+ print(1.23456 % -0.7)
+ print(-1.23456 % -0.7)
+
+ a = 1.23456
+ b = 0.7
+ print(a % b)
+ print(a % -b)
+ print(-a % b)
+ print(-a % -b)
diff --git a/tests/float/string-format-modulo.py b/tests/float/string-format-modulo.py
new file mode 100644
index 0000000000..f2117f3565
--- /dev/null
+++ b/tests/float/string-format-modulo.py
@@ -0,0 +1,16 @@
+print("%s" % 1.0)
+print("%r" % 1.0)
+
+print("%d" % 1.0)
+print("%i" % 1.0)
+print("%u" % 1.0)
+print("%x" % 18.0)
+print("%o" % 18.0)
+print("%X" % 18.0)
+
+print("%e" % 1.23456)
+print("%E" % 1.23456)
+print("%f" % 1.23456)
+print("%F" % 1.23456)
+print("%g" % 1.23456)
+print("%G" % 1.23456)
diff --git a/tests/float/string-format.py b/tests/float/string-format.py
new file mode 100644
index 0000000000..b5ff68b8ca
--- /dev/null
+++ b/tests/float/string-format.py
@@ -0,0 +1,123 @@
+# Change the following to True to get a much more comprehensive set of tests
+# to run, albeit, which take considerably longer.
+
+full_tests = False
+
+def test(fmt, *args):
+ print('{:8s}'.format(fmt) + '>' + fmt.format(*args) + '<')
+
+test("{:10.4e}", 123.456)
+test("{:10.4e}", -123.456)
+test("{:10.4f}", 123.456)
+test("{:10.4f}", -123.456)
+test("{:10.4g}", 123.456)
+test("{:10.4g}", -123.456)
+test("{:e}", 100)
+test("{:f}", 200)
+test("{:g}", 300)
+
+test("{:10.4E}", 123.456)
+test("{:10.4E}", -123.456)
+test("{:10.4F}", 123.456)
+test("{:10.4F}", -123.456)
+test("{:10.4G}", 123.456)
+test("{:10.4G}", -123.456)
+
+# The following fails right now
+#test("{:10.1}", 0.0)
+
+def test_fmt(conv, fill, alignment, sign, prefix, width, precision, type, arg):
+ fmt = '{'
+ if conv:
+ fmt += '!'
+ fmt += conv
+ fmt += ':'
+ if alignment:
+ fmt += fill
+ fmt += alignment
+ fmt += sign
+ fmt += prefix
+ fmt += width
+ if precision:
+ fmt += '.'
+ fmt += precision
+ fmt += type
+ fmt += '}'
+ test(fmt, arg)
+ if fill == '0' and alignment == '=':
+ fmt = '{:'
+ fmt += sign
+ fmt += prefix
+ fmt += width
+ if precision:
+ fmt += '.'
+ fmt += precision
+ fmt += type
+ fmt += '}'
+ test(fmt, arg)
+
+eg_nums = (0.0, -0.0, 0.1, 1.234, 12.3459, 1.23456789, 123456789.0, -0.0,
+ -0.1, -1.234, -12.3459, 1e4, 1e-4, 1e5, 1e-5, 1e6, 1e-6, 1e10,
+ 1e37, -1e37, 1e-37, -1e-37,
+ 1.23456e8, 1.23456e7, 1.23456e6, 1.23456e5, 1.23456e4, 1.23456e3, 1.23456e2, 1.23456e1, 1.23456e0,
+ 1.23456e-1, 1.23456e-2, 1.23456e-3, 1.23456e-4, 1.23456e-5, 1.23456e-6, 1.23456e-7, 1.23456e-8,
+ -1.23456e8, -1.23456e7, -1.23456e6, -1.23456e5, -1.23456e4, -1.23456e3, -1.23456e2, -1.23456e1, -1.23456e0,
+ -1.23456e-1, -1.23456e-2, -1.23456e-3, -1.23456e-4, -1.23456e-5, -1.23456e-6, -1.23456e-7, -1.23456e-8)
+
+if full_tests:
+ for type in ('e', 'E', 'g', 'G', 'n'):
+ for width in ('', '4', '6', '8', '10'):
+ for alignment in ('', '<', '>', '=', '^'):
+ for fill in ('', '@', '0', ' '):
+ for sign in ('', '+', '-', ' '):
+ for prec in ('', '1', '3', '6'):
+ for num in eg_nums:
+ test_fmt('', fill, alignment, sign, '', width, prec, type, num)
+
+# Note: We use 1.23459 rather than 1.2345 because '{:3f}'.format(1.2345)
+# rounds differently than print("%.3f", 1.2345);
+
+f_nums = (0.0, -0.0, 0.0001, 0.001, 0.01, 0.1, 1.0, 10.0,
+ 0.0012, 0.0123, 0.1234, 1.23459, 12.3456,
+ -0.0001, -0.001, -0.01, -0.1, -1.0, -10.0,
+ -0.0012, -0.0123, -0.1234, -1.23459, -12.3456)
+
+if full_tests:
+ for type in ('f', 'F'):
+ for width in ('', '4', '6', '8', '10'):
+ for alignment in ('', '<', '>', '=', '^'):
+ for fill in ('', ' ', '0', '@'):
+ for sign in ('', '+', '-', ' '):
+ # An empty precision defaults to 6, but when uPy is
+ # configured to use a float, we can only use a
+ # precision of 6 with numbers less than 10 and still
+ # get results that compare to CPython (which uses
+ # long doubles).
+ for prec in ('1', '2', '3'):
+ for num in f_nums:
+ test_fmt('', fill, alignment, sign, '', width, prec, type, num)
+ for num in int_nums2:
+ test_fmt('', fill, alignment, sign, '', width, '', type, num)
+
+pct_nums1 = (0.1, 0.58, 0.99, -0.1, -0.58, -0.99)
+pct_nums2 = (True, False, 1, 0, -1)
+
+if full_tests:
+ type = '%'
+ for width in ('', '4', '6', '8', '10'):
+ for alignment in ('', '<', '>', '=', '^'):
+ for fill in ('', ' ', '0', '@'):
+ for sign in ('', '+', '-', ' '):
+ # An empty precision defaults to 6, but when uPy is
+ # configured to use a float, we can only use a
+ # precision of 6 with numbers less than 10 and still
+ # get results that compare to CPython (which uses
+ # long doubles).
+ for prec in ('1', '2', '3'):
+ for num in pct_nums1:
+ test_fmt('', fill, alignment, sign, '', width, prec, type, num)
+ for num in pct_nums2:
+ test_fmt('', fill, alignment, sign, '', width, '', type, num)
+
+# We don't currently test a type of '' with floats (see the detailed comment
+# in objstr.c)
diff --git a/tests/float/true-value.py b/tests/float/true-value.py
new file mode 100644
index 0000000000..df415f0031
--- /dev/null
+++ b/tests/float/true-value.py
@@ -0,0 +1,7 @@
+# Test true-ish value handling
+
+if not 0.0:
+ print("float 0")
+
+if not 0+0j:
+ print("complex 0")
diff --git a/tests/float/types.py b/tests/float/types.py
new file mode 100644
index 0000000000..75674c9246
--- /dev/null
+++ b/tests/float/types.py
@@ -0,0 +1,17 @@
+# float types
+
+print(float)
+print(complex)
+
+print(type(float()) == float)
+print(type(complex()) == complex)
+
+print(type(0.0) == float)
+print(type(1j) == complex)
+
+# hashing float types
+
+d = dict()
+d[float] = complex
+d[complex] = float
+print(len(d))
diff --git a/tests/basics/import-pkg1.py b/tests/import/import-pkg1.py
index 8cd77af79d..8cd77af79d 100644
--- a/tests/basics/import-pkg1.py
+++ b/tests/import/import-pkg1.py
diff --git a/tests/basics/import-pkg2.py b/tests/import/import-pkg2.py
index 2e9f34121b..2e9f34121b 100644
--- a/tests/basics/import-pkg2.py
+++ b/tests/import/import-pkg2.py
diff --git a/tests/basics/import-pkg3.py b/tests/import/import-pkg3.py
index 0ee885b220..0ee885b220 100644
--- a/tests/basics/import-pkg3.py
+++ b/tests/import/import-pkg3.py
diff --git a/tests/basics/import-pkg4.py b/tests/import/import-pkg4.py
index 90b6f2e0ee..90b6f2e0ee 100644
--- a/tests/basics/import-pkg4.py
+++ b/tests/import/import-pkg4.py
diff --git a/tests/basics/import-pkg5.py b/tests/import/import-pkg5.py
index aa74bb45f0..aa74bb45f0 100644
--- a/tests/basics/import-pkg5.py
+++ b/tests/import/import-pkg5.py
diff --git a/tests/basics/import1a.py b/tests/import/import1a.py
index 16b2d4d30f..16b2d4d30f 100644
--- a/tests/basics/import1a.py
+++ b/tests/import/import1a.py
diff --git a/tests/basics/import1b.py b/tests/import/import1b.py
index be74eca094..be74eca094 100644
--- a/tests/basics/import1b.py
+++ b/tests/import/import1b.py
diff --git a/tests/basics/import2a.py b/tests/import/import2a.py
index ce32b10b1b..ce32b10b1b 100644
--- a/tests/basics/import2a.py
+++ b/tests/import/import2a.py
diff --git a/tests/basics/import3a.py b/tests/import/import3a.py
index 2e9d41f71d..2e9d41f71d 100644
--- a/tests/basics/import3a.py
+++ b/tests/import/import3a.py
diff --git a/tests/basics/pkg/__init__.py b/tests/import/pkg/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/tests/basics/pkg/__init__.py
+++ b/tests/import/pkg/__init__.py
diff --git a/tests/basics/pkg/mod.py b/tests/import/pkg/mod.py
index 9e67bdd291..9e67bdd291 100644
--- a/tests/basics/pkg/mod.py
+++ b/tests/import/pkg/mod.py
diff --git a/tests/basics/pkg2/__init__.py b/tests/import/pkg2/__init__.py
index 101ac7d400..101ac7d400 100644
--- a/tests/basics/pkg2/__init__.py
+++ b/tests/import/pkg2/__init__.py
diff --git a/tests/basics/pkg2/mod1.py b/tests/import/pkg2/mod1.py
index 03754a45f6..03754a45f6 100644
--- a/tests/basics/pkg2/mod1.py
+++ b/tests/import/pkg2/mod1.py
diff --git a/tests/basics/pkg2/mod2.py b/tests/import/pkg2/mod2.py
index 97dadcde46..97dadcde46 100644
--- a/tests/basics/pkg2/mod2.py
+++ b/tests/import/pkg2/mod2.py
diff --git a/tests/basics/pkg3/__init__.py b/tests/import/pkg3/__init__.py
index 8b92fa9967..8b92fa9967 100644
--- a/tests/basics/pkg3/__init__.py
+++ b/tests/import/pkg3/__init__.py
diff --git a/tests/basics/pkg3/mod1.py b/tests/import/pkg3/mod1.py
index 28a0f5bf10..28a0f5bf10 100644
--- a/tests/basics/pkg3/mod1.py
+++ b/tests/import/pkg3/mod1.py
diff --git a/tests/basics/pkg3/mod2.py b/tests/import/pkg3/mod2.py
index 67f43bad52..67f43bad52 100644
--- a/tests/basics/pkg3/mod2.py
+++ b/tests/import/pkg3/mod2.py
diff --git a/tests/basics/pkg3/subpkg1/__init__.py b/tests/import/pkg3/subpkg1/__init__.py
index 72b5423958..72b5423958 100644
--- a/tests/basics/pkg3/subpkg1/__init__.py
+++ b/tests/import/pkg3/subpkg1/__init__.py
diff --git a/tests/basics/pkg3/subpkg1/mod1.py b/tests/import/pkg3/subpkg1/mod1.py
index 7a2ae44b54..7a2ae44b54 100644
--- a/tests/basics/pkg3/subpkg1/mod1.py
+++ b/tests/import/pkg3/subpkg1/mod1.py
diff --git a/tests/basics/try-module.py b/tests/import/try-module.py
index 03a9db15b5..03a9db15b5 100644
--- a/tests/basics/try-module.py
+++ b/tests/import/try-module.py
diff --git a/tests/run-tests b/tests/run-tests
index bd6e50bbd2..9e94026fa2 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -10,10 +10,10 @@ from glob import glob
# to the correct executable.
if os.name == 'nt':
CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe')
- MP_PY = '../windows/micropython.exe'
+ MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../windows/micropython.exe')
else:
CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3')
- MP_PY = '../unix/micropython'
+ 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'])
@@ -29,7 +29,8 @@ failed_tests = []
tests = []
if not sys.argv[1:]:
- tests = sorted(glob('basics/*.py') + glob('io/*.py') + glob('misc/*.py'))
+ 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:]
@@ -39,7 +40,7 @@ if test_on_pyboard:
pyb = pyboard.Pyboard('/dev/ttyACM0')
pyb.enter_raw_repl()
-running_under_travis = os.environ.get('TRAVIS', 'false') == 'true'
+running_under_travis = os.getenv('TRAVIS') == 'true'
for test_file in tests:
if running_under_travis and test_file in skip_travis_tests:
@@ -56,16 +57,12 @@ for test_file in tests:
if test_on_pyboard:
pyb.enter_raw_repl()
try:
- if test_file == 'basics/memoryerror.py':
- # this test crashes the pyboard
- output_mupy = b'CRASH'
- else:
- output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n')
+ output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n')
except pyboard.PyboardError:
- output_mupy = b'CRASH\n' + output_mupy
+ output_mupy = b'CRASH'
else:
try:
- output_mupy = subprocess.check_output([MP_PY, '-X', 'emit=bytecode', test_file])
+ output_mupy = subprocess.check_output([MICROPYTHON, '-X', 'emit=bytecode', test_file])
except subprocess.CalledProcessError:
output_mupy = b'CRASH'
diff --git a/unix/Makefile b/unix/Makefile
index 64483d90df..1a29363c91 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -71,3 +71,8 @@ OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
include ../py/mkrules.mk
+.PHONY: test
+
+test: $(PROG) ../tests/run-tests
+ $(eval DIRNAME=$(notdir $(CURDIR)))
+ cd ../tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests
diff --git a/unix/modffi.c b/unix/modffi.c
index cb6a4424f3..f2bd6fcecf 100644
--- a/unix/modffi.c
+++ b/unix/modffi.c
@@ -61,6 +61,8 @@ STATIC ffi_type *char2ffi_type(char c)
case 'I': return &ffi_type_uint;
case 'l': return &ffi_type_slong;
case 'L': return &ffi_type_ulong;
+ case 'f': return &ffi_type_float;
+ case 'd': return &ffi_type_double;
case 'p':
case 's': return &ffi_type_pointer;
case 'v': return &ffi_type_void;
@@ -92,6 +94,14 @@ STATIC mp_obj_t return_ffi_value(ffi_arg val, char type)
}
case 'v':
return mp_const_none;
+ case 'f': {
+ float *p = (float*)&val;
+ return mp_obj_new_float(*p);
+ }
+ case 'd': {
+ double *p = (double*)&val;
+ return mp_obj_new_float(*p);
+ }
default:
return mp_obj_new_int(val);
}
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index 9c91b757a8..cf6e6fae26 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -10,12 +10,12 @@
#define MICROPY_ENABLE_REPL_HELPERS (1)
#define MICROPY_ENABLE_LEXER_UNIX (1)
#define MICROPY_ENABLE_SOURCE_LINE (1)
-#define MICROPY_ENABLE_PROPERTY (1)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_PATH_MAX (PATH_MAX)
#define MICROPY_USE_COMPUTED_GOTOS (1)
#define MICROPY_MOD_SYS_STDFILES (1)
+#define MICROPY_ENABLE_MOD_CMATH (1)
// type definitions for the specific machine