diff --git a/minimal/Makefile b/minimal/Makefile index a59bb9f89a..65a40a2507 100644 --- a/minimal/Makefile +++ b/minimal/Makefile @@ -1,19 +1,29 @@ include ../py/mkenv.mk +CROSS = 0 + # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h # include py core make definitions include ../py/py.mk +ifeq ($(CROSS), 1) CROSS_COMPILE = arm-none-eabi- +endif INC = -I. INC += -I.. +INC += -I../lib/mp-readline +INC += -I$(PY_SRC) -I../stmhal INC += -I$(BUILD) +ifeq ($(CROSS), 1) CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) +else +CFLAGS = -m32 $(INC) -Wall -Werror -ansi -std=gnu99 $(COPT) +endif #Debugging/Optimization ifeq ($(DEBUG), 1) @@ -22,15 +32,22 @@ else CFLAGS += -Os -DNDEBUG endif +ifeq ($(CROSS), 1) LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref +else +LD = gcc +LDFLAGS = -m32 -Wl,-Map=$@.map,--cref +endif LIBS = SRC_C = \ main.c \ -# printf.c \ - string0.c \ - malloc0.c \ - gccollect.c \ + uart_core.c \ + uart_extra.c \ + stmhal/printf.c \ + stmhal/string0.c \ + stmhal/pyexec.c \ + lib/mp-readline/readline.c \ SRC_S = \ # startup_stm32f40xx.s \ diff --git a/minimal/main.c b/minimal/main.c index a1e94313c5..29956c91a6 100644 --- a/minimal/main.c +++ b/minimal/main.c @@ -8,6 +8,9 @@ #include "py/runtime.h" #include "py/repl.h" #include "py/pfenv.h" +#include "py/gc.h" +#include "pyexec.h" +#include "pybstdio.h" void do_str(const char *src) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); @@ -46,14 +49,31 @@ void do_str(const char *src) { } } +static char *stack_top; +static char heap[2048]; + int main(int argc, char **argv) { + int stack_dummy; + stack_top = (char*)&stack_dummy; + +#if MICROPY_ENABLE_GC + gc_init(heap, heap + sizeof(heap)); +#endif mp_init(); - do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\n')"); + pyexec_friendly_repl(); + //do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')"); mp_deinit(); return 0; } void gc_collect(void) { + // WARNING: This gc_collect implementation doesn't try to get root + // pointers from CPU registers, and thus may function incorrectly. + void *dummy; + gc_collect_start(); + gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t)); + gc_collect_end(); + gc_dump_info(); } mp_lexer_t *mp_lexer_new_from_file(const char *filename) { @@ -83,39 +103,6 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c } #endif -/* -int _lseek() {return 0;} -int _read() {return 0;} -int _write() {return 0;} -int _close() {return 0;} -void _exit(int x) {for(;;){}} -int _sbrk() {return 0;} -int _kill() {return 0;} -int _getpid() {return 0;} -int _fstat() {return 0;} -int _isatty() {return 0;} -*/ - -void *malloc(size_t n) {return NULL;} -void *calloc(size_t nmemb, size_t size) {return NULL;} -void *realloc(void *ptr, size_t size) {return NULL;} -void free(void *p) {} -int printf(const char *m, ...) {return 0;} -void *memcpy(void *dest, const void *src, size_t n) {return NULL;} -int memcmp(const void *s1, const void *s2, size_t n) {return 0;} -void *memmove(void *dest, const void *src, size_t n) {return NULL;} -void *memset(void *s, int c, size_t n) {return NULL;} -int strcmp(const char *s1, const char* s2) {return 0;} -int strncmp(const char *s1, const char* s2, size_t n) {return 0;} -size_t strlen(const char *s) {return 0;} -char *strcat(char *dest, const char *src) {return NULL;} -char *strchr(const char *dest, int c) {return NULL;} -#include -int vprintf(const char *format, va_list ap) {return 0;} -int vsnprintf(char *str, size_t size, const char *format, va_list ap) {return 0;} - -#undef putchar -int putchar(int c) {return 0;} -int puts(const char *s) {return 0;} - +#if !MICROPY_MIN_USE_STDOUT void _start(void) {main(0, NULL);} +#endif diff --git a/minimal/mpconfigport.h b/minimal/mpconfigport.h index e9a755294f..cc6055df3d 100644 --- a/minimal/mpconfigport.h +++ b/minimal/mpconfigport.h @@ -2,7 +2,7 @@ // options to control how Micro Python is built -#define MICROPY_ALLOC_PATH_MAX (512) +#define MICROPY_ALLOC_PATH_MAX (256) #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) @@ -10,8 +10,8 @@ #define MICROPY_COMP_CONST (0) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTERS (0) -#define MICROPY_ENABLE_GC (0) -#define MICROPY_HELPER_REPL (0) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (0) #define MICROPY_ENABLE_DOC_STRING (0) @@ -41,11 +41,15 @@ #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) -#define UINT_FMT "%lu" -#define INT_FMT "%ld" +// This port is intended to be 32-bit, but unfortunately, int32_t for +// different targets may be defined in different ways - either as int +// or as long. This requires different printf formatting specifiers +// to print such value. So, we avoid int32_t and use int directly. +#define UINT_FMT "%u" +#define INT_FMT "%d" +typedef int mp_int_t; // must be pointer size +typedef unsigned mp_uint_t; // must be pointer size -typedef int32_t mp_int_t; // must be pointer size -typedef uint32_t mp_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 long mp_off_t; @@ -57,3 +61,19 @@ extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; // We need to provide a declaration/definition of alloca() #include + +#define HAL_GetTick() 0 + +static inline void mp_hal_set_interrupt_char(char c) {} + +#define MICROPY_HW_BOARD_NAME "minimal" +#define MICROPY_HW_MCU_NAME "unknown-cpu" + +#ifdef __linux__ +#define MICROPY_MIN_USE_STDOUT (1) +#endif + +#define MP_STATE_PORT MP_STATE_VM + +#define MICROPY_PORT_ROOT_POINTERS \ + const char *readline_hist[8]; diff --git a/minimal/uart_core.c b/minimal/uart_core.c new file mode 100644 index 0000000000..92c81ecc9e --- /dev/null +++ b/minimal/uart_core.c @@ -0,0 +1,24 @@ +#include +#include "py/mpconfig.h" + +/* + * Core UART functions to implement for a port + */ + +// Receive single character +int stdin_rx_chr(void) { + unsigned char c = 0; +#if MICROPY_MIN_USE_STDOUT + int r = read(0, &c, 1); + (void)r; +#endif + return c; +} + +// Send string of given length +void stdout_tx_strn(const char *str, mp_uint_t len) { +#if MICROPY_MIN_USE_STDOUT + int r = write(1, str, len); + (void)r; +#endif +} diff --git a/minimal/uart_extra.c b/minimal/uart_extra.c new file mode 100644 index 0000000000..a49bff7b96 --- /dev/null +++ b/minimal/uart_extra.c @@ -0,0 +1,26 @@ +#include +#include +#include "py/mpconfig.h" +#include "pybstdio.h" + +/* + * Extra UART functions + * These can be either optimized for a particular port, or reference, + * not very optimal implementation below can be used. + */ + +// Send "cooked" string of length, where every occurance of +// LF character is replaced with CR LF. +void stdout_tx_strn_cooked(const char *str, mp_uint_t len) { + while (len--) { + if (*str == '\n') { + stdout_tx_strn("\r", 1); + } + stdout_tx_strn(str++, 1); + } +} + +// Send zero-terminated string +void stdout_tx_str(const char *str) { + stdout_tx_strn(str, strlen(str)); +}