summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--bare-arm/Makefile2
-rw-r--r--bare-arm/mpconfigport.h4
-rw-r--r--py/asmthumb.c2
-rw-r--r--py/asmx64.c2
-rw-r--r--py/binary.c50
-rw-r--r--py/binary.h1
-rw-r--r--py/builtin.c54
-rw-r--r--py/builtintables.c16
-rw-r--r--py/compile.c10
-rw-r--r--py/emit.h5
-rw-r--r--py/emitbc.c13
-rw-r--r--py/emitcommon.c2
-rw-r--r--py/emitcpy.c13
-rw-r--r--py/emitglue.c2
-rw-r--r--py/emitinlinethumb.c6
-rw-r--r--py/emitnative.c119
-rw-r--r--py/emitpass1.c6
-rw-r--r--py/gc.c12
-rw-r--r--py/gc.h1
-rw-r--r--py/lexer.c37
-rw-r--r--py/lexerstr.c2
-rw-r--r--py/lexerunix.c2
-rw-r--r--py/malloc.c2
-rw-r--r--py/map.c2
-rw-r--r--py/misc.h20
-rw-r--r--py/mkrules.mk10
-rw-r--r--py/modarray.c10
-rw-r--r--py/modcmath.c6
-rw-r--r--py/modcollections.c6
-rw-r--r--py/modgc.c22
-rw-r--r--py/modio.c6
-rw-r--r--py/modmath.c6
-rw-r--r--py/modmicropython.c6
-rw-r--r--py/modstruct.c6
-rw-r--r--py/modsys.c6
-rw-r--r--py/mpconfig.h32
-rw-r--r--py/mpz.c2
-rw-r--r--py/nlr.h3
-rw-r--r--py/nlrthumb.S12
-rw-r--r--py/obj.c12
-rw-r--r--py/objarray.c4
-rw-r--r--py/objcomplex.c2
-rw-r--r--py/objenumerate.c4
-rw-r--r--py/objexcept.c8
-rw-r--r--py/objfloat.c5
-rw-r--r--py/objfun.c6
-rw-r--r--py/objint_mpz.c2
-rw-r--r--py/objstr.c112
-rw-r--r--py/objstr.h48
-rw-r--r--py/objstrunicode.c359
-rw-r--r--py/parse.c2
-rw-r--r--py/parsehelper.c2
-rw-r--r--py/parsenum.c8
-rw-r--r--py/parsenumbase.c2
-rw-r--r--py/pfenv.c2
-rw-r--r--py/py.mk2
-rw-r--r--py/qstr.c2
-rw-r--r--py/qstrdefs.h2
-rw-r--r--py/repl.c2
-rw-r--r--py/runtime.c5
-rw-r--r--py/scope.c2
-rw-r--r--py/smallint.c2
-rw-r--r--py/stackctrl.c63
-rw-r--r--py/stackctrl.h41
-rw-r--r--py/stream.c11
-rw-r--r--py/unicode.c53
-rw-r--r--py/unicode.h1
-rw-r--r--py/vstr.c40
-rw-r--r--stmhal/adc.c4
-rw-r--r--stmhal/boards/HYDRABUS/mpconfigboard.h1
-rw-r--r--stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h1
-rw-r--r--stmhal/boards/PYBV10/mpconfigboard.h1
-rw-r--r--stmhal/boards/PYBV3/mpconfigboard.h1
-rw-r--r--stmhal/boards/PYBV4/mpconfigboard.h1
-rw-r--r--stmhal/boards/STM32F4DISC/mpconfigboard.h1
-rw-r--r--stmhal/boards/stm32f4xx-prefix.c2
-rw-r--r--stmhal/bufhelper.c2
-rw-r--r--stmhal/dac.c2
-rw-r--r--stmhal/diskio.c2
-rw-r--r--stmhal/extint.c2
-rw-r--r--stmhal/gccollect.c6
-rw-r--r--stmhal/i2c.c10
-rw-r--r--stmhal/import.c2
-rw-r--r--stmhal/led.c2
-rw-r--r--stmhal/lexerfatfs.c2
-rw-r--r--stmhal/main.c14
-rw-r--r--stmhal/math.c13
-rw-r--r--stmhal/modos.c4
-rw-r--r--stmhal/modpyb.c4
-rw-r--r--stmhal/modstm.c4
-rw-r--r--stmhal/modtime.c4
-rw-r--r--stmhal/mpconfigport.h4
-rw-r--r--stmhal/mphal.h7
-rw-r--r--stmhal/pendsv.c2
-rw-r--r--stmhal/pin.c21
-rw-r--r--stmhal/pin.h80
-rw-r--r--stmhal/pin_defs_stmhal.h96
-rw-r--r--stmhal/pin_named_pins.c5
-rw-r--r--stmhal/printf.c2
-rw-r--r--stmhal/pybstdio.c6
-rw-r--r--stmhal/pyexec.c6
-rw-r--r--stmhal/readline.c6
-rw-r--r--stmhal/rng.c2
-rw-r--r--stmhal/rtc.c2
-rw-r--r--stmhal/sdcard.c2
-rw-r--r--stmhal/spi.c10
-rw-r--r--stmhal/stm32f4xx_hal_msp.c2
-rw-r--r--stmhal/stm32f4xx_it.c2
-rw-r--r--stmhal/storage.c2
-rw-r--r--stmhal/systick.c1
-rw-r--r--stmhal/timer.c4
-rw-r--r--stmhal/uart.c6
-rw-r--r--stmhal/usrsw.c2
-rw-r--r--teensy/Makefile59
-rw-r--r--teensy/hal_gpio.c115
-rw-r--r--teensy/help.c123
-rw-r--r--teensy/import.c22
-rw-r--r--teensy/lcd.c7
-rw-r--r--teensy/led.c136
-rw-r--r--teensy/led.h4
-rw-r--r--teensy/lexerfatfs.c11
-rw-r--r--teensy/lexermemzip.c2
-rw-r--r--teensy/main.c409
-rwxr-xr-xteensy/make-pins.py326
-rw-r--r--teensy/memzip.c86
-rw-r--r--teensy/memzip.h10
-rw-r--r--teensy/memzip_files/boot.py1
-rw-r--r--teensy/memzip_files/main.py (renamed from teensy/memzip_files/src/main.py)10
-rw-r--r--teensy/memzip_files/src/test.py1
-rw-r--r--teensy/memzip_files/test.py1
-rw-r--r--teensy/mk20dx256-af.csv65
-rw-r--r--teensy/mk20dx256-prefix.c37
-rw-r--r--teensy/mk20dx256.ld196
-rw-r--r--teensy/modpyb.c341
-rw-r--r--teensy/mpconfigport.h84
-rw-r--r--teensy/pin_defs_teensy.h46
-rw-r--r--teensy/qstrdefsport.h62
-rw-r--r--teensy/servo.h7
-rw-r--r--teensy/teensy-pins.csv55
-rw-r--r--teensy/teensy_hal.c16
-rw-r--r--teensy/teensy_hal.h111
-rw-r--r--teensy/uart.c522
-rw-r--r--teensy/usart.c38
-rw-r--r--teensy/usb.c9
-rw-r--r--tests/basics/struct1.py4
-rw-r--r--tests/float/math-fun-bool.py7
-rw-r--r--tests/float/math-fun.py7
-rw-r--r--tests/misc/recursion.py7
-rw-r--r--tests/misc/recursive_data.py_9
-rwxr-xr-xtests/run-tests8
-rw-r--r--tests/unicode/data/utf-8_1.txt1
-rw-r--r--tests/unicode/file1.py4
-rw-r--r--tests/unicode/unicode.py18
-rw-r--r--tests/unicode/unicode_index.py6
-rw-r--r--tests/unicode/unicode_iter.py4
-rw-r--r--tests/unicode/unicode_pos.py5
-rw-r--r--tools/gendoc.py18
-rw-r--r--unix/Makefile32
-rw-r--r--unix/gccollect.c14
-rw-r--r--unix/input.c2
-rw-r--r--unix/main.c21
-rw-r--r--unix/modffi.c11
-rw-r--r--unix/modos.c6
-rw-r--r--unix/modsocket.c31
-rw-r--r--unix/modtime.c6
-rw-r--r--unix/mpconfigport.h3
-rw-r--r--windows/Makefile2
-rw-r--r--windows/bss.c74
-rw-r--r--windows/init.c3
-rw-r--r--windows/mpconfigport.h35
-rw-r--r--windows/msvc/common.props3
-rw-r--r--windows/msvc/sources.props2
173 files changed, 4012 insertions, 922 deletions
diff --git a/.travis.yml b/.travis.yml
index e6c12b9677..489cceaa27 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,4 +20,4 @@ script:
- (cd tests && MICROPY_CPYTHON3=python3.3 ./run-tests)
after_failure:
- - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff $testbase.exp $testbase.out; done)
+ - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done)
diff --git a/bare-arm/Makefile b/bare-arm/Makefile
index ed8c00482b..eeaaf423d0 100644
--- a/bare-arm/Makefile
+++ b/bare-arm/Makefile
@@ -22,7 +22,7 @@ else
CFLAGS += -Os -DNDEBUG
endif
-LDFLAGS = -nostdlib -T stm32f405.ld
+LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref
LIBS =
SRC_C = \
diff --git a/bare-arm/mpconfigport.h b/bare-arm/mpconfigport.h
index 1587dca57a..8598735480 100644
--- a/bare-arm/mpconfigport.h
+++ b/bare-arm/mpconfigport.h
@@ -12,10 +12,12 @@
#define MICROPY_HELPER_REPL (0)
#define MICROPY_HELPER_LEXER_UNIX (0)
#define MICROPY_ENABLE_SOURCE_LINE (0)
+#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
#define MICROPY_PY_BUILTINS_FROZENSET (0)
#define MICROPY_PY_BUILTINS_SET (0)
#define MICROPY_PY_BUILTINS_SLICE (0)
#define MICROPY_PY_BUILTINS_PROPERTY (0)
+#define MICROPY_PY_ARRAY (0)
#define MICROPY_PY_COLLECTIONS (0)
#define MICROPY_PY_MATH (0)
#define MICROPY_PY_CMATH (0)
@@ -26,6 +28,8 @@
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
+//#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
+
// type definitions for the specific machine
#define BYTES_PER_WORD (4)
diff --git a/py/asmthumb.c b/py/asmthumb.c
index 891947567b..03752ed938 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -28,8 +28,8 @@
#include <assert.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "asmthumb.h"
// wrapper around everything in this file
diff --git a/py/asmx64.c b/py/asmx64.c
index 6c22ea25de..4695bdc731 100644
--- a/py/asmx64.c
+++ b/py/asmx64.c
@@ -29,8 +29,8 @@
#include <assert.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
// wrapper around everything in this file
#if MICROPY_EMIT_X64
diff --git a/py/binary.c b/py/binary.c
index 833d9c85ad..d755bc86e0 100644
--- a/py/binary.c
+++ b/py/binary.c
@@ -29,8 +29,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "binary.h"
@@ -125,24 +125,9 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) {
return MP_OBJ_NEW_SMALL_INT(val);
}
-#define is_signed(typecode) (typecode > 'Z')
-mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
- byte *p = *ptr;
- uint align;
-
- int size = mp_binary_get_size(struct_type, val_type, &align);
- if (struct_type == '@') {
- // Make pointer aligned
- p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1));
- #if MP_ENDIANNESS_LITTLE
- struct_type = '<';
- #else
- struct_type = '>';
- #endif
- }
-
+machine_int_t mp_binary_get_int(uint size, bool is_signed, bool big_endian, byte *p) {
int delta;
- if (struct_type == '<') {
+ if (!big_endian) {
delta = -1;
p += size - 1;
} else {
@@ -150,7 +135,7 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
}
machine_int_t val = 0;
- if (is_signed(val_type) && *p & 0x80) {
+ if (is_signed && *p & 0x80) {
val = -1;
}
for (uint i = 0; i < size; i++) {
@@ -159,7 +144,28 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
p += delta;
}
- *ptr += size;
+ return val;
+}
+
+#define is_signed(typecode) (typecode > 'Z')
+mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
+ byte *p = *ptr;
+ uint align;
+
+ int size = mp_binary_get_size(struct_type, val_type, &align);
+ if (struct_type == '@') {
+ // Make pointer aligned
+ p = (byte*)(((machine_uint_t)p + align - 1) & ~((machine_uint_t)align - 1));
+ #if MP_ENDIANNESS_LITTLE
+ struct_type = '<';
+ #else
+ struct_type = '>';
+ #endif
+ }
+ *ptr = p + size;
+
+ machine_int_t val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);
+
if (val_type == 'O') {
return (mp_obj_t)val;
} else if (val_type == 'S') {
@@ -178,13 +184,14 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
int size = mp_binary_get_size(struct_type, val_type, &align);
if (struct_type == '@') {
// Make pointer aligned
- p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1));
+ p = (byte*)(((machine_uint_t)p + align - 1) & ~((machine_uint_t)align - 1));
#if MP_ENDIANNESS_LITTLE
struct_type = '<';
#else
struct_type = '>';
#endif
}
+ *ptr = p + size;
#if MP_ENDIANNESS_BIG
#error Not implemented
@@ -215,7 +222,6 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
in += in_delta;
}
- *ptr += size;
}
void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in) {
diff --git a/py/binary.h b/py/binary.h
index f15a2fd7fb..63ea5d741e 100644
--- a/py/binary.h
+++ b/py/binary.h
@@ -34,3 +34,4 @@ void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in)
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine_int_t val);
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr);
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr);
+machine_int_t mp_binary_get_int(uint size, bool is_signed, bool big_endian, byte *p);
diff --git a/py/builtin.c b/py/builtin.c
index 834108f1b5..f4bbe0e237 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -113,11 +113,13 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
} else {
return o_in;
}
+#if MICROPY_PY_BUILTINS_COMPLEX
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) {
mp_float_t real, imag;
mp_obj_complex_get(o_in, &real, &imag);
return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag));
#endif
+#endif
} else {
assert(0);
return mp_const_none;
@@ -154,7 +156,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any);
STATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) {
mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in };
- return mp_obj_str_format(ARRAY_SIZE(args), args);
+ return mp_obj_str_format(MP_ARRAY_SIZE(args), args);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin);
@@ -170,13 +172,40 @@ STATIC mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable);
STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
- int ord = mp_obj_get_int(o_in);
+ #if MICROPY_PY_BUILTINS_STR_UNICODE
+ machine_int_t c = mp_obj_get_int(o_in);
+ char str[4];
+ int len = 0;
+ if (c < 0x80) {
+ *str = c; len = 1;
+ } else if (c < 0x800) {
+ str[0] = (c >> 6) | 0xC0;
+ str[1] = (c & 0x3F) | 0x80;
+ len = 2;
+ } else if (c < 0x10000) {
+ str[0] = (c >> 12) | 0xE0;
+ str[1] = ((c >> 6) & 0x3F) | 0x80;
+ str[2] = (c & 0x3F) | 0x80;
+ len = 3;
+ } else if (c < 0x110000) {
+ str[0] = (c >> 18) | 0xF0;
+ str[1] = ((c >> 12) & 0x3F) | 0x80;
+ str[2] = ((c >> 6) & 0x3F) | 0x80;
+ str[3] = (c & 0x3F) | 0x80;
+ len = 4;
+ } else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"));
+ }
+ return mp_obj_new_str(str, len, true);
+ #else
+ machine_int_t ord = mp_obj_get_int(o_in);
if (0 <= ord && ord <= 0x10ffff) {
char str[1] = {ord};
return mp_obj_new_str(str, 1, true);
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"));
}
+ #endif
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr);
@@ -342,13 +371,32 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct);
STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
uint len;
const char *str = mp_obj_str_get_data(o_in, &len);
+ #if MICROPY_PY_BUILTINS_STR_UNICODE
+ machine_uint_t charlen = unichar_charlen(str, len);
+ if (charlen == 1) {
+ if (MP_OBJ_IS_STR(o_in) && UTF8_IS_NONASCII(*str)) {
+ machine_int_t ord = *str++ & 0x7F;
+ for (machine_int_t mask = 0x40; ord & mask; mask >>= 1) {
+ ord &= ~mask;
+ }
+ while (UTF8_IS_CONT(*str)) {
+ ord = (ord << 6) | (*str++ & 0x3F);
+ }
+ return mp_obj_new_int(ord);
+ } else {
+ return mp_obj_new_int(((const byte*)str)[0]);
+ }
+ } else {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", charlen));
+ }
+ #else
if (len == 1) {
// don't sign extend when converting to ord
- // TODO unicode
return mp_obj_new_int(((const byte*)str)[0]);
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", len));
}
+ #endif
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord);
diff --git a/py/builtintables.c b/py/builtintables.c
index 857a581de4..c42cdf89bb 100644
--- a/py/builtintables.c
+++ b/py/builtintables.c
@@ -26,8 +26,8 @@
#include <stdlib.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -43,8 +43,10 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
// built-in types
{ MP_OBJ_NEW_QSTR(MP_QSTR_bool), (mp_obj_t)&mp_type_bool },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytes), (mp_obj_t)&mp_type_bytes },
+#if MICROPY_PY_BUILTINS_BYTEARRAY
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytearray), (mp_obj_t)&mp_type_bytearray },
-#if MICROPY_PY_BUILTINS_FLOAT
+#endif
+#if MICROPY_PY_BUILTINS_COMPLEX
{ MP_OBJ_NEW_QSTR(MP_QSTR_complex), (mp_obj_t)&mp_type_complex },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&mp_type_dict },
@@ -150,8 +152,8 @@ const mp_obj_dict_t mp_builtin_object_dict_obj = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_builtin_object_table),
- .alloc = ARRAY_SIZE(mp_builtin_object_table),
+ .used = MP_ARRAY_SIZE(mp_builtin_object_table),
+ .alloc = MP_ARRAY_SIZE(mp_builtin_object_table),
.table = (mp_map_elem_t*)mp_builtin_object_table,
},
};
@@ -160,7 +162,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___main__), (mp_obj_t)&mp_module___main__ },
{ MP_OBJ_NEW_QSTR(MP_QSTR_micropython), (mp_obj_t)&mp_module_micropython },
+#if MICROPY_PY_ARRAY
{ MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&mp_module_array },
+#endif
#if MICROPY_PY_IO
{ MP_OBJ_NEW_QSTR(MP_QSTR__io), (mp_obj_t)&mp_module_io },
#endif
@@ -195,8 +199,8 @@ const mp_obj_dict_t mp_builtin_module_dict_obj = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_builtin_module_table),
- .alloc = ARRAY_SIZE(mp_builtin_module_table),
+ .used = MP_ARRAY_SIZE(mp_builtin_module_table),
+ .alloc = MP_ARRAY_SIZE(mp_builtin_module_table),
.table = (mp_map_elem_t*)mp_builtin_module_table,
},
};
diff --git a/py/compile.c b/py/compile.c
index 946c8924b2..f2a108074f 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -31,8 +31,8 @@
#include <assert.h>
#include <math.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -111,8 +111,8 @@ STATIC const mp_map_elem_t mp_constants_table[] = {
STATIC const mp_map_t mp_constants_map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_constants_table),
- .alloc = ARRAY_SIZE(mp_constants_table),
+ .used = MP_ARRAY_SIZE(mp_constants_table),
+ .alloc = MP_ARRAY_SIZE(mp_constants_table),
.table = (mp_map_elem_t*)mp_constants_table,
};
@@ -1894,7 +1894,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
EMIT_ARG(jump, success_label); // jump over exception handler
EMIT_ARG(label_assign, l1); // start of exception handler
- EMIT_ARG(adjust_stack_size, 6); // stack adjust for the 3 exception items, +3 for possible UNWIND_JUMP state
+ EMIT(start_except_handler);
uint l2 = comp_next_label(comp);
@@ -1966,7 +1966,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
compile_decrease_except_level(comp);
EMIT(end_finally);
- EMIT_ARG(adjust_stack_size, -5); // stack adjust
+ EMIT(end_except_handler);
EMIT_ARG(label_assign, success_label);
compile_node(comp, pn_else); // else block, can be null
diff --git a/py/emit.h b/py/emit.h
index 874ec8819a..03834cb213 100644
--- a/py/emit.h
+++ b/py/emit.h
@@ -134,6 +134,11 @@ typedef struct _emit_method_table_t {
void (*yield_value)(emit_t *emit);
void (*yield_from)(emit_t *emit);
+ // these methods are used to control entry to/exit from an exception handler
+ // they may or may not emit code
+ void (*start_except_handler)(emit_t *emit);
+ void (*end_except_handler)(emit_t *emit);
+
#if MICROPY_EMIT_CPYTHON
// these methods are only needed for emitcpy
void (*load_const_verbatim_str)(emit_t *emit, const char *str);
diff --git a/py/emitbc.c b/py/emitbc.c
index 841dd4aabb..f9fbed4aaf 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -849,6 +849,14 @@ STATIC void emit_bc_yield_from(emit_t *emit) {
emit_write_bytecode_byte(emit, MP_BC_YIELD_FROM);
}
+STATIC void emit_bc_start_except_handler(emit_t *emit) {
+ emit_bc_adjust_stack_size(emit, 6); // stack adjust for the 3 exception items, +3 for possible UNWIND_JUMP state
+}
+
+STATIC void emit_bc_end_except_handler(emit_t *emit) {
+ emit_bc_adjust_stack_size(emit, -5); // stack adjust
+}
+
const emit_method_table_t emit_bc_method_table = {
emit_bc_set_native_types,
emit_bc_start_pass,
@@ -934,6 +942,9 @@ const emit_method_table_t emit_bc_method_table = {
emit_bc_raise_varargs,
emit_bc_yield_value,
emit_bc_yield_from,
+
+ emit_bc_start_except_handler,
+ emit_bc_end_except_handler,
};
#endif // !MICROPY_EMIT_CPYTHON
diff --git a/py/emitcommon.c b/py/emitcommon.c
index ea65183623..4649793134 100644
--- a/py/emitcommon.c
+++ b/py/emitcommon.c
@@ -28,8 +28,8 @@
#include <stdint.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
diff --git a/py/emitcpy.c b/py/emitcpy.c
index a8a6265b8c..4ff99866a0 100644
--- a/py/emitcpy.c
+++ b/py/emitcpy.c
@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -792,6 +792,14 @@ STATIC void emit_cpy_yield_from(emit_t *emit) {
}
}
+STATIC void emit_cpy_start_except_handler(emit_t *emit) {
+ emit_cpy_adjust_stack_size(emit, 3); // stack adjust for the 3 exception items
+}
+
+STATIC void emit_cpy_end_except_handler(emit_t *emit) {
+ emit_cpy_adjust_stack_size(emit, -5); // stack adjust
+}
+
STATIC void emit_cpy_load_const_verbatim_str(emit_t *emit, const char *str) {
emit_pre(emit, 1, 3);
if (emit->pass == MP_PASS_EMIT) {
@@ -899,6 +907,9 @@ const emit_method_table_t emit_cpython_method_table = {
emit_cpy_yield_value,
emit_cpy_yield_from,
+ emit_cpy_start_except_handler,
+ emit_cpy_end_except_handler,
+
// emitcpy specific functions
emit_cpy_load_const_verbatim_str,
emit_cpy_load_closure,
diff --git a/py/emitglue.c b/py/emitglue.c
index f9b9460837..17dc8f867c 100644
--- a/py/emitglue.c
+++ b/py/emitglue.c
@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index 79ed1c4a02..435e1b64d9 100644
--- a/py/emitinlinethumb.c
+++ b/py/emitinlinethumb.c
@@ -30,8 +30,8 @@
#include <stdarg.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -167,7 +167,7 @@ STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t
if (MP_PARSE_NODE_IS_ID(pn)) {
qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn);
const char *reg_str = qstr_str(reg_qstr);
- for (uint i = 0; i < ARRAY_SIZE(reg_name_table); i++) {
+ for (uint i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) {
const reg_name_t *r = &reg_name_table[i];
if (reg_str[0] == r->name[0] && reg_str[1] == r->name[1] && reg_str[2] == r->name[2] && (reg_str[2] == '\0' || reg_str[3] == '\0')) {
if (r->reg > max_reg) {
@@ -286,7 +286,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
asm_thumb_b_n(emit->as, label_num);
} else if (op_str[0] == 'b' && op_len == 3) {
uint cc = -1;
- for (uint i = 0; i < ARRAY_SIZE(cc_name_table); i++) {
+ for (uint i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) {
if (op_str[1] == cc_name_table[i].name[0] && op_str[2] == cc_name_table[i].name[1]) {
cc = cc_name_table[i].cc;
}
diff --git a/py/emitnative.c b/py/emitnative.c
index 4dac5ffb09..4cab3f4697 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -48,8 +48,9 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "nlr.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -723,7 +724,11 @@ STATIC void emit_native_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
assert(0);
emit_post_push_imm(emit, VTYPE_PTR, (machine_uint_t)qstr_str(qstr));
} else {
- emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_STR, mp_load_const_str, qstr, REG_ARG_1);
+ if (bytes) {
+ emit_call_with_imm_arg(emit, 0, mp_load_const_bytes, qstr, REG_ARG_1); // TODO need to add function to runtime table
+ } else {
+ emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_STR, mp_load_const_str, qstr, REG_ARG_1);
+ }
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
}
@@ -917,8 +922,11 @@ STATIC void emit_native_delete_global(emit_t *emit, qstr qstr) {
}
STATIC void emit_native_delete_attr(emit_t *emit, qstr qstr) {
- // not supported
- assert(0);
+ vtype_kind_t vtype_base;
+ emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
+ assert(vtype_base == VTYPE_PYOBJ);
+ emit_call_with_2_imm_args(emit, MP_F_STORE_ATTR, mp_store_attr, qstr, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); // arg2 = attribute name, arg3 = value (null for delete)
+ emit_post(emit);
}
STATIC void emit_native_delete_subscr(emit_t *emit) {
@@ -1054,17 +1062,33 @@ STATIC void emit_native_setup_with(emit_t *emit, uint label) {
// not supported, or could be with runtime call
assert(0);
}
+
STATIC void emit_native_with_cleanup(emit_t *emit) {
assert(0);
}
+
STATIC void emit_native_setup_except(emit_t *emit, uint label) {
- assert(0);
+ emit_native_pre(emit);
+ // need to commit stack because we may jump elsewhere
+ need_stack_settled(emit);
+ emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_1, sizeof(nlr_buf_t) / sizeof(machine_uint_t)); // arg1 = pointer to nlr buf
+ emit_call(emit, 0, nlr_push); // TODO need to add function to runtime table
+#if N_X64
+ asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
+ asm_x64_jcc_label(emit->as, JCC_JNZ, label);
+#elif N_THUMB
+ asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
+ asm_thumb_bcc_label(emit->as, THUMB_CC_NE, label);
+#endif
+ emit_post(emit);
}
+
STATIC void emit_native_setup_finally(emit_t *emit, uint label) {
assert(0);
}
+
STATIC void emit_native_end_finally(emit_t *emit) {
- assert(0);
+ //assert(0);
}
STATIC void emit_native_get_iter(emit_t *emit) {
@@ -1104,19 +1128,31 @@ STATIC void emit_native_for_iter_end(emit_t *emit) {
STATIC void emit_native_pop_block(emit_t *emit) {
emit_native_pre(emit);
+ emit_call(emit, 0, nlr_pop); // TODO need to add function to runtime table
+ adjust_stack(emit, -(machine_int_t)(sizeof(nlr_buf_t) / sizeof(machine_uint_t)));
emit_post(emit);
}
STATIC void emit_native_pop_except(emit_t *emit) {
- assert(0);
+ /*
+ emit_native_pre(emit);
+ emit_call(emit, 0, nlr_pop); // TODO need to add function to runtime table
+ adjust_stack(emit, -(machine_int_t)(sizeof(nlr_buf_t) / sizeof(machine_uint_t)));
+ emit_post(emit);
+ */
}
STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
- vtype_kind_t vtype;
- emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
- assert(vtype == VTYPE_PYOBJ);
- emit_call_with_imm_arg(emit, MP_F_UNARY_OP, mp_unary_op, op, REG_ARG_1);
- emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
+ if (op == MP_UNARY_OP_NOT) {
+ // we need to synthesise this operation
+ assert(0);
+ } else {
+ vtype_kind_t vtype;
+ emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
+ assert(vtype == VTYPE_PYOBJ);
+ emit_call_with_imm_arg(emit, MP_F_UNARY_OP, mp_unary_op, op, REG_ARG_1);
+ emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
+ }
}
STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
@@ -1230,17 +1266,26 @@ STATIC void emit_native_set_add(emit_t *emit, int set_index) {
STATIC void emit_native_build_slice(emit_t *emit, int n_args) {
DEBUG_printf("build_slice %d\n", n_args);
- assert(n_args == 2);
- vtype_kind_t vtype_start, vtype_stop;
- emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop
- assert(vtype_start == VTYPE_PYOBJ);
- assert(vtype_stop == VTYPE_PYOBJ);
- emit_call_with_imm_arg(emit, MP_F_NEW_SLICE, mp_obj_new_slice, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); // arg3 = step
- emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
+ if (n_args == 2) {
+ vtype_kind_t vtype_start, vtype_stop;
+ emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop
+ assert(vtype_start == VTYPE_PYOBJ);
+ assert(vtype_stop == VTYPE_PYOBJ);
+ emit_call_with_imm_arg(emit, MP_F_NEW_SLICE, mp_obj_new_slice, (machine_uint_t)mp_const_none, REG_ARG_3); // arg3 = step
+ emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
+ } else {
+ assert(n_args == 3);
+ vtype_kind_t vtype_start, vtype_stop, vtype_step;
+ emit_pre_pop_reg_reg_reg(emit, &vtype_step, REG_ARG_3, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop, arg3 = step
+ assert(vtype_start == VTYPE_PYOBJ);
+ assert(vtype_stop == VTYPE_PYOBJ);
+ assert(vtype_step == VTYPE_PYOBJ);
+ emit_call(emit, MP_F_NEW_SLICE, mp_obj_new_slice);
+ emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
+ }
}
STATIC void emit_native_unpack_sequence(emit_t *emit, int n_args) {
- // TODO this is untested
DEBUG_printf("unpack_sequence %d\n", n_args);
vtype_kind_t vtype_base;
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
@@ -1250,13 +1295,12 @@ STATIC void emit_native_unpack_sequence(emit_t *emit, int n_args) {
}
STATIC void emit_native_unpack_ex(emit_t *emit, int n_left, int n_right) {
- // TODO this is untested
DEBUG_printf("unpack_ex %d %d\n", n_left, n_right);
vtype_kind_t vtype_base;
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
assert(vtype_base == VTYPE_PYOBJ);
- emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right); // arg3 = dest ptr
- emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, mp_unpack_ex, n_left + n_right, REG_ARG_2); // arg2 = n_left + n_right
+ emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right + 1); // arg3 = dest ptr
+ emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, mp_unpack_ex, n_left | (n_right << 8), REG_ARG_2); // arg2 = n_left + n_right
}
STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
@@ -1365,9 +1409,16 @@ STATIC void emit_native_return_value(emit_t *emit) {
}
STATIC void emit_native_raise_varargs(emit_t *emit, int n_args) {
- // call runtime
- assert(0);
+ assert(n_args == 1);
+ vtype_kind_t vtype_err;
+ emit_pre_pop_reg(emit, &vtype_err, REG_ARG_1); // arg1 = object to raise
+ assert(vtype_err == VTYPE_PYOBJ);
+ emit_call(emit, 0, mp_make_raise_obj); // TODO need to add function to runtime table
+ emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
+ emit_pre_pop_reg(emit, &vtype_err, REG_ARG_1);
+ emit_call(emit, 0, nlr_jump); // TODO need to add function to runtime table
}
+
STATIC void emit_native_yield_value(emit_t *emit) {
// not supported (for now)
assert(0);
@@ -1377,6 +1428,21 @@ STATIC void emit_native_yield_from(emit_t *emit) {
assert(0);
}
+STATIC void emit_native_start_except_handler(emit_t *emit) {
+ // This instruction follows an nlr_pop, so the stack counter is back to zero, when really
+ // it should be up by a whole nlr_buf_t. We then want to pop the nlr_buf_t here, but save
+ // the first 2 elements, so we can get the thrown value.
+ adjust_stack(emit, 2);
+ vtype_kind_t vtype_nlr;
+ emit_pre_pop_reg(emit, &vtype_nlr, REG_ARG_1); // get the thrown value
+ emit_pre_pop_discard(emit, &vtype_nlr); // discard the linked-list pointer in the nlr_buf
+ emit_post_push_reg_reg_reg(emit, VTYPE_PYOBJ, REG_ARG_1, VTYPE_PYOBJ, REG_ARG_1, VTYPE_PYOBJ, REG_ARG_1); // push the 3 exception items
+}
+
+STATIC void emit_native_end_except_handler(emit_t *emit) {
+ adjust_stack(emit, -3); // stack adjust (not sure why it's this much...)
+}
+
const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_set_viper_types,
emit_native_start_pass,
@@ -1462,6 +1528,9 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_raise_varargs,
emit_native_yield_value,
emit_native_yield_from,
+
+ emit_native_start_except_handler,
+ emit_native_end_except_handler,
};
#endif // (MICROPY_EMIT_X64 && N_X64) || (MICROPY_EMIT_THUMB && N_THUMB)
diff --git a/py/emitpass1.c b/py/emitpass1.c
index 2e76420a21..b39597318a 100644
--- a/py/emitpass1.c
+++ b/py/emitpass1.c
@@ -28,8 +28,8 @@
#include <stdint.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -214,6 +214,10 @@ const emit_method_table_t emit_pass1_method_table = {
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
+
+ (void*)emit_pass1_dummy,
+ (void*)emit_pass1_dummy,
+
#if MICROPY_EMIT_CPYTHON
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
diff --git a/py/gc.c b/py/gc.c
index 30bae5054a..7aa5bc326e 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -33,7 +33,6 @@
#include "misc.h"
#include "gc.h"
-#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -113,7 +112,7 @@ STATIC machine_uint_t gc_lock_depth;
void gc_init(void *start, void *end) {
// align end pointer on block boundary
end = (void*)((machine_uint_t)end & (~(BYTES_PER_BLOCK - 1)));
- DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, end - start);
+ DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte*)end - (byte*)start);
// calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes):
// T = A + F + P
@@ -173,6 +172,10 @@ void gc_unlock(void) {
gc_lock_depth--;
}
+bool gc_is_locked(void) {
+ return gc_lock_depth != 0;
+}
+
#define VERIFY_PTR(ptr) ( \
(ptr & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \
&& ptr >= (machine_uint_t)gc_pool_start /* must be above start of pool */ \
@@ -268,6 +271,7 @@ STATIC void gc_sweep(void) {
case AT_TAIL:
if (free_tail) {
+ DEBUG_printf("gc_sweep(%p)\n",PTR_FROM_BLOCK(block));
ATB_ANY_TO_FREE(block);
}
break;
@@ -401,6 +405,7 @@ found:
// get pointer to first block
void *ret_ptr = (void*)(gc_pool_start + start_block * WORDS_PER_BLOCK);
+ DEBUG_printf("gc_alloc(%p)\n", ret_ptr);
// zero out the additional bytes of the newly allocated blocks
// This is needed because the blocks may have previously held pointers
@@ -439,6 +444,7 @@ void gc_free(void *ptr_in) {
}
machine_uint_t ptr = (machine_uint_t)ptr_in;
+ DEBUG_printf("gc_free(%p)\n", ptr);
if (VERIFY_PTR(ptr)) {
machine_uint_t block = BLOCK_FROM_PTR(ptr);
@@ -590,7 +596,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
return NULL;
}
- DEBUG_printf("gc_realloc: allocating new block\n");
+ DEBUG_printf("gc_realloc(%p -> %p)\n", ptr_in, ptr_out);
memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK);
gc_free(ptr_in);
return ptr_out;
diff --git a/py/gc.h b/py/gc.h
index cea368f480..3b3b7dbb50 100644
--- a/py/gc.h
+++ b/py/gc.h
@@ -30,6 +30,7 @@ void gc_init(void *start, void *end);
// They can be used to prevent the GC from allocating/freeing.
void gc_lock(void);
void gc_unlock(void);
+bool gc_is_locked(void);
// A given port must implement gc_collect by using the other collect functions.
void gc_collect(void);
diff --git a/py/lexer.c b/py/lexer.c
index a65df54ba6..8732d64362 100644
--- a/py/lexer.c
+++ b/py/lexer.c
@@ -32,8 +32,8 @@
#include <stdio.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
@@ -502,19 +502,32 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
case 'v': c = 0x0b; break;
case 'f': c = 0x0c; break;
case 'r': c = 0x0d; break;
+ case 'u':
+ case 'U':
+ if (is_bytes) {
+ // b'\u1234' == b'\\u1234'
+ vstr_add_char(&lex->vstr, '\\');
+ break;
+ }
+ // Otherwise fall through.
case 'x':
{
uint num = 0;
- if (!get_hex(lex, 2, &num)) {
+ if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) {
// TODO error message
assert(0);
}
c = num;
break;
}
- case 'N': break; // TODO \N{name} only in strings
- case 'u': break; // TODO \uxxxx only in strings
- case 'U': break; // TODO \Uxxxxxxxx only in strings
+ case 'N':
+ // Supporting '\N{LATIN SMALL LETTER A}' == 'a' would require keeping the
+ // entire Unicode name table in the core. As of Unicode 6.3.0, that's nearly
+ // 3MB of text; even gzip-compressed and with minimal structure, it'll take
+ // roughly half a meg of storage. This form of Unicode escape may be added
+ // later on, but it's definitely not a priority right now. -- CJA 20140607
+ assert(!"Unicode name escapes not supported");
+ break;
default:
if (c >= '0' && c <= '7') {
// Octal sequence, 1-3 chars
@@ -533,7 +546,13 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
}
}
if (c != MP_LEXER_CHAR_EOF) {
- vstr_add_char(&lex->vstr, c);
+ if (c < 0x110000 && !is_bytes) {
+ vstr_add_char(&lex->vstr, c);
+ } else if (c < 0x100 && is_bytes) {
+ vstr_add_byte(&lex->vstr, c);
+ } else {
+ assert(!"TODO: Throw an error, invalid escape code probably");
+ }
}
} else {
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
@@ -694,10 +713,10 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
// need to check for this special token in many places in the compiler.
// TODO improve speed of these string comparisons
//for (int i = 0; tok_kw[i] != NULL; i++) {
- for (int i = 0; i < ARRAY_SIZE(tok_kw); i++) {
+ for (int i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) {
if (str_strn_equal(tok_kw[i], tok->str, tok->len)) {
- if (i == ARRAY_SIZE(tok_kw) - 1) {
- // tok_kw[ARRAY_SIZE(tok_kw) - 1] == "__debug__"
+ if (i == MP_ARRAY_SIZE(tok_kw) - 1) {
+ // tok_kw[MP_ARRAY_SIZE(tok_kw) - 1] == "__debug__"
tok->kind = (mp_optimise_value == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);
} else {
tok->kind = MP_TOKEN_KW_FALSE + i;
diff --git a/py/lexerstr.c b/py/lexerstr.c
index 76e90671be..666dbfa37c 100644
--- a/py/lexerstr.c
+++ b/py/lexerstr.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
diff --git a/py/lexerunix.c b/py/lexerunix.c
index 89dc80b004..51bc915b22 100644
--- a/py/lexerunix.c
+++ b/py/lexerunix.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#if MICROPY_HELPER_LEXER_UNIX
diff --git a/py/malloc.c b/py/malloc.c
index b180ddf6b5..8e90849e93 100644
--- a/py/malloc.c
+++ b/py/malloc.c
@@ -28,8 +28,8 @@
#include <stdlib.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#if 0 // print debugging info
#define DEBUG_printf DEBUG_printf
diff --git a/py/map.c b/py/map.c
index 4020401622..dcc13c52cc 100644
--- a/py/map.c
+++ b/py/map.c
@@ -27,8 +27,8 @@
#include <stdlib.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/misc.h b/py/misc.h
index 044fef6236..2ac64a7b76 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -82,7 +82,7 @@ int m_get_peak_bytes_allocated(void);
/** array helpers ***********************************************/
// get the number of elements in a fixed-size array
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/** unichar / UTF-8 *********************************************/
@@ -100,7 +100,9 @@ bool unichar_isupper(unichar c);
bool unichar_islower(unichar c);
unichar unichar_tolower(unichar c);
unichar unichar_toupper(unichar c);
-#define unichar_charlen(s, bytelen) (bytelen)
+machine_uint_t unichar_charlen(const char *str, machine_uint_t len);
+#define UTF8_IS_NONASCII(ch) ((ch) & 0x80)
+#define UTF8_IS_CONT(ch) (((ch) & 0xC0) == 0x80)
/** variable string *********************************************/
@@ -164,4 +166,18 @@ int DEBUG_printf(const char *fmt, ...);
extern uint mp_verbose_flag;
+// This is useful for unicode handling. Some CPU archs has
+// special instructions for efficient implentation of this
+// function (e.g. CLZ on ARM).
+// NOTE: this function is unused at the moment
+#ifndef count_lead_ones
+static inline uint count_lead_ones(byte val) {
+ uint c = 0;
+ for (byte mask = 0x80; val & mask; mask >>= 1) {
+ c++;
+ }
+ return c;
+}
+#endif
+
#endif // _INCLUDED_MINILIB_H
diff --git a/py/mkrules.mk b/py/mkrules.mk
index 9592d6c590..6127ece8fe 100644
--- a/py/mkrules.mk
+++ b/py/mkrules.mk
@@ -73,9 +73,9 @@ all: $(PROG)
$(PROG): $(OBJ)
$(ECHO) "LINK $@"
- $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS)
+ $(Q)$(CC) $(COPT) -o $@ $(OBJ) $(LIB) $(LDFLAGS)
ifndef DEBUG
- $(Q)$(STRIP) $(PROG)
+ $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG)
endif
$(Q)$(SIZE) $(PROG)
@@ -97,4 +97,10 @@ print-cfg:
$(ECHO) "OBJ = $(OBJ)"
.PHONY: print-cfg
+print-def:
+ @$(ECHO) "The following defines are built into the $(CC) compiler"
+ touch __empty__.c
+ @$(CC) -E -Wp,-dM __empty__.c
+ @$(RM) -f __empty__.c
+
-include $(OBJ:.o=.P)
diff --git a/py/modarray.c b/py/modarray.c
index a741a0ecb4..c0fe331643 100644
--- a/py/modarray.c
+++ b/py/modarray.c
@@ -24,12 +24,14 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
+#if MICROPY_PY_ARRAY
+
STATIC const mp_map_elem_t mp_module_array_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_array) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&mp_type_array },
@@ -40,8 +42,8 @@ STATIC const mp_obj_dict_t mp_module_array_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_array_globals_table),
- .alloc = ARRAY_SIZE(mp_module_array_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_array_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_array_globals_table),
.table = (mp_map_elem_t*)mp_module_array_globals_table,
},
};
@@ -51,3 +53,5 @@ const mp_obj_module_t mp_module_array = {
.name = MP_QSTR_array,
.globals = (mp_obj_dict_t*)&mp_module_array_globals,
};
+
+#endif
diff --git a/py/modcmath.c b/py/modcmath.c
index 3bc3055dc8..ddd8abf71e 100644
--- a/py/modcmath.c
+++ b/py/modcmath.c
@@ -26,8 +26,8 @@
#include <math.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -142,8 +142,8 @@ STATIC const mp_obj_dict_t mp_module_cmath_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_cmath_globals_table),
- .alloc = ARRAY_SIZE(mp_module_cmath_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_cmath_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_cmath_globals_table),
.table = (mp_map_elem_t*)mp_module_cmath_globals_table,
},
};
diff --git a/py/modcollections.c b/py/modcollections.c
index 9e3da7e666..5cd0b317a1 100644
--- a/py/modcollections.c
+++ b/py/modcollections.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -42,8 +42,8 @@ STATIC const mp_obj_dict_t mp_module_collections_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_collections_globals_table),
- .alloc = ARRAY_SIZE(mp_module_collections_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_collections_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_collections_globals_table),
.table = (mp_map_elem_t*)mp_module_collections_globals_table,
},
};
diff --git a/py/modgc.c b/py/modgc.c
index c53eed235f..4ffdc2be68 100644
--- a/py/modgc.c
+++ b/py/modgc.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -61,11 +61,27 @@ STATIC mp_obj_t gc_enable(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, gc_enable);
+STATIC mp_obj_t gc_mem_free(void) {
+ gc_info_t info;
+ gc_info(&info);
+ return MP_OBJ_NEW_SMALL_INT((machine_uint_t)info.free);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_free_obj, gc_mem_free);
+
+STATIC mp_obj_t gc_mem_alloc(void) {
+ gc_info_t info;
+ gc_info(&info);
+ return MP_OBJ_NEW_SMALL_INT((machine_uint_t)info.used);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_alloc_obj, gc_mem_alloc);
+
STATIC const mp_map_elem_t mp_module_gc_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_gc) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_collect), (mp_obj_t)&gc_collect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&gc_disable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&gc_enable_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mem_free), (mp_obj_t)&gc_mem_free_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mem_alloc), (mp_obj_t)&gc_mem_alloc_obj },
};
STATIC const mp_obj_dict_t mp_module_gc_globals = {
@@ -73,8 +89,8 @@ STATIC const mp_obj_dict_t mp_module_gc_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_gc_globals_table),
- .alloc = ARRAY_SIZE(mp_module_gc_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_gc_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_gc_globals_table),
.table = (mp_map_elem_t*)mp_module_gc_globals_table,
},
};
diff --git a/py/modio.c b/py/modio.c
index 08c6c59dd9..ef3b29b53f 100644
--- a/py/modio.c
+++ b/py/modio.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -57,8 +57,8 @@ STATIC const mp_obj_dict_t mp_module_io_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_io_globals_table),
- .alloc = ARRAY_SIZE(mp_module_io_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_io_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_io_globals_table),
.table = (mp_map_elem_t*)mp_module_io_globals_table,
},
};
diff --git a/py/modmath.c b/py/modmath.c
index 0fd583c2ff..0d0d13b4e2 100644
--- a/py/modmath.c
+++ b/py/modmath.c
@@ -26,8 +26,8 @@
#include <math.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -172,8 +172,8 @@ STATIC const mp_obj_dict_t mp_module_math_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_math_globals_table),
- .alloc = ARRAY_SIZE(mp_module_math_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_math_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_math_globals_table),
.table = (mp_map_elem_t*)mp_module_math_globals_table,
},
};
diff --git a/py/modmicropython.c b/py/modmicropython.c
index 40d749da2d..bbb315189b 100644
--- a/py/modmicropython.c
+++ b/py/modmicropython.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -65,8 +65,8 @@ STATIC const mp_obj_dict_t mp_module_micropython_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_micropython_globals_table),
- .alloc = ARRAY_SIZE(mp_module_micropython_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_micropython_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_micropython_globals_table),
.table = (mp_map_elem_t*)mp_module_micropython_globals_table,
},
};
diff --git a/py/modstruct.c b/py/modstruct.c
index a45181852c..2e40264e8d 100644
--- a/py/modstruct.c
+++ b/py/modstruct.c
@@ -27,8 +27,8 @@
#include <assert.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -210,8 +210,8 @@ STATIC const mp_obj_dict_t mp_module_struct_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_struct_globals_table),
- .alloc = ARRAY_SIZE(mp_module_struct_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_struct_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_struct_globals_table),
.table = (mp_map_elem_t*)mp_module_struct_globals_table,
},
};
diff --git a/py/modsys.c b/py/modsys.c
index a99db1b7f8..1e7f7eff7f 100644
--- a/py/modsys.c
+++ b/py/modsys.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -87,8 +87,8 @@ STATIC const mp_obj_dict_t mp_module_sys_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_sys_globals_table),
- .alloc = ARRAY_SIZE(mp_module_sys_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_sys_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_sys_globals_table),
.table = (mp_map_elem_t*)mp_module_sys_globals_table,
},
};
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 93e98c25b6..3a9d342ea3 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -157,6 +157,12 @@
#define MICROPY_ENABLE_GC_FINALISER (0)
#endif
+// Whether to check C stack usage. C stack used for calling Python functions,
+// etc. Not checking means segfault on overflow.
+#ifndef MICROPY_STACK_CHECK
+#define MICROPY_STACK_CHECK (1)
+#endif
+
// Whether to include REPL helper function
#ifndef MICROPY_HELPER_REPL
#define MICROPY_HELPER_REPL (0)
@@ -223,6 +229,10 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_FLOAT (0)
#endif
+#ifndef MICROPY_PY_BUILTINS_COMPLEX
+#define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT)
+#endif
+
// Enable features which improve CPython compatibility
// but may lead to more code size/memory usage.
// TODO: Originally intended as generic category to not
@@ -239,6 +249,16 @@ typedef double mp_float_t;
/*****************************************************************************/
/* Fine control over Python builtins, classes, modules, etc */
+// Whether str object is proper unicode
+#ifndef MICROPY_PY_BUILTINS_STR_UNICODE
+#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
+#endif
+
+// Whether to support bytearray object
+#ifndef MICROPY_PY_BUILTINS_BYTEARRAY
+#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
+#endif
+
// Whether to support set object
#ifndef MICROPY_PY_BUILTINS_SET
#define MICROPY_PY_BUILTINS_SET (1)
@@ -259,6 +279,13 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_PROPERTY (1)
#endif
+// Whether to provide "array" module. Note that large chunk of the
+// underlying code is shared with "bytearray" builtin type, so to
+// get real savings, it should be disabled too.
+#ifndef MICROPY_PY_ARRAY
+#define MICROPY_PY_ARRAY (1)
+#endif
+
// Whether to provide "collections" module
#ifndef MICROPY_PY_COLLECTIONS
#define MICROPY_PY_COLLECTIONS (1)
@@ -377,3 +404,8 @@ typedef double mp_float_t;
#ifndef NORETURN
#define NORETURN __attribute__((noreturn))
#endif
+
+// Modifier for weak functions
+#ifndef MP_WEAK
+#define MP_WEAK __attribute__((weak))
+#endif
diff --git a/py/mpz.c b/py/mpz.c
index ab300b91df..3f1e859fc6 100644
--- a/py/mpz.c
+++ b/py/mpz.c
@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "mpz.h"
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
diff --git a/py/nlr.h b/py/nlr.h
index 43a0c4f6a9..cb2b53b854 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -29,6 +29,7 @@
#include <limits.h>
#include <setjmp.h>
+#include <assert.h>
typedef struct _nlr_buf_t nlr_buf_t;
struct _nlr_buf_t {
@@ -44,7 +45,7 @@ struct _nlr_buf_t {
#else
void *regs[8];
#endif
-#elif defined(__thumb2__)
+#elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__)
void *regs[10];
#else
#define MICROPY_NLR_SETJMP (1)
diff --git a/py/nlrthumb.S b/py/nlrthumb.S
index b306c01753..dabf57cf85 100644
--- a/py/nlrthumb.S
+++ b/py/nlrthumb.S
@@ -24,19 +24,21 @@
* THE SOFTWARE.
*/
-#if defined(__thumb2__) && !MICROPY_NLR_SETJMP
-/* thumb callee save: bx, bp, sp, r12, r14, r14, r15 */
+#if !MICROPY_NLR_SETJMP && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__))
+/* arm callee save: bx, bp, sp, r12, r14, r14, r15 */
.syntax unified
/*.cpu cortex-m4*/
- .thumb
+ /*.thumb*/
.text
.align 2
/* uint nlr_push(r0=nlr_buf_t *nlr) */
.global nlr_push
+#if defined(__thumb2__)
.thumb
.thumb_func
+#endif
.type nlr_push, %function
nlr_push:
str lr, [r0, #8] @ store lr into nlr_buf
@@ -64,8 +66,10 @@ nlr_push:
@ void nlr_pop()
.global nlr_pop
+#if defined(__thumb2__)
.thumb
.thumb_func
+#endif
.type nlr_pop, %function
nlr_pop:
ldr r3, .L5 @ load addr of nlr_top
@@ -80,8 +84,10 @@ nlr_pop:
/* void nlr_jump(r0=uint val) */
.global nlr_jump
+#if defined(__thumb2__)
.thumb
.thumb_func
+#endif
.type nlr_jump, %function
nlr_jump:
ldr r3, .L2 @ load addr of nlr_top
diff --git a/py/obj.c b/py/obj.c
index 6d0966db24..3077fd2937 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -35,6 +35,7 @@
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
+#include "stackctrl.h"
mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
@@ -59,6 +60,8 @@ void printf_wrapper(void *env, const char *fmt, ...) {
}
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
+ // There can be data structures nested too deep, or just recursive
+ MP_STACK_CHECK();
#if !NDEBUG
if (o_in == NULL) {
print(env, "(nil)");
@@ -274,6 +277,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) {
}
}
+#if MICROPY_PY_BUILTINS_COMPLEX
void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
if (arg == mp_const_false) {
*real = 0;
@@ -297,6 +301,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
}
}
#endif
+#endif
void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items) {
if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) {
@@ -352,7 +357,12 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index,
// may return MP_OBJ_NULL
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
- if (MP_OBJ_IS_STR(o_in) || MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) {
+ if (
+#if !MICROPY_PY_BUILTINS_STR_UNICODE
+ // It's simple - unicode is slow, non-unicode is fast
+ MP_OBJ_IS_STR(o_in) ||
+#endif
+ MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) {
return MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_str_get_len(o_in));
} else {
mp_obj_type_t *type = mp_obj_get_type(o_in);
diff --git a/py/objarray.c b/py/objarray.c
index 05821e8de4..b13df2bdba 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -37,6 +37,8 @@
#include "runtime.h"
#include "binary.h"
+#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY
+
typedef struct _mp_obj_array_t {
mp_obj_base_t base;
machine_uint_t typecode : 8;
@@ -310,3 +312,5 @@ STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) {
o->cur = 0;
return o;
}
+
+#endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY
diff --git a/py/objcomplex.c b/py/objcomplex.c
index d58b53463c..20e7c97d37 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -36,7 +36,7 @@
#include "runtime0.h"
#include "runtime.h"
-#if MICROPY_PY_BUILTINS_FLOAT
+#if MICROPY_PY_BUILTINS_COMPLEX
#include <math.h>
diff --git a/py/objenumerate.c b/py/objenumerate.c
index 7d9ea9915a..37414464de 100644
--- a/py/objenumerate.c
+++ b/py/objenumerate.c
@@ -27,8 +27,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"
@@ -45,7 +45,7 @@ STATIC const mp_arg_t enumerate_make_new_args[] = {
{ MP_QSTR_iterable, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_start, MP_ARG_INT, {.u_int = 0} },
};
-#define ENUMERATE_MAKE_NEW_NUM_ARGS ARRAY_SIZE(enumerate_make_new_args)
+#define ENUMERATE_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(enumerate_make_new_args)
STATIC mp_obj_t enumerate_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
#if MICROPY_CPYTHON_COMPAT
diff --git a/py/objexcept.c b/py/objexcept.c
index 9f421373bb..ad66bb50fe 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -37,6 +37,7 @@
#include "objtype.h"
#include "runtime.h"
#include "runtime0.h"
+#include "gc.h"
typedef struct _mp_obj_exception_t {
mp_obj_base_t base;
@@ -335,6 +336,13 @@ 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) {
+ #if MICROPY_ENABLE_GC
+ if (gc_is_locked()) {
+ // We can't allocate memory, so don't bother to try
+ return;
+ }
+ #endif
+
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
diff --git a/py/objfloat.c b/py/objfloat.c
index b608b1a3d7..e3fefad8db 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -102,9 +102,12 @@ STATIC mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
STATIC mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_float_t *lhs = lhs_in;
+#if MICROPY_PY_BUILTINS_COMPLEX
if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
return mp_obj_complex_binary_op(op, lhs->value, 0, rhs_in);
- } else {
+ } else
+#endif
+ {
return mp_obj_float_binary_op(op, lhs->value, rhs_in);
}
}
diff --git a/py/objfun.c b/py/objfun.c
index 29363129b2..74e959f9d3 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -39,6 +39,7 @@
#include "runtime0.h"
#include "runtime.h"
#include "bc.h"
+#include "stackctrl.h"
#if 0 // print debugging info
#define DEBUG_PRINT (1)
@@ -204,6 +205,8 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, uint expected, ui
// code_state should have ->ip filled in (pointing past code info block),
// as well as ->n_state.
void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+ // This function is pretty complicated. It's main aim is to be efficient in speed and RAM
+ // usage for the common case of positional only args.
mp_obj_fun_bc_t *self = self_in;
machine_uint_t n_state = code_state->n_state;
const byte *ip = code_state->ip;
@@ -353,8 +356,7 @@ continue2:;
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
- // This function is pretty complicated. It's main aim is to be efficient in speed and RAM
- // usage for the common case of positional only args.
+ MP_STACK_CHECK();
DEBUG_printf("Input n_args: %d, n_kw: %d\n", n_args, n_kw);
DEBUG_printf("Input pos args: ");
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 516fb52746..cf7896f9e1 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -121,9 +121,11 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
#if MICROPY_PY_BUILTINS_FLOAT
} else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_float)) {
return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
+#if MICROPY_PY_BUILTINS_COMPLEX
} else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in);
#endif
+#endif
} else {
// delegate to generic function to check for extra cases
return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
diff --git a/py/objstr.c b/py/objstr.c
index c84d7c900d..b13517b63d 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -32,6 +32,7 @@
#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
+#include "unicode.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
@@ -43,16 +44,7 @@
STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t *args, mp_obj_t dict);
const mp_obj_t mp_const_empty_bytes;
-// use this macro to extract the string hash
-#define GET_STR_HASH(str_obj_in, str_hash) uint str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)str_obj_in)->hash; }
-
-// use this macro to extract the string length
-#define GET_STR_LEN(str_obj_in, str_len) uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; }
-
-// use this macro to extract the string data and length
-#define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) const byte *str_data; uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
-
-STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
+mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str);
STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);
STATIC NORETURN void arg_type_mixup();
@@ -259,7 +251,7 @@ STATIC const byte *find_subbytes(const byte *haystack, machine_uint_t hlen, cons
return NULL;
}
-STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+mp_obj_t mp_obj_str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
GET_STR_DATA_LEN(lhs_in, lhs_data, lhs_len);
mp_obj_type_t *lhs_type = mp_obj_get_type(lhs_in);
mp_obj_type_t *rhs_type = mp_obj_get_type(rhs_in);
@@ -352,11 +344,14 @@ uncomparable:
return MP_OBJ_NULL; // op not supported
}
+#if !MICROPY_PY_BUILTINS_STR_UNICODE
+// objstrunicode defines own version
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, uint self_len,
mp_obj_t index, bool is_slice) {
machine_uint_t index_val = mp_get_index(type, self_len, index, is_slice);
return self_data + index_val;
}
+#endif
STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_type_t *type = mp_obj_get_type(self_in);
@@ -571,7 +566,6 @@ STATIC mp_obj_t str_rsplit(uint n_args, const mp_obj_t *args) {
return res;
}
-
STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t direction, bool is_index) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
assert(2 <= n_args && n_args <= 4);
@@ -600,6 +594,11 @@ STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t dire
}
} else {
// found
+ #if MICROPY_PY_BUILTINS_STR_UNICODE
+ if (self_type == &mp_type_str) {
+ return MP_OBJ_NEW_SMALL_INT(utf8_ptr_to_index(haystack, p));
+ }
+ #endif
return MP_OBJ_NEW_SMALL_INT(p - haystack);
}
}
@@ -1610,7 +1609,7 @@ STATIC mp_obj_t str_encode(uint n_args, const mp_obj_t *args) {
}
#endif
-STATIC machine_int_t str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, int flags) {
+machine_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, int flags) {
if (flags == MP_BUFFER_READ) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
bufinfo->buf = (void*)str_data;
@@ -1627,38 +1626,45 @@ STATIC machine_int_t str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo,
}
#if MICROPY_CPYTHON_COMPAT
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode);
#endif
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex);
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, mp_obj_str_format);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace);
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count);
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition);
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_lower_obj, str_lower);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_upper_obj, str_upper);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isspace_obj, str_isspace);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isalpha_obj, str_isalpha);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isdigit_obj, str_isdigit);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isupper_obj, str_isupper);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_islower_obj, str_islower);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex);
+MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip);
+MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, mp_obj_str_format);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count);
+MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition);
+MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition);
+MP_DEFINE_CONST_FUN_OBJ_1(str_lower_obj, str_lower);
+MP_DEFINE_CONST_FUN_OBJ_1(str_upper_obj, str_upper);
+MP_DEFINE_CONST_FUN_OBJ_1(str_isspace_obj, str_isspace);
+MP_DEFINE_CONST_FUN_OBJ_1(str_isalpha_obj, str_isalpha);
+MP_DEFINE_CONST_FUN_OBJ_1(str_isdigit_obj, str_isdigit);
+MP_DEFINE_CONST_FUN_OBJ_1(str_isupper_obj, str_isupper);
+MP_DEFINE_CONST_FUN_OBJ_1(str_islower_obj, str_islower);
STATIC const mp_map_elem_t str_locals_dict_table[] = {
#if MICROPY_CPYTHON_COMPAT
{ MP_OBJ_NEW_QSTR(MP_QSTR_decode), (mp_obj_t)&bytes_decode_obj },
+ #if !MICROPY_PY_BUILTINS_STR_UNICODE
+ // If we have separate unicode type, then here we have methods only
+ // for bytes type, and it should not have encode() methods. Otherwise,
+ // we have non-compliant-but-practical bytestring type, which shares
+ // method table with bytes, so they both have encode() and decode()
+ // methods (which should do type checking at runtime).
{ MP_OBJ_NEW_QSTR(MP_QSTR_encode), (mp_obj_t)&str_encode_obj },
+ #endif
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_find), (mp_obj_t)&str_find_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rfind), (mp_obj_t)&str_rfind_obj },
@@ -1688,17 +1694,19 @@ STATIC const mp_map_elem_t str_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(str_locals_dict, str_locals_dict_table);
+#if !MICROPY_PY_BUILTINS_STR_UNICODE
const mp_obj_type_t mp_type_str = {
{ &mp_type_type },
.name = MP_QSTR_str,
.print = str_print,
.make_new = str_make_new,
- .binary_op = str_binary_op,
+ .binary_op = mp_obj_str_binary_op,
.subscr = str_subscr,
.getiter = mp_obj_new_str_iterator,
- .buffer_p = { .get_buffer = str_get_buffer },
+ .buffer_p = { .get_buffer = mp_obj_str_get_buffer },
.locals_dict = (mp_obj_t)&str_locals_dict,
};
+#endif
// Reuses most of methods from str
const mp_obj_type_t mp_type_bytes = {
@@ -1706,10 +1714,10 @@ const mp_obj_type_t mp_type_bytes = {
.name = MP_QSTR_bytes,
.print = str_print,
.make_new = bytes_make_new,
- .binary_op = str_binary_op,
+ .binary_op = mp_obj_str_binary_op,
.subscr = str_subscr,
.getiter = mp_obj_new_bytes_iterator,
- .buffer_p = { .get_buffer = str_get_buffer },
+ .buffer_p = { .get_buffer = mp_obj_str_get_buffer },
.locals_dict = (mp_obj_t)&str_locals_dict,
};
@@ -1866,6 +1874,7 @@ typedef struct _mp_obj_str_it_t {
machine_uint_t cur;
} mp_obj_str_it_t;
+#if !MICROPY_PY_BUILTINS_STR_UNICODE
STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
mp_obj_str_it_t *self = self_in;
GET_STR_DATA_LEN(self->str, str, len);
@@ -1885,6 +1894,15 @@ STATIC const mp_obj_type_t mp_type_str_it = {
.iternext = str_it_iternext,
};
+mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
+ mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
+ o->base.type = &mp_type_str_it;
+ o->str = str;
+ o->cur = 0;
+ return o;
+}
+#endif
+
STATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) {
mp_obj_str_it_t *self = self_in;
GET_STR_DATA_LEN(self->str, str, len);
@@ -1904,14 +1922,6 @@ STATIC const mp_obj_type_t mp_type_bytes_it = {
.iternext = bytes_it_iternext,
};
-mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
- mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
- o->base.type = &mp_type_str_it;
- o->str = str;
- o->cur = 0;
- return o;
-}
-
mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str) {
mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
o->base.type = &mp_type_bytes_it;
diff --git a/py/objstr.h b/py/objstr.h
index 5be137d36d..515890c6e1 100644
--- a/py/objstr.h
+++ b/py/objstr.h
@@ -35,5 +35,53 @@ typedef struct _mp_obj_str_t {
#define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte*)str};
+// use this macro to extract the string hash
+#define GET_STR_HASH(str_obj_in, str_hash) \
+ uint str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) \
+ { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)str_obj_in)->hash; }
+
+// use this macro to extract the string length
+#define GET_STR_LEN(str_obj_in, str_len) \
+ uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) \
+ { str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; }
+
+// use this macro to extract the string data and length
+#define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \
+ const byte *str_data; uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) \
+ { str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } \
+ else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
+
mp_obj_t mp_obj_str_format(uint n_args, const mp_obj_t *args);
mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, uint len);
+
+mp_obj_t mp_obj_str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in);
+machine_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, int flags);
+
+const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, uint self_len,
+ mp_obj_t index, bool is_slice);
+
+MP_DECLARE_CONST_FUN_OBJ(str_encode_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_find_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_rfind_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_index_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_rindex_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_join_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_split_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_rsplit_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_startswith_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_endswith_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_strip_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_lstrip_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_rstrip_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_format_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_replace_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_count_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_partition_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_rpartition_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_lower_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_upper_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_isspace_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_isalpha_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_isdigit_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_isupper_obj);
+MP_DECLARE_CONST_FUN_OBJ(str_islower_obj);
diff --git a/py/objstrunicode.c b/py/objstrunicode.c
new file mode 100644
index 0000000000..d96ce0a552
--- /dev/null
+++ b/py/objstrunicode.c
@@ -0,0 +1,359 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2014 Paul Sokolovsky
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+#include "mpconfig.h"
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime0.h"
+#include "runtime.h"
+#include "pfenv.h"
+#include "objstr.h"
+#include "objlist.h"
+
+#if MICROPY_PY_BUILTINS_STR_UNICODE
+
+STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
+
+/******************************************************************************/
+/* str */
+
+STATIC void uni_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
+ // this escapes characters, but it will be very slow to print (calling print many times)
+ bool has_single_quote = false;
+ bool has_double_quote = false;
+ for (const byte *s = str_data, *top = str_data + str_len; !has_double_quote && s < top; s++) {
+ if (*s == '\'') {
+ has_single_quote = true;
+ } else if (*s == '"') {
+ has_double_quote = true;
+ }
+ }
+ int quote_char = '\'';
+ if (has_single_quote && !has_double_quote) {
+ quote_char = '"';
+ }
+ print(env, "%c", quote_char);
+ const byte *s = str_data, *top = str_data + str_len;
+ while (s < top) {
+ unichar ch;
+ ch = utf8_get_char(s);
+ s = utf8_next_char(s);
+ if (ch == quote_char) {
+ print(env, "\\%c", quote_char);
+ } else if (ch == '\\') {
+ print(env, "\\\\");
+ } else if (32 <= ch && ch <= 126) {
+ print(env, "%c", ch);
+ } else if (ch == '\n') {
+ print(env, "\\n");
+ } else if (ch == '\r') {
+ print(env, "\\r");
+ } else if (ch == '\t') {
+ print(env, "\\t");
+ } else if (ch < 0x100) {
+ print(env, "\\x%02x", ch);
+ } else if (ch < 0x10000) {
+ print(env, "\\u%04x", ch);
+ } else {
+ print(env, "\\U%08x", ch);
+ }
+ }
+ print(env, "%c", quote_char);
+}
+
+STATIC void uni_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ GET_STR_DATA_LEN(self_in, str_data, str_len);
+ if (kind == PRINT_STR) {
+ print(env, "%.*s", str_len, str_data);
+ } else {
+ uni_print_quoted(print, env, str_data, str_len);
+ }
+}
+
+STATIC mp_obj_t uni_unary_op(int op, mp_obj_t self_in) {
+ GET_STR_DATA_LEN(self_in, str_data, str_len);
+ switch (op) {
+ case MP_UNARY_OP_BOOL:
+ return MP_BOOL(str_len != 0);
+ case MP_UNARY_OP_LEN:
+ return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char *)str_data, str_len));
+ default:
+ return MP_OBJ_NULL; // op not supported
+ }
+}
+
+STATIC mp_obj_t str_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+#if MICROPY_CPYTHON_COMPAT
+ if (n_kw != 0) {
+ mp_arg_error_unimpl_kw();
+ }
+#endif
+
+ switch (n_args) {
+ case 0:
+ return MP_OBJ_NEW_QSTR(MP_QSTR_);
+
+ case 1:
+ {
+ vstr_t *vstr = vstr_new();
+ mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[0], PRINT_STR);
+ mp_obj_t s = mp_obj_new_str(vstr->buf, vstr->len, false);
+ vstr_free(vstr);
+ return s;
+ }
+
+ case 2:
+ case 3:
+ {
+ // TODO: validate 2nd/3rd args
+ if (!MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
+ }
+ GET_STR_DATA_LEN(args[0], str_data, str_len);
+ GET_STR_HASH(args[0], str_hash);
+ mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
+ o->data = str_data;
+ o->hash = str_hash;
+ return o;
+ }
+
+ default:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "str takes at most 3 arguments"));
+ }
+}
+
+// Convert an index into a pointer to its lead byte. Out of bounds indexing will raise IndexError or
+// be capped to the first/last character of the string, depending on is_slice.
+const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, uint self_len,
+ mp_obj_t index, bool is_slice) {
+ machine_int_t i;
+ // Copied from mp_get_index; I don't want bounds checking, just give me
+ // the integer as-is. (I can't bounds-check without scanning the whole
+ // string; an out-of-bounds index will be caught in the loops below.)
+ if (MP_OBJ_IS_SMALL_INT(index)) {
+ i = MP_OBJ_SMALL_INT_VALUE(index);
+ } else if (!mp_obj_get_int_maybe(index, &i)) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "string indices must be integers, not %s", mp_obj_get_type_str(index)));
+ }
+ const byte *s, *top = self_data + self_len;
+ if (i < 0)
+ {
+ // Negative indexing is performed by counting from the end of the string.
+ for (s = top - 1; i; --s) {
+ if (s < self_data) {
+ if (is_slice) {
+ return self_data;
+ }
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "string index out of range"));
+ }
+ if (!UTF8_IS_CONT(*s)) {
+ ++i;
+ }
+ }
+ ++s;
+ } else if (!i) {
+ return self_data; // Shortcut - str[0] is its base pointer
+ } else {
+ // Positive indexing, correspondingly, counts from the start of the string.
+ // It's assumed that negative indexing will generally be used with small
+ // absolute values (eg str[-1], not str[-1000000]), which means it'll be
+ // more efficient this way.
+ for (s = self_data; true; ++s) {
+ if (s >= top) {
+ if (is_slice) {
+ return top;
+ }
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "string index out of range"));
+ }
+ while (UTF8_IS_CONT(*s)) {
+ ++s;
+ }
+ if (!i--) {
+ return s;
+ }
+ }
+ }
+ return s;
+}
+
+STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
+ mp_obj_type_t *type = mp_obj_get_type(self_in);
+ GET_STR_DATA_LEN(self_in, self_data, self_len);
+ if (value == MP_OBJ_SENTINEL) {
+ // load
+#if MICROPY_PY_BUILTINS_SLICE
+ if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
+ mp_obj_t ostart, ostop, ostep;
+ mp_obj_slice_get(index, &ostart, &ostop, &ostep);
+ if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
+ "only slices with step=1 (aka None) are supported"));
+ }
+
+ if (type == &mp_type_bytes) {
+ machine_int_t start = 0, stop = self_len;
+ if (ostart != mp_const_none) {
+ start = MP_OBJ_SMALL_INT_VALUE(ostart);
+ if (start < 0) {
+ start = self_len + start;
+ }
+ }
+ if (ostop != mp_const_none) {
+ stop = MP_OBJ_SMALL_INT_VALUE(ostop);
+ if (stop < 0) {
+ stop = self_len + stop;
+ }
+ }
+ return mp_obj_new_str_of_type(type, self_data + start, stop - start);
+ }
+ const byte *pstart, *pstop;
+ if (ostart != mp_const_none) {
+ pstart = str_index_to_ptr(type, self_data, self_len, ostart, true);
+ } else {
+ pstart = self_data;
+ }
+ if (ostop != mp_const_none) {
+ // pstop will point just after the stop character. This depends on
+ // the \0 at the end of the string.
+ pstop = str_index_to_ptr(type, self_data, self_len, ostop, true);
+ } else {
+ pstop = self_data + self_len;
+ }
+ if (pstop < pstart) {
+ return MP_OBJ_NEW_QSTR(MP_QSTR_);
+ }
+ return mp_obj_new_str_of_type(type, (const byte *)pstart, pstop - pstart);
+ }
+#endif
+ if (type == &mp_type_bytes) {
+ uint index_val = mp_get_index(type, self_len, index, false);
+ return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self_data[index_val]);
+ }
+ const byte *s = str_index_to_ptr(type, self_data, self_len, index, false);
+ int len = 1;
+ if (UTF8_IS_NONASCII(*s)) {
+ // Count the number of 1 bits (after the first)
+ for (char mask = 0x40; *s & mask; mask >>= 1) {
+ ++len;
+ }
+ }
+ return mp_obj_new_str((const char*)s, len, true); // This will create a one-character string
+ } else {
+ return MP_OBJ_NULL; // op not supported
+ }
+}
+
+STATIC const mp_map_elem_t str_locals_dict_table[] = {
+#if MICROPY_CPYTHON_COMPAT
+ { MP_OBJ_NEW_QSTR(MP_QSTR_encode), (mp_obj_t)&str_encode_obj },
+#endif
+ { MP_OBJ_NEW_QSTR(MP_QSTR_find), (mp_obj_t)&str_find_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rfind), (mp_obj_t)&str_rfind_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&str_index_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rindex), (mp_obj_t)&str_rindex_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_join), (mp_obj_t)&str_join_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_split), (mp_obj_t)&str_split_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rsplit), (mp_obj_t)&str_rsplit_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_startswith), (mp_obj_t)&str_startswith_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_endswith), (mp_obj_t)&str_endswith_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_strip), (mp_obj_t)&str_strip_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_lstrip), (mp_obj_t)&str_lstrip_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rstrip), (mp_obj_t)&str_rstrip_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_format), (mp_obj_t)&str_format_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_replace), (mp_obj_t)&str_replace_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_count), (mp_obj_t)&str_count_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_partition), (mp_obj_t)&str_partition_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rpartition), (mp_obj_t)&str_rpartition_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_lower), (mp_obj_t)&str_lower_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_upper), (mp_obj_t)&str_upper_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_isspace), (mp_obj_t)&str_isspace_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_isalpha), (mp_obj_t)&str_isalpha_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_isdigit), (mp_obj_t)&str_isdigit_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_isupper), (mp_obj_t)&str_isupper_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_islower), (mp_obj_t)&str_islower_obj },
+};
+
+STATIC MP_DEFINE_CONST_DICT(str_locals_dict, str_locals_dict_table);
+
+const mp_obj_type_t mp_type_str = {
+ { &mp_type_type },
+ .name = MP_QSTR_str,
+ .print = uni_print,
+ .make_new = str_make_new,
+ .unary_op = uni_unary_op,
+ .binary_op = mp_obj_str_binary_op,
+ .subscr = str_subscr,
+ .getiter = mp_obj_new_str_iterator,
+ .buffer_p = { .get_buffer = mp_obj_str_get_buffer },
+ .locals_dict = (mp_obj_t)&str_locals_dict,
+};
+
+/******************************************************************************/
+/* str iterator */
+
+typedef struct _mp_obj_str_it_t {
+ mp_obj_base_t base;
+ mp_obj_t str;
+ machine_uint_t cur;
+} mp_obj_str_it_t;
+
+STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
+ mp_obj_str_it_t *self = self_in;
+ GET_STR_DATA_LEN(self->str, str, len);
+ if (self->cur < len) {
+ const byte *cur = str + self->cur;
+ const byte *end = utf8_next_char(str + self->cur);
+ mp_obj_t o_out = mp_obj_new_str((const char*)cur, end - cur, true);
+ self->cur += end - cur;
+ return o_out;
+ } else {
+ return MP_OBJ_STOP_ITERATION;
+ }
+}
+
+STATIC const mp_obj_type_t mp_type_str_it = {
+ { &mp_type_type },
+ .name = MP_QSTR_iterator,
+ .getiter = mp_identity,
+ .iternext = str_it_iternext,
+};
+
+mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
+ mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
+ o->base.type = &mp_type_str_it;
+ o->str = str;
+ o->cur = 0;
+ return o;
+}
+
+#endif // MICROPY_PY_BUILTINS_STR_UNICODE
diff --git a/py/parse.c b/py/parse.c
index af09c335f2..492c1678b5 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -30,8 +30,8 @@
#include <assert.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parsenumbase.h"
diff --git a/py/parsehelper.c b/py/parsehelper.c
index 3ead5a3031..105afe711e 100644
--- a/py/parsehelper.c
+++ b/py/parsehelper.c
@@ -29,8 +29,8 @@
#include <stdint.h>
#include <stdio.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
diff --git a/py/parsenum.c b/py/parsenum.c
index 1c1868ae0a..b9801ab6a1 100644
--- a/py/parsenum.c
+++ b/py/parsenum.c
@@ -27,14 +27,15 @@
#include <stdbool.h>
#include <stdlib.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "nlr.h"
#include "obj.h"
#include "parsenumbase.h"
#include "parsenum.h"
#include "smallint.h"
+#include "runtime.h"
#if MICROPY_PY_BUILTINS_FLOAT
#include <math.h>
@@ -252,10 +253,15 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f
}
// return the object
+#if MICROPY_PY_BUILTINS_COMPLEX
if (imag) {
return mp_obj_new_complex(0, dec_val);
} else if (force_complex) {
return mp_obj_new_complex(dec_val, 0);
+#else
+ if (imag || force_complex) {
+ mp_not_implemented("complex values not supported");
+#endif
} else {
return mp_obj_new_float(dec_val);
}
diff --git a/py/parsenumbase.c b/py/parsenumbase.c
index ce140655bd..4fddac9c3d 100644
--- a/py/parsenumbase.c
+++ b/py/parsenumbase.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "parsenumbase.h"
// find real radix base, and strip preceding '0x', '0o' and '0b'
diff --git a/py/pfenv.c b/py/pfenv.c
index e631f8654a..ca1e3e919b 100644
--- a/py/pfenv.c
+++ b/py/pfenv.c
@@ -27,8 +27,8 @@
#include <stdint.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "mpz.h"
diff --git a/py/py.mk b/py/py.mk
index 2b74f252cf..549c35d320 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -43,6 +43,7 @@ PY_O_BASENAME = \
parsenum.o \
emitglue.o \
runtime.o \
+ stackctrl.o \
argcheck.o \
map.o \
obj.o \
@@ -74,6 +75,7 @@ PY_O_BASENAME = \
objset.o \
objslice.o \
objstr.o \
+ objstrunicode.o \
objstringio.o \
objtuple.o \
objtype.o \
diff --git a/py/qstr.c b/py/qstr.c
index 7ccb34f1c3..10bc20ecba 100644
--- a/py/qstr.c
+++ b/py/qstr.c
@@ -27,8 +27,8 @@
#include <assert.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
// NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 856853fa55..4ff9ca87c8 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -377,6 +377,8 @@ Q(gc)
Q(collect)
Q(disable)
Q(enable)
+Q(mem_free)
+Q(mem_alloc)
#endif
#if MICROPY_PY_BUILTINS_PROPERTY
diff --git a/py/repl.c b/py/repl.c
index 457ce165b7..2c3dfbd4d9 100644
--- a/py/repl.c
+++ b/py/repl.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "repl.h"
#if MICROPY_HELPER_REPL
diff --git a/py/runtime.c b/py/runtime.c
index d57bb686d1..5490bcbac5 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -45,6 +45,7 @@
#include "smallint.h"
#include "objgenerator.h"
#include "lexer.h"
+#include "stackctrl.h"
#if 0 // print debugging info
#define DEBUG_PRINT (1)
@@ -69,6 +70,8 @@ const mp_obj_module_t mp_module___main__ = {
};
void mp_init(void) {
+ mp_stack_ctrl_init();
+
// call port specific initialization if any
#ifdef MICROPY_PORT_INIT_FUNC
MICROPY_PORT_INIT_FUNC;
@@ -426,6 +429,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
} else {
return res;
}
+#if MICROPY_PY_BUILTINS_COMPLEX
} else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) {
mp_obj_t res = mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
if (res == MP_OBJ_NULL) {
@@ -434,6 +438,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
return res;
}
#endif
+#endif
}
}
diff --git a/py/scope.c b/py/scope.c
index 839e8216c1..83c2b6e07c 100644
--- a/py/scope.c
+++ b/py/scope.c
@@ -29,8 +29,8 @@
#include <stdio.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "parse.h"
diff --git a/py/smallint.c b/py/smallint.c
index 5543f126c3..c57f364e36 100644
--- a/py/smallint.c
+++ b/py/smallint.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "smallint.h"
diff --git a/py/stackctrl.c b/py/stackctrl.c
new file mode 100644
index 0000000000..724d54a1be
--- /dev/null
+++ b/py/stackctrl.c
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Paul Sokolovsky
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "mpconfig.h"
+#include "misc.h"
+#include "nlr.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "stackctrl.h"
+
+// Stack top at the start of program
+char *stack_top;
+
+void mp_stack_ctrl_init() {
+ volatile int stack_dummy;
+ stack_top = (char*)&stack_dummy;
+}
+
+uint mp_stack_usage() {
+ // Assumes descending stack
+ volatile int stack_dummy;
+ return stack_top - (char*)&stack_dummy;
+}
+
+#if MICROPY_STACK_CHECK
+
+static uint stack_limit = 10240;
+
+void mp_stack_set_limit(uint limit) {
+ stack_limit = limit;
+}
+
+void mp_stack_check() {
+ if (mp_stack_usage() >= stack_limit) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "maximum recursion depth exceeded"));
+ }
+}
+
+#endif // MICROPY_STACK_CHECK
diff --git a/py/stackctrl.h b/py/stackctrl.h
new file mode 100644
index 0000000000..92de882bfa
--- /dev/null
+++ b/py/stackctrl.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Paul Sokolovsky
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+void mp_stack_ctrl_init();
+uint mp_stack_usage();
+
+#if MICROPY_STACK_CHECK
+
+void mp_stack_set_limit(uint limit);
+void mp_stack_check();
+#define MP_STACK_CHECK() mp_stack_check()
+
+#else
+
+#define mp_stack_set_limit(limit)
+#define MP_STACK_CHECK()
+
+#endif
diff --git a/py/stream.c b/py/stream.c
index 07a79248ab..cfdea15cca 100644
--- a/py/stream.c
+++ b/py/stream.c
@@ -33,9 +33,13 @@
#include "qstr.h"
#include "obj.h"
#include "objstr.h"
+#include "runtime.h"
#include "stream.h"
#if MICROPY_STREAMS_NON_BLOCK
#include <errno.h>
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+#define EWOULDBLOCK 140
+#endif
#endif
// This file defines generic Python stream read/write methods which
@@ -67,6 +71,13 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) {
if (n_args == 1 || ((sz = mp_obj_get_int(args[1])) == -1)) {
return stream_readall(args[0]);
}
+
+ #if MICROPY_PY_BUILTINS_STR_UNICODE
+ if (!o->type->stream_p->is_bytes) {
+ mp_not_implemented("Reading from unicode text streams by character count");
+ }
+ #endif
+
byte *buf = m_new(byte, sz);
int error;
machine_int_t out_sz = o->type->stream_p->read(o, buf, sz, &error);
diff --git a/py/unicode.c b/py/unicode.c
index c8faa57009..d69e81c8e0 100644
--- a/py/unicode.c
+++ b/py/unicode.c
@@ -26,8 +26,8 @@
#include <stdint.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
// attribute flags
#define FL_PRINT (0x01)
@@ -65,14 +65,65 @@ STATIC const uint8_t attr[] = {
AT_LO, AT_LO, AT_LO, AT_PR, AT_PR, AT_PR, AT_PR, 0
};
+// TODO: Rename to str_get_char
unichar utf8_get_char(const byte *s) {
+#if MICROPY_PY_BUILTINS_STR_UNICODE
+ unichar ord = *s++;
+ if (!UTF8_IS_NONASCII(ord)) return ord;
+ ord &= 0x7F;
+ for (unichar mask = 0x40; ord & mask; mask >>= 1) {
+ ord &= ~mask;
+ }
+ while (UTF8_IS_CONT(*s)) {
+ ord = (ord << 6) | (*s++ & 0x3F);
+ }
+ return ord;
+#else
return *s;
+#endif
}
+// TODO: Rename to str_next_char
const byte *utf8_next_char(const byte *s) {
+#if MICROPY_PY_BUILTINS_STR_UNICODE
+ ++s;
+ while (UTF8_IS_CONT(*s)) {
+ ++s;
+ }
+ return s;
+#else
return s + 1;
+#endif
+}
+
+machine_uint_t utf8_ptr_to_index(const char *s, const char *ptr) {
+ machine_uint_t i = 0;
+ while (ptr > s) {
+ if (!UTF8_IS_CONT(*--ptr)) {
+ i++;
+ }
+ }
+
+ return i;
+}
+
+// TODO: Rename to str_charlen
+machine_uint_t unichar_charlen(const char *str, machine_uint_t len)
+{
+#if MICROPY_PY_BUILTINS_STR_UNICODE
+ machine_uint_t charlen = 0;
+ for (const char *top = str + len; str < top; ++str) {
+ if (!UTF8_IS_CONT(*str)) {
+ ++charlen;
+ }
+ }
+ return charlen;
+#else
+ return len;
+#endif
}
+// Be aware: These unichar_is* functions are actually ASCII-only!
bool unichar_isspace(unichar c) {
return c < 128 && (attr[c] & FL_SPACE) != 0;
}
diff --git a/py/unicode.h b/py/unicode.h
new file mode 100644
index 0000000000..2468b2fecf
--- /dev/null
+++ b/py/unicode.h
@@ -0,0 +1 @@
+machine_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr);
diff --git a/py/vstr.c b/py/vstr.c
index ea6a1c937f..9ccc95d49b 100644
--- a/py/vstr.c
+++ b/py/vstr.c
@@ -29,8 +29,8 @@
#include <stdarg.h>
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
// returned value is always at least 1 greater than argument
#define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8)
@@ -199,12 +199,48 @@ void vstr_add_byte(vstr_t *vstr, byte b) {
}
void vstr_add_char(vstr_t *vstr, unichar c) {
- // TODO UNICODE
+#if MICROPY_PY_BUILTINS_STR_UNICODE
+ // TODO: Can this be simplified and deduplicated?
+ // Is it worth just calling vstr_add_len(vstr, 4)?
+ if (c < 0x80) {
+ byte *buf = (byte*)vstr_add_len(vstr, 1);
+ if (buf == NULL) {
+ return;
+ }
+ *buf = (byte)c;
+ } else if (c < 0x800) {
+ byte *buf = (byte*)vstr_add_len(vstr, 2);
+ if (buf == NULL) {
+ return;
+ }
+ buf[0] = (c >> 6) | 0xC0;
+ buf[1] = (c & 0x3F) | 0x80;
+ } else if (c < 0x10000) {
+ byte *buf = (byte*)vstr_add_len(vstr, 3);
+ if (buf == NULL) {
+ return;
+ }
+ buf[0] = (c >> 12) | 0xE0;
+ buf[1] = ((c >> 6) & 0x3F) | 0x80;
+ buf[2] = (c & 0x3F) | 0x80;
+ } else {
+ assert(c < 0x110000);
+ byte *buf = (byte*)vstr_add_len(vstr, 4);
+ if (buf == NULL) {
+ return;
+ }
+ buf[0] = (c >> 18) | 0xF0;
+ buf[1] = ((c >> 12) & 0x3F) | 0x80;
+ buf[2] = ((c >> 6) & 0x3F) | 0x80;
+ buf[3] = (c & 0x3F) | 0x80;
+ }
+#else
byte *buf = (byte*)vstr_add_len(vstr, 1);
if (buf == NULL) {
return;
}
buf[0] = c;
+#endif
}
void vstr_add_str(vstr_t *vstr, const char *str) {
diff --git a/stmhal/adc.c b/stmhal/adc.c
index c2419d543f..817b32ea89 100644
--- a/stmhal/adc.c
+++ b/stmhal/adc.c
@@ -202,7 +202,9 @@ STATIC mp_obj_t adc_read(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read);
/// \method read_timed(buf, freq)
-/// Read analog values into the given buffer at the given frequency.
+/// Read analog values into the given buffer at the given frequency. Buffer
+/// can be bytearray or array.array for example. If a buffer with 8-bit elements
+/// is used, sample resolution will be reduced to 8 bits.
///
/// Example:
///
diff --git a/stmhal/boards/HYDRABUS/mpconfigboard.h b/stmhal/boards/HYDRABUS/mpconfigboard.h
index f87a14142e..db49434b5b 100644
--- a/stmhal/boards/HYDRABUS/mpconfigboard.h
+++ b/stmhal/boards/HYDRABUS/mpconfigboard.h
@@ -1,6 +1,7 @@
#define HYDRABUSV10
#define MICROPY_HW_BOARD_NAME "HydraBus1.0"
+#define MICROPY_HW_MCU_NAME "STM32F4"
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_HAS_SDCARD (1)
diff --git a/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h b/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h
index 0e40545253..2679aee576 100644
--- a/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h
+++ b/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h
@@ -1,6 +1,7 @@
#define NETDUINO_PLUS_2
#define MICROPY_HW_BOARD_NAME "NetduinoPlus2"
+#define MICROPY_HW_MCU_NAME "STM32F405RG"
#define MICROPY_HW_HAS_SWITCH (1)
diff --git a/stmhal/boards/PYBV10/mpconfigboard.h b/stmhal/boards/PYBV10/mpconfigboard.h
index 3def531232..4ae6954a7d 100644
--- a/stmhal/boards/PYBV10/mpconfigboard.h
+++ b/stmhal/boards/PYBV10/mpconfigboard.h
@@ -1,6 +1,7 @@
#define PYBV10
#define MICROPY_HW_BOARD_NAME "PYBv1.0"
+#define MICROPY_HW_MCU_NAME "STM32F405RG"
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_HAS_SDCARD (1)
diff --git a/stmhal/boards/PYBV3/mpconfigboard.h b/stmhal/boards/PYBV3/mpconfigboard.h
index ac0d84ca29..43d860a0cc 100644
--- a/stmhal/boards/PYBV3/mpconfigboard.h
+++ b/stmhal/boards/PYBV3/mpconfigboard.h
@@ -1,6 +1,7 @@
#define PYBV3
#define MICROPY_HW_BOARD_NAME "PYBv3"
+#define MICROPY_HW_MCU_NAME "STM32F405RG"
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_HAS_SDCARD (1)
diff --git a/stmhal/boards/PYBV4/mpconfigboard.h b/stmhal/boards/PYBV4/mpconfigboard.h
index 9fedb70136..a278dea9fb 100644
--- a/stmhal/boards/PYBV4/mpconfigboard.h
+++ b/stmhal/boards/PYBV4/mpconfigboard.h
@@ -1,6 +1,7 @@
#define PYBV4
#define MICROPY_HW_BOARD_NAME "PYBv4"
+#define MICROPY_HW_MCU_NAME "STM32F405RG"
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_HAS_SDCARD (1)
diff --git a/stmhal/boards/STM32F4DISC/mpconfigboard.h b/stmhal/boards/STM32F4DISC/mpconfigboard.h
index e6780eacbd..10bbe45188 100644
--- a/stmhal/boards/STM32F4DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32F4DISC/mpconfigboard.h
@@ -1,6 +1,7 @@
#define STM32F4DISC
#define MICROPY_HW_BOARD_NAME "F4DISC"
+#define MICROPY_HW_MCU_NAME "STM32F407"
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_HAS_SDCARD (0)
diff --git a/stmhal/boards/stm32f4xx-prefix.c b/stmhal/boards/stm32f4xx-prefix.c
index 4d2313075a..3bbb6bda0e 100644
--- a/stmhal/boards/stm32f4xx-prefix.c
+++ b/stmhal/boards/stm32f4xx-prefix.c
@@ -5,8 +5,8 @@
#include "stm32f4xx_hal.h"
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "pin.h"
diff --git a/stmhal/bufhelper.c b/stmhal/bufhelper.c
index dd72655520..1f823ea963 100644
--- a/stmhal/bufhelper.c
+++ b/stmhal/bufhelper.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "bufhelper.h"
diff --git a/stmhal/dac.c b/stmhal/dac.c
index 81ce993a8c..725e14e906 100644
--- a/stmhal/dac.c
+++ b/stmhal/dac.c
@@ -237,7 +237,7 @@ STATIC const mp_arg_t pyb_dac_write_timed_args[] = {
{ MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DMA_NORMAL} },
};
-#define PYB_DAC_WRITE_TIMED_NUM_ARGS ARRAY_SIZE(pyb_dac_write_timed_args)
+#define PYB_DAC_WRITE_TIMED_NUM_ARGS MP_ARRAY_SIZE(pyb_dac_write_timed_args)
mp_obj_t pyb_dac_write_timed(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_dac_obj_t *self = args[0];
diff --git a/stmhal/diskio.c b/stmhal/diskio.c
index cde5874946..35b9eab99f 100644
--- a/stmhal/diskio.c
+++ b/stmhal/diskio.c
@@ -32,8 +32,8 @@
#include "stm32f4xx_hal.h"
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "systick.h"
diff --git a/stmhal/extint.c b/stmhal/extint.c
index 24d51ffb8d..591246cdd1 100644
--- a/stmhal/extint.c
+++ b/stmhal/extint.c
@@ -296,7 +296,7 @@ STATIC const mp_arg_t pyb_extint_make_new_args[] = {
{ MP_QSTR_pull, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_callback, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
-#define PYB_EXTINT_MAKE_NEW_NUM_ARGS ARRAY_SIZE(pyb_extint_make_new_args)
+#define PYB_EXTINT_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(pyb_extint_make_new_args)
STATIC mp_obj_t extint_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// type_in == extint_obj_type
diff --git a/stmhal/gccollect.c b/stmhal/gccollect.c
index 79082e2f2e..c71ed13a5e 100644
--- a/stmhal/gccollect.c
+++ b/stmhal/gccollect.c
@@ -25,15 +25,15 @@
*/
#include <stdio.h>
+#include <stdint.h>
-#include <stm32f4xx_hal.h>
-
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "gc.h"
#include "gccollect.h"
+#include MICROPY_HAL_H
machine_uint_t gc_helper_get_regs_and_sp(machine_uint_t *regs);
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index 00501a57da..b6ab531293 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -220,7 +220,7 @@ STATIC const mp_arg_t pyb_i2c_init_args[] = {
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
{ MP_QSTR_gencall, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
-#define PYB_I2C_INIT_NUM_ARGS ARRAY_SIZE(pyb_i2c_init_args)
+#define PYB_I2C_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_init_args)
STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
@@ -271,7 +271,7 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
machine_int_t i2c_id = mp_obj_get_int(args[0]) - 1;
// check i2c number
- if (!(0 <= i2c_id && i2c_id < ARRAY_SIZE(pyb_i2c_obj) && pyb_i2c_obj[i2c_id].i2c != NULL)) {
+ if (!(0 <= i2c_id && i2c_id < MP_ARRAY_SIZE(pyb_i2c_obj) && pyb_i2c_obj[i2c_id].i2c != NULL)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C bus %d does not exist", i2c_id + 1));
}
@@ -363,7 +363,7 @@ STATIC const mp_arg_t pyb_i2c_send_args[] = {
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = PYB_I2C_MASTER_ADDRESS} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_I2C_SEND_NUM_ARGS ARRAY_SIZE(pyb_i2c_send_args)
+#define PYB_I2C_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_send_args)
STATIC mp_obj_t pyb_i2c_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = args[0];
@@ -414,7 +414,7 @@ STATIC const mp_arg_t pyb_i2c_recv_args[] = {
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = PYB_I2C_MASTER_ADDRESS} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_I2C_RECV_NUM_ARGS ARRAY_SIZE(pyb_i2c_recv_args)
+#define PYB_I2C_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_recv_args)
STATIC mp_obj_t pyb_i2c_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = args[0];
@@ -470,7 +470,7 @@ STATIC const mp_arg_t pyb_i2c_mem_read_args[] = {
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_I2C_MEM_READ_NUM_ARGS ARRAY_SIZE(pyb_i2c_mem_read_args)
+#define PYB_I2C_MEM_READ_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_mem_read_args)
STATIC mp_obj_t pyb_i2c_mem_read(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = args[0];
diff --git a/stmhal/import.c b/stmhal/import.c
index abc618bef0..88ddaefacf 100644
--- a/stmhal/import.c
+++ b/stmhal/import.c
@@ -27,8 +27,8 @@
#include <stdio.h>
#include <stdint.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "ff.h"
diff --git a/stmhal/led.c b/stmhal/led.c
index e23b30ab75..c1b298b179 100644
--- a/stmhal/led.c
+++ b/stmhal/led.c
@@ -61,7 +61,7 @@ STATIC const pyb_led_obj_t pyb_led_obj[] = {
#endif
#endif
};
-#define NUM_LEDS ARRAY_SIZE(pyb_led_obj)
+#define NUM_LEDS MP_ARRAY_SIZE(pyb_led_obj)
void led_init(void) {
/* GPIO structure */
diff --git a/stmhal/lexerfatfs.c b/stmhal/lexerfatfs.c
index 6a0e83fb13..c578b13af6 100644
--- a/stmhal/lexerfatfs.c
+++ b/stmhal/lexerfatfs.c
@@ -27,8 +27,8 @@
#include <stdint.h>
#include <stdio.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "lexerfatfs.h"
diff --git a/stmhal/main.c b/stmhal/main.c
index 9751dcac2e..0e260e18cd 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -29,10 +29,10 @@
#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
#include "misc.h"
#include "systick.h"
#include "pendsv.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "misc.h"
#include "nlr.h"
@@ -40,6 +40,7 @@
#include "parse.h"
#include "obj.h"
#include "runtime.h"
+#include "stackctrl.h"
#include "gc.h"
#include "gccollect.h"
#include "pybstdio.h"
@@ -85,7 +86,7 @@ void flash_error(int n) {
led_state(PYB_LED_R2, 0);
}
-void __fatal_error(const char *msg) {
+void NORETURN __fatal_error(const char *msg) {
for (volatile uint delay = 0; delay < 10000000; delay++) {
}
led_state(1, 1);
@@ -111,8 +112,7 @@ void nlr_jump_fail(void *val) {
}
#ifndef NDEBUG
-void __attribute__((weak))
- __assert_func(const char *file, int line, const char *func, const char *expr) {
+void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) {
(void)func;
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
__fatal_error("");
@@ -186,6 +186,10 @@ static const char fresh_readme_txt[] =
int main(void) {
// TODO disable JTAG
+ // Stack limit should be less than real stack size, so we
+ // had chance to recover from limit hit.
+ mp_stack_set_limit(&_ram_end - &_heap_end - 512);
+
/* STM32F4xx HAL library initialization:
- Configure the Flash prefetch, instruction and Data caches
- Configure the Systick to generate an interrupt each 1 msec
@@ -308,7 +312,7 @@ soft_reset:
MP_OBJ_NEW_SMALL_INT(115200),
};
pyb_uart_global_debug = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type,
- ARRAY_SIZE(args),
+ MP_ARRAY_SIZE(args),
0, args);
}
#else
diff --git a/stmhal/math.c b/stmhal/math.c
index 637f447cf1..91ffb2503f 100644
--- a/stmhal/math.c
+++ b/stmhal/math.c
@@ -72,6 +72,7 @@ float __attribute__((pcs("aapcs"))) __aeabi_d2f(double x) {
fx.m = (dx.m>>(52-23)); // right justify
return fx.f;
}
+
double __aeabi_dmul(double x , double y) {
return 0.0;
@@ -85,6 +86,18 @@ float sqrtf(float x) {
return x;
}
+#ifndef NDEBUG
+float copysignf(float x, float y) {
+ float_s_t fx={.f = x};
+ float_s_t fy={.f = y};
+
+ // copy sign bit;
+ fx.s = fy.s;
+
+ return fx.f;
+}
+#endif
+
// some compilers define log2f in terms of logf
#ifdef log2f
#undef log2f
diff --git a/stmhal/modos.c b/stmhal/modos.c
index 4a6949a844..e0df05ca6b 100644
--- a/stmhal/modos.c
+++ b/stmhal/modos.c
@@ -194,8 +194,8 @@ STATIC const mp_obj_dict_t os_module_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(os_module_globals_table),
- .alloc = ARRAY_SIZE(os_module_globals_table),
+ .used = MP_ARRAY_SIZE(os_module_globals_table),
+ .alloc = MP_ARRAY_SIZE(os_module_globals_table),
.table = (mp_map_elem_t*)os_module_globals_table,
},
};
diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c
index 6879a2c1b7..9dcd0e76ca 100644
--- a/stmhal/modpyb.c
+++ b/stmhal/modpyb.c
@@ -426,8 +426,8 @@ STATIC const mp_obj_dict_t pyb_module_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(pyb_module_globals_table),
- .alloc = ARRAY_SIZE(pyb_module_globals_table),
+ .used = MP_ARRAY_SIZE(pyb_module_globals_table),
+ .alloc = MP_ARRAY_SIZE(pyb_module_globals_table),
.table = (mp_map_elem_t*)pyb_module_globals_table,
},
};
diff --git a/stmhal/modstm.c b/stmhal/modstm.c
index 520c8e51bd..1196ff82ff 100644
--- a/stmhal/modstm.c
+++ b/stmhal/modstm.c
@@ -131,8 +131,8 @@ STATIC const mp_obj_dict_t stm_module_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(stm_module_globals_table),
- .alloc = ARRAY_SIZE(stm_module_globals_table),
+ .used = MP_ARRAY_SIZE(stm_module_globals_table),
+ .alloc = MP_ARRAY_SIZE(stm_module_globals_table),
.table = (mp_map_elem_t*)stm_module_globals_table,
},
};
diff --git a/stmhal/modtime.c b/stmhal/modtime.c
index 4fbee31293..ea4e3210a6 100644
--- a/stmhal/modtime.c
+++ b/stmhal/modtime.c
@@ -122,8 +122,8 @@ STATIC const mp_obj_dict_t time_module_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(time_module_globals_table),
- .alloc = ARRAY_SIZE(time_module_globals_table),
+ .used = MP_ARRAY_SIZE(time_module_globals_table),
+ .alloc = MP_ARRAY_SIZE(time_module_globals_table),
.table = (mp_map_elem_t*)time_module_globals_table,
},
};
diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h
index 28cd90bb01..28e654c8a6 100644
--- a/stmhal/mpconfigport.h
+++ b/stmhal/mpconfigport.h
@@ -44,6 +44,7 @@
*/
#define MICROPY_ENABLE_LFN (1)
#define MICROPY_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
+#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_SYS_EXIT (1)
#define MICROPY_PY_SYS_STDFILES (1)
@@ -104,3 +105,6 @@ typedef const void *machine_const_ptr_t; // must be of pointer size
// We need to provide a declaration/definition of alloca()
#include <alloca.h>
+
+#define MICROPY_HAL_H "mphal.h"
+#define MICROPY_PIN_DEFS_PORT_H "pin_defs_stmhal.h"
diff --git a/stmhal/mphal.h b/stmhal/mphal.h
new file mode 100644
index 0000000000..4e9a8b2bb8
--- /dev/null
+++ b/stmhal/mphal.h
@@ -0,0 +1,7 @@
+// We use the ST Cube HAL library for most hardware peripherals
+#include <stm32f4xx_hal.h>
+
+// Basic GPIO functions
+#define GPIO_read_pin(gpio, pin) (((gpio)->IDR >> (pin)) & 1)
+#define GPIO_set_pin(gpio, pin_mask) (((gpio)->BSRRL) = (pin_mask))
+#define GPIO_clear_pin(gpio, pin_mask) (((gpio)->BSRRH) = (pin_mask))
diff --git a/stmhal/pendsv.c b/stmhal/pendsv.c
index f8e3b30072..a0eff7e5de 100644
--- a/stmhal/pendsv.c
+++ b/stmhal/pendsv.c
@@ -27,8 +27,8 @@
#include <stdlib.h>
#include <stm32f4xx_hal.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "pendsv.h"
diff --git a/stmhal/pin.c b/stmhal/pin.c
index 9806a8c49a..a9ebfa9766 100644
--- a/stmhal/pin.c
+++ b/stmhal/pin.c
@@ -28,14 +28,13 @@
#include <stdint.h>
#include <string.h>
-#include "stm32f4xx_hal.h"
-
#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
+#include MICROPY_HAL_H
#include "pin.h"
/// \moduleref pyb
@@ -100,8 +99,8 @@ STATIC mp_obj_t pin_class_map_dict;
STATIC bool pin_class_debug;
void pin_init(void) {
- pin_class_mapper = MP_OBJ_NULL;
- pin_class_map_dict = MP_OBJ_NULL;
+ pin_class_mapper = mp_const_none;
+ pin_class_map_dict = mp_const_none;
pin_class_debug = false;
}
@@ -120,7 +119,7 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
return pin_obj;
}
- if (pin_class_mapper != MP_OBJ_NULL) {
+ if (pin_class_mapper != mp_const_none) {
pin_obj = mp_call_function_1(pin_class_mapper, user_obj);
if (pin_obj != mp_const_none) {
if (!MP_OBJ_IS_TYPE(pin_obj, &pin_type)) {
@@ -139,7 +138,7 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
// other lookup methods.
}
- if (pin_class_map_dict != MP_OBJ_NULL) {
+ if (pin_class_map_dict != mp_const_none) {
mp_map_t *pin_map_map = mp_obj_dict_get_map(pin_class_map_dict);
mp_map_elem_t *elem = mp_map_lookup(pin_map_map, user_obj, MP_MAP_LOOKUP);
if (elem != NULL && elem->value != NULL) {
@@ -310,13 +309,13 @@ STATIC mp_obj_t pin_value(uint n_args, mp_obj_t *args) {
pin_obj_t *self = args[0];
if (n_args == 1) {
// get pin
- return MP_OBJ_NEW_SMALL_INT((self->gpio->IDR >> self->pin) & 1);
+ return MP_OBJ_NEW_SMALL_INT(GPIO_read_pin(self->gpio, self->pin));
} else {
// set pin
if (mp_obj_is_true(args[1])) {
- self->gpio->BSRRL = self->pin_mask;
+ GPIO_set_pin(self->gpio, self->pin_mask);
} else {
- self->gpio->BSRRH = self->pin_mask;
+ GPIO_clear_pin(self->gpio, self->pin_mask);
}
return mp_const_none;
}
@@ -327,7 +326,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value);
/// Set the pin to a low logic level.
STATIC mp_obj_t pin_low(mp_obj_t self_in) {
pin_obj_t *self = self_in;
- self->gpio->BSRRH = self->pin_mask;
+ GPIO_clear_pin(self->gpio, self->pin_mask);;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_low_obj, pin_low);
@@ -336,7 +335,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_low_obj, pin_low);
/// Set the pin to a high logic level.
STATIC mp_obj_t pin_high(mp_obj_t self_in) {
pin_obj_t *self = self_in;
- self->gpio->BSRRL = self->pin_mask;
+ GPIO_set_pin(self->gpio, self->pin_mask);;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_high_obj, pin_high);
diff --git a/stmhal/pin.h b/stmhal/pin.h
index d60bd22fd7..8513db109b 100644
--- a/stmhal/pin.h
+++ b/stmhal/pin.h
@@ -24,63 +24,10 @@
* THE SOFTWARE.
*/
-enum {
- PORT_A,
- PORT_B,
- PORT_C,
- PORT_D,
- PORT_E,
- PORT_F,
- PORT_G,
- PORT_H,
- PORT_I,
- PORT_J,
-};
+// This file requires pin_defs_xxx.h (which has port specific enums and
+// defines, so we include it here. It should never be included directly
-enum {
- AF_FN_TIM,
- AF_FN_I2C,
- AF_FN_USART,
- AF_FN_UART = AF_FN_USART,
- AF_FN_SPI
-};
-
-enum {
- AF_PIN_TYPE_TIM_CH1 = 0,
- AF_PIN_TYPE_TIM_CH2,
- AF_PIN_TYPE_TIM_CH3,
- AF_PIN_TYPE_TIM_CH4,
- AF_PIN_TYPE_TIM_CH1N,
- AF_PIN_TYPE_TIM_CH2N,
- AF_PIN_TYPE_TIM_CH3N,
- AF_PIN_TYPE_TIM_CH1_ETR,
- AF_PIN_TYPE_TIM_ETR,
- AF_PIN_TYPE_TIM_BKIN,
-
- AF_PIN_TYPE_I2C_SDA = 0,
- AF_PIN_TYPE_I2C_SCL,
-
- AF_PIN_TYPE_USART_TX = 0,
- AF_PIN_TYPE_USART_RX,
- AF_PIN_TYPE_USART_CTS,
- AF_PIN_TYPE_USART_RTS,
- AF_PIN_TYPE_USART_CK,
- AF_PIN_TYPE_UART_TX = AF_PIN_TYPE_USART_TX,
- AF_PIN_TYPE_UART_RX = AF_PIN_TYPE_USART_RX,
- AF_PIN_TYPE_UART_CTS = AF_PIN_TYPE_USART_CTS,
- AF_PIN_TYPE_UART_RTS = AF_PIN_TYPE_USART_RTS,
-
- AF_PIN_TYPE_SPI_MOSI = 0,
- AF_PIN_TYPE_SPI_MISO,
- AF_PIN_TYPE_SPI_SCK,
- AF_PIN_TYPE_SPI_NSS,
-};
-
-enum {
- PIN_ADC1 = (1 << 0),
- PIN_ADC2 = (1 << 1),
- PIN_ADC3 = (1 << 2),
-};
+#include MICROPY_PIN_DEFS_PORT_H
typedef struct {
mp_obj_base_t base;
@@ -91,24 +38,21 @@ typedef struct {
union {
void *reg;
- TIM_TypeDef *TIM;
- I2C_TypeDef *I2C;
- USART_TypeDef *USART;
- USART_TypeDef *UART;
- SPI_TypeDef *SPI;
+
+ PIN_DEFS_PORT_AF_UNION
};
} pin_af_obj_t;
typedef struct {
mp_obj_base_t base;
const char *name;
- uint16_t port : 4;
- uint16_t pin : 4;
- uint16_t num_af : 4;
- uint16_t adc_channel : 4;
- uint16_t adc_num : 3; // 1 bit per ADC
- uint16_t pin_mask;
- GPIO_TypeDef *gpio;
+ uint32_t port : 4;
+ uint32_t pin : 5; // Some ARM processors use 32 bits/PORT
+ uint32_t num_af : 4;
+ uint32_t adc_channel : 5; // Some ARM processors use 32 bits/PORT
+ uint32_t adc_num : 3; // 1 bit per ADC
+ uint32_t pin_mask;
+ pin_gpio_t *gpio;
const pin_af_obj_t *af;
} pin_obj_t;
diff --git a/stmhal/pin_defs_stmhal.h b/stmhal/pin_defs_stmhal.h
new file mode 100644
index 0000000000..2b6d9da0e7
--- /dev/null
+++ b/stmhal/pin_defs_stmhal.h
@@ -0,0 +1,96 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// This file contains pin definitions that are specific to the stmhal port.
+// This file should only ever be #included by pin.h and not directly.
+
+enum {
+ PORT_A,
+ PORT_B,
+ PORT_C,
+ PORT_D,
+ PORT_E,
+ PORT_F,
+ PORT_G,
+ PORT_H,
+ PORT_I,
+ PORT_J,
+};
+
+enum {
+ AF_FN_TIM,
+ AF_FN_I2C,
+ AF_FN_USART,
+ AF_FN_UART = AF_FN_USART,
+ AF_FN_SPI
+};
+
+enum {
+ AF_PIN_TYPE_TIM_CH1 = 0,
+ AF_PIN_TYPE_TIM_CH2,
+ AF_PIN_TYPE_TIM_CH3,
+ AF_PIN_TYPE_TIM_CH4,
+ AF_PIN_TYPE_TIM_CH1N,
+ AF_PIN_TYPE_TIM_CH2N,
+ AF_PIN_TYPE_TIM_CH3N,
+ AF_PIN_TYPE_TIM_CH1_ETR,
+ AF_PIN_TYPE_TIM_ETR,
+ AF_PIN_TYPE_TIM_BKIN,
+
+ AF_PIN_TYPE_I2C_SDA = 0,
+ AF_PIN_TYPE_I2C_SCL,
+
+ AF_PIN_TYPE_USART_TX = 0,
+ AF_PIN_TYPE_USART_RX,
+ AF_PIN_TYPE_USART_CTS,
+ AF_PIN_TYPE_USART_RTS,
+ AF_PIN_TYPE_USART_CK,
+ AF_PIN_TYPE_UART_TX = AF_PIN_TYPE_USART_TX,
+ AF_PIN_TYPE_UART_RX = AF_PIN_TYPE_USART_RX,
+ AF_PIN_TYPE_UART_CTS = AF_PIN_TYPE_USART_CTS,
+ AF_PIN_TYPE_UART_RTS = AF_PIN_TYPE_USART_RTS,
+
+ AF_PIN_TYPE_SPI_MOSI = 0,
+ AF_PIN_TYPE_SPI_MISO,
+ AF_PIN_TYPE_SPI_SCK,
+ AF_PIN_TYPE_SPI_NSS,
+};
+
+enum {
+ PIN_ADC1 = (1 << 0),
+ PIN_ADC2 = (1 << 1),
+ PIN_ADC3 = (1 << 2),
+};
+
+#define PIN_DEFS_PORT_AF_UNION \
+ TIM_TypeDef *TIM; \
+ I2C_TypeDef *I2C; \
+ USART_TypeDef *USART; \
+ USART_TypeDef *UART; \
+ SPI_TypeDef *SPI;
+
+typedef GPIO_TypeDef pin_gpio_t;
+
diff --git a/stmhal/pin_named_pins.c b/stmhal/pin_named_pins.c
index 3a1794e1d9..dbf03d1a0f 100644
--- a/stmhal/pin_named_pins.c
+++ b/stmhal/pin_named_pins.c
@@ -28,13 +28,12 @@
#include <stdint.h>
#include <string.h>
-#include "stm32f4xx_hal.h"
-
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
+#include MICROPY_HAL_H
#include "pin.h"
STATIC void pin_named_pins_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
diff --git a/stmhal/printf.c b/stmhal/printf.c
index 26c552039f..c4731aa88d 100644
--- a/stmhal/printf.c
+++ b/stmhal/printf.c
@@ -28,10 +28,10 @@
#include <string.h>
#include <stdarg.h>
+#include "mpconfig.h"
#include "std.h"
#include "misc.h"
#include "systick.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "pfenv.h"
diff --git a/stmhal/pybstdio.c b/stmhal/pybstdio.c
index 05ea06eb44..5447a62202 100644
--- a/stmhal/pybstdio.c
+++ b/stmhal/pybstdio.c
@@ -25,15 +25,15 @@
*/
#include <stdio.h>
+#include <stdint.h>
-#include <stm32f4xx_hal.h>
-
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "misc.h"
#include "obj.h"
#include "stream.h"
+#include MICROPY_HAL_H
#include "pybstdio.h"
#include "usb.h"
#include "uart.h"
diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c
index 45928427e1..93f4d62a96 100644
--- a/stmhal/pyexec.c
+++ b/stmhal/pyexec.c
@@ -26,8 +26,7 @@
#include <stdlib.h>
#include <stdio.h>
-
-#include <stm32f4xx_hal.h>
+#include <stdint.h>
#include "mpconfig.h"
#include "nlr.h"
@@ -43,6 +42,7 @@
#include "repl.h"
#include "gc.h"
#include "gccollect.h"
+#include MICROPY_HAL_H
#include "systick.h"
#include "pybstdio.h"
#include "readline.h"
@@ -185,7 +185,7 @@ int pyexec_friendly_repl(void) {
#endif
friendly_repl_reset:
- stdout_tx_str("Micro Python " MICROPY_GIT_TAG " 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 " MICROPY_HW_MCU_NAME "\r\n");
stdout_tx_str("Type \"help()\" for more information.\r\n");
// to test ctrl-C
diff --git a/stmhal/readline.c b/stmhal/readline.c
index d40bd4219b..0703dcf4ea 100644
--- a/stmhal/readline.c
+++ b/stmhal/readline.c
@@ -25,15 +25,15 @@
*/
#include <stdio.h>
+#include <stdint.h>
#include <string.h>
-#include <stm32f4xx_hal.h>
-
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "misc.h"
#include "obj.h"
+#include MICROPY_HAL_H
#include "pybstdio.h"
#include "readline.h"
#include "usb.h"
diff --git a/stmhal/rng.c b/stmhal/rng.c
index 69fcb9d6ff..ea636770c0 100644
--- a/stmhal/rng.c
+++ b/stmhal/rng.c
@@ -28,8 +28,8 @@
#include "stm32f4xx_hal.h"
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "rng.h"
diff --git a/stmhal/rtc.c b/stmhal/rtc.c
index 412816c396..8f0d007327 100644
--- a/stmhal/rtc.c
+++ b/stmhal/rtc.c
@@ -28,8 +28,8 @@
#include "stm32f4xx_hal.h"
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c
index bd45af3a14..204dbe3b46 100644
--- a/stmhal/sdcard.c
+++ b/stmhal/sdcard.c
@@ -28,8 +28,8 @@
#include <stm32f4xx_hal.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/stmhal/spi.c b/stmhal/spi.c
index 10ecf7ec8e..448b8696ea 100644
--- a/stmhal/spi.c
+++ b/stmhal/spi.c
@@ -188,7 +188,7 @@ STATIC const pyb_spi_obj_t pyb_spi_obj[] = {
{{&pyb_spi_type}, NULL},
#endif
};
-#define PYB_NUM_SPI ARRAY_SIZE(pyb_spi_obj)
+#define PYB_NUM_SPI MP_ARRAY_SIZE(pyb_spi_obj)
STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_spi_obj_t *self = self_in;
@@ -242,7 +242,7 @@ STATIC const mp_arg_t pyb_spi_init_args[] = {
{ MP_QSTR_ti, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_crc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
-#define PYB_SPI_INIT_NUM_ARGS ARRAY_SIZE(pyb_spi_init_args)
+#define PYB_SPI_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_init_args)
STATIC mp_obj_t pyb_spi_init_helper(const pyb_spi_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
@@ -359,7 +359,7 @@ STATIC const mp_arg_t pyb_spi_send_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_SPI_SEND_NUM_ARGS ARRAY_SIZE(pyb_spi_send_args)
+#define PYB_SPI_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_send_args)
STATIC mp_obj_t pyb_spi_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
@@ -401,7 +401,7 @@ STATIC const mp_arg_t pyb_spi_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_SPI_RECV_NUM_ARGS ARRAY_SIZE(pyb_spi_recv_args)
+#define PYB_SPI_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_recv_args)
STATIC mp_obj_t pyb_spi_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
@@ -449,7 +449,7 @@ STATIC const mp_arg_t pyb_spi_send_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_SPI_SEND_RECV_NUM_ARGS ARRAY_SIZE(pyb_spi_send_recv_args)
+#define PYB_SPI_SEND_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_send_recv_args)
STATIC mp_obj_t pyb_spi_send_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
diff --git a/stmhal/stm32f4xx_hal_msp.c b/stmhal/stm32f4xx_hal_msp.c
index 5816249e25..90baa41f82 100644
--- a/stmhal/stm32f4xx_hal_msp.c
+++ b/stmhal/stm32f4xx_hal_msp.c
@@ -66,8 +66,8 @@
#include "stm32f4xx_hal.h"
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "servo.h"
diff --git a/stmhal/stm32f4xx_it.c b/stmhal/stm32f4xx_it.c
index 17cdaf5fa2..5fa7f8289d 100644
--- a/stmhal/stm32f4xx_it.c
+++ b/stmhal/stm32f4xx_it.c
@@ -70,8 +70,8 @@
#include "stm32f4xx_it.h"
#include "stm32f4xx_hal.h"
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "extint.h"
diff --git a/stmhal/storage.c b/stmhal/storage.c
index ba7e303e21..001d87afe0 100644
--- a/stmhal/storage.c
+++ b/stmhal/storage.c
@@ -28,9 +28,9 @@
#include <string.h>
#include <stm32f4xx_hal.h>
+#include "mpconfig.h"
#include "misc.h"
#include "systick.h"
-#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "led.h"
diff --git a/stmhal/systick.c b/stmhal/systick.c
index 8a8d6403dc..196f1fbcae 100644
--- a/stmhal/systick.c
+++ b/stmhal/systick.c
@@ -25,6 +25,7 @@
*/
#include <stm32f4xx_hal.h>
+#include "mpconfig.h"
#include "misc.h"
#include "systick.h"
diff --git a/stmhal/timer.c b/stmhal/timer.c
index 0ba24754b2..ec0c4dec4c 100644
--- a/stmhal/timer.c
+++ b/stmhal/timer.c
@@ -105,7 +105,7 @@ static uint32_t tim3_counter = 0;
// Used to do callbacks to Python code on interrupt
STATIC pyb_timer_obj_t *pyb_timer_obj_all[14];
-#define PYB_TIMER_OBJ_ALL_NUM ARRAY_SIZE(pyb_timer_obj_all)
+#define PYB_TIMER_OBJ_ALL_NUM MP_ARRAY_SIZE(pyb_timer_obj_all)
void timer_init0(void) {
tim3_counter = 0;
@@ -234,7 +234,7 @@ STATIC const mp_arg_t pyb_timer_init_args[] = {
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIM_COUNTERMODE_UP} },
{ MP_QSTR_div, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIM_CLOCKDIVISION_DIV1} },
};
-#define PYB_TIMER_INIT_NUM_ARGS ARRAY_SIZE(pyb_timer_init_args)
+#define PYB_TIMER_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_timer_init_args)
STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
diff --git a/stmhal/uart.c b/stmhal/uart.c
index 5bbd9f299e..a85f7f9e3a 100644
--- a/stmhal/uart.c
+++ b/stmhal/uart.c
@@ -270,7 +270,7 @@ STATIC const mp_arg_t pyb_uart_init_args[] = {
{ MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_parity, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
-#define PYB_UART_INIT_NUM_ARGS ARRAY_SIZE(pyb_uart_init_args)
+#define PYB_UART_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_init_args)
STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
@@ -396,7 +396,7 @@ STATIC const mp_arg_t pyb_uart_send_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_UART_SEND_NUM_ARGS ARRAY_SIZE(pyb_uart_send_args)
+#define PYB_UART_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_send_args)
STATIC mp_obj_t pyb_uart_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
@@ -438,7 +438,7 @@ STATIC const mp_arg_t pyb_uart_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_UART_RECV_NUM_ARGS ARRAY_SIZE(pyb_uart_recv_args)
+#define PYB_UART_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_recv_args)
STATIC mp_obj_t pyb_uart_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
diff --git a/stmhal/usrsw.c b/stmhal/usrsw.c
index 4ed9e3abe4..8a082eac95 100644
--- a/stmhal/usrsw.c
+++ b/stmhal/usrsw.c
@@ -28,8 +28,8 @@
#include "stm32f4xx_hal.h"
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
diff --git a/teensy/Makefile b/teensy/Makefile
index 8244d52d31..18ffb32af9 100644
--- a/teensy/Makefile
+++ b/teensy/Makefile
@@ -20,12 +20,15 @@ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -fsingle-precision-c
INC = -I.
INC += -I$(PY_SRC)
+INC += -I../stmhal
INC += -I$(BUILD)
INC += -I$(CORE_PATH)
CFLAGS = $(INC) -Wall -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4)
LDFLAGS = -nostdlib -T mk20dx256.ld
-LIBS = -L $(COMPILER_PATH)/../lib/gcc/arm-none-eabi/4.7.2/thumb2 -lgcc
+LIBS = -L $(COMPILER_PATH)/../arm-none-eabi/lib/thumb2 -lm
+LIBS += -L $(COMPILER_PATH)/../arm-none-eabi/lib/thumb2 -lc
+LIBS += -L $(COMPILER_PATH)/../lib/gcc/arm-none-eabi/4.7.2/thumb2 -lgcc
#Debugging/Optimization
ifdef DEBUG
@@ -35,23 +38,32 @@ CFLAGS += -Os #-DNDEBUG
endif
SRC_C = \
+ hal_gpio.c \
+ help.c \
+ import.c \
main.c \
lcd.c \
led.c \
- lexerfatfs.c \
lexermemzip.c \
memzip.c \
- servo.c \
- usart.c \
+ modpyb.c \
+ teensy_hal.c \
+ uart.c \
usb.c \
-STM_SRC_C = $(addprefix stm/,\
- malloc0.c \
+STM_SRC_C = $(addprefix stmhal/,\
+ gccollect.c \
+ input.c \
+ pin.c \
+ pin_named_pins.c \
printf.c \
+ pyexec.c \
+ pybstdio.c \
+ readline.c \
string0.c \
)
-STM_SRC_S = $(addprefix stm/,\
+STM_SRC_S = $(addprefix stmhal/,\
gchelper.s \
)
@@ -66,9 +78,7 @@ SRC_TEENSY = \
yield.c \
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(STM_SRC_S:.s=.o) $(SRC_TEENSY:.c=.o))
-#LIB = -lreadline
-# the following is needed for BSD
-#LIB += -ltermcap
+OBJ += $(BUILD)/pins_gen.o
all: hex
hex: $(BUILD)/micropython-mz.hex
@@ -84,7 +94,7 @@ reboot:
upload: post_compile reboot
$(BUILD)/micropython.elf: $(OBJ)
- $(ECHO) "LINK $<"
+ $(ECHO) "LINK $@"
$(Q)$(CC) $(LDFLAGS) -o "$@" -Wl,-Map,$(@:.elf=.map) $(OBJ) $(LIBS)
$(Q)$(SIZE) $@
@@ -103,4 +113,31 @@ $(BUILD)/%.hex: $(BUILD)/%.elf
$(BUILD)/%.o: $(CORE_PATH)/%.c
$(call compile_c)
+MAKE_PINS = make-pins.py
+BOARD_PINS = teensy-pins.csv
+AF_FILE = mk20dx256-af.csv
+PREFIX_FILE = mk20dx256-prefix.c
+GEN_PINS_SRC = $(BUILD)/pins_gen.c
+GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
+
+# Making OBJ use an order-only depenedency on the generated pins.h file
+# has the side effect of making the pins.h file before we actually compile
+# any of the objects. The normal dependency generation will deal with the
+# case when pins.h is modified. But when it doesn't exist, we don't know
+# which source files might need it.
+$(OBJ): | $(HEADER_BUILD)/pins.h
+
+# Use a pattern rule here so that make will only call make-pins.py once to make
+# both pins_$(BOARD).c and pins.h
+$(BUILD)/%_gen.c $(HEADER_BUILD)/%.h: teensy-%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE)
+ $(ECHO) "Create $@"
+ $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) > $(GEN_PINS_SRC)
+
+$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c
+ $(call compile_c)
+
+$(BUILD)/%.pp: $(BUILD)/%.c
+ $(ECHO) "PreProcess $<"
+ $(Q)$(CC) $(CFLAGS) -E -Wp,-C,-dD,-dI -o $@ $<
+
include ../py/mkrules.mk
diff --git a/teensy/hal_gpio.c b/teensy/hal_gpio.c
new file mode 100644
index 0000000000..0811f76fda
--- /dev/null
+++ b/teensy/hal_gpio.c
@@ -0,0 +1,115 @@
+#include <stdint.h>
+#include <mk20dx128.h>
+#include "teensy_hal.h"
+
+#define GPIO_NUMBER 32
+
+void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
+{
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
+ assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
+ assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
+
+ /* Configure the port pins */
+ for (uint32_t position = 0; position < GPIO_NUMBER; position++) {
+ uint32_t bitmask = 1 << position;
+ if ((GPIO_Init->Pin & bitmask) == 0) {
+ continue;
+ }
+
+ volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(GPIOx, position);
+
+ /*--------------------- GPIO Mode Configuration ------------------------*/
+ /* In case of Alternate function mode selection */
+ if ((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) {
+ /* Check the Alternate function parameter */
+ assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
+ /* Configure Alternate function mapped with the current IO */
+
+ *port_pcr &= ~PORT_PCR_MUX_MASK;
+ *port_pcr |= PORT_PCR_MUX(GPIO_Init->Alternate);
+ }
+
+ /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
+ if (GPIO_Init->Mode == GPIO_MODE_INPUT || GPIO_Init->Mode == GPIO_MODE_ANALOG) {
+ GPIOx->PDDR &= ~bitmask;
+ } else {
+ GPIOx->PDDR |= bitmask;
+ }
+
+ /* In case of Output or Alternate function mode selection */
+ if ((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
+ (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) {
+ /* Check the Speed parameter */
+ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
+
+ /* Configure the IO Speed */
+ if (GPIO_Init->Speed > GPIO_SPEED_MEDIUM) {
+ *port_pcr &= ~PORT_PCR_SRE;
+ } else {
+ *port_pcr |= PORT_PCR_SRE;
+ }
+
+ /* Configure the IO Output Type */
+ if (GPIO_Init->Mode & GPIO_OUTPUT_TYPE) {
+ *port_pcr |= PORT_PCR_ODE;
+ } else {
+ *port_pcr &= ~PORT_PCR_ODE;
+ }
+ }
+
+ /* Activate the Pull-up or Pull down resistor for the current IO */
+ if (GPIO_Init->Pull == GPIO_NOPULL) {
+ *port_pcr &= ~PORT_PCR_PE;
+ } else {
+ *port_pcr |= PORT_PCR_PE;
+ if (GPIO_Init->Pull == GPIO_PULLDOWN) {
+ *port_pcr &= ~PORT_PCR_PS;
+ } else {
+ *port_pcr |= PORT_PCR_PS;
+ }
+ }
+
+#if 0
+ /*--------------------- EXTI Mode Configuration ------------------------*/
+ /* Configure the External Interrupt or event for the current IO */
+ if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
+ {
+ /* Enable SYSCFG Clock */
+ __SYSCFG_CLK_ENABLE();
+
+ temp = ((uint32_t)0x0F) << (4 * (position & 0x03));
+ SYSCFG->EXTICR[position >> 2] &= ~temp;
+ SYSCFG->EXTICR[position >> 2] |= ((uint32_t)(__HAL_GET_GPIO_SOURCE(GPIOx)) << (4 * (position & 0x03)));
+
+ /* Clear EXTI line configuration */
+ EXTI->IMR &= ~((uint32_t)iocurrent);
+ EXTI->EMR &= ~((uint32_t)iocurrent);
+
+ if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
+ {
+ EXTI->IMR |= iocurrent;
+ }
+ if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
+ {
+ EXTI->EMR |= iocurrent;
+ }
+
+ /* Clear Rising Falling edge configuration */
+ EXTI->RTSR &= ~((uint32_t)iocurrent);
+ EXTI->FTSR &= ~((uint32_t)iocurrent);
+
+ if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
+ {
+ EXTI->RTSR |= iocurrent;
+ }
+ if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
+ {
+ EXTI->FTSR |= iocurrent;
+ }
+ }
+#endif
+ }
+}
+
diff --git a/teensy/help.c b/teensy/help.c
new file mode 100644
index 0000000000..598b6f4e30
--- /dev/null
+++ b/teensy/help.c
@@ -0,0 +1,123 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+#include "mpconfig.h"
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+
+STATIC const char *help_text =
+"Welcome to Micro Python!\n"
+"\n"
+"For online help please visit http://micropython.org/help/.\n"
+"\n"
+"Quick overview of commands for the board:\n"
+" pyb.info() -- print some general information\n"
+" pyb.gc() -- run the garbage collector\n"
+" pyb.delay(n) -- wait for n milliseconds\n"
+" pyb.Switch() -- create a switch object\n"
+" Switch methods: (), callback(f)\n"
+" pyb.LED(n) -- create an LED object for LED n (n=1,2,3,4)\n"
+" LED methods: on(), off(), toggle(), intensity(<n>)\n"
+" pyb.Pin(pin) -- get a pin, eg pyb.Pin('X1')\n"
+" pyb.Pin(pin, m, [p]) -- get a pin and configure it for IO mode m, pull mode p\n"
+" Pin methods: init(..), value([v]), high(), low()\n"
+" pyb.ExtInt(pin, m, p, callback) -- create an external interrupt object\n"
+" pyb.ADC(pin) -- make an analog object from a pin\n"
+" ADC methods: read(), read_timed(buf, freq)\n"
+" pyb.DAC(port) -- make a DAC object\n"
+" DAC methods: triangle(freq), write(n), write_timed(buf, freq)\n"
+" pyb.RTC() -- make an RTC object; methods: datetime([val])\n"
+" pyb.rng() -- get a 30-bit hardware random number\n"
+" pyb.Servo(n) -- create Servo object for servo n (n=1,2,3,4)\n"
+" Servo methods: calibration(..), angle([x, [t]]), speed([x, [t]])\n"
+" pyb.Accel() -- create an Accelerometer object\n"
+" Accelerometer methods: x(), y(), z(), tilt(), filtered_xyz()\n"
+"\n"
+"Pins are numbered X1-X12, X17-X22, Y1-Y12, or by their MCU name\n"
+"Pin IO modes are: pyb.Pin.IN, pyb.Pin.OUT_PP, pyb.Pin.OUT_OD\n"
+"Pin pull modes are: pyb.Pin.PULL_NONE, pyb.Pin.PULL_UP, pyb.Pin.PULL_DOWN\n"
+"Additional serial bus objects: pyb.I2C(n), pyb.SPI(n), pyb.UART(n)\n"
+"\n"
+"Control commands:\n"
+" CTRL-A -- on a blank line, enter raw REPL mode\n"
+" CTRL-B -- on a blank line, enter normal REPL mode\n"
+" CTRL-C -- interrupt a running program\n"
+" CTRL-D -- on a blank line, do a soft reset of the board\n"
+"\n"
+"For further help on a specific object, type help(obj)\n"
+;
+
+STATIC void pyb_help_print_info_about_object(mp_obj_t name_o, mp_obj_t value) {
+ printf(" ");
+ mp_obj_print(name_o, PRINT_STR);
+ printf(" -- ");
+ mp_obj_print(value, PRINT_STR);
+ printf("\n");
+}
+
+STATIC mp_obj_t pyb_help(uint n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ // print a general help message
+ printf("%s", help_text);
+
+ } else {
+ // try to print something sensible about the given object
+
+ printf("object ");
+ mp_obj_print(args[0], PRINT_STR);
+ printf(" is of type %s\n", mp_obj_get_type_str(args[0]));
+
+ mp_map_t *map = NULL;
+ if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) {
+ map = mp_obj_dict_get_map(mp_obj_module_get_globals(args[0]));
+ } else {
+ mp_obj_type_t *type;
+ if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) {
+ type = args[0];
+ } else {
+ type = mp_obj_get_type(args[0]);
+ }
+ if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
+ map = mp_obj_dict_get_map(type->locals_dict);
+ }
+ }
+ if (map != NULL) {
+ for (uint i = 0; i < map->alloc; i++) {
+ if (map->table[i].key != MP_OBJ_NULL) {
+ pyb_help_print_info_about_object(map->table[i].key, map->table[i].value);
+ }
+ }
+ }
+ }
+
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, pyb_help);
diff --git a/teensy/import.c b/teensy/import.c
new file mode 100644
index 0000000000..967de102ac
--- /dev/null
+++ b/teensy/import.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "lexer.h"
+
+#include "memzip.h"
+
+mp_import_stat_t mp_import_stat(const char *path) {
+ MEMZIP_FILE_INFO info;
+
+ if (memzip_stat(path, &info) != MZ_OK) {
+ return MP_IMPORT_STAT_NO_EXIST;
+ }
+
+ if (info.is_dir) {
+ return MP_IMPORT_STAT_DIR;
+ }
+ return MP_IMPORT_STAT_FILE;
+}
diff --git a/teensy/lcd.c b/teensy/lcd.c
index cc3f52bad5..5b991aac77 100644
--- a/teensy/lcd.c
+++ b/teensy/lcd.c
@@ -1,5 +1,10 @@
+#include "mpconfig.h"
+#include "nlr.h"
#include "misc.h"
-#include "../stm/lcd.h"
+#include "qstr.h"
+#include "parse.h"
+#include "obj.h"
+#include "../stmhal/lcd.h"
void lcd_init(void) {
}
diff --git a/teensy/led.c b/teensy/led.c
index e2a0574168..5a9d8701d2 100644
--- a/teensy/led.c
+++ b/teensy/led.c
@@ -1,53 +1,114 @@
#include <stdio.h>
-#include "misc.h"
+#include "Arduino.h"
+
#include "mpconfig.h"
+#include "nlr.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
+#include "runtime.h"
#include "led.h"
+#include MICROPY_HAL_H
+#include "pin.h"
+#include "genhdr/pins.h"
-#include "Arduino.h"
+typedef struct _pyb_led_obj_t {
+ mp_obj_base_t base;
+ machine_uint_t led_id;
+ const pin_obj_t *led_pin;
+} pyb_led_obj_t;
+
+STATIC const pyb_led_obj_t pyb_led_obj[] = {
+ {{&pyb_led_type}, 1, &MICROPY_HW_LED1},
+#if defined(MICROPY_HW_LED2)
+ {{&pyb_led_type}, 2, &MICROPY_HW_LED2},
+#if defined(MICROPY_HW_LED3)
+ {{&pyb_led_type}, 3, &MICROPY_HW_LED3},
+#if defined(MICROPY_HW_LED4)
+ {{&pyb_led_type}, 4, &MICROPY_HW_LED4},
+#endif
+#endif
+#endif
+};
+#define NUM_LEDS ARRAY_SIZE(pyb_led_obj)
void led_init(void) {
+ /* GPIO structure */
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ /* Configure I/O speed, mode, output type and pull */
+ GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ GPIO_InitStructure.Mode = MICROPY_HW_LED_OTYPE;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+
+ /* Turn off LEDs and initialize */
+ for (int led = 0; led < NUM_LEDS; led++) {
+ const pin_obj_t *led_pin = pyb_led_obj[led].led_pin;
+ MICROPY_HW_LED_OFF(led_pin);
+ GPIO_InitStructure.Pin = led_pin->pin_mask;
+ HAL_GPIO_Init(led_pin->gpio, &GPIO_InitStructure);
+ }
}
void led_state(pyb_led_t led, int state) {
- uint8_t pin;
-
- if (led == 0) {
- pin = LED_BUILTIN;
- } else {
+ if (led < 1 || led > NUM_LEDS) {
return;
}
- digitalWrite(pin, state);
+ const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin;
+ //printf("led_state(%d,%d)\n", led, state);
+ if (state == 0) {
+ // turn LED off
+ MICROPY_HW_LED_OFF(led_pin);
+ } else {
+ // turn LED on
+ MICROPY_HW_LED_ON(led_pin);
+ }
}
void led_toggle(pyb_led_t led) {
- uint8_t pin;
-
- if (led == 0) {
- pin = LED_BUILTIN;
- } else {
+ if (led < 1 || led > NUM_LEDS) {
return;
}
-
- digitalWrite(pin, !digitalRead(pin));
+ const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin;
+ GPIO_TypeDef *gpio = led_pin->gpio;
+
+ // We don't know if we're turning the LED on or off, but we don't really
+ // care. Just invert the state.
+ if (gpio->PDOR & led_pin->pin_mask) {
+ // pin is high, make it low
+ gpio->PCOR = led_pin->pin_mask;
+ } else {
+ // pin is low, make it high
+ gpio->PSOR = led_pin->pin_mask;
+ }
}
/******************************************************************************/
/* Micro Python bindings */
-typedef struct _pyb_led_obj_t {
- mp_obj_base_t base;
- uint led_id;
-} pyb_led_obj_t;
-
void led_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_led_obj_t *self = self_in;
(void)kind;
print(env, "<LED %lu>", self->led_id);
}
+STATIC mp_obj_t led_obj_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);
+
+ // get led number
+ machine_int_t led_id = mp_obj_get_int(args[0]);
+
+ // check led number
+ if (!(1 <= led_id && led_id <= NUM_LEDS)) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "LED %d does not exist", led_id));
+ }
+
+ // return static led object
+ return (mp_obj_t)&pyb_led_obj[led_id - 1];
+}
+
mp_obj_t led_obj_on(mp_obj_t self_in) {
pyb_led_obj_t *self = self_in;
led_state(self->led_id, 1);
@@ -60,25 +121,28 @@ mp_obj_t led_obj_off(mp_obj_t self_in) {
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_on_obj, led_obj_on);
-static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off);
+mp_obj_t led_obj_toggle(mp_obj_t self_in) {
+ pyb_led_obj_t *self = self_in;
+ led_toggle(self->led_id);
+ return mp_const_none;
+}
-static const mp_method_t led_methods[] = {
- { "on", &led_obj_on_obj },
- { "off", &led_obj_off_obj },
- { NULL, NULL },
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_on_obj, led_obj_on);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_toggle_obj, led_obj_toggle);
+
+STATIC const mp_map_elem_t led_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_on), (mp_obj_t)&led_obj_on_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_off), (mp_obj_t)&led_obj_off_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_toggle), (mp_obj_t)&led_obj_toggle_obj },
};
-static const mp_obj_type_t led_obj_type = {
+STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table);
+
+const mp_obj_type_t pyb_led_type = {
{ &mp_type_type },
- .name = MP_QSTR_Led,
+ .name = MP_QSTR_LED,
.print = led_obj_print,
- .methods = led_methods,
+ .make_new = led_obj_make_new,
+ .locals_dict = (mp_obj_t)&led_locals_dict,
};
-
-mp_obj_t pyb_Led(mp_obj_t led_id) {
- pyb_led_obj_t *o = m_new_obj(pyb_led_obj_t);
- o->base.type = &led_obj_type;
- o->led_id = mp_obj_get_int(led_id);
- return o;
-}
diff --git a/teensy/led.h b/teensy/led.h
index c5a4812549..7f4ba18f26 100644
--- a/teensy/led.h
+++ b/teensy/led.h
@@ -1,9 +1,9 @@
typedef enum {
- PYB_LED_BUILTIN = 0,
+ PYB_LED_BUILTIN = 1,
} pyb_led_t;
void led_init(void);
void led_state(pyb_led_t led, int state);
void led_toggle(pyb_led_t led);
-mp_obj_t pyb_Led(mp_obj_t led_id);
+extern const mp_obj_type_t pyb_led_type;
diff --git a/teensy/lexerfatfs.c b/teensy/lexerfatfs.c
index 95084b6501..84245f8878 100644
--- a/teensy/lexerfatfs.c
+++ b/teensy/lexerfatfs.c
@@ -6,19 +6,10 @@
#include "qstr.h"
#include "lexer.h"
typedef int FIL;
-#include "../stm/lexerfatfs.h"
+#include "../stmhal/lexerfatfs.h"
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
printf("import not implemented\n");
return NULL;
}
-mp_lexer_t *mp_import_open_file(qstr mod_name) {
- printf("import not implemented\n");
- return NULL;
-}
-
-mp_import_stat_t mp_import_stat(const char *path) {
- // TODO implement me!
- return MP_IMPORT_STAT_NO_EXIST;
-}
diff --git a/teensy/lexermemzip.c b/teensy/lexermemzip.c
index 3e15717acf..f50a3c0808 100644
--- a/teensy/lexermemzip.c
+++ b/teensy/lexermemzip.c
@@ -7,7 +7,7 @@
#include "lexer.h"
#include "memzip.h"
-mp_lexer_t *mp_lexer_new_from_memzip_file(const char *filename)
+mp_lexer_t *mp_lexer_new_from_file(const char *filename)
{
void *data;
size_t len;
diff --git a/teensy/main.c b/teensy/main.c
index eb153c245d..97c1db6528 100644
--- a/teensy/main.c
+++ b/teensy/main.c
@@ -3,29 +3,32 @@
#include <string.h>
#include <stdlib.h>
-#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
+#include "nlr.h"
#include "lexer.h"
#include "lexermemzip.h"
#include "parse.h"
#include "obj.h"
-#include "compile.h"
-#include "runtime0.h"
#include "runtime.h"
-#include "repl.h"
+#include "gc.h"
+#include "gccollect.h"
+#include "pyexec.h"
+#include "pybstdio.h"
+#include "readline.h"
+
+#include "Arduino.h"
+#include MICROPY_HAL_H
+
#include "servo.h"
#include "usb.h"
-#include "gc.h"
#include "led.h"
-#include "build/py/py-version.h"
-#include "Arduino.h"
+//#include "pin.h"
-extern uint32_t _heap_start;
-bool do_file(const char *filename);
+extern uint32_t _heap_start;
void flash_error(int n) {
for (int i = 0; i < n; i++) {
@@ -36,25 +39,36 @@ void flash_error(int n) {
}
}
-static const char *help_text =
-"Welcome to Micro Python!\n\n"
-"This is a *very* early version of Micro Python and has minimal functionality.\n\n"
-"Specific commands for the board:\n"
-" pyb.info() -- print some general information\n"
-" pyb.gc() -- run the garbage collector\n"
-" pyb.delay(<n>) -- wait for n milliseconds\n"
-" pyb.Led(<n>) -- create Led object for LED n (n=0)\n"
-" Led methods: on(), off()\n"
-" pyb.gpio(<pin>) -- read gpio pin\n"
-" pyb.gpio(<pin>, <val>) -- set gpio pin\n"
-#if 0
-" pyb.Servo(<n>) -- create Servo object for servo n (n=1,2,3,4)\n"
-" Servo methods: angle(<x>)\n"
-" pyb.switch() -- return True/False if switch pressed or not\n"
-" pyb.accel() -- get accelerometer values\n"
-" pyb.rand() -- get a 16-bit random number\n"
-#endif
-;
+void __fatal_error(const char *msg) {
+ 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));
+ for (uint i = 0;;) {
+ led_toggle(((i++) & 3) + 1);
+ for (volatile uint delay = 0; delay < 10000000; delay++) {
+ }
+ if (i >= 16) {
+ // to conserve power
+ __WFI();
+ }
+ }
+}
+
+void nlr_jump_fail(void *val) {
+ printf("FATAL: uncaught exception %p\n", val);
+ __fatal_error("");
+}
+
+void __assert_func(const char *file, int line, const char *func, const char *expr) {
+
+ printf("Assertion failed: %s, file %s, line %d\n", expr, file, line);
+ __fatal_error("");
+}
mp_obj_t pyb_analog_read(mp_obj_t pin_obj) {
uint pin = mp_obj_get_int(pin_obj);
@@ -82,12 +96,7 @@ mp_obj_t pyb_analog_write_frequency(mp_obj_t pin_obj, mp_obj_t freq_obj) {
return mp_const_none;
}
-// get some help about available functions
-static mp_obj_t pyb_help(void) {
- printf("%s", help_text);
- return mp_const_none;
-}
-
+#if 0
// get lots of info about the board
static mp_obj_t pyb_info(void) {
// get and print unique id; 96 bits
@@ -101,12 +110,6 @@ static mp_obj_t pyb_info(void) {
// to print info about memory
{
- extern void *_sdata;
- extern void *_edata;
- extern void *_sbss;
- extern void *_ebss;
- extern void *_estack;
- extern void *_etext;
printf("_sdata=%p\n", &_sdata);
printf("_edata=%p\n", &_edata);
printf("_sbss=%p\n", &_sbss);
@@ -121,9 +124,9 @@ static mp_obj_t pyb_info(void) {
gc_info_t info;
gc_info(&info);
printf("GC:\n");
- printf(" %lu total\n", info.total);
- printf(" %lu used %lu free\n", info.used, info.free);
- printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
+ printf(" %u total\n", info.total);
+ printf(" %u used %u free\n", info.used, info.free);
+ printf(" 1=%u 2=%u m=%u\n", info.num_1block, info.num_2block, info.max_block);
}
#if 0
@@ -139,32 +142,15 @@ static mp_obj_t pyb_info(void) {
return mp_const_none;
}
+#endif
+
#define RAM_START (0x1FFF8000) // fixed for chip
#define HEAP_END (0x20006000) // tunable
#define RAM_END (0x20008000) // fixed for chip
-void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
+#if 0
-void gc_collect(void) {
- uint32_t start = micros();
- gc_collect_start();
- gc_collect_root((void**)RAM_START, (((uint32_t)&_heap_start) - RAM_START) / 4);
- machine_uint_t regs[10];
- gc_helper_get_regs_and_clean_stack(regs, HEAP_END);
- gc_collect_root((void**)HEAP_END, (RAM_END - HEAP_END) / 4); // will trace regs since they now live in this function on the stack
- gc_collect_end();
- uint32_t ticks = micros() - start; // TODO implement a function that does this properly
-
- if (0) {
- // print GC info
- gc_info_t info;
- gc_info(&info);
- printf("GC@%lu %luus\n", start, ticks);
- printf(" %lu total\n", info.total);
- printf(" %lu used %lu free\n", info.used, info.free);
- printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
- }
-}
+void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
mp_obj_t pyb_gc(void) {
gc_collect();
@@ -191,7 +177,7 @@ mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) {
return mp_const_none;
pin_error:
- nlr_raise(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "pin %d does not exist", pin));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %d does not exist", pin));
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio);
@@ -209,29 +195,41 @@ mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
}
#endif
-static mp_obj_t pyb_config_source_dir = MP_OBJ_NULL;
-static mp_obj_t pyb_config_main = MP_OBJ_NULL;
+#endif // 0
+
+STATIC mp_obj_t pyb_config_source_dir = MP_OBJ_NULL;
+STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL;
+STATIC mp_obj_t pyb_config_usb_mode = MP_OBJ_NULL;
mp_obj_t pyb_source_dir(mp_obj_t source_dir) {
if (MP_OBJ_IS_STR(source_dir)) {
pyb_config_source_dir = source_dir;
- printf("source_dir = '");
- mp_obj_print(source_dir, PRINT_STR);
- printf("'\n");
}
return mp_const_none;
}
+MP_DEFINE_CONST_FUN_OBJ_1(pyb_source_dir_obj, pyb_source_dir);
+
mp_obj_t pyb_main(mp_obj_t main) {
if (MP_OBJ_IS_STR(main)) {
pyb_config_main = main;
- printf("main = '");
- mp_obj_print(main, PRINT_STR);
- printf("'\n");
}
return mp_const_none;
}
+MP_DEFINE_CONST_FUN_OBJ_1(pyb_main_obj, pyb_main);
+
+STATIC mp_obj_t pyb_usb_mode(mp_obj_t usb_mode) {
+ if (MP_OBJ_IS_STR(usb_mode)) {
+ pyb_config_usb_mode = usb_mode;
+ }
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_mode_obj, pyb_usb_mode);
+
+#if 0
+
mp_obj_t pyb_delay(mp_obj_t count) {
delay(mp_obj_get_int(count));
return mp_const_none;
@@ -242,12 +240,9 @@ mp_obj_t pyb_led(mp_obj_t state) {
return state;
}
-mp_obj_t pyb_run(mp_obj_t filename_obj) {
- const char *filename = qstr_str(mp_obj_str_get_qstr(filename_obj));
- do_file(filename);
- return mp_const_none;
-}
+#endif // 0
+#if 0
char *strdup(const char *str) {
uint32_t len = strlen(str);
char *s2 = m_new(char, len + 1);
@@ -255,219 +250,31 @@ char *strdup(const char *str) {
s2[len] = 0;
return s2;
}
-
-#define READLINE_HIST_SIZE (8)
-
-static const char *readline_hist[READLINE_HIST_SIZE] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
-
-void stdout_tx_str(const char *str) {
-// usart_tx_str(str);
- usb_vcp_send_str(str);
-}
-
-int readline(vstr_t *line, const char *prompt) {
- stdout_tx_str(prompt);
- int len = vstr_len(line);
- int escape = 0;
- int hist_num = 0;
- for (;;) {
- char c;
- for (;;) {
- if (usb_vcp_rx_any() != 0) {
- c = usb_vcp_rx_get();
- break;
-#if 0
- } else if (usart_rx_any()) {
- c = usart_rx_char();
- break;
#endif
- }
- //delay(1);
- //if (storage_needs_flush()) {
- // storage_flush();
- //}
- }
- if (escape == 0) {
- if (c == 4 && vstr_len(line) == len) {
- return 0;
- } else if (c == '\r') {
- stdout_tx_str("\r\n");
- for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) {
- readline_hist[i] = readline_hist[i - 1];
- }
- readline_hist[0] = strdup(vstr_str(line));
- return 1;
- } else if (c == 27) {
- escape = true;
- } else if (c == 127) {
- if (vstr_len(line) > len) {
- vstr_cut_tail(line, 1);
- stdout_tx_str("\b \b");
- }
- } else if (32 <= c && c <= 126) {
- vstr_add_char(line, c);
- stdout_tx_str(line->buf + line->len - 1);
- }
- } else if (escape == 1) {
- if (c == '[') {
- escape = 2;
- } else {
- escape = 0;
- }
- } else if (escape == 2) {
- escape = 0;
- if (c == 'A') {
- // up arrow
- if (hist_num < READLINE_HIST_SIZE && readline_hist[hist_num] != NULL) {
- // erase line
- for (int i = line->len - len; i > 0; i--) {
- stdout_tx_str("\b \b");
- }
- // set line to history
- line->len = len;
- vstr_add_str(line, readline_hist[hist_num]);
- // draw line
- stdout_tx_str(readline_hist[hist_num]);
- // increase hist num
- hist_num += 1;
- }
- }
- } else {
- escape = 0;
- }
- delay(10);
- }
-}
-
-bool do_file(const char *filename) {
- mp_lexer_t *lex = mp_lexer_new_from_memzip_file(filename);
-
- if (lex == NULL) {
- printf("could not open file '%s' for reading\n", filename);
- return false;
- }
-
- mp_parse_error_kind_t parse_error_kind;
- mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind);
- qstr source_name = mp_lexer_source_name(lex);
-
- if (pn == MP_PARSE_NODE_NULL) {
- // parse error
- mp_parse_show_exception(lex, parse_error_kind);
- mp_lexer_free(lex);
- return false;
- }
-
- mp_lexer_free(lex);
-
- mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false);
- mp_parse_node_free(pn);
-
- if (module_fun == mp_const_none) {
- return false;
- }
-
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- mp_call_function_0(module_fun);
- nlr_pop();
- return true;
- } else {
- // uncaught exception
- mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
- printf("\n");
- return false;
- }
-}
-
-void do_repl(void) {
- stdout_tx_str("Micro Python build " MICROPY_GIT_HASH " on " MICROPY_BUILD_DATE "; Teensy 3.1 version\n");
- stdout_tx_str("Type \"help()\" for more information.\r\n");
-
- vstr_t line;
- vstr_init(&line, 32);
-
- for (;;) {
- vstr_reset(&line);
- int ret = readline(&line, ">>> ");
- if (ret == 0) {
- // EOF
- break;
- }
-
- if (vstr_len(&line) == 0) {
- continue;
- }
-
- while (mp_repl_continue_with_input(vstr_str(&line))) {
- vstr_add_char(&line, '\n');
- int ret = readline(&line, "... ");
- if (ret == 0) {
- // stop entering compound statement
- break;
- }
- }
-
- mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0);
- mp_parse_error_kind_t parse_error_kind;
- mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_error_kind);
- qstr source_name = mp_lexer_source_name(lex);
-
- if (pn == MP_PARSE_NODE_NULL) {
- // parse error
- mp_parse_show_exception(lex, parse_error_kind);
- mp_lexer_free(lex);
- } else {
- // parse okay
- mp_lexer_free(lex);
- mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true);
- if (module_fun != mp_const_none) {
- nlr_buf_t nlr;
- uint32_t start = micros();
- if (nlr_push(&nlr) == 0) {
- mp_call_function_0(module_fun);
- nlr_pop();
- // optional timing
- if (0) {
- uint32_t ticks = micros() - start; // TODO implement a function that does this properly
- printf("(took %lu ms)\n", ticks);
- }
- } else {
- // uncaught exception
- mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
- printf("\n");
- }
- }
- }
- }
-
- stdout_tx_str("\r\n");
-}
int main(void) {
pinMode(LED_BUILTIN, OUTPUT);
-#if 0
- // Wait for host side to get connected
- while (!usb_vcp_is_connected()) {
- ;
- }
-#else
delay(1000);
-#endif
led_init();
- led_state(PYB_LED_BUILTIN, 1);
// int first_soft_reset = true;
soft_reset:
+ led_state(PYB_LED_BUILTIN, 1);
+
// GC init
gc_init(&_heap_start, (void*)HEAP_END);
qstr_init();
mp_init();
+ readline_init();
+
+ //pin_init();
+
+#if 0
// add some functions to the python namespace
{
mp_store_name(MP_QSTR_help, mp_make_function_n(0, pyb_help));
@@ -478,7 +285,7 @@ soft_reset:
mp_store_attr(m, MP_QSTR_gc, mp_make_function_n(0, pyb_gc));
mp_store_attr(m, MP_QSTR_delay, mp_make_function_n(1, pyb_delay));
mp_store_attr(m, MP_QSTR_led, mp_make_function_n(1, pyb_led));
- mp_store_attr(m, MP_QSTR_Led, mp_make_function_n(1, pyb_Led));
+ mp_store_attr(m, MP_QSTR_LED, (mp_obj_t)&pyb_led_type);
mp_store_attr(m, MP_QSTR_analogRead, mp_make_function_n(1, pyb_analog_read));
mp_store_attr(m, MP_QSTR_analogWrite, mp_make_function_n(2, pyb_analog_write));
mp_store_attr(m, MP_QSTR_analogWriteResolution, mp_make_function_n(1, pyb_analog_write_resolution));
@@ -487,15 +294,12 @@ soft_reset:
mp_store_attr(m, MP_QSTR_gpio, (mp_obj_t)&pyb_gpio_obj);
mp_store_attr(m, MP_QSTR_Servo, mp_make_function_n(0, pyb_Servo));
mp_store_name(MP_QSTR_pyb, m);
- mp_store_name(MP_QSTR_run, mp_make_function_n(1, pyb_run));
}
+#endif
- printf("About execute /boot.py\n");
- if (!do_file("/boot.py")) {
- printf("Unable to open '/boot.py'\n");
+ if (!pyexec_file("/boot.py")) {
flash_error(4);
}
- printf("Done executing /boot.py\n");
// Turn bootup LED off
led_state(PYB_LED_BUILTIN, 0);
@@ -504,27 +308,30 @@ soft_reset:
{
vstr_t *vstr = vstr_new();
vstr_add_str(vstr, "/");
- if (pyb_config_source_dir == MP_OBJ_NULL) {
- vstr_add_str(vstr, "src");
- } else {
- vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_source_dir));
- }
- vstr_add_char(vstr, '/');
if (pyb_config_main == MP_OBJ_NULL) {
vstr_add_str(vstr, "main.py");
} else {
vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_main));
}
- printf("About execute '%s'\n", vstr_str(vstr));
- if (!do_file(vstr_str(vstr))) {
- printf("Unable to open '%s'\n", vstr_str(vstr));
+ if (!pyexec_file(vstr_str(vstr))) {
flash_error(3);
}
- printf("Done executing '%s'\n", vstr_str(vstr));
vstr_free(vstr);
}
- do_repl();
+ // enter REPL
+ // REPL mode can change, or it can request a soft reset
+ for (;;) {
+ if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
+ if (pyexec_raw_repl() != 0) {
+ break;
+ }
+ } else {
+ if (pyexec_friendly_repl() != 0) {
+ break;
+ }
+ }
+ }
printf("PYB: soft reboot\n");
@@ -532,22 +339,15 @@ soft_reset:
goto soft_reset;
}
-double sqrt(double x) {
- // TODO
- return 0.0;
-}
-
-machine_float_t machine_sqrt(machine_float_t x) {
- // TODO
- return x;
-}
-
// stub out __libc_init_array. It's called by mk20dx128.c and is used to call
// global C++ constructors. Since this is a C-only projects, we don't need to
// call constructors.
void __libc_init_array(void) {
}
+// ultoa is used by usb_init_serialnumber. Normally ultoa would be provided
+// by nonstd.c from the teensy core, but it conflicts with some of the
+// MicroPython functions in string0.c, so we provide ultoa here.
char * ultoa(unsigned long val, char *buf, int radix)
{
unsigned digit;
@@ -569,3 +369,12 @@ char * ultoa(unsigned long val, char *buf, int radix)
}
return buf;
}
+
+STATIC NORETURN mp_obj_t mp_sys_exit(uint n_args, const mp_obj_t *args) {
+ int rc = 0;
+ if (n_args > 0) {
+ rc = mp_obj_get_int(args[0]);
+ }
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_SystemExit, mp_obj_new_int(rc)));
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit);
diff --git a/teensy/make-pins.py b/teensy/make-pins.py
new file mode 100755
index 0000000000..1fd05ec207
--- /dev/null
+++ b/teensy/make-pins.py
@@ -0,0 +1,326 @@
+#!/usr/bin/env python
+"""Creates the pin file for the Teensy."""
+
+from __future__ import print_function
+
+import argparse
+import sys
+import csv
+
+SUPPORTED_FN = {
+ 'FTM' : ['CH0', 'CH1', 'CH2', 'CH3',
+ 'QD_PHA', 'QD_PHB'],
+ 'I2C' : ['SDA', 'SCL'],
+ 'UART' : ['RX', 'TX', 'CTS', 'RTS'],
+ 'SPI' : ['NSS', 'SCK', 'MISO', 'MOSI']
+}
+
+def parse_port_pin(name_str):
+ """Parses a string and returns a (port-num, pin-num) tuple."""
+ if len(name_str) < 4:
+ raise ValueError("Expecting pin name to be at least 4 charcters.")
+ if name_str[0:2] != 'PT':
+ raise ValueError("Expecting pin name to start with PT")
+ if name_str[2] not in ('A', 'B', 'C', 'D', 'E', 'Z'):
+ raise ValueError("Expecting pin port to be between A and E or Z")
+ port = ord(name_str[2]) - ord('A')
+ pin_str = name_str[3:].split('/')[0]
+ if not pin_str.isdigit():
+ raise ValueError("Expecting numeric pin number.")
+ return (port, int(pin_str))
+
+def split_name_num(name_num):
+ num = None
+ for num_idx in range(len(name_num) - 1, -1, -1):
+ if not name_num[num_idx].isdigit():
+ name = name_num[0:num_idx + 1]
+ num_str = name_num[num_idx + 1:]
+ if len(num_str) > 0:
+ num = int(num_str)
+ break
+ return name, num
+
+
+class AlternateFunction(object):
+ """Holds the information associated with a pins alternate function."""
+
+ def __init__(self, idx, af_str):
+ self.idx = idx
+ self.af_str = af_str
+
+ self.func = ''
+ self.fn_num = None
+ self.pin_type = ''
+ self.supported = False
+
+ af_words = af_str.split('_', 1)
+ self.func, self.fn_num = split_name_num(af_words[0])
+ if len(af_words) > 1:
+ self.pin_type = af_words[1]
+ if self.func in SUPPORTED_FN:
+ pin_types = SUPPORTED_FN[self.func]
+ if self.pin_type in pin_types:
+ self.supported = True
+
+ def is_supported(self):
+ return self.supported
+
+ def ptr(self):
+ """Returns the numbered function (i.e. USART6) for this AF."""
+ if self.fn_num is None:
+ return self.func
+ return '{:s}{:d}'.format(self.func, self.fn_num)
+
+ def print(self):
+ """Prints the C representation of this AF."""
+ if self.supported:
+ print(' AF', end='')
+ else:
+ print(' //', end='')
+ fn_num = self.fn_num
+ if fn_num is None:
+ fn_num = 0
+ print('({:2d}, {:8s}, {:2d}, {:10s}, {:8s}), // {:s}'.format(self.idx,
+ self.func, fn_num, self.pin_type, self.ptr(), self.af_str))
+
+
+class Pin(object):
+ """Holds the information associated with a pin."""
+
+ def __init__(self, port, pin):
+ self.port = port
+ self.pin = pin
+ self.alt_fn = []
+ self.alt_fn_count = 0
+ self.adc_num = 0
+ self.adc_channel = 0
+ self.board_pin = False
+
+ def port_letter(self):
+ return chr(self.port + ord('A'))
+
+ def cpu_pin_name(self):
+ return '{:s}{:d}'.format(self.port_letter(), self.pin)
+
+ def is_board_pin(self):
+ return self.board_pin
+
+ def set_is_board_pin(self):
+ self.board_pin = True
+
+ def parse_adc(self, adc_str):
+ if (adc_str[:3] != 'ADC'):
+ return
+ (adc,channel) = adc_str.split('_')
+ for idx in range(3, len(adc)):
+ adc_num = int(adc[idx]) # 1, 2, or 3
+ self.adc_num |= (1 << (adc_num - 1))
+ self.adc_channel = int(channel[2:])
+
+ def parse_af(self, af_idx, af_strs_in):
+ if len(af_strs_in) == 0:
+ return
+ # If there is a slash, then the slash separates 2 aliases for the
+ # same alternate function.
+ af_strs = af_strs_in.split('/')
+ for af_str in af_strs:
+ alt_fn = AlternateFunction(af_idx, af_str)
+ self.alt_fn.append(alt_fn)
+ if alt_fn.is_supported():
+ self.alt_fn_count += 1
+
+ def alt_fn_name(self, null_if_0=False):
+ if null_if_0 and self.alt_fn_count == 0:
+ return 'NULL'
+ return 'pin_{:s}_af'.format(self.cpu_pin_name())
+
+ def adc_num_str(self):
+ str = ''
+ for adc_num in range(1,4):
+ if self.adc_num & (1 << (adc_num - 1)):
+ if len(str) > 0:
+ str += ' | '
+ str += 'PIN_ADC'
+ str += chr(ord('0') + adc_num)
+ if len(str) == 0:
+ str = '0'
+ return str
+
+ def print(self):
+ if self.alt_fn_count == 0:
+ print("// ", end='')
+ print('const pin_af_obj_t {:s}[] = {{'.format(self.alt_fn_name()))
+ for alt_fn in self.alt_fn:
+ alt_fn.print()
+ if self.alt_fn_count == 0:
+ print("// ", end='')
+ print('};')
+ print('')
+ print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:d}, {:s}, {:s}, {:d});'.format(
+ self.cpu_pin_name(), self.port_letter(), self.pin,
+ self.alt_fn_count, self.alt_fn_name(null_if_0=True),
+ self.adc_num_str(), self.adc_channel))
+ print('')
+
+ def print_header(self, hdr_file):
+ hdr_file.write('extern const pin_obj_t pin_{:s};\n'.
+ format(self.cpu_pin_name()))
+ if self.alt_fn_count > 0:
+ hdr_file.write('extern const pin_af_obj_t pin_{:s}_af[];\n'.
+ format(self.cpu_pin_name()))
+
+class NamedPin(object):
+
+ def __init__(self, name, pin):
+ self._name = name
+ self._pin = pin
+
+ def pin(self):
+ return self._pin
+
+ def name(self):
+ return self._name
+
+
+class Pins(object):
+
+ def __init__(self):
+ self.cpu_pins = [] # list of NamedPin objects
+ self.board_pins = [] # list of NamedPin objects
+
+ def find_pin(self, port_num, pin_num):
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ if pin.port == port_num and pin.pin == pin_num:
+ return pin
+
+ def parse_af_file(self, filename, pinname_col, af_col):
+ with open(filename, 'r') as csvfile:
+ rows = csv.reader(csvfile)
+ for row in rows:
+ try:
+ (port_num, pin_num) = parse_port_pin(row[pinname_col])
+ except:
+ continue
+ pin = Pin(port_num, pin_num)
+ for af_idx in range(af_col, len(row)):
+ if af_idx >= af_col:
+ pin.parse_af(af_idx - af_col, row[af_idx])
+ self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin))
+
+ def parse_board_file(self, filename):
+ with open(filename, 'r') as csvfile:
+ rows = csv.reader(csvfile)
+ for row in rows:
+ try:
+ (port_num, pin_num) = parse_port_pin(row[1])
+ except:
+ continue
+ pin = self.find_pin(port_num, pin_num)
+ if pin:
+ pin.set_is_board_pin()
+ self.board_pins.append(NamedPin(row[0], pin))
+
+ def print_named(self, label, named_pins):
+ print('const pin_named_pin_t pin_{:s}_pins[] = {{'.format(label))
+ for named_pin in named_pins:
+ pin = named_pin.pin()
+ if pin.is_board_pin():
+ print(' {{ "{:s}", &pin_{:s} }},'.format(named_pin.name(), pin.cpu_pin_name()))
+ print(' { NULL, NULL }')
+ print('};')
+
+ def print(self):
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ if pin.is_board_pin():
+ pin.print()
+ self.print_named('cpu', self.cpu_pins)
+ print('')
+ self.print_named('board', self.board_pins)
+
+ def print_adc(self, adc_num):
+ print('');
+ print('const pin_obj_t * const pin_adc{:d}[] = {{'.format(adc_num))
+ for channel in range(16):
+ adc_found = False
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ if (pin.is_board_pin() and
+ (pin.adc_num & (1 << (adc_num - 1))) and (pin.adc_channel == channel)):
+ print(' &pin_{:s}, // {:d}'.format(pin.cpu_pin_name(), channel))
+ adc_found = True
+ break
+ if not adc_found:
+ print(' NULL, // {:d}'.format(channel))
+ print('};')
+
+
+ def print_header(self, hdr_filename):
+ with open(hdr_filename, 'wt') as hdr_file:
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ if pin.is_board_pin():
+ pin.print_header(hdr_file)
+ hdr_file.write('extern const pin_obj_t * const pin_adc1[];\n')
+ hdr_file.write('extern const pin_obj_t * const pin_adc2[];\n')
+ hdr_file.write('extern const pin_obj_t * const pin_adc3[];\n')
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ prog="make-pins.py",
+ usage="%(prog)s [options] [command]",
+ description="Generate board specific pin file"
+ )
+ parser.add_argument(
+ "-a", "--af",
+ dest="af_filename",
+ help="Specifies the alternate function file for the chip",
+ default="stm32f4xx-af.csv"
+ )
+ parser.add_argument(
+ "-b", "--board",
+ dest="board_filename",
+ help="Specifies the board file",
+ )
+ parser.add_argument(
+ "-p", "--prefix",
+ dest="prefix_filename",
+ help="Specifies beginning portion of generated pins file",
+ default="stm32f4xx-prefix.c"
+ )
+ parser.add_argument(
+ "-r", "--hdr",
+ dest="hdr_filename",
+ help="Specifies name of generated pin header file",
+ default="build/pins.h"
+ )
+ args = parser.parse_args(sys.argv[1:])
+
+ pins = Pins()
+
+ print('// This file was automatically generated by make-pins.py')
+ print('//')
+ if args.af_filename:
+ print('// --af {:s}'.format(args.af_filename))
+ pins.parse_af_file(args.af_filename, 4, 3)
+
+ if args.board_filename:
+ print('// --board {:s}'.format(args.board_filename))
+ pins.parse_board_file(args.board_filename)
+
+ if args.prefix_filename:
+ print('// --prefix {:s}'.format(args.prefix_filename))
+ print('')
+ with open(args.prefix_filename, 'r') as prefix_file:
+ print(prefix_file.read())
+ pins.print()
+ pins.print_adc(1)
+ pins.print_adc(2)
+ pins.print_adc(3)
+ pins.print_header(args.hdr_filename)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/teensy/memzip.c b/teensy/memzip.c
index ec6c26980c..b269c472a1 100644
--- a/teensy/memzip.c
+++ b/teensy/memzip.c
@@ -1,12 +1,13 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include "misc.h"
#include "memzip.h"
extern uint8_t _staticfs[];
-MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len)
-{
+const MEMZIP_FILE_HDR *memzip_find_file_header(const char *filename) {
+
const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)_staticfs;
uint8_t *mem_data;
@@ -22,16 +23,83 @@ MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len)
mem_data += file_hdr->extra_len;
if (!strncmp(file_hdr_filename, filename, file_hdr->filename_len)) {
/* We found a match */
- if (file_hdr->compression_method != 0) {
- return MZ_FILE_COMPRESSED;
- }
+ return file_hdr;
+ }
+ mem_data += file_hdr->uncompressed_size;
+ file_hdr = (const MEMZIP_FILE_HDR *)mem_data;
+ }
+ return NULL;
+}
- *data = mem_data;
- *len = file_hdr->uncompressed_size;
- return MZ_OK;
+bool memzip_is_dir(const char *filename) {
+ const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)_staticfs;
+ uint8_t *mem_data;
+
+ if (strcmp(filename, "/") == 0) {
+ // The root directory is a directory.
+ return true;
+ }
+
+ // Zip filenames don't have a leading /, so we strip it off
+ if (*filename == '/') {
+ filename++;
+ }
+ size_t filename_len = strlen(filename);
+
+ while (file_hdr->signature == MEMZIP_FILE_HEADER_SIGNATURE) {
+ const char *file_hdr_filename = (const char *)&file_hdr[1];
+ if (filename_len < file_hdr->filename_len &&
+ strncmp(file_hdr_filename, filename, filename_len) == 0 &&
+ file_hdr_filename[filename_len] == '/') {
+ return true;
}
+
+ mem_data = (uint8_t *)file_hdr_filename;
+ mem_data += file_hdr->filename_len;
+ mem_data += file_hdr->extra_len;
mem_data += file_hdr->uncompressed_size;
file_hdr = (const MEMZIP_FILE_HDR *)mem_data;
}
- return MZ_NO_FILE;
+ return NULL;
+
+}
+
+MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len)
+{
+ const MEMZIP_FILE_HDR *file_hdr = memzip_find_file_header(filename);
+ if (file_hdr == NULL) {
+ return MZ_NO_FILE;
+ }
+ if (file_hdr->compression_method != 0) {
+ return MZ_FILE_COMPRESSED;
+ }
+
+ uint8_t *mem_data;
+ mem_data = (uint8_t *)&file_hdr[1];
+ mem_data += file_hdr->filename_len;
+ mem_data += file_hdr->extra_len;
+
+ *data = mem_data;
+ *len = file_hdr->uncompressed_size;
+ return MZ_OK;
+}
+
+MEMZIP_RESULT memzip_stat(const char *path, MEMZIP_FILE_INFO *info) {
+ const MEMZIP_FILE_HDR *file_hdr = memzip_find_file_header(path);
+ if (file_hdr == NULL) {
+ if (memzip_is_dir(path)) {
+ info->file_size = 0;
+ info->last_mod_date = 0;
+ info->last_mod_time = 0;
+ info->is_dir = 1;
+ return MZ_OK;
+ }
+ return MZ_NO_FILE;
+ }
+ info->file_size = file_hdr->uncompressed_size;
+ info->last_mod_date = file_hdr->last_mod_date;
+ info->last_mod_time = file_hdr->last_mod_time;
+ info->is_dir = 0;
+
+ return MZ_OK;
}
diff --git a/teensy/memzip.h b/teensy/memzip.h
index ecbd98763c..667e2df7e1 100644
--- a/teensy/memzip.h
+++ b/teensy/memzip.h
@@ -70,4 +70,14 @@ typedef enum {
} MEMZIP_RESULT;
+typedef struct {
+ uint32_t file_size;
+ uint16_t last_mod_date;
+ uint16_t last_mod_time;
+ uint8_t is_dir;
+
+} MEMZIP_FILE_INFO;
+
MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len);
+
+MEMZIP_RESULT memzip_stat(const char *path, MEMZIP_FILE_INFO *info);
diff --git a/teensy/memzip_files/boot.py b/teensy/memzip_files/boot.py
index 3fe9f05e53..4702d7b5d3 100644
--- a/teensy/memzip_files/boot.py
+++ b/teensy/memzip_files/boot.py
@@ -1 +1,2 @@
+import pyb
print("Executing boot.py")
diff --git a/teensy/memzip_files/src/main.py b/teensy/memzip_files/main.py
index 8fc08db15e..4f30f2fc5f 100644
--- a/teensy/memzip_files/src/main.py
+++ b/teensy/memzip_files/main.py
@@ -1,11 +1,13 @@
print("Executing main.py")
-x=pyb.led(1)
+led = pyb.LED(1)
+
+led.on()
pyb.delay(100)
-x=pyb.led(0)
+led.off()
pyb.delay(100)
-x=pyb.led(1)
+led.on()
pyb.delay(100)
-x=pyb.led(0)
+led.off()
diff --git a/teensy/memzip_files/src/test.py b/teensy/memzip_files/src/test.py
deleted file mode 100644
index 7957b27caf..0000000000
--- a/teensy/memzip_files/src/test.py
+++ /dev/null
@@ -1 +0,0 @@
-print("Executing /src/test.py")
diff --git a/teensy/memzip_files/test.py b/teensy/memzip_files/test.py
deleted file mode 100644
index 088cb4383a..0000000000
--- a/teensy/memzip_files/test.py
+++ /dev/null
@@ -1 +0,0 @@
-print("Executing /test.py")
diff --git a/teensy/mk20dx256-af.csv b/teensy/mk20dx256-af.csv
new file mode 100644
index 0000000000..3015c6c7a1
--- /dev/null
+++ b/teensy/mk20dx256-af.csv
@@ -0,0 +1,65 @@
+Pin,Name,Default,ALT0,ALT1,ALT2,ALT3,ALT4,ALT5,ALT6,ALT7,EzPort
+1,PTE0,ADC1_SE4a,ADC1_SE4a,PTE0,SPI1_PCS1,UART1_TX,,,I2C1_SDA,RTC_CLKOUT,
+2,PTE1/LLWU_P0,ADC1_SE5a,ADC1_SE5a,PTE1/LLWU_P0,SPI1_SOUT,UART1_RX,,,I2C1_SCL,SPI1_SIN,
+3,VDD,VDD,VDD,,,,,,,,
+4,VSS,VSS,VSS,,,,,,,,
+5,USB0_DP,USB0_DP,USB0_DP,,,,,,,,
+6,USB0_DM,USB0_DM,USB0_DM,,,,,,,,
+7,VOUT33,VOUT33,VOUT33,,,,,,,,
+8,VREGIN,VREGIN,VREGIN,,,,,,,,
+9,PGA0_DP/ADC0_DP0/ADC1_DP3,PGA0_DP/ADC0_DP0/ADC1_DP3,PGA0_DP/ADC0_DP0/ADC1_DP3,PTZ0,,,,,,,
+10,PGA0_DM/ADC0_DM0/ADC1_DM3,PGA0_DM/ADC0_DM0/ADC1_DM3,PGA0_DM/ADC0_DM0/ADC1_DM3,PTZ1,,,,,,,
+11,PGA1_DP/ADC1_DP0/ADC0_DP3,PGA1_DP/ADC1_DP0/ADC0_DP3,PGA1_DP/ADC1_DP0/ADC0_DP3,PTZ2,,,,,,,
+12,PGA1_DM/ADC1_DM0/ADC0_DM3,PGA1_DM/ADC1_DM0/ADC0_DM3,PGA1_DM/ADC1_DM0/ADC0_DM3,PTZ3,,,,,,,
+13,VDDA,VDDA,VDDA,,,,,,,,
+14,VREFH,VREFH,VREFH,,,,,,,,
+15,VREFL,VREFL,VREFL,,,,,,,,
+16,VSSA,VSSA,VSSA,,,,,,,,
+17,VREF_OUT/CMP1_IN5/CMP0_IN5/ADC1_SE18,VREF_OUT/CMP1_IN5/CMP0_IN5/ADC1_SE18,VREF_OUT/CMP1_IN5/CMP0_IN5/ADC1_SE18,PTZ4,,,,,,,
+18,DAC0_OUT/CMP1_IN3/ADC0_SE23,DAC0_OUT/CMP1_IN3/ADC0_SE23,DAC0_OUT/CMP1_IN3/ADC0_SE23,PTZ5,,,,,,,
+19,XTAL32,XTAL32,XTAL32,,,,,,,,
+20,EXTAL32,EXTAL32,EXTAL32,,,,,,,,
+21,VBAT,VBAT,VBAT,,,,,,,,
+22,PTA0,JTAG_TCLK/SWD_CLK/EZP_CLK,TSI0_CH1,PTA0,UART0_CTS_b/UART0_COL_b,FTM0_CH5,,,,JTAG_TCLK/SWD_CLK,EZP_CLK
+23,PTA1,JTAG_TDI/EZP_DI,TSI0_CH2,PTA1,UART0_RX,FTM0_CH6,,,,JTAG_TDI,EZP_DI
+24,PTA2,JTAG_TDO/TRACE_SWO/EZP_DO,TSI0_CH3,PTA2,UART0_TX,FTM0_CH7,,,,JTAG_TDO/TRACE_SWO,EZP_DO
+25,PTA3,JTAG_TMS/SWD_DIO,TSI0_CH4,PTA3,UART0_RTS_b,FTM0_CH0,,,,JTAG_TMS/SWD_DIO,
+26,PTA4/LLWU_P3,NMI_b/EZP_CS_b,TSI0_CH5,PTA4/LLWU_P3,,FTM0_CH1,,,NMI_b,EZP_CS_b,
+27,PTA5,DISABLED,,PTA5,USB_CLKIN,FTM0_CH2,,CMP2_OUT,I2S0_TX_BCLK,JTAG_TRST_b,
+28,PTA12,CMP2_IN0,CMP2_IN0,PTA12,CAN0_TX,FTM1_CH0,,,I2S0_TXD0,FTM1_QD_PHA,
+29,PTA13/LLWU_P4,CMP2_IN1,CMP2_IN1,PTA13/LLWU_P4,CAN0_RX,FTM1_CH1,,,I2S0_TX_FS,FTM1_QD_PHB,
+30,VDD,VDD,VDD,,,,,,,,
+31,VSS,VSS,VSS,,,,,,,,
+32,PTA18,EXTAL0,EXTAL0,PTA18,,FTM0_FLT2,FTM_CLKIN0,,,,
+33,PTA19,XTAL0,XTAL0,PTA19,,FTM1_FLT0,FTM_CLKIN1,,LPTMR0_ALT1,,
+34,RESET_b,RESET_b,RESET_b,,,,,,,,
+35,PTB0/LLWU_P5,ADC0_SE8/ADC1_SE8/TSI0_CH0,ADC0_SE8/ADC1_SE8/TSI0_CH0,PTB0/LLWU_P5,I2C0_SCL,FTM1_CH0,,,FTM1_QD_PHA,,
+36,PTB1,ADC0_SE9/ADC1_SE9/TSI0_CH6,ADC0_SE9/ADC1_SE9/TSI0_CH6,PTB1,I2C0_SDA,FTM1_CH1,,,FTM1_QD_PHB,,
+37,PTB2,ADC0_SE12/TSI0_CH7,ADC0_SE12/TSI0_CH7,PTB2,I2C0_SCL,UART0_RTS_b,,,FTM0_FLT3,,
+38,PTB3,ADC0_SE13/TSI0_CH8,ADC0_SE13/TSI0_CH8,PTB3,I2C0_SDA,UART0_CTS_b/UART0_COL_b,,,FTM0_FLT0,,
+39,PTB16,TSI0_CH9,TSI0_CH9,PTB16,SPI1_SOUT,UART0_RX,,FB_AD17,EWM_IN,,
+40,PTB17,TSI0_CH10,TSI0_CH10,PTB17,SPI1_SIN,UART0_TX,,FB_AD16,EWM_OUT_b,,
+41,PTB18,TSI0_CH11,TSI0_CH11,PTB18,CAN0_TX,FTM2_CH0,I2S0_TX_BCLK,FB_AD15,FTM2_QD_PHA,,
+42,PTB19,TSI0_CH12,TSI0_CH12,PTB19,CAN0_RX,FTM2_CH1,I2S0_TX_FS,FB_OE_b,FTM2_QD_PHB,,
+43,PTC0,ADC0_SE14/TSI0_CH13,ADC0_SE14/TSI0_CH13,PTC0,SPI0_PCS4,PDB0_EXTRG,,FB_AD14,I2S0_TXD1,,
+44,PTC1/LLWU_P6,ADC0_SE15/TSI0_CH14,ADC0_SE15/TSI0_CH14,PTC1/LLWU_P6,SPI0_PCS3,UART1_RTS_b,FTM0_CH0,FB_AD13,I2S0_TXD0,,
+45,PTC2,ADC0_SE4b/CMP1_IN0/TSI0_CH15,ADC0_SE4b/CMP1_IN0/TSI0_CH15,PTC2,SPI0_PCS2,UART1_CTS_b,FTM0_CH1,FB_AD12,I2S0_TX_FS,,
+46,PTC3/LLWU_P7,CMP1_IN1,CMP1_IN1,PTC3/LLWU_P7,SPI0_PCS1,UART1_RX,FTM0_CH2,CLKOUT,I2S0_TX_BCLK,,
+47,VSS,VSS,VSS,,,,,,,,
+48,VDD,VDD,VDD,,,,,,,,
+49,PTC4/LLWU_P8,DISABLED,,PTC4/LLWU_P8,SPI0_PCS0,UART1_TX,FTM0_CH3,FB_AD11,CMP1_OUT,,
+50,PTC5/LLWU_P9,DISABLED,,PTC5/LLWU_P9,SPI0_SCK,LPTMR0_ALT2,I2S0_RXD0,FB_AD10,CMP0_OUT,,
+51,PTC6/LLWU_P10,CMP0_IN0,CMP0_IN0,PTC6/LLWU_P10,SPI0_SOUT,PDB0_EXTRG,I2S0_RX_BCLK,FB_AD9,I2S0_MCLK,,
+52,PTC7,CMP0_IN1,CMP0_IN1,PTC7,SPI0_SIN,USB_SOF_OUT,I2S0_RX_FS,FB_AD8,,,
+53,PTC8,ADC1_SE4b/CMP0_IN2,ADC1_SE4b/CMP0_IN2,PTC8,,,I2S0_MCLK,FB_AD7,,,
+54,PTC9,ADC1_SE5b/CMP0_IN3,ADC1_SE5b/CMP0_IN3,PTC9,,,I2S0_RX_BCLK,FB_AD6,FTM2_FLT0,,
+55,PTC10,ADC1_SE6b,ADC1_SE6b,PTC10,I2C1_SCL,,I2S0_RX_FS,FB_AD5,,,
+56,PTC11/LLWU_P11,ADC1_SE7b,ADC1_SE7b,PTC11/LLWU_P11,I2C1_SDA,,I2S0_RXD1,FB_RW_b,,,
+57,PTD0/LLWU_P12,DISABLED,,PTD0/LLWU_P12,SPI0_PCS0,UART2_RTS_b,,FB_ALE/FB_CS1_b/FB_TS_b,,,
+58,PTD1,ADC0_SE5b,ADC0_SE5b,PTD1,SPI0_SCK,UART2_CTS_b,,FB_CS0_b,,,
+59,PTD2/LLWU_P13,DISABLED,,PTD2/LLWU_P13,SPI0_SOUT,UART2_RX,,FB_AD4,,,
+60,PTD3,DISABLED,,PTD3,SPI0_SIN,UART2_TX,,FB_AD3,,,
+61,PTD4/LLWU_P14,DISABLED,,PTD4/LLWU_P14,SPI0_PCS1,UART0_RTS_b,FTM0_CH4,FB_AD2,EWM_IN,,
+62,PTD5,ADC0_SE6b,ADC0_SE6b,PTD5,SPI0_PCS2,UART0_CTS_b/UART0_COL_b,FTM0_CH5,FB_AD1,EWM_OUT_b,,
+63,PTD6/LLWU_P15,ADC0_SE7b,ADC0_SE7b,PTD6/LLWU_P15,SPI0_PCS3,UART0_RX,FTM0_CH6,FB_AD0,FTM0_FLT0,,
+64,PTD7,DISABLED,,PTD7,CMT_IRO,UART0_TX,FTM0_CH7,,FTM0_FLT1,,
diff --git a/teensy/mk20dx256-prefix.c b/teensy/mk20dx256-prefix.c
new file mode 100644
index 0000000000..ea9eec74a2
--- /dev/null
+++ b/teensy/mk20dx256-prefix.c
@@ -0,0 +1,37 @@
+// stm32fxx-prefix.c becomes the initial portion of the generated pins file.
+
+#include <stdio.h>
+#include <stdint.h>
+#include <mk20dx128.h>
+
+#include "teensy_hal.h"
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "pin.h"
+
+#define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \
+{ \
+ { &pin_af_type }, \
+ .idx = (af_idx), \
+ .fn = AF_FN_ ## af_fn, \
+ .unit = (af_unit), \
+ .type = AF_PIN_TYPE_ ## af_fn ## _ ## af_type, \
+ .af_fn = (af_ptr) \
+}
+
+#define PIN(p_port, p_pin, p_num_af, p_af, p_adc_num, p_adc_channel) \
+{ \
+ { &pin_type }, \
+ .name = #p_port #p_pin, \
+ .port = PORT_ ## p_port, \
+ .pin = (p_pin), \
+ .num_af = (p_num_af), \
+ .pin_mask = (1 << (p_pin)), \
+ .gpio = GPIO ## p_port, \
+ .af = p_af, \
+ .adc_num = p_adc_num, \
+ .adc_channel = p_adc_channel, \
+}
diff --git a/teensy/mk20dx256.ld b/teensy/mk20dx256.ld
index e46efd3e26..bff0a8c4aa 100644
--- a/teensy/mk20dx256.ld
+++ b/teensy/mk20dx256.ld
@@ -10,10 +10,10 @@
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
- * 1. The above copyright notice and this permission notice shall be
+ * 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
- * 2. If the Software is incorporated into a build system that allows
+ * 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
@@ -30,8 +30,8 @@
MEMORY
{
- FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K
- RAM (rwx) : ORIGIN = 0x1FFF8000, LENGTH = 64K
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K
+ RAM (rwx) : ORIGIN = 0x1FFF8000, LENGTH = 64K
}
/* produce a link error if there is not this amount of RAM for these sections */
@@ -52,10 +52,10 @@ _minimum_heap_size = 16K;
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
- * 1. The above copyright notice and this permission notice shall be
+ * 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
- * 2. If the Software is incorporated into a build system that allows
+ * 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
@@ -74,95 +74,101 @@ _minimum_heap_size = 16K;
SECTIONS
{
- .text : {
- . = 0;
- KEEP(*(.vectors))
- *(.startup*)
- /* TODO: does linker detect startup overflow onto flashconfig? */
- . = 0x400;
- KEEP(*(.flashconfig*))
- *(.text*)
- *(.rodata*)
- . = ALIGN(4);
- KEEP(*(.init))
- . = ALIGN(4);
- __preinit_array_start = .;
- KEEP (*(.preinit_array))
- __preinit_array_end = .;
- __init_array_start = .;
- KEEP (*(SORT(.init_array.*)))
- KEEP (*(.init_array))
- __init_array_end = .;
- } > FLASH = 0xFF
-
- .ARM.exidx : {
- __exidx_start = .;
- *(.ARM.exidx* .gnu.linkonce.armexidx.*)
- __exidx_end = .;
- } > FLASH
- _etext = .;
-
- .usbdescriptortable (NOLOAD) : {
- /* . = ORIGIN(RAM); */
- . = ALIGN(512);
- *(.usbdescriptortable*)
- } > RAM
-
- .dmabuffers (NOLOAD) : {
- . = ALIGN(4);
- *(.dmabuffers*)
- } > RAM
-
- .usbbuffers (NOLOAD) : {
- . = ALIGN(4);
- *(.usbbuffers*)
- } > RAM
-
- .data : AT (_etext) {
- . = ALIGN(4);
- _sdata = .;
- *(.data*)
- . = ALIGN(4);
- _edata = .;
- } > RAM
-
- /*
- * _staticfs is the place in flash where the static filesystem which
- * is concatenated to the .hex file will wind up.
- */
- _staticfs = LOADADDR(.data) + SIZEOF(.data);
-
- .noinit (NOLOAD) : {
- *(.noinit*)
- } > RAM
-
- .bss : {
- . = ALIGN(4);
- _sbss = .;
- *(.bss*)
- *(COMMON)
- . = ALIGN(4);
- _ebss = .;
- __bss_end = .;
- } > RAM
-
- /* this is to define the start of the heap, and make sure we have a minimum size */
- .heap :
- {
- . = ALIGN(4);
- _heap_start = .; /* define a global symbol at heap start */
- . = . + _minimum_heap_size;
- } >RAM
-
- /* this just checks there is enough RAM for the stack */
- .stack :
- {
- . = ALIGN(4);
- . = . + _minimum_stack_size;
- . = ALIGN(4);
- } >RAM
-
- _estack = ORIGIN(RAM) + LENGTH(RAM);
+ .text : {
+ . = 0;
+ KEEP(*(.vectors))
+ *(.startup*)
+ /* TODO: does linker detect startup overflow onto flashconfig? */
+ . = 0x400;
+ KEEP(*(.flashconfig*))
+ *(.text*)
+ *(.rodata*)
+ . = ALIGN(4);
+ KEEP(*(.init))
+ . = ALIGN(4);
+ __preinit_array_start = .;
+ KEEP (*(.preinit_array))
+ __preinit_array_end = .;
+ __init_array_start = .;
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ __init_array_end = .;
+ } > FLASH = 0xFF
+
+ .ARM.exidx : {
+ __exidx_start = .;
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ __exidx_end = .;
+ } > FLASH
+ _etext = .;
+
+ .usbdescriptortable (NOLOAD) : {
+ /* . = ORIGIN(RAM); */
+ . = ALIGN(512);
+ *(.usbdescriptortable*)
+ } > RAM
+
+ .dmabuffers (NOLOAD) : {
+ . = ALIGN(4);
+ *(.dmabuffers*)
+ } > RAM
+
+ .usbbuffers (NOLOAD) : {
+ . = ALIGN(4);
+ *(.usbbuffers*)
+ } > RAM
+
+ /* used by the startup to initialize data */
+ _sidata = LOADADDR(.data);
+
+ .data : AT (_etext) {
+ . = ALIGN(4);
+ _sdata = .;
+ _ram_start = .;
+ *(.data*)
+ . = ALIGN(4);
+ _edata = .;
+ } > RAM
+
+ /*
+ * _staticfs is the place in flash where the static filesystem which
+ * is concatenated to the .hex file will wind up.
+ */
+ _staticfs = LOADADDR(.data) + SIZEOF(.data);
+
+ .noinit (NOLOAD) : {
+ *(.noinit*)
+ } > RAM
+
+ .bss : {
+ . = ALIGN(4);
+ _sbss = .;
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ __bss_end = .;
+ } > RAM
+
+ /* this is to define the start of the heap, and make sure we have a minimum size */
+ .heap :
+ {
+ . = ALIGN(4);
+ _heap_start = .; /* define a global symbol at heap start */
+ . = . + _minimum_heap_size;
+ } >RAM
+
+ /* this just checks there is enough RAM for the stack */
+ .stack :
+ {
+ . = ALIGN(4);
+ . = . + _minimum_stack_size;
+ . = ALIGN(4);
+ } >RAM
+
+ _estack = ORIGIN(RAM) + LENGTH(RAM);
+ _ram_end = ORIGIN(RAM) + LENGTH(RAM);
+ _heap_end = ORIGIN(RAM) + 0xe000;
}
diff --git a/teensy/modpyb.c b/teensy/modpyb.c
new file mode 100644
index 0000000000..0240395dc7
--- /dev/null
+++ b/teensy/modpyb.c
@@ -0,0 +1,341 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <mk20dx128.h>
+#include "Arduino.h"
+
+#include "misc.h"
+#include "mpconfig.h"
+
+#include "teensy_hal.h"
+
+#include "qstr.h"
+#include "obj.h"
+#include "gc.h"
+#include "gccollect.h"
+#include "systick.h"
+#include "pybstdio.h"
+#include "pyexec.h"
+#include "led.h"
+#include "pin.h"
+//#include "timer.h"
+#include "extint.h"
+#include "usrsw.h"
+#include "rng.h"
+//#include "rtc.h"
+//#include "i2c.h"
+//#include "spi.h"
+#include "uart.h"
+#include "adc.h"
+#include "storage.h"
+#include "sdcard.h"
+#include "accel.h"
+#include "servo.h"
+#include "dac.h"
+#include "usb.h"
+#include "portmodules.h"
+
+/// \module pyb - functions related to the pyboard
+///
+/// The `pyb` module contains specific functions related to the pyboard.
+
+/// \function bootloader()
+/// Activate the bootloader without BOOT* pins.
+STATIC mp_obj_t pyb_bootloader(void) {
+ printf("bootloader command not current supported\n");
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_bootloader_obj, pyb_bootloader);
+
+/// \function info([dump_alloc_table])
+/// Print out lots of information about the board.
+STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) {
+ // get and print unique id; 96 bits
+ {
+ byte *id = (byte*)0x40048058;
+ printf("ID=%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x\n", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11]);
+ }
+
+ // get and print clock speeds
+ printf("CPU=%u\nBUS=%u\nMEM=%u\n", F_CPU, F_BUS, F_MEM);
+
+ // to print info about memory
+ {
+ printf("_etext=%p\n", &_etext);
+ printf("_sidata=%p\n", &_sidata);
+ printf("_sdata=%p\n", &_sdata);
+ printf("_edata=%p\n", &_edata);
+ printf("_sbss=%p\n", &_sbss);
+ printf("_ebss=%p\n", &_ebss);
+ printf("_estack=%p\n", &_estack);
+ printf("_ram_start=%p\n", &_ram_start);
+ printf("_heap_start=%p\n", &_heap_start);
+ printf("_heap_end=%p\n", &_heap_end);
+ printf("_ram_end=%p\n", &_ram_end);
+ }
+
+ // qstr info
+ {
+ uint n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
+ qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
+ printf("qstr:\n n_pool=%u\n n_qstr=%u\n n_str_data_bytes=%u\n n_total_bytes=%u\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
+ }
+
+ // GC info
+ {
+ gc_info_t info;
+ gc_info(&info);
+ printf("GC:\n");
+ 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);
+ }
+
+ if (n_args == 1) {
+ // arg given means dump gc allocation table
+ gc_dump_alloc_table();
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info);
+
+/// \function unique_id()
+/// Returns a string of 12 bytes (96 bits), which is the unique ID for the MCU.
+STATIC mp_obj_t pyb_unique_id(void) {
+ byte *id = (byte*)0x40048058;
+ return mp_obj_new_bytes(id, 12);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_unique_id_obj, pyb_unique_id);
+
+/// \function freq()
+/// Return a tuple of clock frequencies: (SYSCLK, HCLK, PCLK1, PCLK2).
+// TODO should also be able to set frequency via this function
+STATIC mp_obj_t pyb_freq(void) {
+ mp_obj_t tuple[3] = {
+ mp_obj_new_int(F_CPU),
+ mp_obj_new_int(F_BUS),
+ mp_obj_new_int(F_MEM),
+ };
+ return mp_obj_new_tuple(3, tuple);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_freq_obj, pyb_freq);
+
+/// \function sync()
+/// Sync all file systems.
+STATIC mp_obj_t pyb_sync(void) {
+ printf("sync not currently implemented\n");
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_sync_obj, pyb_sync);
+
+/// \function millis()
+/// Returns the number of milliseconds since the board was last reset.
+STATIC mp_obj_t pyb_millis(void) {
+ return mp_obj_new_int(HAL_GetTick());
+}
+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 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_in) {
+ machine_int_t usec = mp_obj_get_int(usec_in);
+ delayMicroseconds(usec);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay);
+
+/// \function wfi()
+/// Wait for an interrupt.
+/// This executies a `wfi` instruction which reduces power consumption
+/// of the MCU until an interrupt occurs, at which point execution continues.
+STATIC mp_obj_t pyb_wfi(void) {
+ __WFI();
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_wfi_obj, pyb_wfi);
+
+/// \function disable_irq()
+/// Disable interrupt requests.
+STATIC mp_obj_t pyb_disable_irq(void) {
+ __disable_irq();
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_disable_irq_obj, pyb_disable_irq);
+
+/// \function enable_irq()
+/// Enable interrupt requests.
+STATIC mp_obj_t pyb_enable_irq(void) {
+ __enable_irq();
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_enable_irq_obj, pyb_enable_irq);
+
+STATIC mp_obj_t pyb_stop(void) {
+ printf("stop not currently implemented\n");
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_stop_obj, pyb_stop);
+
+STATIC mp_obj_t pyb_standby(void) {
+ printf("standby not currently implemented\n");
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_standby_obj, pyb_standby);
+
+/// \function have_cdc()
+/// Return True if USB is connected as a serial device, False otherwise.
+STATIC mp_obj_t pyb_have_cdc(void ) {
+ return MP_BOOL(usb_vcp_is_connected());
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc);
+
+/// \function hid((buttons, x, y, z))
+/// Takes a 4-tuple (or list) and sends it to the USB host (the PC) to
+/// signal a HID mouse-motion event.
+STATIC mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
+#if 1
+ printf("hid_send_report not currently implemented\n");
+#else
+ mp_obj_t *items;
+ mp_obj_get_array_fixed_n(arg, 4, &items);
+ uint8_t data[4];
+ data[0] = mp_obj_get_int(items[0]);
+ data[1] = mp_obj_get_int(items[1]);
+ data[2] = mp_obj_get_int(items[2]);
+ data[3] = mp_obj_get_int(items[3]);
+ usb_hid_send_report(data);
+#endif
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj, pyb_hid_send_report);
+
+MP_DECLARE_CONST_FUN_OBJ(pyb_source_dir_obj); // defined in main.c
+MP_DECLARE_CONST_FUN_OBJ(pyb_main_obj); // defined in main.c
+MP_DECLARE_CONST_FUN_OBJ(pyb_usb_mode_obj); // defined in main.c
+
+STATIC const mp_map_elem_t pyb_module_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_bootloader), (mp_obj_t)&pyb_bootloader_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_unique_id), (mp_obj_t)&pyb_unique_id_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_freq_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_repl_info), (mp_obj_t)&pyb_set_repl_info_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_wfi), (mp_obj_t)&pyb_wfi_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_disable_irq), (mp_obj_t)&pyb_disable_irq_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_enable_irq), (mp_obj_t)&pyb_enable_irq_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_stop), (mp_obj_t)&pyb_stop_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_standby), (mp_obj_t)&pyb_standby_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_source_dir), (mp_obj_t)&pyb_source_dir_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_main), (mp_obj_t)&pyb_main_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_usb_mode), (mp_obj_t)&pyb_usb_mode_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_have_cdc), (mp_obj_t)&pyb_have_cdc_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&pyb_delay_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&pyb_udelay_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&pyb_sync_obj },
+
+// { MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type },
+
+//#if MICROPY_HW_ENABLE_RNG
+// { MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)&pyb_rng_get_obj },
+//#endif
+
+//#if MICROPY_HW_ENABLE_RTC
+// { MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_type },
+//#endif
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type },
+// { MP_OBJ_NEW_QSTR(MP_QSTR_ExtInt), (mp_obj_t)&extint_type },
+
+#if MICROPY_HW_ENABLE_SERVO
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pwm), (mp_obj_t)&pyb_pwm_set_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_servo), (mp_obj_t)&pyb_servo_set_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Servo), (mp_obj_t)&pyb_servo_type },
+#endif
+
+#if MICROPY_HW_HAS_SWITCH
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Switch), (mp_obj_t)&pyb_switch_type },
+#endif
+
+//#if MICROPY_HW_HAS_SDCARD
+// { MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sdcard_obj },
+//#endif
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LED), (mp_obj_t)&pyb_led_type },
+// { MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
+// { MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
+
+// { MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type },
+// { MP_OBJ_NEW_QSTR(MP_QSTR_ADCAll), (mp_obj_t)&pyb_adc_all_type },
+
+//#if MICROPY_HW_ENABLE_DAC
+// { MP_OBJ_NEW_QSTR(MP_QSTR_DAC), (mp_obj_t)&pyb_dac_type },
+//#endif
+
+//#if MICROPY_HW_HAS_MMA7660
+// { MP_OBJ_NEW_QSTR(MP_QSTR_Accel), (mp_obj_t)&pyb_accel_type },
+//#endif
+};
+
+STATIC const mp_obj_dict_t pyb_module_globals = {
+ .base = {&mp_type_dict},
+ .map = {
+ .all_keys_are_qstrs = 1,
+ .table_is_fixed_array = 1,
+ .used = ARRAY_SIZE(pyb_module_globals_table),
+ .alloc = ARRAY_SIZE(pyb_module_globals_table),
+ .table = (mp_map_elem_t*)pyb_module_globals_table,
+ },
+};
+
+const mp_obj_module_t pyb_module = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_pyb,
+ .globals = (mp_obj_dict_t*)&pyb_module_globals,
+};
diff --git a/teensy/mpconfigport.h b/teensy/mpconfigport.h
index f7c66d8874..ff0a31f272 100644
--- a/teensy/mpconfigport.h
+++ b/teensy/mpconfigport.h
@@ -2,20 +2,98 @@
// options to control how Micro Python is built
+#define MICROPY_ALLOC_PATH_MAX (128)
#define MICROPY_EMIT_THUMB (1)
#define MICROPY_EMIT_INLINE_THUMB (1)
#define MICROPY_ENABLE_GC (1)
+#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_HELPER_REPL (1)
#define MICROPY_PY_BUILTINS_FLOAT (1)
+#define MICROPY_ENABLE_SOURCE_LINE (1)
+#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
+#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
+#define MICROPY_OPT_COMPUTED_GOTO (1)
+
+#define MICROPY_PY_IO (0)
+#define MICROPY_PY_FROZENSET (1)
+#define MICROPY_PY_SYS_EXIT (1)
+#define MICROPY_PY_SYS_STDFILES (1)
+#define MICROPY_PY_CMATH (1)
+
+// extra built in names to add to the global namespace
+extern const struct _mp_obj_fun_native_t mp_builtin_help_obj;
+extern const struct _mp_obj_fun_native_t mp_builtin_input_obj;
+extern const struct _mp_obj_fun_native_t mp_builtin_open_obj;
+#define MICROPY_PORT_BUILTINS \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \
+
+// extra built in modules to add to the list of known ones
+extern const struct _mp_obj_module_t os_module;
+extern const struct _mp_obj_module_t pyb_module;
+extern const struct _mp_obj_module_t time_module;
+#define MICROPY_PORT_BUILTIN_MODULES \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \
+
+// extra constants
+#define MICROPY_PORT_CONSTANTS \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \
// type definitions for the specific machine
#define BYTES_PER_WORD (4)
+#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 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
-typedef float machine_float_t;
-machine_float_t machine_sqrt(machine_float_t x);
+// There is no classical C heap in bare-metal ports, only Python
+// garbage-collected heap. For completeness, emulate C heap via
+// GC heap. Note that MicroPython core never uses malloc() and friends,
+// so these defines are mostly to help extension module writers.
+#define malloc gc_alloc
+#define free gc_free
+#define realloc gc_realloc
+
+// We need to provide a declaration/definition of alloca()
+#include <alloca.h>
+
+// The following would be from a board specific file, if one existed
+
+#define MICROPY_HW_BOARD_NAME "Teensy-3.1"
+
+#define MICROPY_HW_HAS_SWITCH (0)
+#define MICROPY_HW_HAS_SDCARD (0)
+#define MICROPY_HW_HAS_MMA7660 (0)
+#define MICROPY_HW_HAS_LIS3DSH (0)
+#define MICROPY_HW_HAS_LCD (0)
+#define MICROPY_HW_ENABLE_RNG (0)
+#define MICROPY_HW_ENABLE_RTC (0)
+#define MICROPY_HW_ENABLE_TIMER (0)
+#define MICROPY_HW_ENABLE_SERVO (0)
+#define MICROPY_HW_ENABLE_DAC (0)
+#define MICROPY_HW_ENABLE_I2C1 (0)
+#define MICROPY_HW_ENABLE_SPI1 (0)
+#define MICROPY_HW_ENABLE_SPI3 (0)
+#define MICROPY_HW_ENABLE_CC3K (0)
+
+#define MICROPY_HW_LED1 (pin_C5)
+#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP)
+#define MICROPY_HW_LED_ON(pin) (pin->gpio->PSOR = pin->pin_mask)
+#define MICROPY_HW_LED_OFF(pin) (pin->gpio->PCOR = pin->pin_mask)
+
+#if 0
+// SD card detect switch
+#define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8)
+#define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP)
+#define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET)
+#endif
+
+#define MICROPY_MATH_SQRT_ASM (1)
+
+#define MICROPY_HAL_H "teensy_hal.h"
+#define MICROPY_PIN_DEFS_PORT_H "pin_defs_teensy.h"
diff --git a/teensy/pin_defs_teensy.h b/teensy/pin_defs_teensy.h
new file mode 100644
index 0000000000..66942c2ea8
--- /dev/null
+++ b/teensy/pin_defs_teensy.h
@@ -0,0 +1,46 @@
+enum {
+ PORT_A,
+ PORT_B,
+ PORT_C,
+ PORT_D,
+ PORT_E,
+ PORT_Z,
+};
+
+enum {
+ AF_FN_FTM,
+ AF_FN_I2C,
+ AF_FN_UART,
+ AF_FN_SPI
+};
+
+enum {
+ AF_PIN_TYPE_FTM_CH0 = 0,
+ AF_PIN_TYPE_FTM_CH1,
+ AF_PIN_TYPE_FTM_CH2,
+ AF_PIN_TYPE_FTM_CH3,
+ AF_PIN_TYPE_FTM_QD_PHA,
+ AF_PIN_TYPE_FTM_QD_PHB,
+
+ AF_PIN_TYPE_I2C_SDA = 0,
+ AF_PIN_TYPE_I2C_SCL,
+
+ AF_PIN_TYPE_SPI_MOSI = 0,
+ AF_PIN_TYPE_SPI_MISO,
+ AF_PIN_TYPE_SPI_SCK,
+ AF_PIN_TYPE_SPI_NSS,
+
+ AF_PIN_TYPE_UART_TX = 0,
+ AF_PIN_TYPE_UART_RX,
+ AF_PIN_TYPE_UART_CTS,
+ AF_PIN_TYPE_UART_RTS,
+};
+
+#define PIN_DEFS_PORT_AF_UNION \
+ FTM_TypeDef *FTM; \
+ I2C_TypeDef *I2C; \
+ UART_TypeDef *UART; \
+ SPI_TypeDef *SPI;
+
+typedef GPIO_TypeDef pin_gpio_t;
+
diff --git a/teensy/qstrdefsport.h b/teensy/qstrdefsport.h
index 8b23a86bf0..2fb70af7b4 100644
--- a/teensy/qstrdefsport.h
+++ b/teensy/qstrdefsport.h
@@ -20,7 +20,7 @@ Q(mma_mode)
Q(hid)
Q(time)
Q(rand)
-Q(Led)
+Q(LED)
Q(led)
Q(Servo)
Q(I2C)
@@ -32,5 +32,63 @@ Q(analogRead)
Q(analogWrite)
Q(analogWriteResolution)
Q(analogWriteFrequency)
-Q(run)
+Q(on)
+Q(off)
+Q(toggle)
+Q(readall)
+Q(readline)
+Q(FileIO)
+Q(input)
+Q(os)
+Q(bootloader)
+Q(unique_id)
+Q(freq)
+Q(repl_info)
+Q(wfi)
+Q(disable_irq)
+Q(enable_irq)
+Q(usb_mode)
+Q(have_cdc)
+Q(millis)
+Q(udelay)
+Q(UART)
+
+// for Pin class
+Q(Pin)
+Q(PinAF)
+Q(PinNamed)
+Q(init)
+Q(value)
+Q(low)
+Q(high)
+Q(name)
+Q(port)
+Q(pin)
+Q(mapper)
+Q(dict)
+Q(debug)
+Q(board)
+Q(cpu)
+Q(IN)
+Q(OUT_PP)
+Q(OUT_OD)
+Q(AF_PP)
+Q(AF_OD)
+Q(ANALOG)
+Q(PULL_NONE)
+Q(PULL_UP)
+Q(PULL_DOWN)
+
+// for UART class
+Q(UART)
+Q(baudrate)
+Q(bits)
+Q(stop)
+Q(parity)
+Q(init)
+Q(deinit)
+Q(all)
+Q(send)
+Q(recv)
+Q(timeout)
diff --git a/teensy/servo.h b/teensy/servo.h
index c4a5bd49b1..5dad041138 100644
--- a/teensy/servo.h
+++ b/teensy/servo.h
@@ -1,2 +1,7 @@
-mp_obj_t pyb_Servo(void);
+void servo_init(void);
+
+extern const mp_obj_type_t pyb_servo_type;
+
+MP_DECLARE_CONST_FUN_OBJ(pyb_servo_set_obj);
+MP_DECLARE_CONST_FUN_OBJ(pyb_pwm_set_obj);
diff --git a/teensy/teensy-pins.csv b/teensy/teensy-pins.csv
new file mode 100644
index 0000000000..acaef63aad
--- /dev/null
+++ b/teensy/teensy-pins.csv
@@ -0,0 +1,55 @@
+D0,PTB16
+D1,PTB17
+D2,PTD0
+D3,PTA12
+D4,PTA13
+D5,PTD7
+D6,PTD4
+D7,PTD2
+D8,PTD3
+D9,PTC3
+D10,PTC4
+D11,PTC6
+D12,PTC7
+D13,PTC5
+D14,PTD1
+D15,PTC0
+D16,PTB0
+D17,PTB1
+D18,PTB3
+D19,PTB2
+D20,PTD5
+D21,PTD6
+D22,PTC1
+D23,PTC2
+D24,PTA5
+D25,PTB19
+D26,PTE1
+D27,PTC9
+D28,PTC8
+D29,PTC10
+D30,PTC11
+D31,PTE0
+D32,PTB18
+D33,PTA4
+A0,PTD1
+A1,PTC0
+A2,PTB0
+A3,PTB1
+A4,PTB3
+A5,PTB2
+A6,PTD5
+A7,PTD6
+A8,PTC1
+A9,PTC2
+A10,PTZ0
+A11,PTZ1
+A12,PTZ2
+A13,PTZ3
+A14,PTZ5
+A15,PTE1
+A16,PTC9
+A17,PTC8
+A18,PTC10
+A19,PTC11
+A20,PTE0
diff --git a/teensy/teensy_hal.c b/teensy/teensy_hal.c
new file mode 100644
index 0000000000..b7ac842af8
--- /dev/null
+++ b/teensy/teensy_hal.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#include "mpconfig.h"
+
+#include "Arduino.h"
+
+#include MICROPY_HAL_H
+
+uint32_t HAL_GetTick(void) {
+ return micros();
+}
+
+void HAL_Delay(uint32_t Delay) {
+ delay(Delay);
+}
diff --git a/teensy/teensy_hal.h b/teensy/teensy_hal.h
new file mode 100644
index 0000000000..ff16c98c5c
--- /dev/null
+++ b/teensy/teensy_hal.h
@@ -0,0 +1,111 @@
+
+#ifdef USE_FULL_ASSERT
+ #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
+ void assert_failed(uint8_t* file, uint32_t line);
+#else
+ #define assert_param(expr) ((void)0)
+#endif /* USE_FULL_ASSERT */
+
+#define FTM0 ((FTM_TypeDef *)&FTM0_SC)
+#define FTM1 ((FTM_TypeDef *)&FTM1_SC)
+#define FTM2 ((FTM_TypeDef *)&FTM2_SC)
+
+#define GPIOA ((GPIO_TypeDef *)&GPIOA_PDOR)
+#define GPIOB ((GPIO_TypeDef *)&GPIOB_PDOR)
+#define GPIOC ((GPIO_TypeDef *)&GPIOC_PDOR)
+#define GPIOD ((GPIO_TypeDef *)&GPIOD_PDOR)
+#define GPIOE ((GPIO_TypeDef *)&GPIOE_PDOR)
+#define GPIOZ ((GPIO_TypeDef *)NULL)
+
+#define I2C0 ((I2C_TypeDef *)0x40066000)
+#define I2C1 ((I2C_TypeDef *)0x40067000)
+
+#undef SPI0
+#define SPI0 ((SPI_TypeDef *)0x4002C000)
+#define SPI1 ((SPI_TypeDef *)0x4002D000)
+
+#define UART0 ((UART_TypeDef *)&UART0_BDH)
+#define UART1 ((UART_TypeDef *)&UART1_BDH)
+#define UART2 ((UART_TypeDef *)&UART2_BDH)
+
+typedef struct {
+ uint32_t dummy;
+} FTM_TypeDef;
+
+typedef struct {
+ uint32_t dummy;
+} I2C_TypeDef;
+
+typedef struct {
+ uint32_t dummy;
+} UART_TypeDef;
+
+typedef struct {
+ uint32_t dummy;
+} SPI_TypeDef;
+
+typedef struct {
+ volatile uint32_t PDOR; // Output register
+ volatile uint32_t PSOR; // Set output register
+ volatile uint32_t PCOR; // Clear output register
+ volatile uint32_t PTOR; // Toggle output register
+ volatile uint32_t PDIR; // Data Input register
+ volatile uint32_t PDDR; // Data Direction register
+} GPIO_TypeDef;
+
+#define GPIO_OUTPUT_TYPE ((uint32_t)0x00000010) // Indicates OD
+
+#define GPIO_MODE_INPUT ((uint32_t)0x00000000)
+#define GPIO_MODE_OUTPUT_PP ((uint32_t)0x00000001)
+#define GPIO_MODE_OUTPUT_OD ((uint32_t)0x00000011)
+#define GPIO_MODE_AF_PP ((uint32_t)0x00000002)
+#define GPIO_MODE_AF_OD ((uint32_t)0x00000012)
+#define GPIO_MODE_ANALOG ((uint32_t)0x00000003)
+
+#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_MODE_INPUT) ||\
+ ((MODE) == GPIO_MODE_OUTPUT_PP) ||\
+ ((MODE) == GPIO_MODE_OUTPUT_OD) ||\
+ ((MODE) == GPIO_MODE_AF_PP) ||\
+ ((MODE) == GPIO_MODE_AF_OD) ||\
+ ((MODE) == GPIO_MODE_ANALOG))
+
+#define GPIO_NOPULL ((uint32_t)0)
+#define GPIO_PULLUP ((uint32_t)1)
+#define GPIO_PULLDOWN ((uint32_t)2)
+
+#define IS_GPIO_PULL(PULL) (((PULL) == GPIO_NOPULL) || ((PULL) == GPIO_PULLUP) || \
+ ((PULL) == GPIO_PULLDOWN))
+
+#define GPIO_SPEED_LOW ((uint32_t)0)
+#define GPIO_SPEED_MEDIUM ((uint32_t)1)
+#define GPIO_SPEED_FAST ((uint32_t)2)
+#define GPIO_SPEED_HIGH ((uint32_t)3)
+
+
+typedef struct {
+ uint32_t Pin;
+ uint32_t Mode;
+ uint32_t Pull;
+ uint32_t Speed;
+ uint32_t Alternate;
+} GPIO_InitTypeDef;
+
+#define GPIO_PORT_TO_PORT_NUM(GPIOx) \
+ ((GPIOx->PDOR - GPIOA_PDOR) / (GPIOB_PDOR - GPIOA_PDOR))
+
+#define GPIO_PIN_TO_PORT_PCR(GPIOx, pin) \
+ (&PORTA_PCR0 + GPIO_PORT_TO_PORT_NUM(GPIOx) * 32 + (pin))
+
+__attribute__(( always_inline )) static inline void __WFI(void)
+{
+ __asm volatile ("wfi");
+}
+
+uint32_t HAL_GetTick(void);
+void HAL_Delay(uint32_t Delay);
+
+void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *init);
+
+#define GPIO_read_pin(gpio, pin) (((gpio)->PDIR >> (pin)) & 1)
+#define GPIO_set_pin(gpio, pin_mask) (((gpio)->PSOR) = (pin_mask))
+#define GPIO_clear_pin(gpio, pin_mask) (((gpio)->PCOR) = (pin_mask))
diff --git a/teensy/uart.c b/teensy/uart.c
new file mode 100644
index 0000000000..97a1a058c9
--- /dev/null
+++ b/teensy/uart.c
@@ -0,0 +1,522 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "mpconfig.h"
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include MICROPY_HAL_H
+#include "bufhelper.h"
+#include "uart.h"
+
+/// \moduleref pyb
+/// \class UART - duplex serial communication bus
+///
+/// UART implements the standard UART/USART duplex serial communications protocol. At
+/// the physical level it consists of 2 lines: RX and TX.
+///
+/// See usage model of I2C. UART is very similar. Main difference is
+/// parameters to init the UART bus:
+///
+/// from pyb import UART
+///
+/// uart = UART(1, 9600) # init with given baudrate
+/// uart.init(9600, bits=8, stop=1, parity=None) # init with given parameters
+///
+/// Bits can be 8 or 9, stop can be 1 or 2, parity can be None, 0 (even), 1 (odd).
+///
+/// Extra method:
+///
+/// uart.any() # returns True if any characters waiting
+
+struct _pyb_uart_obj_t {
+ mp_obj_base_t base;
+ pyb_uart_t uart_id;
+ bool is_enabled;
+// UART_HandleTypeDef uart;
+};
+
+pyb_uart_obj_t *pyb_uart_global_debug = NULL;
+
+// assumes Init parameters have been set up correctly
+bool uart_init2(pyb_uart_obj_t *uart_obj) {
+#if 0
+ USART_TypeDef *UARTx = NULL;
+
+ uint32_t GPIO_Pin = 0;
+ uint8_t GPIO_AF_UARTx = 0;
+ GPIO_TypeDef* GPIO_Port = NULL;
+
+ switch (uart_obj->uart_id) {
+ // USART1 is on PA9/PA10 (CK on PA8), PB6/PB7
+ case PYB_UART_1:
+ UARTx = USART1;
+ GPIO_AF_UARTx = GPIO_AF7_USART1;
+
+#if defined (PYBV4) || defined(PYBV10)
+ GPIO_Port = GPIOB;
+ GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7;
+#else
+ GPIO_Port = GPIOA;
+ GPIO_Pin = GPIO_PIN_9 | GPIO_PIN_10;
+#endif
+
+ __USART1_CLK_ENABLE();
+ break;
+
+ // USART2 is on PA2/PA3 (CK on PA4), PD5/PD6 (CK on PD7)
+ case PYB_UART_2:
+ UARTx = USART2;
+ GPIO_AF_UARTx = GPIO_AF7_USART2;
+
+ GPIO_Port = GPIOA;
+ GPIO_Pin = GPIO_PIN_2 | GPIO_PIN_3;
+
+ __USART2_CLK_ENABLE();
+ break;
+
+ // USART3 is on PB10/PB11 (CK on PB12), PC10/PC11 (CK on PC12), PD8/PD9 (CK on PD10)
+ case PYB_UART_3:
+ UARTx = USART3;
+ GPIO_AF_UARTx = GPIO_AF7_USART3;
+
+#if defined(PYBV3) || defined(PYBV4) | defined(PYBV10)
+ GPIO_Port = GPIOB;
+ GPIO_Pin = GPIO_PIN_10 | GPIO_PIN_11;
+#else
+ GPIO_Port = GPIOD;
+ GPIO_Pin = GPIO_PIN_8 | GPIO_PIN_9;
+#endif
+ __USART3_CLK_ENABLE();
+ break;
+
+ // UART4 is on PA0/PA1, PC10/PC11
+ case PYB_UART_4:
+ UARTx = UART4;
+ GPIO_AF_UARTx = GPIO_AF8_UART4;
+
+ GPIO_Port = GPIOA;
+ GPIO_Pin = GPIO_PIN_0 | GPIO_PIN_1;
+
+ __UART4_CLK_ENABLE();
+ break;
+
+ // USART6 is on PC6/PC7 (CK on PC8)
+ case PYB_UART_6:
+ UARTx = USART6;
+ GPIO_AF_UARTx = GPIO_AF8_USART6;
+
+ GPIO_Port = GPIOC;
+ GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7;
+
+ __USART6_CLK_ENABLE();
+ break;
+
+ default:
+ return false;
+ }
+
+ // init GPIO
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.Pin = GPIO_Pin;
+ GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
+ GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStructure.Pull = GPIO_PULLUP;
+ GPIO_InitStructure.Alternate = GPIO_AF_UARTx;
+ HAL_GPIO_Init(GPIO_Port, &GPIO_InitStructure);
+
+ // init UARTx
+ uart_obj->uart.Instance = UARTx;
+ HAL_UART_Init(&uart_obj->uart);
+
+ uart_obj->is_enabled = true;
+#endif
+ return true;
+}
+
+bool uart_init(pyb_uart_obj_t *uart_obj, uint32_t baudrate) {
+#if 0
+ UART_HandleTypeDef *uh = &uart_obj->uart;
+ memset(uh, 0, sizeof(*uh));
+ uh->Init.BaudRate = baudrate;
+ uh->Init.WordLength = UART_WORDLENGTH_8B;
+ uh->Init.StopBits = UART_STOPBITS_1;
+ uh->Init.Parity = UART_PARITY_NONE;
+ uh->Init.Mode = UART_MODE_TX_RX;
+ uh->Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ uh->Init.OverSampling = UART_OVERSAMPLING_16;
+#endif
+ return uart_init2(uart_obj);
+}
+
+void uart_deinit(pyb_uart_obj_t *uart_obj) {
+#if 0
+ uart_obj->is_enabled = false;
+ UART_HandleTypeDef *uart = &uart_obj->uart;
+ HAL_UART_DeInit(uart);
+ if (uart->Instance == USART1) {
+ __USART1_FORCE_RESET();
+ __USART1_RELEASE_RESET();
+ __USART1_CLK_DISABLE();
+ } else if (uart->Instance == USART2) {
+ __USART2_FORCE_RESET();
+ __USART2_RELEASE_RESET();
+ __USART2_CLK_DISABLE();
+ } else if (uart->Instance == USART3) {
+ __USART3_FORCE_RESET();
+ __USART3_RELEASE_RESET();
+ __USART3_CLK_DISABLE();
+ } else if (uart->Instance == UART4) {
+ __UART4_FORCE_RESET();
+ __UART4_RELEASE_RESET();
+ __UART4_CLK_DISABLE();
+ } else if (uart->Instance == USART6) {
+ __USART6_FORCE_RESET();
+ __USART6_RELEASE_RESET();
+ __USART6_CLK_DISABLE();
+ }
+#endif
+}
+
+bool uart_rx_any(pyb_uart_obj_t *uart_obj) {
+#if 0
+ return __HAL_UART_GET_FLAG(&uart_obj->uart, UART_FLAG_RXNE);
+#else
+ return false;
+#endif
+}
+
+int uart_rx_char(pyb_uart_obj_t *uart_obj) {
+ uint8_t ch;
+#if 0
+ if (HAL_UART_Receive(&uart_obj->uart, &ch, 1, 0) != HAL_OK) {
+ ch = 0;
+ }
+#else
+ ch = 'A';
+#endif
+ return ch;
+}
+
+void uart_tx_char(pyb_uart_obj_t *uart_obj, int c) {
+#if 0
+ uint8_t ch = c;
+ HAL_UART_Transmit(&uart_obj->uart, &ch, 1, 100000);
+#endif
+}
+
+void uart_tx_str(pyb_uart_obj_t *uart_obj, const char *str) {
+#if 0
+ HAL_UART_Transmit(&uart_obj->uart, (uint8_t*)str, strlen(str), 100000);
+#endif
+}
+
+void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len) {
+#if 0
+ HAL_UART_Transmit(&uart_obj->uart, (uint8_t*)str, len, 100000);
+#endif
+}
+
+void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len) {
+ for (const char *top = str + len; str < top; str++) {
+ if (*str == '\n') {
+ uart_tx_char(uart_obj, '\r');
+ }
+ uart_tx_char(uart_obj, *str);
+ }
+}
+
+/******************************************************************************/
+/* Micro Python bindings */
+
+STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ pyb_uart_obj_t *self = self_in;
+ if (!self->is_enabled) {
+ print(env, "UART(%lu)", self->uart_id);
+ } else {
+#if 0
+ print(env, "UART(%lu, baudrate=%u, bits=%u, stop=%u",
+ self->uart_id, self->uart.Init.BaudRate,
+ self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9,
+ self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2);
+ if (self->uart.Init.Parity == UART_PARITY_NONE) {
+ print(env, ", parity=None)");
+ } else {
+ print(env, ", parity=%u)", self->uart.Init.Parity == UART_PARITY_EVEN ? 0 : 1);
+ }
+#endif
+ }
+}
+
+/// \method init(baudrate, *, bits=8, stop=1, parity=None)
+///
+/// Initialise the SPI bus with the given parameters:
+///
+/// - `baudrate` is the clock rate.
+/// - `bits` is the number of bits per byte, 8 or 9.
+/// - `stop` is the number of stop bits, 1 or 2.
+/// - `parity` is the parity, `None`, 0 (even) or 1 (odd).
+STATIC const mp_arg_t pyb_uart_init_args[] = {
+ { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} },
+ { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
+ { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
+ { MP_QSTR_parity, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+};
+#define PYB_UART_INIT_NUM_ARGS ARRAY_SIZE(pyb_uart_init_args)
+
+STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ // parse args
+ mp_arg_val_t vals[PYB_UART_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args, args, kw_args, PYB_UART_INIT_NUM_ARGS, pyb_uart_init_args, vals);
+#if 0
+ // set the UART configuration values
+ memset(&self->uart, 0, sizeof(self->uart));
+ UART_InitTypeDef *init = &self->uart.Init;
+ init->BaudRate = vals[0].u_int;
+ init->WordLength = vals[1].u_int == 8 ? UART_WORDLENGTH_8B : UART_WORDLENGTH_9B;
+ switch (vals[2].u_int) {
+ case 1: init->StopBits = UART_STOPBITS_1; break;
+ default: init->StopBits = UART_STOPBITS_2; break;
+ }
+ if (vals[3].u_obj == mp_const_none) {
+ init->Parity = UART_PARITY_NONE;
+ } else {
+ machine_int_t parity = mp_obj_get_int(vals[3].u_obj);
+ init->Parity = (parity & 1) ? UART_PARITY_ODD : UART_PARITY_EVEN;
+ }
+ init->Mode = UART_MODE_TX_RX;
+ init->HwFlowCtl = UART_HWCONTROL_NONE;
+ init->OverSampling = UART_OVERSAMPLING_16;
+
+ // init UART (if it fails, it's because the port doesn't exist)
+ if (!uart_init2(self)) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART port %d does not exist", self->uart_id));
+ }
+#endif
+
+ return mp_const_none;
+}
+
+/// \classmethod \constructor(bus, ...)
+///
+/// Construct a UART object on the given bus. `bus` can be 1-6, or 'XA', 'XB', 'YA', or 'YB'.
+/// With no additional parameters, the UART object is created but not
+/// initialised (it has the settings from the last initialisation of
+/// the bus, if any). If extra arguments are given, the bus is initialised.
+/// See `init` for parameters of initialisation.
+///
+/// The physical pins of the UART busses are:
+///
+/// - `UART(4)` is on `XA`: `(TX, RX) = (X1, X2) = (PA0, PA1)`
+/// - `UART(1)` is on `XB`: `(TX, RX) = (X9, X10) = (PB6, PB7)`
+/// - `UART(6)` is on `YA`: `(TX, RX) = (Y1, Y2) = (PC6, PC7)`
+/// - `UART(3)` is on `YB`: `(TX, RX) = (Y9, Y10) = (PB10, PB11)`
+/// - `UART(2)` is on: `(TX, RX) = (X3, X4) = (PA2, PA3)`
+STATIC mp_obj_t pyb_uart_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);
+
+ // create object
+ pyb_uart_obj_t *o = m_new_obj(pyb_uart_obj_t);
+ o->base.type = &pyb_uart_type;
+
+ // work out port
+ o->uart_id = 0;
+#if 0
+ if (MP_OBJ_IS_STR(args[0])) {
+ const char *port = mp_obj_str_get_str(args[0]);
+ if (0) {
+#if defined(PYBV10)
+ } else if (strcmp(port, "XA") == 0) {
+ o->uart_id = PYB_UART_XA;
+ } else if (strcmp(port, "XB") == 0) {
+ o->uart_id = PYB_UART_XB;
+ } else if (strcmp(port, "YA") == 0) {
+ o->uart_id = PYB_UART_YA;
+ } else if (strcmp(port, "YB") == 0) {
+ o->uart_id = PYB_UART_YB;
+#endif
+ } else {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART port %s does not exist", port));
+ }
+ } else {
+ o->uart_id = mp_obj_get_int(args[0]);
+ }
+#endif
+
+ if (n_args > 1 || n_kw > 0) {
+ // start the peripheral
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ pyb_uart_init_helper(o, n_args - 1, args + 1, &kw_args);
+ }
+
+ return o;
+}
+
+STATIC mp_obj_t pyb_uart_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ return pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init);
+
+/// \method deinit()
+/// Turn off the UART bus.
+STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) {
+ pyb_uart_obj_t *self = self_in;
+ uart_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_deinit_obj, pyb_uart_deinit);
+
+/// \method any()
+/// Return `True` if any characters waiting, else `False`.
+STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) {
+ pyb_uart_obj_t *self = self_in;
+ if (uart_rx_any(self)) {
+ return mp_const_true;
+ } else {
+ return mp_const_false;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any);
+
+/// \method send(send, *, timeout=5000)
+/// Send data on the bus:
+///
+/// - `send` is the data to send (an integer to send, or a buffer object).
+/// - `timeout` is the timeout in milliseconds to wait for the send.
+///
+/// Return value: `None`.
+STATIC const mp_arg_t pyb_uart_send_args[] = {
+ { MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
+};
+#define PYB_UART_SEND_NUM_ARGS ARRAY_SIZE(pyb_uart_send_args)
+
+STATIC mp_obj_t pyb_uart_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ // TODO assumes transmission size is 8-bits wide
+
+ pyb_uart_obj_t *self = args[0];
+
+ // parse args
+ mp_arg_val_t vals[PYB_UART_SEND_NUM_ARGS];
+ mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_UART_SEND_NUM_ARGS, pyb_uart_send_args, vals);
+
+#if 0
+ // get the buffer to send from
+ mp_buffer_info_t bufinfo;
+ uint8_t data[1];
+ pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data);
+
+ // send the data
+ HAL_StatusTypeDef status = HAL_UART_Transmit(&self->uart, bufinfo.buf, bufinfo.len, vals[1].u_int);
+
+ if (status != HAL_OK) {
+ // TODO really need a HardwareError object, or something
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_UART_Transmit failed with code %d", status));
+ }
+#else
+ (void)self;
+#endif
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_send_obj, 1, pyb_uart_send);
+
+/// \method recv(recv, *, timeout=5000)
+///
+/// Receive data on the bus:
+///
+/// - `recv` can be an integer, which is the number of bytes to receive,
+/// or a mutable buffer, which will be filled with received bytes.
+/// - `timeout` is the timeout in milliseconds to wait for the receive.
+///
+/// Return value: if `recv` is an integer then a new buffer of the bytes received,
+/// otherwise the same buffer that was passed in to `recv`.
+STATIC const mp_arg_t pyb_uart_recv_args[] = {
+ { MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
+};
+#define PYB_UART_RECV_NUM_ARGS ARRAY_SIZE(pyb_uart_recv_args)
+
+STATIC mp_obj_t pyb_uart_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ // TODO assumes transmission size is 8-bits wide
+
+ pyb_uart_obj_t *self = args[0];
+
+#if 0
+ // parse args
+ mp_arg_val_t vals[PYB_UART_RECV_NUM_ARGS];
+ mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_UART_RECV_NUM_ARGS, pyb_uart_recv_args, vals);
+
+ // get the buffer to receive into
+ mp_buffer_info_t bufinfo;
+ mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &bufinfo);
+
+ // receive the data
+ HAL_StatusTypeDef status = HAL_UART_Receive(&self->uart, bufinfo.buf, bufinfo.len, vals[1].u_int);
+
+ if (status != HAL_OK) {
+ // TODO really need a HardwareError object, or something
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_UART_Receive failed with code %d", status));
+ }
+
+ // return the received data
+ if (o_ret == MP_OBJ_NULL) {
+ return vals[0].u_obj;
+ } else {
+ return mp_obj_str_builder_end(o_ret);
+ }
+#else
+ (void)self;
+ return mp_const_none;
+#endif
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_recv_obj, 1, pyb_uart_recv);
+
+STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
+ // instance methods
+ { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_uart_init_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_uart_deinit_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_uart_any_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_uart_send_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_uart_recv_obj },
+};
+
+STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
+
+const mp_obj_type_t pyb_uart_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_UART,
+ .print = pyb_uart_print,
+ .make_new = pyb_uart_make_new,
+ .locals_dict = (mp_obj_t)&pyb_uart_locals_dict,
+};
diff --git a/teensy/usart.c b/teensy/usart.c
deleted file mode 100644
index a700e8e379..0000000000
--- a/teensy/usart.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "misc.h"
-#include "mpconfig.h"
-#include "qstr.h"
-#include "obj.h"
-#include "../stm/usart.h"
-
-pyb_usart_t pyb_usart_global_debug = PYB_USART_NONE;
-
-void usart_init(pyb_usart_t usart_id, uint32_t baudrate)
-{
- (void)usart_id;
- (void)baudrate;
-}
-
-bool usart_rx_any(pyb_usart_t usart_id)
-{
- (void)usart_id;
- return false;
-}
-
-int usart_rx_char(pyb_usart_t usart_id)
-{
- (void)usart_id;
- return 0;
-}
-
-void usart_tx_str(pyb_usart_t usart_id, const char *str)
-{
- (void)usart_id;
- (void)str;
-}
-
-void usart_tx_strn_cooked(pyb_usart_t usart_id, const char *str, int len)
-{
- (void)usart_id;
- (void)str;
- (void)len;
-}
diff --git a/teensy/usb.c b/teensy/usb.c
index a045a2ed69..ab4731f27b 100644
--- a/teensy/usb.c
+++ b/teensy/usb.c
@@ -13,8 +13,13 @@ int usb_vcp_is_enabled(void)
return 1;
}
-int usb_vcp_rx_any(void)
-{
+void usb_vcp_set_interrupt_char(int c) {
+ // The teensy 3.1 usb stack doesn't currently have the notion of generating
+ // an exception when a certain character is received. That just means that
+ // you can't press Control-C and get your python script to stop.
+}
+
+int usb_vcp_rx_num(void) {
return usb_serial_available();
}
diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py
index b114a789b5..c3049c55d6 100644
--- a/tests/basics/struct1.py
+++ b/tests/basics/struct1.py
@@ -21,3 +21,7 @@ print(struct.calcsize("100sI"))
print(struct.calcsize("97sI"))
print(struct.unpack("<6sH", b"foo\0\0\0\x12\x34"))
print(struct.pack("<6sH", b"foo", 10000))
+
+s = struct.pack("BHBI", 10, 100, 200, 300)
+v = struct.unpack("BHBI", s)
+print(v == (10, 100, 200, 300))
diff --git a/tests/float/math-fun-bool.py b/tests/float/math-fun-bool.py
index cf718d4b80..57232857ab 100644
--- a/tests/float/math-fun-bool.py
+++ b/tests/float/math-fun-bool.py
@@ -1,6 +1,11 @@
# Test the bool functions from math
-from math import isfinite, isnan, isinf
+try:
+ from math import isfinite, isnan, isinf
+except ImportError:
+ print("SKIP")
+ import sys
+ sys.exit()
test_values = [1, 0, -1, 1.0, 0.0, -1.0, float('NaN'), float('Inf'),
-float('NaN'), -float('Inf')]
diff --git a/tests/float/math-fun.py b/tests/float/math-fun.py
index 7a37c58454..fa111e33e3 100644
--- a/tests/float/math-fun.py
+++ b/tests/float/math-fun.py
@@ -1,6 +1,11 @@
# Tests the functions imported from math
-from math import *
+try:
+ from math import *
+except ImportError:
+ print("SKIP")
+ import sys
+ sys.exit()
test_values = [-100., -1.23456, -1, -0.5, 0.0, 0.5, 1.23456, 100.]
p_test_values = [0.1, 0.5, 1.23456]
diff --git a/tests/misc/recursion.py b/tests/misc/recursion.py
new file mode 100644
index 0000000000..227f48396a
--- /dev/null
+++ b/tests/misc/recursion.py
@@ -0,0 +1,7 @@
+def foo():
+ foo()
+
+try:
+ foo()
+except RuntimeError:
+ print("RuntimeError")
diff --git a/tests/misc/recursive_data.py_ b/tests/misc/recursive_data.py_
new file mode 100644
index 0000000000..6a52a3c0e8
--- /dev/null
+++ b/tests/misc/recursive_data.py_
@@ -0,0 +1,9 @@
+# This tests that printing recursive data structure doesn't lead to segfault.
+# Unfortunately, print() so far doesn't support "file "kwarg, so variable-len
+# output of this test cannot be redirected, and this test cannot be validated.
+l = [1, 2, 3, None]
+l[-1] = l
+try:
+ print(l)
+except RuntimeError:
+ print("RuntimeError")
diff --git a/tests/run-tests b/tests/run-tests
index 8f5f7d470d..c6bc4020d4 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -88,10 +88,10 @@ def run_tests(pyb, tests):
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"))
+ with open(filename_expected, "wb") as f:
+ f.write(output_expected)
+ with open(filename_mupy, "wb") as f:
+ f.write(output_mupy)
print("FAIL ", test_file)
failed_tests.append(test_name)
diff --git a/tests/unicode/data/utf-8_1.txt b/tests/unicode/data/utf-8_1.txt
new file mode 100644
index 0000000000..d84c480d1d
--- /dev/null
+++ b/tests/unicode/data/utf-8_1.txt
@@ -0,0 +1 @@
+Привет
diff --git a/tests/unicode/file1.py b/tests/unicode/file1.py
new file mode 100644
index 0000000000..554e886743
--- /dev/null
+++ b/tests/unicode/file1.py
@@ -0,0 +1,4 @@
+f = open("unicode/data/utf-8_1.txt")
+l = f.readline()
+print(l)
+print(len(l))
diff --git a/tests/unicode/unicode.py b/tests/unicode/unicode.py
new file mode 100644
index 0000000000..c7e523f06a
--- /dev/null
+++ b/tests/unicode/unicode.py
@@ -0,0 +1,18 @@
+# Test a UTF-8 encoded literal
+s = "asdf©qwer"
+for i in range(len(s)):
+ print("s[%d]: %s %X"%(i, s[i], ord(s[i])))
+
+# Test all three forms of Unicode escape, and
+# all blocks of UTF-8 byte patterns
+s = "a\xA9\xFF\u0123\u0800\uFFEE\U0001F44C"
+for i in range(-len(s), len(s)):
+ print("s[%d]: %s %X"%(i, s[i], ord(s[i])))
+ print("s[:%d]: %d chars, '%s'"%(i, len(s[:i]), s[:i]))
+ for j in range(i, len(s)):
+ print("s[%d:%d]: %d chars, '%s'"%(i, j, len(s[i:j]), s[i:j]))
+ print("s[%d:]: %d chars, '%s'"%(i, len(s[i:]), s[i:]))
+
+# Test UTF-8 encode and decode
+enc = s.encode()
+print(enc, enc.decode() == s)
diff --git a/tests/unicode/unicode_index.py b/tests/unicode/unicode_index.py
new file mode 100644
index 0000000000..3c31468a41
--- /dev/null
+++ b/tests/unicode/unicode_index.py
@@ -0,0 +1,6 @@
+print("Привет".find("т"))
+print("Привет".find("П"))
+print("Привет".rfind("т"))
+print("Привет".rfind("П"))
+print("Привет".index("т"))
+print("Привет".index("П"))
diff --git a/tests/unicode/unicode_iter.py b/tests/unicode/unicode_iter.py
new file mode 100644
index 0000000000..f08a4aceed
--- /dev/null
+++ b/tests/unicode/unicode_iter.py
@@ -0,0 +1,4 @@
+for c in "Hello":
+ print(c)
+for c in "Привет":
+ print(c)
diff --git a/tests/unicode/unicode_pos.py b/tests/unicode/unicode_pos.py
new file mode 100644
index 0000000000..6a5982920a
--- /dev/null
+++ b/tests/unicode/unicode_pos.py
@@ -0,0 +1,5 @@
+# str methods with explicit start/end pos
+print("Привет".startswith("П"))
+print("Привет".startswith("р", 1))
+print("абвба".find("а", 1))
+print("абвба".find("а", 1, -1))
diff --git a/tools/gendoc.py b/tools/gendoc.py
index 5a33a8195d..727bc60d76 100644
--- a/tools/gendoc.py
+++ b/tools/gendoc.py
@@ -228,16 +228,18 @@ class DocModule(DocItem):
s.append('# module {}'.format(self.name))
s.append('')
s.append(super().dump())
- s.append('')
- s.append('## Functions')
- for f in sorted(self.functions.values(), key=lambda x:x.name):
+ if self.functions:
s.append('')
- s.append(f.dump(self.name))
- s.append('')
- s.append('## Classes')
- for c in sorted(self.classes.values(), key=lambda x:x.name):
+ s.append('## Functions')
+ for f in sorted(self.functions.values(), key=lambda x:x.name):
+ s.append('')
+ s.append(f.dump(self.name))
+ if self.classes:
s.append('')
- s.append('[`{}.{}`]({}) - {}'.format(self.name, c.name, c.name, c.descr))
+ s.append('## Classes')
+ for c in sorted(self.classes.values(), key=lambda x:x.name):
+ s.append('')
+ s.append('[`{}.{}`]({}) - {}'.format(self.name, c.name, c.name, c.descr))
return '\n'.join(s)
def write(self, dir):
diff --git a/unix/Makefile b/unix/Makefile
index 485009135f..afe268ae45 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -7,6 +7,9 @@ PROG = micropython
# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h
+# OS name, for simple autoconfig
+UNAME_S := $(shell uname -s)
+
# include py core make definitions
include ../py/py.mk
@@ -15,14 +18,18 @@ INC += -I$(PY_SRC)
INC += -I$(BUILD)
# compiler settings
-CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT)
+CWARN = -Wall -Werror -Wno-error=cpp
+CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
-UNAME_S := $(shell uname -s)
- ifeq ($(UNAME_S),Darwin)
- LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-map,$@.map,-order_file,$(BUILD)/order.def
- else
- LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-Map=$@.map,--cref
- endif
+# Debugging/Optimization
+ifdef DEBUG
+CFLAGS += -g
+COPT = -O0
+else
+COPT = -Os #-DNDEBUG
+endif
+
+LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-Map=$@.map,--cref $(LDFLAGS_EXTRA)
ifeq ($(MICROPY_FORCE_32BIT),1)
CFLAGS += -m32
@@ -56,14 +63,6 @@ SRC_MOD += modffi.c
endif
-# Debugging/Optimization
-ifdef DEBUG
-CFLAGS += -g
-COPT = -O0
-else
-COPT = -Os #-DNDEBUG
-endif
-
# source files
SRC_C = \
main.c \
@@ -75,6 +74,9 @@ SRC_C = \
$(SRC_MOD)
ifeq ($(UNAME_S),Darwin)
+
+LDFLAGS+ = -Wl,-order_file,$(BUILD)/order.def
+
# Must be the last file in list of sources
SRC_C += seg_helpers.c
diff --git a/unix/gccollect.c b/unix/gccollect.c
index 4f3b786e72..d04e5d87fb 100644
--- a/unix/gccollect.c
+++ b/unix/gccollect.c
@@ -26,13 +26,13 @@
#include <stdio.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "gc.h"
#if MICROPY_ENABLE_GC
-extern void *stack_top;
+extern char *stack_top;
#if MICROPY_GCREGS_SETJMP
#include <setjmp.h>
@@ -97,7 +97,7 @@ void gc_helper_get_regs(regs_t arr) {
}
#endif
-#ifdef __thumb2__
+#if defined(__thumb2__) || defined(__thumb__) || defined(__arm__)
typedef machine_uint_t regs_t[10];
void gc_helper_get_regs(regs_t arr) {
@@ -130,8 +130,11 @@ void gc_collect(void) {
gc_collect_start();
// this traces the .bss section
-#ifdef __CYGWIN__
+#if defined( __CYGWIN__ )
#define BSS_START __bss_start__
+#elif defined( _MSC_VER ) || defined( __MINGW32__ )
+#define BSS_START *bss_start
+#define _end *bss_end
#else
#define BSS_START __bss_start
#endif
@@ -141,7 +144,8 @@ void gc_collect(void) {
regs_t regs;
gc_helper_get_regs(regs);
// GC stack (and regs because we captured them)
- gc_collect_root((void**)&regs, ((machine_uint_t)stack_top - (machine_uint_t)&regs) / sizeof(machine_uint_t));
+ void **regs_ptr = (void**)(void*)&regs;
+ gc_collect_root(regs_ptr, ((machine_uint_t)stack_top - (machine_uint_t)&regs) / sizeof(machine_uint_t));
gc_collect_end();
//printf("-----\n");
diff --git a/unix/input.c b/unix/input.c
index 4d856f2ff8..19ca649c9f 100644
--- a/unix/input.c
+++ b/unix/input.c
@@ -41,8 +41,6 @@
#include <readline/history.h>
#endif
-#define CTRL_D '\x04'
-
char *prompt(char *p) {
#if MICROPY_USE_READLINE
char *line = readline(p);
diff --git a/unix/main.c b/unix/main.c
index 26736e4318..176cbc6ec3 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -51,6 +51,7 @@
#include "gc.h"
#include "genhdr/py-version.h"
#include "input.h"
+#include "stackctrl.h"
// Command line options, with their defaults
bool compile_only = false;
@@ -63,9 +64,6 @@ uint mp_verbose_flag;
long heap_size = 128*1024 * (sizeof(machine_uint_t) / 4);
#endif
-// Stack top at the start of program
-char *stack_top;
-
void microsocket_init();
void time_init();
void ffi_init();
@@ -149,7 +147,7 @@ STATIC char *strjoin(const char *s1, int sep_char, const char *s2) {
}
STATIC void do_repl(void) {
- printf("Micro Python " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; UNIX version\n");
+ printf("Micro Python " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_PY_SYS_PLATFORM " version\n");
for (;;) {
char *line = prompt(">>> ");
@@ -201,8 +199,8 @@ int usage(char **argv) {
impl_opts_cnt++;
#if MICROPY_ENABLE_GC
printf(
-" heapsize=<n> -- set the heap size for the GC\n"
-);
+" heapsize=<n> -- set the heap size for the GC (default %ld)\n"
+, heap_size);
impl_opts_cnt++;
#endif
@@ -214,10 +212,9 @@ int usage(char **argv) {
}
mp_obj_t mem_info(void) {
- volatile int stack_dummy;
printf("mem: total=%d, current=%d, peak=%d\n",
m_get_total_bytes_allocated(), m_get_current_bytes_allocated(), m_get_peak_bytes_allocated());
- printf("stack: " INT_FMT "\n", stack_top - (char*)&stack_dummy);
+ printf("stack: %u\n", mp_stack_usage());
#if MICROPY_ENABLE_GC
gc_dump_info();
#endif
@@ -268,8 +265,7 @@ void pre_process_options(int argc, char **argv) {
#endif
int main(int argc, char **argv) {
- volatile int stack_dummy;
- stack_top = (char*)&stack_dummy;
+ mp_stack_set_limit(32768);
pre_process_options(argc, argv);
@@ -365,7 +361,8 @@ int main(int argc, char **argv) {
return usage(argv);
}
} else {
- char *basedir = realpath(argv[a], NULL);
+ char *pathbuf = malloc(PATH_MAX);
+ char *basedir = realpath(argv[a], pathbuf);
if (basedir == NULL) {
fprintf(stderr, "%s: can't open file '%s': [Errno %d] ", argv[0], argv[a], errno);
perror("");
@@ -377,7 +374,7 @@ int main(int argc, char **argv) {
// Set base dir of the script as first entry in sys.path
char *p = strrchr(basedir, '/');
path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir));
- free(basedir);
+ free(pathbuf);
for (int i = a; i < argc; i++) {
mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
diff --git a/unix/modffi.c b/unix/modffi.c
index bfc840ceff..eca3f9131b 100644
--- a/unix/modffi.c
+++ b/unix/modffi.c
@@ -51,6 +51,10 @@
* s - as argument, the same as "p", as return value, causes string
* to be allocated and returned, instead of pointer value.
*
+ * TODO:
+ * O - mp_obj_t, passed as is (mostly useful as callback param)
+ * C - callback function
+ *
* Note: all constraint specified by typecode can be not enforced at this time,
* but may be later.
*/
@@ -100,12 +104,15 @@ STATIC ffi_type *char2ffi_type(char c)
switch (c) {
case 'b': return &ffi_type_schar;
case 'B': return &ffi_type_uchar;
+ case 'h': return &ffi_type_sshort;
+ case 'H': return &ffi_type_ushort;
case 'i': return &ffi_type_sint;
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 'C': // (*)()
case 'P': // const void*
case 'p': // void*
case 's': return &ffi_type_pointer;
@@ -421,8 +428,8 @@ STATIC const mp_obj_dict_t mp_module_ffi_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_ffi_globals_table),
- .alloc = ARRAY_SIZE(mp_module_ffi_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_ffi_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_ffi_globals_table),
.table = (mp_map_elem_t*)mp_module_ffi_globals_table,
},
};
diff --git a/unix/modos.c b/unix/modos.c
index 657958d04c..9b034cdbc2 100644
--- a/unix/modos.c
+++ b/unix/modos.c
@@ -30,8 +30,8 @@
#include <unistd.h>
#include <errno.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "nlr.h"
#include "qstr.h"
#include "obj.h"
@@ -75,8 +75,8 @@ STATIC const mp_obj_dict_t mp_module_os_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_os_globals_table),
- .alloc = ARRAY_SIZE(mp_module_os_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_os_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_os_globals_table),
.table = (mp_map_elem_t*)mp_module_os_globals_table,
},
};
diff --git a/unix/modsocket.c b/unix/modsocket.c
index b1a34a39b8..5b3fb01877 100644
--- a/unix/modsocket.c
+++ b/unix/modsocket.c
@@ -356,6 +356,8 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
const char *host = mp_obj_str_get_str(args[0]);
const char *serv = NULL;
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
// getaddrinfo accepts port in string notation, so however
// it may seem stupid, we need to convert int to str
if (MP_OBJ_IS_SMALL_INT(args[1])) {
@@ -363,23 +365,35 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
char buf[6];
sprintf(buf, "%d", port);
serv = buf;
+ hints.ai_flags = AI_NUMERICSERV;
+#ifdef __UCLIBC_MAJOR__
+#if __UCLIBC_MAJOR__ == 0 && (__UCLIBC_MINOR__ < 9 || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ <= 32))
+#warning Working around uClibc bug with numeric service name
+ // Older versions og uClibc have bugs when numeric ports in service
+ // arg require also hints.ai_socktype (or hints.ai_protocol) != 0
+ // This actually was fixed in 0.9.32.1, but uClibc doesn't allow to
+ // test for that.
+ // http://git.uclibc.org/uClibc/commit/libc/inet/getaddrinfo.c?id=bc3be18145e4d5
+ // Note that this is crude workaround, precluding UDP socket addresses
+ // to be returned. TODO: set only if not set by Python args.
+ hints.ai_socktype = SOCK_STREAM;
+#endif
+#endif
} else {
serv = mp_obj_str_get_str(args[1]);
}
- struct addrinfo hints;
- struct addrinfo *addr;
- memset(&hints, 0, sizeof(hints));
- int res = getaddrinfo(host, serv, NULL/*&hints*/, &addr);
+ struct addrinfo *addr_list;
+ int res = getaddrinfo(host, serv, &hints, &addr_list);
if (res != 0) {
// CPython: socket.gaierror
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res));
}
- assert(addr);
+ assert(addr_list);
mp_obj_t list = mp_obj_new_list(0, NULL);
- for (; addr; addr = addr->ai_next) {
+ for (struct addrinfo *addr = addr_list; addr; addr = addr->ai_next) {
mp_obj_tuple_t *t = mp_obj_new_tuple(5, NULL);
t->items[0] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_family);
t->items[1] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_socktype);
@@ -394,6 +408,7 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr);
mp_obj_list_append(list, t);
}
+ freeaddrinfo(addr_list);
return list;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 6, mod_socket_getaddrinfo);
@@ -436,8 +451,8 @@ STATIC const mp_obj_dict_t mp_module_socket_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_socket_globals_table),
- .alloc = ARRAY_SIZE(mp_module_socket_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_socket_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_socket_globals_table),
.table = (mp_map_elem_t*)mp_module_socket_globals_table,
},
};
diff --git a/unix/modtime.c b/unix/modtime.c
index 3cc09e3cd8..286d8ea97e 100644
--- a/unix/modtime.c
+++ b/unix/modtime.c
@@ -30,8 +30,8 @@
#include <sys/time.h>
#include <math.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -113,8 +113,8 @@ STATIC const mp_obj_dict_t mp_module_time_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_time_globals_table),
- .alloc = ARRAY_SIZE(mp_module_time_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_time_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_time_globals_table),
.table = (mp_map_elem_t*)mp_module_time_globals_table,
},
};
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index 3426ae44fe..763b34ba3e 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -41,6 +41,7 @@
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_OPT_COMPUTED_GOTO (1)
+#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_SYS_EXIT (1)
#define MICROPY_PY_SYS_PLATFORM "linux"
@@ -53,7 +54,9 @@
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED)
// Define to 1 to use untested inefficient GC helper implementation
// (if more efficient arch-specific one is not available).
+#ifndef MICROPY_GCREGS_SETJMP
#define MICROPY_GCREGS_SETJMP (0)
+#endif
extern const struct _mp_obj_module_t mp_module_os;
extern const struct _mp_obj_module_t mp_module_time;
diff --git a/windows/Makefile b/windows/Makefile
index a188979bd5..e3085ff23b 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -35,9 +35,11 @@ SRC_C = \
unix/file.c \
unix/input.c \
unix/modtime.c \
+ unix/gccollect.c \
realpath.c \
init.c \
sleep.c \
+ bss.c \
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
diff --git a/windows/bss.c b/windows/bss.c
new file mode 100644
index 0000000000..b860c4ee85
--- /dev/null
+++ b/windows/bss.c
@@ -0,0 +1,74 @@
+/*
+* This file is part of the Micro Python project, http://micropython.org/
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2013, 2014 Damien P. George
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+#include "mpconfig.h"
+#include "misc.h"
+#include "nlr.h"
+#include "qstr.h"
+#include "obj.h"
+#include <windows.h>
+
+IMAGE_NT_HEADERS *header_from_memory(const char *module) {
+ BYTE *base_addr = (BYTE*)GetModuleHandleA(module);
+ IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER*)base_addr;
+ return (IMAGE_NT_HEADERS*)(base_addr + dos_header->e_lfanew);
+}
+
+IMAGE_SECTION_HEADER *find_section(IMAGE_NT_HEADERS *nt_header, const char *name) {
+ int i;
+ IMAGE_SECTION_HEADER *section = IMAGE_FIRST_SECTION(nt_header);
+ for (i = 0; i < nt_header->FileHeader.NumberOfSections; ++i) {
+ if (strcmp((const char *)section->Name, name) == 0) {
+ return section;
+ }
+ ++section;
+ }
+ return NULL;
+}
+
+void section_boundaries(IMAGE_NT_HEADERS *nt_header, IMAGE_SECTION_HEADER *section, char **start, char **end) {
+ if (section == NULL) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Could not lookup section boundaries"));
+ }
+ *start = (char*)(nt_header->OptionalHeader.ImageBase + section->VirtualAddress);
+ *end = *start + section->Misc.VirtualSize;
+}
+
+void section_boundaries_from_module(const char *module, const char *section, char **start, char **end) {
+ IMAGE_NT_HEADERS *nt_header = header_from_memory(module);
+ IMAGE_SECTION_HEADER *dsection = find_section(nt_header, section);
+ section_boundaries(nt_header, dsection, start, end);
+}
+
+char *bss_start = 0;
+char *bss_end = 0;
+
+//MSVC has no __bss_start and _end but we can get accurate section info from the PE header.
+//The standard .bss section is appended to the standard .data section however so it cannot
+//be looked up by name. To deal with that we put all uPy static variables in a named section.
+void getbss() {
+ section_boundaries_from_module(NULL, MICROPY_PORT_BSSSECTION, &bss_start, &bss_end);
+}
diff --git a/windows/init.c b/windows/init.c
index a370c464e8..57f349ef89 100644
--- a/windows/init.c
+++ b/windows/init.c
@@ -28,9 +28,12 @@
#include <stdio.h>
#include <windows.h>
+extern void getbss();
+
HANDLE hSleepEvent = NULL;
void init() {
+ getbss();
hSleepEvent = CreateEvent(NULL, TRUE, FALSE, FALSE);
#ifdef __MINGW32__
putenv("PRINTF_EXPONENT_DIGITS=2");
diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h
index b9a50b0841..963fcfe768 100644
--- a/windows/mpconfigport.h
+++ b/windows/mpconfigport.h
@@ -35,16 +35,30 @@
#define MICROPY_EMIT_X64 (0)
#define MICROPY_EMIT_THUMB (0)
#define MICROPY_EMIT_INLINE_THUMB (0)
+#define MICROPY_ENABLE_GC (1)
+#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_MEM_STATS (1)
#define MICROPY_DEBUG_PRINTERS (1)
#define MICROPY_HELPER_REPL (1)
#define MICROPY_HELPER_LEXER_UNIX (1)
-#define MICROPY_PY_BUILTINS_FROZENSET (1)
-#define MICROPY_PY_CMATH (1)
-#define MICROPY_PY_SYS_STDFILES (1)
-#define MICROPY_PY_SYS_EXIT (1)
+#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
+#define MICROPY_STREAMS_NON_BLOCK (1)
+#define MICROPY_OPT_COMPUTED_GOTO (0)
+#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
+#define MICROPY_PY_BUILTINS_FROZENSET (1)
+#define MICROPY_PY_SYS_EXIT (1)
+#define MICROPY_PY_SYS_PLATFORM "win32"
+#define MICROPY_PY_SYS_STDFILES (1)
+#define MICROPY_PY_CMATH (1)
+#define MICROPY_PY_IO_FILEIO (1)
+#define MICROPY_PY_GC_COLLECT_RETVAL (1)
+#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED)
+#ifdef _MSC_VER
+#define MICROPY_GCREGS_SETJMP (1)
+#endif
+
#define MICROPY_PORT_INIT_FUNC init()
#define MICROPY_PORT_DEINIT_FUNC deinit()
@@ -113,6 +127,14 @@ void msec_sleep(double msec);
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+// Put static/global variables in sections with a known name we can lookup for the GC
+// For this to work this header must be included by all sources, which is the case normally
+#define MICROPY_PORT_DATASECTION "upydata"
+#define MICROPY_PORT_BSSSECTION "upybss"
+#pragma data_seg(MICROPY_PORT_DATASECTION)
+#pragma bss_seg(MICROPY_PORT_BSSSECTION)
+
+
// System headers (needed e.g. for nlr.h)
#include <stddef.h> //for NULL
@@ -122,3 +144,8 @@ void msec_sleep(double msec);
int snprintf(char *dest, size_t count, const char *format, ...);
#endif
+
+// MingW specifics
+#ifdef __MINGW32__
+#define MICROPY_PORT_BSSSECTION ".bss"
+#endif
diff --git a/windows/msvc/common.props b/windows/msvc/common.props
index 300de46a53..b6f22c6151 100644
--- a/windows/msvc/common.props
+++ b/windows/msvc/common.props
@@ -16,7 +16,8 @@
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
+ <GenerateMapFile>true</GenerateMapFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
-</Project> \ No newline at end of file
+</Project>
diff --git a/windows/msvc/sources.props b/windows/msvc/sources.props
index 8af03e7563..6fd3306b92 100644
--- a/windows/msvc/sources.props
+++ b/windows/msvc/sources.props
@@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<ClCompile Include="$(PyBaseDir)py\*.c" />
- <ClCompile Include="$(PyBaseDir)unix\*.c" Exclude="$(PyBaseDir)unix\modffi.c;$(PyBaseDir)unix\modsocket.c" />
+ <ClCompile Include="$(PyBaseDir)unix\*.c" Exclude="$(PyBaseDir)unix\modffi.c;$(PyBaseDir)unix\modsocket.c;$(PyBaseDir)unix\seg_helpers.c" />
<ClCompile Include="$(PyBaseDir)windows\*.c" />
<ClCompile Include="$(PyBaseDir)windows\msvc\*.c" />
</ItemGroup>