summaryrefslogtreecommitdiffstatshomepage
path: root/teensy
diff options
context:
space:
mode:
authorDave Hylands <dhylands@gmail.com>2014-06-15 22:33:14 -0700
committerDave Hylands <dhylands@gmail.com>2014-06-15 22:48:05 -0700
commit4f1b7fec9f103c92de40875e9a06b7decc4923f4 (patch)
treed9e0f1b0e7dd290a728c065960500ecf30967997 /teensy
parent2547928148aefcf163953057979e14f46bef1170 (diff)
downloadmicropython-4f1b7fec9f103c92de40875e9a06b7decc4923f4.tar.gz
micropython-4f1b7fec9f103c92de40875e9a06b7decc4923f4.zip
Updated teensy to build.
Refactored some stmhal files which are shared with teensy.
Diffstat (limited to 'teensy')
-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.c137
-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.h88
-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.h108
-rw-r--r--teensy/uart.c524
-rw-r--r--teensy/usart.c38
-rw-r--r--teensy/usb.c9
31 files changed, 2399 insertions, 517 deletions
diff --git a/teensy/Makefile b/teensy/Makefile
index 00f3514724..76cc81ee19 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 $(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..d825f32198 100644
--- a/teensy/led.c
+++ b/teensy/led.c
@@ -1,53 +1,115 @@
#include <stdio.h>
-#include "misc.h"
+#include "Arduino.h"
+
#include "mpconfig.h"
+#include HAL_H
+#include "nlr.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
+#include "runtime.h"
#include "led.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 +122,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..c22382675d 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 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..417335cfcb 100644
--- a/teensy/mpconfigport.h
+++ b/teensy/mpconfigport.h
@@ -2,20 +2,102 @@
// 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 HAL_H "teensy_hal.h"
+#define PIN_DEFS_PORT_H "pin_defs_teensy.h"
+
+#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/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..5f162f1e78
--- /dev/null
+++ b/teensy/teensy_hal.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#include "mpconfig.h"
+
+#include "Arduino.h"
+
+#include 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..3afe01b1c9
--- /dev/null
+++ b/teensy/teensy_hal.h
@@ -0,0 +1,108 @@
+
+#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);
+
diff --git a/teensy/uart.c b/teensy/uart.c
new file mode 100644
index 0000000000..3dd546dd54
--- /dev/null
+++ b/teensy/uart.c
@@ -0,0 +1,524 @@
+/*
+ * 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 HAL_H
+
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.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();
}