diff options
-rw-r--r-- | examples/conwaylife.py | 6 | ||||
-rw-r--r-- | examples/mandel.py | 3 | ||||
-rw-r--r-- | examples/pyb.py | 4 | ||||
-rw-r--r-- | py/compile.c | 30 | ||||
-rw-r--r-- | py/emit.h | 8 | ||||
-rw-r--r-- | py/emitbc.c | 5 | ||||
-rw-r--r-- | py/emitinlinethumb.c | 10 | ||||
-rw-r--r-- | py/emitnative.c | 9 | ||||
-rw-r--r-- | py/makeqstrdata.py | 22 | ||||
-rw-r--r-- | py/mkenv.mk | 52 | ||||
-rw-r--r-- | py/mkrules.mk | 92 | ||||
-rw-r--r-- | py/py.mk | 92 | ||||
-rw-r--r-- | py/qstr.c | 2 | ||||
-rw-r--r-- | py/qstr.h | 2 | ||||
-rw-r--r-- | py/qstrdefs.h | 8 | ||||
-rw-r--r-- | py/scope.c | 12 | ||||
-rw-r--r-- | stm/Makefile | 56 | ||||
-rw-r--r-- | stm/file.c | 94 | ||||
-rw-r--r-- | stm/file.h | 1 | ||||
-rw-r--r-- | stm/main.c | 85 | ||||
-rw-r--r-- | teensy/Makefile | 49 | ||||
-rw-r--r-- | unix-cpy/Makefile | 25 | ||||
-rw-r--r-- | unix/Makefile | 27 |
23 files changed, 384 insertions, 310 deletions
diff --git a/examples/conwaylife.py b/examples/conwaylife.py index 7c6ac4d548..89ef94c8c6 100644 --- a/examples/conwaylife.py +++ b/examples/conwaylife.py @@ -1,3 +1,7 @@ +#import essential libraries +import lcd +import pyb + # do 1 iteration of Conway's Game of Life def conway_step(): for x in range(128): # loop over x coordinates @@ -37,8 +41,6 @@ def conway_go(num_frames): pyb.delay(300) # PC testing -import lcd -import pyb lcd = lcd.LCD(128, 32) conway_rand() conway_go(1000) diff --git a/examples/mandel.py b/examples/mandel.py index d2b34fff83..bbb8086470 100644 --- a/examples/mandel.py +++ b/examples/mandel.py @@ -3,10 +3,9 @@ try: except: pass - def mandelbrot(): # returns True if c, complex, is in the Mandelbrot set - @micropython.native + #@micropython.native def in_set(c): z = 0 for i in range(40): diff --git a/examples/pyb.py b/examples/pyb.py index f7b52a2a1e..65fed6647e 100644 --- a/examples/pyb.py +++ b/examples/pyb.py @@ -1,9 +1,9 @@ # pyboard testing functions for CPython import time - def delay(n): - time.sleep(float(n) / 1000) + #time.sleep(float(n) / 1000) + pass rand_seed = 1 def rand(): diff --git a/py/compile.c b/py/compile.c index 7e77832bc3..e1b62a11bf 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3154,8 +3154,28 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) { } } - bool had_error = comp->had_error; - m_del_obj(compiler_t, comp); + // free the emitters +#if !MICROPY_EMIT_CPYTHON + if (emit_bc != NULL) { + emit_bc_free(emit_bc); + } +#if MICROPY_EMIT_NATIVE + if (emit_native != NULL) { +#if MICROPY_EMIT_X64 + emit_native_x64_free(emit_native); +#elif MICROPY_EMIT_THUMB + emit_native_thumb_free(emit_native); +#endif + } +#endif +#if MICROPY_EMIT_INLINE_THUMB + if (emit_inline_thumb != NULL) { + emit_inline_thumb_free(emit_inline_thumb); + } +#endif +#endif // !MICROPY_EMIT_CPYTHON + + // free the scopes uint unique_code_id = module_scope->unique_code_id; for (scope_t *s = module_scope; s;) { scope_t *next = s->next; @@ -3163,13 +3183,17 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) { s = next; } + // free the compiler + bool had_error = comp->had_error; + m_del_obj(compiler_t, comp); + if (had_error) { // TODO return a proper error message return mp_const_none; } else { #if MICROPY_EMIT_CPYTHON // can't create code, so just return true - (void)unique_code_id; // to suppress warning that module_scope is unused + (void)unique_code_id; // to suppress warning that unique_code_id is unused return mp_const_true; #else // return function that executes the outer module @@ -118,12 +118,16 @@ extern const emit_method_table_t emit_native_x64_method_table; extern const emit_method_table_t emit_native_thumb_method_table; emit_t *emit_pass1_new(qstr qstr___class__); -void emit_pass1_free(emit_t *emit); emit_t *emit_cpython_new(uint max_num_labels); emit_t *emit_bc_new(uint max_num_labels); emit_t *emit_native_x64_new(uint max_num_labels); emit_t *emit_native_thumb_new(uint max_num_labels); +void emit_pass1_free(emit_t *emit); +void emit_bc_free(emit_t *emit); +void emit_native_x64_free(emit_t *emit); +void emit_native_thumb_free(emit_t *emit); + typedef struct _emit_inline_asm_t emit_inline_asm_t; typedef struct _emit_inline_asm_method_table_t { @@ -137,3 +141,5 @@ typedef struct _emit_inline_asm_method_table_t { extern const emit_inline_asm_method_table_t emit_inline_thumb_method_table; emit_inline_asm_t *emit_inline_thumb_new(uint max_num_labels); +void emit_inline_thumb_free(emit_inline_asm_t *emit); + diff --git a/py/emitbc.c b/py/emitbc.c index c3385e0b66..10a95fbcfa 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -43,6 +43,11 @@ emit_t *emit_bc_new(uint max_num_labels) { return emit; } +void emit_bc_free(emit_t *emit) { + m_del(uint, emit->label_offsets, emit->max_num_labels); + m_del_obj(emit_t, emit); +} + // all functions must go through this one to emit code info static byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_write) { //printf("emit %d\n", num_bytes_to_write); diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 9d5a4206a0..c35192210c 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -20,13 +20,13 @@ struct _emit_inline_asm_t { int pass; scope_t *scope; - int max_num_labels; + uint max_num_labels; qstr *label_lookup; asm_thumb_t *as; }; emit_inline_asm_t *emit_inline_thumb_new(uint max_num_labels) { - emit_inline_asm_t *emit = m_new(emit_inline_asm_t, 1); + emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t); emit->max_num_labels = max_num_labels; emit->label_lookup = m_new(qstr, max_num_labels); memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr)); @@ -34,6 +34,12 @@ emit_inline_asm_t *emit_inline_thumb_new(uint max_num_labels) { return emit; } +void emit_inline_thumb_free(emit_inline_asm_t *emit) { + m_del(qstr, emit->label_lookup, emit->max_num_labels); + asm_thumb_free(emit->as, false); + m_del_obj(emit_inline_asm_t, emit); +} + static void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, scope_t *scope) { emit->pass = pass; emit->scope = scope; diff --git a/py/emitnative.c b/py/emitnative.c index 6fc1742489..258aa9fce5 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -146,6 +146,15 @@ emit_t *EXPORT_FUN(new)(uint max_num_labels) { return emit; } +void EXPORT_FUN(free)(emit_t *emit) { +#if N_X64 + asm_x64_free(emit->as, false); +#elif N_THUMB + asm_thumb_free(emit->as, false); +#endif + m_del_obj(emit_t, emit); +} + static void emit_native_set_viper_types(emit_t *emit, bool do_viper_types) { emit->do_viper_types = do_viper_types; } diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index c4b7be42e7..c5ad708e89 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -1,6 +1,13 @@ import argparse import re +# codepoint2name is different in Python 2 to Python 3 +import platform +if platform.python_version_tuple()[0] == '2': + from htmlentitydefs import codepoint2name +elif platform.python_version_tuple()[0] == '3': + from html.entities import codepoint2name + # this must match the equivalent function in qstr.c def compute_hash(qstr): hash = 0 @@ -10,7 +17,7 @@ def compute_hash(qstr): def do_work(infiles): # read the qstrs in from the input files - qstrs = [] + qstrs = {} for infile in infiles: with open(infile, 'rt') as f: line_number = 0 @@ -23,28 +30,29 @@ def do_work(infiles): continue # verify line is of the correct form - match = re.match(r'Q\(([0-9A-Za-z_]+)\)$', line) + match = re.match(r'Q\((.+)\)$', line) if not match: print('({}:{}) bad qstr format, got {}'.format(infile, line_number, line)) return False # get the qstr value qstr = match.group(1) + ident = re.sub(r'[^A-Za-z0-9_]', lambda s: "_" + codepoint2name[ord(s.group(0))] + "_", qstr) # don't add duplicates - if qstr in qstrs: + if ident in qstrs: continue - # add the qstr to the list - qstrs.append(qstr) + # add the qstr to the list, with order number to retain original order in file + qstrs[ident] = (len(qstrs), ident, qstr) # process the qstrs, printing out the generated C header file print('// This file was automatically generated by makeqstrdata.py') print('') - for qstr in qstrs: + for order, ident, qstr in sorted(qstrs.values(), key=lambda x: x[0]): qhash = compute_hash(qstr) qlen = len(qstr) - print('Q({}, (const byte*)"\\x{:02x}\\x{:02x}\\x{:02x}\\x{:02x}" "{}")'.format(qstr, qhash & 0xff, (qhash >> 8) & 0xff, qlen & 0xff, (qlen >> 8) & 0xff, qstr)) + print('Q({}, (const byte*)"\\x{:02x}\\x{:02x}\\x{:02x}\\x{:02x}" "{}")'.format(ident, qhash & 0xff, (qhash >> 8) & 0xff, qlen & 0xff, (qlen >> 8) & 0xff, qstr)) return True diff --git a/py/mkenv.mk b/py/mkenv.mk new file mode 100644 index 0000000000..ed4e22096d --- /dev/null +++ b/py/mkenv.mk @@ -0,0 +1,52 @@ +ifneq ($(lastword a b),b) +$(error These Makefiles require make 3.81 or newer) +endif + +# Set TOP to be the path to get from the current directory (where make was +# invoked) to the top of the tree. $(lastword $(MAKEFILE_LIST)) returns +# the name of this makefile relative to where make was invoked. +# +# We assume that this file is in the py directory so we use $(dir ) twice +# to get to the top of the tree. + +THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) +TOP := $(patsubst %/py/mkenv.mk,%,$(THIS_MAKEFILE)) + +# Turn on increased build verbosity by defining BUILD_VERBOSE in your main +# Makefile or in your environment. You can also use V=1 on the make command +# line. + +ifeq ("$(origin V)", "command line") +BUILD_VERBOSE=$(V) +endif +ifndef BUILD_VERBOSE +BUILD_VERBOSE = 0 +endif +ifeq ($(BUILD_VERBOSE),0) +Q = @ +else +Q = +endif +# Since this is a new feature, advertise it +ifeq ($(BUILD_VERBOSE),0) +$(info Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.) +endif + +# default settings; can be overriden in main Makefile + +PY_SRC ?= $(TOP)/py +BUILD ?= build + +RM = rm +ECHO = @echo + +AS = $(CROSS_COMPILE)as +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +OBJCOPY = $(CROSS_COMPILE)objcopy +SIZE = $(CROSS_COMPILE)size + +all: +.PHONY: all + +MKENV_INCLUDED = 1 diff --git a/py/mkrules.mk b/py/mkrules.mk new file mode 100644 index 0000000000..4c1ea08332 --- /dev/null +++ b/py/mkrules.mk @@ -0,0 +1,92 @@ +ifneq ($(MKENV_INCLUDED),1) +# We assume that mkenv is in the same directory as this file. +THIS_MAKEFILE = $(lastword $(MAKEFILE_LIST)) +include $(dir $(THIS_MAKEFILE))mkenv.mk +endif + +# This file expects that OBJ contains a list of all of the object files. +# The directory portion of each object file is used to locate the source +# and should not contain any ..'s but rather be relative to the top of the +# tree. +# +# So for example, py/map.c would have an object file name py/map.o +# The object files will go into the build directory and mantain the same +# directory structure as the source tree. So the final dependency will look +# like this: +# +# build/py/map.o: py/map.c +# +# We set vpath to point to the top of the tree so that the source files +# can be located. By following this scheme, it allows a single build rule +# to be used to compile all .c files. + +vpath %.S . $(TOP) +$(BUILD)/%.o: %.S + $(ECHO) "CC $<" + $(Q)$(CC) $(CFLAGS) -c -o $@ $< + +vpath %.s . $(TOP) +$(BUILD)/%.o: %.s + $(ECHO) "AS $<" + $(Q)$(AS) -o $@ $< + +define compile_c +$(ECHO) "CC $<" +$(Q)$(CC) $(CFLAGS) -c -MD -o $@ $< +@# The following fixes the dependency file. +@# See http://make.paulandlesley.org/autodep.html for details. +@cp $(@:.o=.d) $(@:.o=.P); \ + sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \ + rm -f $(@:.o=.d) +endef + +vpath %.c . $(TOP) +$(BUILD)/%.o: %.c + $(call compile_c) + +# The following rule uses | to create an order only prereuisite. Order only +# prerequisites only get built if they don't exist. They don't cause timestamp +# checkng to be performed. +# +# $(sort $(var)) removes duplicates +# +# The net effect of this, is it causes the objects to depend on the +# object directories (but only for existance), and the object directories +# will be created if they don't exist. +OBJ_DIRS = $(sort $(dir $(OBJ))) +$(OBJ): | $(OBJ_DIRS) +$(OBJ_DIRS): + mkdir -p $@ + +ifneq ($(PROG),) +# Build a standalone executable (unix and unix-cpy do this) + +all: $(PROG) + +$(PROG): $(OBJ) + $(ECHO) "LINK $<" + $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) +ifndef DEBUG + $(Q)strip $(PROG) +endif + $(Q)size $(PROG) + +clean: clean-prog +clean-prog: + $(RM) -f $(PROG) + +.PHONY: clean-prog +endif + +clean: + $(RM) -rf $(BUILD) +.PHONY: clean + +print-cfg: + $(ECHO) "PY_SRC = $(PY_SRC)" + $(ECHO) "BUILD = $(BUILD)" + $(ECHO) "OBJ = $(OBJ)" +.PHONY: print-cfg + +-include $(OBJ:.o=.P) @@ -1,48 +1,11 @@ -########## -# The following should eventually go into a more central location -# when a reorg is done. -# -# Turn on increased build verbosity by defining BUILD_VERBOSE in your main -# Makefile or in your environment. You can also use V=1 on the make command -# line. -ifeq ("$(origin V)", "command line") -BUILD_VERBOSE=$(V) -endif -ifndef BUILD_VERBOSE -BUILD_VERBOSE = 0 -endif -ifeq ($(BUILD_VERBOSE),0) -Q = @ -else -Q = -endif -# Since this is a new feature, advertise it -ifeq ($(BUILD_VERBOSE),0) -$(info Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.) -endif -# -######### - -# default settings; can be overriden in main Makefile - -PY_SRC ?= ../py -BUILD ?= build - -# to create the build directory - -$(BUILD): - $(Q)mkdir -p $@ - # where py object files go (they have a name prefix to prevent filename clashes) - -PY_BUILD = $(BUILD)/py. +PY_BUILD = $(BUILD)/py # file containing qstr defs for the core Python bit PY_QSTR_DEFS = $(PY_SRC)/qstrdefs.h # py object files - PY_O_BASENAME = \ nlrx86.o \ nlrx64.o \ @@ -108,50 +71,37 @@ PY_O_BASENAME = \ repl.o \ # prepend the build destination prefix to the py object files - -PY_O = $(addprefix $(PY_BUILD), $(PY_O_BASENAME)) +PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME)) # qstr data -$(PY_BUILD)qstr.o: $(PY_BUILD)qstrdefs.generated.h - -$(PY_BUILD)qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(PY_SRC)/makeqstrdata.py +# Adding an order only dependency on $(PY_BUILD) causes $(PY_BUILD) to get +# created before we run the script to generate the .h +$(PY_BUILD)/qstrdefs.generated.h: | $(PY_BUILD) +$(PY_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(PY_SRC)/makeqstrdata.py $(ECHO) "makeqstrdata $(PY_QSTR_DEFS) $(QSTR_DEFS)" $(Q)python $(PY_SRC)/makeqstrdata.py $(PY_QSTR_DEFS) $(QSTR_DEFS) > $@ -# emitters - -$(PY_BUILD)emitnx64.o: $(PY_SRC)/emitnative.c $(PY_SRC)/emit.h mpconfigport.h - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -DN_X64 -c -o $@ $< +# We don't know which source files actually need the generated.h (since +# it is #included from str.h). The compiler generated dependencies will cause +# the right .o's to get recompiled if the generated.h file changes. Adding +# an order-only dependendency to all of the .o's will cause the generated .h +# to get built before we try to compile any of them. +$(PY_O): | $(PY_BUILD)/qstrdefs.generated.h -$(PY_BUILD)emitnthumb.o: $(PY_SRC)/emitnative.c $(PY_SRC)/emit.h mpconfigport.h - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -DN_THUMB -c -o $@ $< - -# general source files +# emitters -$(PY_BUILD)%.o: $(PY_SRC)/%.S - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< +$(PY_BUILD)/emitnx64.o: CFLAGS += -DN_X64 +$(PY_BUILD)/emitnx64.o: py/emitnative.c + $(call compile_c) -$(PY_BUILD)%.o: $(PY_SRC)/%.c mpconfigport.h $(PY_SRC)/qstr.h $(PY_QSTR_DEFS) $(QSTR_DEFS) - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< +$(PY_BUILD)/emitnthumb.o: CFLAGS += -DN_THUMB +$(PY_BUILD)/emitnthumb.o: py/emitnative.c + $(call compile_c) # optimising gc for speed; 5ms down to 4ms on pybv2 -$(PY_BUILD)gc.o: $(PY_SRC)/gc.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -O3 -c -o $@ $< +$(PY_BUILD)gc.o: CFLAGS += -O3 # optimising vm for speed, adds only a small amount to code size but makes a huge difference to speed (20% faster) -$(PY_BUILD)vm.o: $(PY_SRC)/vm.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -O3 -c -o $@ $< - -# header dependencies +$(PY_BUILD)vm.o: CFLAGS += -O3 -$(PY_BUILD)parse.o: $(PY_SRC)/grammar.h -$(PY_BUILD)compile.o: $(PY_SRC)/grammar.h -$(PY_BUILD)emitcpy.o: $(PY_SRC)/emit.h -$(PY_BUILD)emitbc.o: $(PY_SRC)/emit.h @@ -55,7 +55,7 @@ const static qstr_pool_t const_pool = { (const byte*) "\0\0\0\0", // empty qstr #define Q(id, str) str, // TODO having 'build/' here is a bit of a hack, should take config variable from Makefile -#include "build/py.qstrdefs.generated.h" +#include "build/py/qstrdefs.generated.h" #undef Q }, }; @@ -9,7 +9,7 @@ enum { MP_QSTR_ = 1, // the empty qstr #define Q(id, str) MP_QSTR_##id, // TODO having 'build/py.' here is a bit of a hack, should take config variable from Makefile -#include "build/py.qstrdefs.generated.h" +#include "build/py/qstrdefs.generated.h" #undef Q MP_QSTR_number_of, } category_t; diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 9bc01c5851..f2c4dfd97f 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -80,3 +80,11 @@ Q(sort) Q(join) Q(strip) Q(format) + +Q(<module>) +Q(<lambda>) +Q(<listcomp>) +Q(<dictcomp>) +Q(<setcomp>) +Q(<genexpr>) +Q(<stdin>) diff --git a/py/scope.c b/py/scope.c index 1f602ac9c0..ab20f61f37 100644 --- a/py/scope.c +++ b/py/scope.c @@ -18,7 +18,7 @@ scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint scope->source_file = source_file; switch (kind) { case SCOPE_MODULE: - scope->simple_name = QSTR_FROM_STR_STATIC("<module>"); + scope->simple_name = MP_QSTR__lt_module_gt_; break; case SCOPE_FUNCTION: case SCOPE_CLASS: @@ -26,19 +26,19 @@ scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint scope->simple_name = MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pn)->nodes[0]); break; case SCOPE_LAMBDA: - scope->simple_name = QSTR_FROM_STR_STATIC("<lambda>"); + scope->simple_name = MP_QSTR__lt_lambda_gt_; break; case SCOPE_LIST_COMP: - scope->simple_name = QSTR_FROM_STR_STATIC("<listcomp>"); + scope->simple_name = MP_QSTR__lt_listcomp_gt_; break; case SCOPE_DICT_COMP: - scope->simple_name = QSTR_FROM_STR_STATIC("<dictcomp>"); + scope->simple_name = MP_QSTR__lt_dictcomp_gt_; break; case SCOPE_SET_COMP: - scope->simple_name = QSTR_FROM_STR_STATIC("<setcomp>"); + scope->simple_name = MP_QSTR__lt_setcomp_gt_; break; case SCOPE_GEN_EXPR: - scope->simple_name = QSTR_FROM_STR_STATIC("<genexpr>"); + scope->simple_name = MP_QSTR__lt_genexpr_gt_; break; default: assert(0); diff --git a/stm/Makefile b/stm/Makefile index ab69109583..b3483e089d 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -1,5 +1,4 @@ -# define main target -all: all2 +include ../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h @@ -7,10 +6,6 @@ QSTR_DEFS = qstrdefsport.h # include py core make definitions include ../py/py.mk -# program for deletion -RM = /bin/rm -ECHO = @echo - CMSIS=cmsis STMSRC=lib #STMOTGSRC=usbhost @@ -18,11 +13,7 @@ FATFSSRC=fatfs CC3KSRC=cc3k DFU=../tools/dfu.py -AS = arm-none-eabi-as -CC = arm-none-eabi-gcc -LD = arm-none-eabi-ld -OBJCOPY = arm-none-eabi-objcopy -SIZE = arm-none-eabi-size +CROSS_COMPILE = arm-none-eabi- CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion CFLAGS = -I. -I$(PY_SRC) -I$(FATFSSRC) -I$(CMSIS) -I$(STMSRC) -Wall -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) @@ -65,17 +56,19 @@ SRC_C = \ usrsw.c \ adc.c \ rtc.c \ + file.c \ # pybwlan.c \ SRC_S = \ startup_stm32f40xx.s \ gchelper.s \ -SRC_FATFS = \ +SRC_FATFS = $(addprefix $(FATFSSRC)/,\ ff.c \ diskio.c \ + ) -SRC_STM = \ +SRC_STM = $(addprefix $(STMSRC)/,\ stm32f4xx_rcc.c \ stm32f4xx_syscfg.c \ stm_misc.c \ @@ -111,8 +104,9 @@ SRC_STM = \ usbd_msc_data.c \ usbd_msc_scsi.c \ usbd_storage_msd.c \ + ) -#SRC_STM_OTG = \ +#SRC_STM_OTG = $(addprefix $(STMSRC)/,\ usb_hcd.c \ usb_hcd_int.c \ usbh_core.c \ @@ -124,8 +118,9 @@ SRC_STM = \ usbh_hid_mouse.c \ usbh_hid_keybd.c \ # usb_otg.c \ + ) -SRC_CC3K = \ +SRC_CC3K = $(addprefix $(CC3KSRC)/,\ cc3000_common.c \ evnt_handler.c \ hci.c \ @@ -136,11 +131,12 @@ SRC_CC3K = \ wlan.c \ ccspi.c \ pybcc3k.c \ + ) OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o) $(SRC_FATFS:.c=.o) $(SRC_STM:.c=.o)) # $(SRC_CC3K:.c=.o)) #OBJ += $(addprefix $(BUILD)/, $(SRC_STM_OTG:.c=.o)) -all2: $(BUILD) $(BUILD)/flash.dfu +all: $(BUILD) $(BUILD)/flash.dfu $(BUILD)/flash.dfu: $(BUILD)/flash0.bin $(BUILD)/flash1.bin $(ECHO) "Create $@" @@ -157,31 +153,5 @@ $(BUILD)/flash.elf: $(OBJ) $(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(Q)$(SIZE) $@ -$(BUILD)/%.o: %.s - $(ECHO) "AS $<" - $(Q)$(AS) -o $@ $< - -$(BUILD)/%.o: %.c $(QSTR_DEFS) - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/%.o: $(FATFSSRC)/%.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/%.o: $(STMSRC)/%.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -#$(BUILD)/%.o: $(STMOTGSRC)/%.c -# $(ECHO) "CC $<" -# $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/%.o: $(CC3KSRC)/%.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -clean: - $(RM) -rf $(BUILD) +include ../py/mkrules.mk -.PHONY: all all2 clean diff --git a/stm/file.c b/stm/file.c new file mode 100644 index 0000000000..35bfca16a5 --- /dev/null +++ b/stm/file.c @@ -0,0 +1,94 @@ +#include <stdio.h> +#include <stm32f4xx.h> + +#include "misc.h" +#include "mpconfig.h" +#include "mpconfigport.h" +#include "qstr.h" +#include "obj.h" +#include "file.h" +#include "ff.h" + +typedef struct _pyb_file_obj_t { + mp_obj_base_t base; + FIL fp; +} pyb_file_obj_t; + +void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { + printf("<file %p>", self_in); +} + +mp_obj_t file_obj_read(mp_obj_t self_in, mp_obj_t arg) { + pyb_file_obj_t *self = self_in; + int n = mp_obj_get_int(arg); + byte *buf = m_new(byte, n); + UINT n_out; + f_read(&self->fp, buf, n, &n_out); + return mp_obj_new_str(buf, n_out, false); +} + +mp_obj_t file_obj_write(mp_obj_t self_in, mp_obj_t arg) { + pyb_file_obj_t *self = self_in; + uint l; + const byte *s = mp_obj_str_get_data(arg, &l); + UINT n_out; + FRESULT res = f_write(&self->fp, s, l, &n_out); + if (res != FR_OK) { + printf("File error: could not write to file; error code %d\n", res); + } else if (n_out != l) { + printf("File error: could not write all data to file; wrote %d / %d bytes\n", n_out, l); + } + return mp_const_none; +} + +mp_obj_t file_obj_close(mp_obj_t self_in) { + pyb_file_obj_t *self = self_in; + f_close(&self->fp); + return mp_const_none; +} + +static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_read_obj, file_obj_read); +static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_write_obj, file_obj_write); +static MP_DEFINE_CONST_FUN_OBJ_1(file_obj_close_obj, file_obj_close); + +// TODO gc hook to close the file if not already closed + +static const mp_method_t file_methods[] = { + { "read", &file_obj_read_obj }, + { "write", &file_obj_write_obj }, + { "close", &file_obj_close_obj }, + {NULL, NULL}, +}; + +static const mp_obj_type_t file_obj_type = { + { &mp_const_type }, + "File", + .print = file_obj_print, + .methods = file_methods, +}; + +mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) { + const char *filename = mp_obj_str_get_str(o_filename); + const char *mode = mp_obj_str_get_str(o_mode); + pyb_file_obj_t *self = m_new_obj(pyb_file_obj_t); + self->base.type = &file_obj_type; + if (mode[0] == 'r') { + // open for reading + FRESULT res = f_open(&self->fp, filename, FA_READ); + if (res != FR_OK) { + printf("FileNotFoundError: [Errno 2] No such file or directory: '%s'\n", filename); + return mp_const_none; + } + } else if (mode[0] == 'w') { + // open for writing, truncate the file first + FRESULT res = f_open(&self->fp, filename, FA_WRITE | FA_CREATE_ALWAYS); + if (res != FR_OK) { + printf("?FileError: could not create file: '%s'\n", filename); + return mp_const_none; + } + } else { + printf("ValueError: invalid mode: '%s'\n", mode); + return mp_const_none; + } + return self; +} diff --git a/stm/file.h b/stm/file.h new file mode 100644 index 0000000000..3845635deb --- /dev/null +++ b/stm/file.h @@ -0,0 +1 @@ +mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode); diff --git a/stm/main.c b/stm/main.c index 92c3772d5f..2ce2b6dc61 100644 --- a/stm/main.c +++ b/stm/main.c @@ -43,6 +43,7 @@ #include "usrsw.h" #include "adc.h" #include "rtc.h" +#include "file.h" int errno; @@ -544,90 +545,6 @@ mp_obj_t pyb_hid_send_report(mp_obj_t arg) { return mp_const_none; } -typedef struct _pyb_file_obj_t { - mp_obj_base_t base; - FIL fp; -} pyb_file_obj_t; - -void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { - printf("<file %p>", self_in); -} - -mp_obj_t file_obj_read(mp_obj_t self_in, mp_obj_t arg) { - pyb_file_obj_t *self = self_in; - int n = mp_obj_get_int(arg); - byte *buf = m_new(byte, n); - UINT n_out; - f_read(&self->fp, buf, n, &n_out); - return mp_obj_new_str(buf, n_out, false); -} - -mp_obj_t file_obj_write(mp_obj_t self_in, mp_obj_t arg) { - pyb_file_obj_t *self = self_in; - uint l; - const byte *s = mp_obj_str_get_data(arg, &l); - UINT n_out; - FRESULT res = f_write(&self->fp, s, l, &n_out); - if (res != FR_OK) { - printf("File error: could not write to file; error code %d\n", res); - } else if (n_out != l) { - printf("File error: could not write all data to file; wrote %d / %d bytes\n", n_out, l); - } - return mp_const_none; -} - -mp_obj_t file_obj_close(mp_obj_t self_in) { - pyb_file_obj_t *self = self_in; - f_close(&self->fp); - return mp_const_none; -} - -static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_read_obj, file_obj_read); -static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_write_obj, file_obj_write); -static MP_DEFINE_CONST_FUN_OBJ_1(file_obj_close_obj, file_obj_close); - -// TODO gc hook to close the file if not already closed - -static const mp_method_t file_methods[] = { - { "read", &file_obj_read_obj }, - { "write", &file_obj_write_obj }, - { "close", &file_obj_close_obj }, - {NULL, NULL}, -}; - -static const mp_obj_type_t file_obj_type = { - { &mp_const_type }, - "File", - .print = file_obj_print, - .methods = file_methods, -}; - -mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) { - const char *filename = mp_obj_str_get_str(o_filename); - const char *mode = mp_obj_str_get_str(o_mode); - pyb_file_obj_t *self = m_new_obj(pyb_file_obj_t); - self->base.type = &file_obj_type; - if (mode[0] == 'r') { - // open for reading - FRESULT res = f_open(&self->fp, filename, FA_READ); - if (res != FR_OK) { - printf("FileNotFoundError: [Errno 2] No such file or directory: '%s'\n", filename); - return mp_const_none; - } - } else if (mode[0] == 'w') { - // open for writing, truncate the file first - FRESULT res = f_open(&self->fp, filename, FA_WRITE | FA_CREATE_ALWAYS); - if (res != FR_OK) { - printf("?FileError: could not create file: '%s'\n", filename); - return mp_const_none; - } - } else { - printf("ValueError: invalid mode: '%s'\n", mode); - return mp_const_none; - } - return self; -} - mp_obj_t pyb_rng_get(void) { return mp_obj_new_int(RNG_GetRandomNumber() >> 16); } diff --git a/teensy/Makefile b/teensy/Makefile index e25f81481f..0cd7272e71 100644 --- a/teensy/Makefile +++ b/teensy/Makefile @@ -1,30 +1,20 @@ -# define main target -all: all2 +include ../py/mkenv.mk # include py core make definitions include ../py/py.mk -# program for deletion -RM = /bin/rm -ECHO = @echo - ifeq ($(ARDUINO),) $(error Please define ARDUINO (where TeensyDuino is installed)) endif TOOLS_PATH = $(ARDUINO)/hardware/tools COMPILER_PATH = $(TOOLS_PATH)/arm-none-eabi/bin CORE_PATH = $(ARDUINO)/hardware/teensy/cores/teensy3 -TARGET=TEENSY -AS = $(COMPILER_PATH)/arm-none-eabi-as -CC = $(COMPILER_PATH)/arm-none-eabi-gcc -LD = $(COMPILER_PATH)/arm-none-eabi-ld -OBJCOPY = $(COMPILER_PATH)/arm-none-eabi-objcopy -SIZE = $(COMPILER_PATH)/arm-none-eabi-size +CROSS_COMPILE = $(COMPILER_PATH)/arm-none-eabi- CFLAGS_TEENSY = -DF_CPU=96000000 -DUSB_SERIAL -D__MK20DX256__ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -fsingle-precision-constant -Wdouble-promotion $(CFLAGS_TEENSY) -CFLAGS = -I. -I$(PY_SRC) -I$(CORE_PATH) -Wall -ansi -std=gnu99 +CFLAGS = -I. -I$(PY_SRC) -I$(CORE_PATH) -Wall -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) LDFLAGS = -nostdlib -T mk20dx256.ld LIBS = -L $(COMPILER_PATH)/../lib/gcc/arm-none-eabi/4.7.2/thumb2 -lgcc @@ -35,9 +25,6 @@ else CFLAGS += -Os #-DNDEBUG endif -# if order is not important for these, move them up -CFLAGS += $(CFLAGS_CORTEX_M4) -D$(TARGET) - SRC_C = \ main.c \ lcd.c \ @@ -47,13 +34,15 @@ SRC_C = \ memzip.c \ usb.c \ -STM_SRC_C = \ +STM_SRC_C = $(addprefix stm/,\ malloc0.c \ printf.c \ string0.c \ + ) -STM_SRC_S = \ +STM_SRC_S = $(addprefix stm/,\ gchelper.s \ + ) SRC_TEENSY = \ mk20dx128.c \ @@ -70,7 +59,7 @@ OBJ = $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(STM_SRC_S:.s=.o # the following is needed for BSD #LIB += -ltermcap -all2: $(BUILD) hex +all: hex hex: $(BUILD)/micropython-mz.hex post_compile: $(BUILD)/micropython-mz.hex @@ -100,25 +89,7 @@ $(BUILD)/%.hex: $(BUILD)/%.elf $(ECHO) "HEX $<" $(Q)$(OBJCOPY) -O ihex -R .eeprom "$<" "$@" -$(BUILD)/%.o: %.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/%.o: ../stm/%.s - $(ECHO) "AS $<" - $(Q)$(AS) -o $@ $< - -$(BUILD)/%.o: ../stm/%.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - $(BUILD)/%.o: $(CORE_PATH)/%.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/main.o: mpconfigport.h - -clean: - $(RM) -rf $(BUILD) + $(call compile_c) -.PHONY: all all2 clean +include ../py/mkrules.mk diff --git a/unix-cpy/Makefile b/unix-cpy/Makefile index f8ab73c354..84fc581e32 100644 --- a/unix-cpy/Makefile +++ b/unix-cpy/Makefile @@ -1,16 +1,12 @@ +include ../py/mkenv.mk + # define main target PROG = cpy -all: $(PROG) # include py core make definitions include ../py/py.mk -# program for deletion -RM = /bin/rm -ECHO = @echo - # compiler settings -CC = gcc CFLAGS = -I. -I$(PY_SRC) -Wall -Werror -ansi -std=gnu99 -DUNIX LDFLAGS = -lm @@ -28,20 +24,5 @@ SRC_C = \ OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) LIB = -$(PROG): $(BUILD) $(OBJ) - $(ECHO) "LINK $<" - $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) - $(Q)strip $(PROG) - $(Q)size $(PROG) - -$(BUILD)/%.o: %.c - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/main.o: mpconfigport.h - -clean: - $(RM) -f $(PROG) - $(RM) -rf $(BUILD) +include ../py/mkrules.mk -.PHONY: all clean diff --git a/unix/Makefile b/unix/Makefile index 7a4ce3e161..3db6ae9dfd 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -1,6 +1,7 @@ +include ../py/mkenv.mk + # define main target PROG = micropython -all: $(PROG) # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h @@ -8,12 +9,7 @@ QSTR_DEFS = qstrdefsport.h # include py core make definitions include ../py/py.mk -# program for deletion -RM = /bin/rm -ECHO = @echo - # compiler settings -CC = gcc CFLAGS = -I. -I$(PY_SRC) -Wall -Werror -ansi -std=gnu99 -DUNIX LDFLAGS = -lm @@ -35,22 +31,5 @@ LIB = -lreadline # the following is needed for BSD #LIB += -ltermcap -$(PROG): $(BUILD) $(OBJ) - $(ECHO) "LINK $<" - $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) -ifndef DEBUG - $(Q)strip $(PROG) -endif - $(Q)size $(PROG) - -$(BUILD)/%.o: %.c $(QSTR_DEFS) - $(ECHO) "CC $<" - $(Q)$(CC) $(CFLAGS) -c -o $@ $< - -$(BUILD)/main.o: mpconfigport.h - -clean: - $(RM) -f $(PROG) - $(RM) -rf $(BUILD) +include ../py/mkrules.mk -.PHONY: all clean |