From 8c8d49d08db37b889ca93aaf219a813874500603 Mon Sep 17 00:00:00 2001 From: Rahix <rahix@rahix.de> Date: Wed, 5 Jun 2019 00:02:42 +0200 Subject: [PATCH] WIP: Add basic files Signed-off-by: Rahix <rahix@rahix.de> --- ports/card10/Makefile | 50 +++++++++++++++++++ ports/card10/README.md | 47 ++++++++++++++++++ ports/card10/main.c | 86 ++++++++++++++++++++++++++++++++ ports/card10/mpconfigport.h | 98 +++++++++++++++++++++++++++++++++++++ ports/card10/mphalport.h | 3 ++ ports/card10/uart_core.c | 34 +++++++++++++ 6 files changed, 318 insertions(+) create mode 100644 ports/card10/Makefile create mode 100644 ports/card10/README.md create mode 100644 ports/card10/main.c create mode 100644 ports/card10/mpconfigport.h create mode 100644 ports/card10/mphalport.h create mode 100644 ports/card10/uart_core.c diff --git a/ports/card10/Makefile b/ports/card10/Makefile new file mode 100644 index 000000000..33b364014 --- /dev/null +++ b/ports/card10/Makefile @@ -0,0 +1,50 @@ +include ../../py/mkenv.mk + +# qstr definitions (must come before including py.mk) +# QSTR_DEFS = qstrdefsport.h + +# include py core make definitions +include $(TOP)/py/py.mk + +CROSS_COMPILE = arm-none-eabi- + +INC += -I. +INC += -I$(TOP) +INC += -I$(BUILD) + +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 -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) +LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref --gc-sections + +# Tune for Debugging or Optimization +ifeq ($(DEBUG), 1) +CFLAGS += -O0 -ggdb +else +CFLAGS += -Os -DNDEBUG +CFLAGS += -fdata-sections -ffunction-sections +endif + +LIBS = + +SRC_C = \ + main.c \ + uart_core.c \ + lib/utils/printf.c \ + lib/utils/stdout_helpers.c \ + lib/utils/pyexec.c \ + lib/libc/string0.c \ + lib/mp-readline/readline.c \ + +OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) + +all: $(BUILD)/firmware.elf + +$(BUILD)/firmware.elf: $(OBJ) + $(ECHO) "LINK $@" + $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) + $(Q)$(SIZE) $@ + +# $(BUILD)/firmware.bin: $(BUILD)/firmware.elf +# $(Q)$(OBJCOPY) -O binary -j .isr_vector -j .text -j .data $^ $(BUILD)/firmware.bin + +include $(TOP)/py/mkrules.mk diff --git a/ports/card10/README.md b/ports/card10/README.md new file mode 100644 index 000000000..356fc4b3e --- /dev/null +++ b/ports/card10/README.md @@ -0,0 +1,47 @@ +# The minimal port + +This port is intended to be a minimal MicroPython port that actually runs. +It can run under Linux (or similar) and on any STM32F4xx MCU (eg the pyboard). + +## Building and running Linux version + +By default the port will be built for the host machine: + + $ make + +To run the executable and get a basic working REPL do: + + $ make run + +## Building for an STM32 MCU + +The Makefile has the ability to build for a Cortex-M CPU, and by default +includes some start-up code for an STM32F4xx MCU and also enables a UART +for communication. To build: + + $ make CROSS=1 + +If you previously built the Linux version, you will need to first run +`make clean` to get rid of incompatible object files. + +Building will produce the build/firmware.dfu file which can be programmed +to an MCU using: + + $ make CROSS=1 deploy + +This version of the build will work out-of-the-box on a pyboard (and +anything similar), and will give you a MicroPython REPL on UART1 at 9600 +baud. Pin PA13 will also be driven high, and this turns on the red LED on +the pyboard. + +## Building without the built-in MicroPython compiler + +This minimal port can be built with the built-in MicroPython compiler +disabled. This will reduce the firmware by about 20k on a Thumb2 machine, +and by about 40k on 32-bit x86. Without the compiler the REPL will be +disabled, but pre-compiled scripts can still be executed. + +To test out this feature, change the `MICROPY_ENABLE_COMPILER` config +option to "0" in the mpconfigport.h file in this directory. Then +recompile and run the firmware and it will execute the frozentest.py +file. diff --git a/ports/card10/main.c b/ports/card10/main.c new file mode 100644 index 000000000..38b5c947d --- /dev/null +++ b/ports/card10/main.c @@ -0,0 +1,86 @@ +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#include "py/compile.h" +#include "py/runtime.h" +#include "py/repl.h" +#include "py/gc.h" +#include "py/mperrno.h" +#include "lib/utils/pyexec.h" + +static char *stack_top; + +#if MICROPY_ENABLE_GC +static char heap[2048]; +#endif + +int mp_hal_stdin_rx_chr(void); + +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(); + #if MICROPY_REPL_EVENT_DRIVEN + pyexec_event_repl_init(); + for (;;) { + int c = mp_hal_stdin_rx_chr(); + if (pyexec_event_repl_process_char(c)) { + break; + } + } + #else + // pyexec_friendly_repl(); + #error TODO friendly_repl + #endif + + 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) { + mp_raise_OSError(MP_ENOENT); +} + +mp_import_stat_t mp_import_stat(const char *path) { + return MP_IMPORT_STAT_NO_EXIST; +} + +mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); + +void nlr_jump_fail(void *val) { + while (1); +} + +void NORETURN __fatal_error(const char *msg) { + while (1); +} + +#ifndef NDEBUG +void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { + printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); + __fatal_error("Assertion failed"); +} +#endif + +#if MICROPY_MIN_USE_CORTEX_CPU +// TODO +#endif diff --git a/ports/card10/mpconfigport.h b/ports/card10/mpconfigport.h new file mode 100644 index 000000000..14d3833cc --- /dev/null +++ b/ports/card10/mpconfigport.h @@ -0,0 +1,98 @@ +#include <stdint.h> + +// options to control how MicroPython is built + +// You can disable the built-in MicroPython compiler by setting the following +// config option to 0. If you do this then you won't get a REPL prompt, but you +// will still be able to execute pre-compiled scripts, compiled with mpy-cross. +#define MICROPY_ENABLE_COMPILER (1) + +#define MICROPY_QSTR_BYTES_IN_HASH (1) +#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool +#define MICROPY_ALLOC_PATH_MAX (256) +#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16) +#define MICROPY_EMIT_X64 (0) +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB (0) +#define MICROPY_COMP_MODULE_CONST (0) +#define MICROPY_COMP_CONST (0) +#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0) +#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) +#define MICROPY_MEM_STATS (0) +#define MICROPY_DEBUG_PRINTERS (0) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_GC_ALLOC_THRESHOLD (0) +// TODO What value do we want +#define MICROPY_REPL_EVENT_DRIVEN (1) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_HELPER_LEXER_UNIX (0) +#define MICROPY_ENABLE_SOURCE_LINE (0) +#define MICROPY_ENABLE_DOC_STRING (0) +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) +#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) +#define MICROPY_PY_ASYNC_AWAIT (0) +#define MICROPY_PY_BUILTINS_BYTEARRAY (0) +#define MICROPY_PY_BUILTINS_DICT_FROMKEYS (0) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (0) +#define MICROPY_PY_BUILTINS_ENUMERATE (0) +#define MICROPY_PY_BUILTINS_FILTER (0) +#define MICROPY_PY_BUILTINS_FROZENSET (0) +#define MICROPY_PY_BUILTINS_REVERSED (0) +#define MICROPY_PY_BUILTINS_SET (0) +#define MICROPY_PY_BUILTINS_SLICE (0) +#define MICROPY_PY_BUILTINS_PROPERTY (0) +#define MICROPY_PY_BUILTINS_MIN_MAX (0) +#define MICROPY_PY_BUILTINS_STR_COUNT (0) +#define MICROPY_PY_BUILTINS_STR_OP_MODULO (0) +#define MICROPY_PY___FILE__ (0) +#define MICROPY_PY_GC (0) +#define MICROPY_PY_ARRAY (0) +#define MICROPY_PY_ATTRTUPLE (0) +#define MICROPY_PY_COLLECTIONS (0) +#define MICROPY_PY_MATH (0) +#define MICROPY_PY_CMATH (0) +#define MICROPY_PY_IO (0) +#define MICROPY_PY_STRUCT (0) +#define MICROPY_PY_SYS (0) +#define MICROPY_MODULE_FROZEN_MPY (1) +#define MICROPY_CPYTHON_COMPAT (0) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) + +// type definitions for the specific machine + +#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) + +// 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 long mp_off_t; + +#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) + +// extra built in names to add to the global namespace +#define MICROPY_PORT_BUILTINS \ + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, + +// We need to provide a declaration/definition of alloca() +#include <alloca.h> + +#define MICROPY_HW_BOARD_NAME "minimal" +#define MICROPY_HW_MCU_NAME "unknown-cpu" + +// TODO remove +#ifdef __thumb__ +#define MICROPY_MIN_USE_CORTEX_CPU (1) +#define MICROPY_MIN_USE_STM32_MCU (1) +#endif + +#define MP_STATE_PORT MP_STATE_VM + +#define MICROPY_PORT_ROOT_POINTERS \ + const char *readline_hist[8]; diff --git a/ports/card10/mphalport.h b/ports/card10/mphalport.h new file mode 100644 index 000000000..a02cf83e1 --- /dev/null +++ b/ports/card10/mphalport.h @@ -0,0 +1,3 @@ +// TODO what is this +static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; } +static inline void mp_hal_set_interrupt_char(char c) {} diff --git a/ports/card10/uart_core.c b/ports/card10/uart_core.c new file mode 100644 index 000000000..f985e04b8 --- /dev/null +++ b/ports/card10/uart_core.c @@ -0,0 +1,34 @@ +#include <unistd.h> +#include "py/mpconfig.h" +#include "uart.h" + +/* + * Core UART functions to implement for a port + */ + +mxc_uart_regs_t * ConsoleUart = MXC_UART_GET_UART(CONSOLE_UART); + +const uart_cfg_t uart_cfg = { + .parity = UART_PARITY_DISABLE, + .size = UART_DATA_SIZE_8_BITS, + .stop = UART_STOP_1, + .flow = UART_FLOW_CTRL_DIS, + .pol = UART_FLOW_POL_DIS, + .baud = CONSOLE_BAUD, + .clksel = UART_CLKSEL_SYSTEM +}; + +const sys_cfg_uart_t uart_sys_cfg = { + .map = MAP_A, + .flow = Disable +}; + +// Receive single character +int mp_hal_stdin_rx_chr(void) { + return UART_ReadByte(ConsoleUart); +} + +// Send string of given length +void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { + UART_Write(ConsoleUart, str, len); +} -- GitLab