summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-03-13 10:17:51 +0000
committerDamien George <damien.p.george@gmail.com>2014-03-13 10:17:51 +0000
commit659c19c67c00b156cb6890f926d5cc012d129f24 (patch)
tree303a4e00c9612951c8ab3cfbe926121724173fd1
parent19438fd30a3184b656221a59062ea32453d0fd16 (diff)
parentf14b92b9e13c9cb9f54a1d740dbea1eeedeccb5b (diff)
downloadmicropython-659c19c67c00b156cb6890f926d5cc012d129f24.tar.gz
micropython-659c19c67c00b156cb6890f926d5cc012d129f24.zip
Merge pull request #342 from dhylands/stmhal-repl
REPL working on UART6 with STMHAL
-rw-r--r--stmhal/Makefile45
-rw-r--r--stmhal/boards/stm32f4xx-prefix.c2
-rw-r--r--stmhal/gccollect.c56
-rw-r--r--stmhal/gccollect.h17
-rw-r--r--stmhal/gchelper.s62
-rw-r--r--stmhal/import.c24
-rw-r--r--stmhal/led.c133
-rw-r--r--stmhal/led.h25
-rw-r--r--stmhal/lexerfatfs.c61
-rw-r--r--stmhal/lexerfatfs.h1
-rw-r--r--stmhal/main.c158
-rw-r--r--stmhal/malloc0.c36
-rw-r--r--stmhal/math.c407
-rw-r--r--stmhal/mpconfigport.h51
-rw-r--r--stmhal/pin.c78
-rw-r--r--stmhal/pin.h117
-rw-r--r--stmhal/printf.c371
-rw-r--r--stmhal/pybmodule.c312
-rw-r--r--stmhal/pybmodule.h1
-rw-r--r--stmhal/pyexec.c347
-rw-r--r--stmhal/pyexec.h5
-rw-r--r--stmhal/qstrdefsport.h57
-rw-r--r--stmhal/stm32f4xx_it.c2
-rw-r--r--stmhal/string0.c137
-rw-r--r--stmhal/system_stm32f4xx.c60
-rw-r--r--stmhal/systick.c54
-rw-r--r--stmhal/systick.h5
-rw-r--r--stmhal/usart.c269
-rw-r--r--stmhal/usart.h25
29 files changed, 2793 insertions, 125 deletions
diff --git a/stmhal/Makefile b/stmhal/Makefile
index 2b5c5ffe28..f53887b746 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -19,6 +19,7 @@ CROSS_COMPILE = arm-none-eabi-
INC = -I.
INC += -I$(PY_SRC)
+INC += -I$(CMSIS_DIR)
INC += -I$(CMSIS_DIR)/inc
INC += -I$(CMSIS_DIR)/devinc
INC += -I$(HAL_DIR)/inc
@@ -54,28 +55,30 @@ LIBS =
SRC_C = \
main.c \
+ string0.c \
system_stm32f4xx.c \
stm32f4xx_it.c \
stm32f4xx_hal_msp.c \
+ systick.c \
+ led.c \
+ pin.c \
+ usart.c \
+ printf.c \
+ math.c \
+ malloc0.c \
+ gccollect.c \
+ pyexec.c \
+ pybmodule.c \
+ import.c \
+ lexerfatfs.c \
-# printf.c \
-# math.c \
-# string0.c \
-# malloc0.c \
-# systick.c \
# pendsv.c \
-# gccollect.c \
-# lexerfatfs.c \
-# import.c \
-# pyexec.c \
-# led.c \
# gpio.c \
# lcd.c \
# servo.c \
# flash.c \
# storage.c \
# accel.c \
-# usart.c \
# usb.c \
# timer.c \
# audio.c \
@@ -84,24 +87,23 @@ SRC_C = \
# adc.c \
# rtc.c \
# file.c \
-# pin.c \
# pin_named_pins.c \
# pin_map.c \
# exti.c \
# usrsw.c \
-# pybmodule.c \
# pybwlan.c \
SRC_S = \
startup_stm32f40xx.s \
-
-# gchelper.s \
+ gchelper.s \
SRC_HAL = $(addprefix $(HAL_DIR)/src/,\
stm32f4xx_hal.c \
stm32f4xx_hal_cortex.c \
- stm32f4xx_hal_rcc.c \
+ stm32f4xx_hal_dma.c \
stm32f4xx_hal_gpio.c \
+ stm32f4xx_hal_rcc.c \
+ stm32f4xx_hal_uart.c \
)
SRC_STMPERIPH = $(addprefix $(STMPERIPH_DIR)/,\
@@ -182,7 +184,7 @@ SRC_CC3K = $(addprefix $(CC3K_DIR)/,\
)
OBJ =
-#OBJ += $(PY_O)
+OBJ += $(PY_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_HAL:.c=.o))
@@ -191,7 +193,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_HAL:.c=.o))
#OBJ += $(addprefix $(BUILD)/, $(SRC_STMUSBH:.c=.o))
#OBJ += $(addprefix $(BUILD)/, $(SRC_FATFS:.c=.o))
#OBJ += $(addprefix $(BUILD)/, $(SRC_CC3K:.c=.o))
-#OBJ += $(BUILD)/pins_$(BOARD).o
+OBJ += $(BUILD)/pins_$(BOARD).o
all: $(BUILD)/flash.dfu
@@ -222,7 +224,12 @@ GEN_PINS_HDR = $(BUILD)/pins.h
# 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): | $(BUILD)/pins.h
+$(OBJ): | $(BUILD)/pins.h
+
+# temp hack
+$(PY_BUILD):
+ mkdir -p $@
+$(OBJ): | $(PY_BUILD) $(PY_BUILD)/qstrdefs.generated.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
diff --git a/stmhal/boards/stm32f4xx-prefix.c b/stmhal/boards/stm32f4xx-prefix.c
index e68de4cf4e..af3ed325cb 100644
--- a/stmhal/boards/stm32f4xx-prefix.c
+++ b/stmhal/boards/stm32f4xx-prefix.c
@@ -2,7 +2,7 @@
#include <stdio.h>
#include <stdint.h>
-#include <stm32f4xx.h>
+#include <stm32f4xx_hal.h>
#include "misc.h"
#include "mpconfig.h"
diff --git a/stmhal/gccollect.c b/stmhal/gccollect.c
new file mode 100644
index 0000000000..e20e92de14
--- /dev/null
+++ b/stmhal/gccollect.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+
+#include <stm32f4xx_hal.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "gc.h"
+#include "gccollect.h"
+
+machine_uint_t gc_helper_get_regs_and_sp(machine_uint_t *regs);
+
+// obsolete
+// void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
+
+void gc_collect(void) {
+ // get current time, in case we want to time the GC
+ uint32_t start = HAL_GetTick();
+
+ // start the GC
+ gc_collect_start();
+
+ // scan everything in RAM before the heap
+ // this includes the data and bss segments
+ // TODO possibly don't need to scan data, since all pointers should start out NULL and be in bss
+ gc_collect_root((void**)&_ram_start, ((uint32_t)&_ebss - (uint32_t)&_ram_start) / sizeof(uint32_t));
+
+ // get the registers and the sp
+ machine_uint_t regs[10];
+ machine_uint_t sp = gc_helper_get_regs_and_sp(regs);
+
+ // trace the stack, including the registers (since they live on the stack in this function)
+ gc_collect_root((void**)sp, ((uint32_t)&_ram_end - sp) / sizeof(uint32_t));
+
+ // end the GC
+ gc_collect_end();
+
+ if (0) {
+ // print GC info
+ uint32_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly
+ gc_info_t info;
+ gc_info(&info);
+ printf("GC@%lu %lums\n", start, ticks);
+ printf(" %lu total\n", info.total);
+ printf(" %lu : %lu\n", info.used, info.free);
+ printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
+ }
+}
+
+static mp_obj_t pyb_gc(void) {
+ gc_collect();
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_gc_obj, pyb_gc);
diff --git a/stmhal/gccollect.h b/stmhal/gccollect.h
new file mode 100644
index 0000000000..9aa0a44413
--- /dev/null
+++ b/stmhal/gccollect.h
@@ -0,0 +1,17 @@
+// variables defining memory layout
+// (these probably belong somewhere else...)
+extern uint32_t _etext;
+extern uint32_t _sidata;
+extern uint32_t _ram_start;
+extern uint32_t _sdata;
+extern uint32_t _edata;
+extern uint32_t _sbss;
+extern uint32_t _ebss;
+extern uint32_t _heap_start;
+extern uint32_t _heap_end;
+extern uint32_t _estack;
+extern uint32_t _ram_end;
+
+void gc_collect(void);
+
+MP_DECLARE_CONST_FUN_OBJ(pyb_gc_obj);
diff --git a/stmhal/gchelper.s b/stmhal/gchelper.s
new file mode 100644
index 0000000000..6baedcdd0e
--- /dev/null
+++ b/stmhal/gchelper.s
@@ -0,0 +1,62 @@
+ .syntax unified
+ .cpu cortex-m4
+ .thumb
+ .text
+ .align 2
+
+@ uint gc_helper_get_regs_and_sp(r0=uint regs[10])
+ .global gc_helper_get_regs_and_sp
+ .thumb
+ .thumb_func
+ .type gc_helper_get_regs_and_sp, %function
+gc_helper_get_regs_and_sp:
+ @ store registers into given array
+ str r4, [r0], #4
+ str r5, [r0], #4
+ str r6, [r0], #4
+ str r7, [r0], #4
+ str r8, [r0], #4
+ str r9, [r0], #4
+ str r10, [r0], #4
+ str r11, [r0], #4
+ str r12, [r0], #4
+ str r13, [r0], #4
+
+ @ return the sp
+ mov r0, sp
+ bx lr
+
+
+@ this next function is now obsolete
+
+ .size gc_helper_get_regs_and_clean_stack, .-gc_helper_get_regs_and_clean_stack
+@ void gc_helper_get_regs_and_clean_stack(r0=uint regs[10], r1=heap_end)
+ .global gc_helper_get_regs_and_clean_stack
+ .thumb
+ .thumb_func
+ .type gc_helper_get_regs_and_clean_stack, %function
+gc_helper_get_regs_and_clean_stack:
+ @ store registers into given array
+ str r4, [r0], #4
+ str r5, [r0], #4
+ str r6, [r0], #4
+ str r7, [r0], #4
+ str r8, [r0], #4
+ str r9, [r0], #4
+ str r10, [r0], #4
+ str r11, [r0], #4
+ str r12, [r0], #4
+ str r13, [r0], #4
+
+ @ clean the stack from given pointer up to current sp
+ movs r0, #0
+ mov r2, sp
+ b.n .entry
+.loop:
+ str r0, [r1], #4
+.entry:
+ cmp r1, r2
+ bcc.n .loop
+ bx lr
+
+ .size gc_helper_get_regs_and_clean_stack, .-gc_helper_get_regs_and_clean_stack
diff --git a/stmhal/import.c b/stmhal/import.c
new file mode 100644
index 0000000000..f2fd3b3dee
--- /dev/null
+++ b/stmhal/import.c
@@ -0,0 +1,24 @@
+#include <stdint.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "lexer.h"
+#if 0
+#include "ff.h"
+#endif
+
+mp_import_stat_t mp_import_stat(const char *path) {
+#if 0
+ FILINFO fno;
+ FRESULT res = f_stat(path, &fno);
+ if (res == FR_OK) {
+ if ((fno.fattrib & AM_DIR) != 0) {
+ return MP_IMPORT_STAT_DIR;
+ } else {
+ return MP_IMPORT_STAT_FILE;
+ }
+ }
+#endif
+ return MP_IMPORT_STAT_NO_EXIST;
+}
diff --git a/stmhal/led.c b/stmhal/led.c
new file mode 100644
index 0000000000..a643ce84fd
--- /dev/null
+++ b/stmhal/led.c
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <stm32f4xx_hal.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "led.h"
+#include "pin.h"
+#include "build/pins.h"
+
+static const pin_obj_t *gLed[] = {
+ &PYB_LED1,
+#if defined(PYB_LED2)
+ &PYB_LED2,
+#if defined(PYB_LED3)
+ &PYB_LED3,
+#if defined(PYB_LED4)
+ &PYB_LED4,
+#endif
+#endif
+#endif
+};
+#define NUM_LEDS (sizeof(gLed) / sizeof(gLed[0]))
+
+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 = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+
+ /* Turn off LEDs and initialize */
+ for (int led = 0; led < NUM_LEDS; led++) {
+ PYB_LED_OFF(gLed[led]);
+ GPIO_InitStructure.Pin = gLed[led]->pin_mask;
+ HAL_GPIO_Init(gLed[led]->gpio, &GPIO_InitStructure);
+ }
+}
+
+void led_state(pyb_led_t led, int state) {
+ if (led < 1 || led > NUM_LEDS) {
+ return;
+ }
+ const pin_obj_t *led_pin = gLed[led - 1];
+ if (state == 0) {
+ // turn LED off
+ PYB_LED_OFF(led_pin);
+ } else {
+ // turn LED on
+ PYB_LED_ON(led_pin);
+ }
+}
+
+void led_toggle(pyb_led_t led) {
+ if (led < 1 || led > NUM_LEDS) {
+ return;
+ }
+ const pin_obj_t *led_pin = gLed[led - 1];
+ 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->ODR & led_pin->pin_mask) {
+ // pin is high, make it low
+ gpio->BSRRH = led_pin->pin_mask;
+ } else {
+ // pin is low, make it high
+ gpio->BSRRL = led_pin->pin_mask;
+ }
+}
+
+#if 0
+/******************************************************************************/
+/* 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;
+ print(env, "<LED %lu>", self->led_id);
+}
+
+mp_obj_t led_obj_on(mp_obj_t self_in) {
+ pyb_led_obj_t *self = self_in;
+ led_state(self->led_id, 1);
+ return mp_const_none;
+}
+
+mp_obj_t led_obj_off(mp_obj_t self_in) {
+ pyb_led_obj_t *self = self_in;
+ led_state(self->led_id, 0);
+ return mp_const_none;
+}
+
+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 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_method_t led_methods[] = {
+ { "on", &led_obj_on_obj },
+ { "off", &led_obj_off_obj },
+ { "toggle", &led_obj_toggle_obj },
+ { NULL, NULL },
+};
+
+static const mp_obj_type_t led_obj_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Led,
+ .print = led_obj_print,
+ .methods = led_methods,
+};
+
+static 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;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(pyb_Led_obj, pyb_Led);
+#endif
diff --git a/stmhal/led.h b/stmhal/led.h
new file mode 100644
index 0000000000..9e9db16ac3
--- /dev/null
+++ b/stmhal/led.h
@@ -0,0 +1,25 @@
+typedef enum {
+ // PYBv3
+ PYB_LED_R1 = 1,
+ PYB_LED_R2 = 2,
+ PYB_LED_G1 = 3,
+ PYB_LED_G2 = 4,
+ // PYBv4
+ PYB_LED_RED = 1,
+ PYB_LED_GREEN = 2,
+ PYB_LED_YELLOW = 3,
+ PYB_LED_BLUE = 4,
+ //STM32F4DISC
+ PYB_LED_R = 1,
+ PYB_LED_G = 2,
+ PYB_LED_B = 3,
+ PYB_LED_O = 4,
+} pyb_led_t;
+
+void led_init(void);
+void led_state(pyb_led_t led, int state);
+void led_toggle(pyb_led_t led);
+
+#if 0
+MP_DECLARE_CONST_FUN_OBJ(pyb_Led_obj);
+#endif
diff --git a/stmhal/lexerfatfs.c b/stmhal/lexerfatfs.c
new file mode 100644
index 0000000000..1910587d8e
--- /dev/null
+++ b/stmhal/lexerfatfs.c
@@ -0,0 +1,61 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#if 0
+#include "ff.h"
+#endif
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "lexer.h"
+#include "lexerfatfs.h"
+
+#if 0
+typedef struct _mp_lexer_file_buf_t {
+ FIL fp;
+ char buf[20];
+ uint16_t len;
+ uint16_t pos;
+} mp_lexer_file_buf_t;
+
+static unichar file_buf_next_char(mp_lexer_file_buf_t *fb) {
+ if (fb->pos >= fb->len) {
+ if (fb->len < sizeof(fb->buf)) {
+ return MP_LEXER_CHAR_EOF;
+ } else {
+ UINT n;
+ f_read(&fb->fp, fb->buf, sizeof(fb->buf), &n);
+ if (n == 0) {
+ return MP_LEXER_CHAR_EOF;
+ }
+ fb->len = n;
+ fb->pos = 0;
+ }
+ }
+ return fb->buf[fb->pos++];
+}
+
+static void file_buf_close(mp_lexer_file_buf_t *fb) {
+ f_close(&fb->fp);
+ m_del_obj(mp_lexer_file_buf_t, fb);
+}
+#endif
+
+mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
+#if 0
+ mp_lexer_file_buf_t *fb = m_new_obj(mp_lexer_file_buf_t);
+ FRESULT res = f_open(&fb->fp, filename, FA_READ);
+ if (res != FR_OK) {
+ m_del_obj(mp_lexer_file_buf_t, fb);
+ return NULL;
+ }
+ UINT n;
+ f_read(&fb->fp, fb->buf, sizeof(fb->buf), &n);
+ fb->len = n;
+ fb->pos = 0;
+ return mp_lexer_new(qstr_from_str(filename), fb, (mp_lexer_stream_next_char_t)file_buf_next_char, (mp_lexer_stream_close_t)file_buf_close);
+#else
+ return NULL;
+#endif
+}
diff --git a/stmhal/lexerfatfs.h b/stmhal/lexerfatfs.h
new file mode 100644
index 0000000000..55902a3006
--- /dev/null
+++ b/stmhal/lexerfatfs.h
@@ -0,0 +1 @@
+mp_lexer_t *mp_lexer_new_from_file(const char *filename);
diff --git a/stmhal/main.c b/stmhal/main.c
index ec913c30c5..97a512cda7 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -15,19 +15,18 @@
#include <stm32f4xx_usart.h>
#include <stm32f4xx_rng.h>
#include <usbd_storage_msd.h>
-#include <stm_misc.h>
#endif
#include "std.h"
-#if 0
#include "misc.h"
-#include "ff.h"
+#include "systick.h"
+#include "led.h"
+#include "usart.h"
#include "mpconfig.h"
#include "qstr.h"
#include "nlr.h"
#include "misc.h"
#include "lexer.h"
-#include "lexerfatfs.h"
#include "parse.h"
#include "obj.h"
#include "parsehelper.h"
@@ -36,10 +35,12 @@
#include "runtime.h"
#include "gc.h"
#include "gccollect.h"
-#include "systick.h"
-#include "pendsv.h"
#include "pyexec.h"
-#include "led.h"
+#include "pybmodule.h"
+#if 0
+#include "ff.h"
+#include "lexerfatfs.h"
+#include "pendsv.h"
#include "servo.h"
#include "lcd.h"
#include "storage.h"
@@ -53,9 +54,11 @@
#include "file.h"
#include "pin.h"
#include "exti.h"
-#include "pybmodule.h"
#endif
+void SystemClock_Config(void);
+
+
int errno;
#if 0
@@ -65,7 +68,6 @@ static FATFS fatfs1;
#endif
#endif
-#if 0
void flash_error(int n) {
for (int i = 0; i < n; i++) {
led_state(PYB_LED_R1, 1);
@@ -87,9 +89,7 @@ void __fatal_error(const char *msg) {
flash_error(1);
}
}
-#endif
-#if 0
STATIC mp_obj_t pyb_config_source_dir = MP_OBJ_NULL;
STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL;
@@ -161,93 +161,6 @@ static mp_obj_t pyb_help(void) {
printf("%s", help_text);
return mp_const_none;
}
-#endif
-
-void led_init(void) {
- /* GPIO structure */
- GPIO_InitTypeDef GPIO_InitStructure;
-
- /* Configure I/O speed, mode, output type and pull */
- GPIO_InitStructure.Pin = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Pull = GPIO_NOPULL;
- GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
- GPIO_InitStructure.Alternate = 0; // unused
-
- /* initialize */
- HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
-}
-
-void led_state(int led_id, int state) {
- HAL_GPIO_WritePin(GPIOA, 1 << (13 + led_id), state);
-}
-
-/**
- * @brief System Clock Configuration
- * The system Clock is configured as follow :
- * System Clock source = PLL (HSE)
- * SYSCLK(Hz) = 168000000
- * HCLK(Hz) = 168000000
- * AHB Prescaler = 1
- * APB1 Prescaler = 4
- * APB2 Prescaler = 2
- * HSE Frequency(Hz) = 8000000
- * PLL_M = 8
- * PLL_N = 336
- * PLL_P = 2
- * PLL_Q = 7
- * VDD(V) = 3.3
- * Main regulator output voltage = Scale1 mode
- * Flash Latency(WS) = 5
- * @param None
- * @retval None
- */
-static void SystemClock_Config(void) {
- RCC_ClkInitTypeDef RCC_ClkInitStruct;
- RCC_OscInitTypeDef RCC_OscInitStruct;
-
- /* Enable Power Control clock */
- __PWR_CLK_ENABLE();
-
- /* The voltage scaling allows optimizing the power consumption when the device is
- clocked below the maximum system frequency, to update the voltage scaling value
- regarding system frequency refer to product datasheet. */
- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
-
- /* Enable HSE Oscillator and activate PLL with HSE as source */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLM = 8;
- RCC_OscInitStruct.PLL.PLLN = 336;
- RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
- RCC_OscInitStruct.PLL.PLLQ = 7;
- if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- /* Initialization Error */
- for (;;) {
- }
- }
-
- /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
- clocks dividers */
- RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
- if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
- {
- /* Initialization Error */
- for (;;) {
- }
- }
-
- // Make SysTick interrupt have the highest priority
- // This is needed so that SysTick runs in all ISRs.
- NVIC_SetPriority(SysTick_IRQn, 0);
-}
int main(void) {
// TODO disable JTAG
@@ -279,15 +192,13 @@ int main(void) {
led_state(1, 0);
led_state(2, 1);
+#if 0
for (;;) {
HAL_Delay(500);
led_state(1, 1);
HAL_Delay(500);
led_state(1, 0);
}
-
-#if 0
- _fatal_error("done");
#endif
#if 0
@@ -329,28 +240,56 @@ int main(void) {
GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_SET);
}
#endif
+#endif
// basic sub-system init
sys_tick_init();
+#if 0
pendsv_init();
+#endif
led_init();
+#if 0
#if MICROPY_HW_ENABLE_RTC
rtc_init();
#endif
+#endif
// turn on LED to indicate bootup
led_state(PYB_LED_G1, 1);
+#if 0
// more sub-system init
#if MICROPY_HW_HAS_SDCARD
sdcard_init();
#endif
storage_init();
+#endif
// uncomment these 2 lines if you want REPL on USART_6 (or another usart) as well as on USB VCP
- //pyb_usart_global_debug = PYB_USART_YA;
- //usart_init(pyb_usart_global_debug, 115200);
+ pyb_usart_global_debug = PYB_USART_YA;
+ usart_init(pyb_usart_global_debug, 115200);
+
+#if 0
+ pyb_led_t led = 1;
+ while (1) {
+ led_state(led, 1);
+ usart_tx_strn_cooked(pyb_usart_global_debug, "on\n", 3);
+ sys_tick_delay_ms(100);
+ led_state(led, 0);
+ usart_tx_strn_cooked(pyb_usart_global_debug, "off\n", 4);
+ sys_tick_delay_ms(100);
+ led_state(led, 1);
+ usart_tx_strn_cooked(pyb_usart_global_debug, "on\n", 3);
+ sys_tick_delay_ms(100);
+ led_state(led, 0);
+ usart_tx_strn_cooked(pyb_usart_global_debug, "off\n", 4);
+ sys_tick_delay_ms(700);
+
+ led = (led % 4) + 1;
+ }
+ __fatal_error("done");
+#endif
int first_soft_reset = true;
@@ -368,6 +307,7 @@ soft_reset:
def_path[2] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib);
sys_path = mp_obj_new_list(3, def_path);
+#if 0
exti_init();
#if MICROPY_HW_HAS_SWITCH
@@ -396,15 +336,19 @@ soft_reset:
#endif
pin_map_init();
+#endif
// add some functions to the builtin Python namespace
rt_store_name(MP_QSTR_help, rt_make_function_n(0, pyb_help));
+#if 0
rt_store_name(MP_QSTR_open, rt_make_function_n(2, pyb_io_open));
+#endif
// we pre-import the pyb module
// probably shouldn't do this, so we are compatible with CPython
rt_store_name(MP_QSTR_pyb, (mp_obj_t)&pyb_module);
+#if 0
// check if user switch held (initiates reset of filesystem)
bool reset_filesystem = false;
#if MICROPY_HW_HAS_SWITCH
@@ -497,16 +441,20 @@ soft_reset:
flash_error(4);
}
+#endif
if (first_soft_reset) {
+#if 0
#if MICROPY_HW_HAS_MMA7660
// MMA accel: init and reset address to zero
accel_init();
#endif
+#endif
}
// turn boot-up LED off
led_state(PYB_LED_G1, 0);
+#if 0
#if MICROPY_HW_HAS_SDCARD
// if an SD card is present then mount it on 1:/
if (sdcard_is_present()) {
@@ -592,15 +540,17 @@ soft_reset:
pyb_wlan_init();
pyb_wlan_start();
#endif
+#endif
pyexec_repl();
+#if 0
printf("PYB: sync filesystems\n");
storage_flush();
+#endif
printf("PYB: soft reboot\n");
first_soft_reset = false;
goto soft_reset;
-#endif
}
diff --git a/stmhal/malloc0.c b/stmhal/malloc0.c
new file mode 100644
index 0000000000..85a643f72d
--- /dev/null
+++ b/stmhal/malloc0.c
@@ -0,0 +1,36 @@
+#include <stdint.h>
+#include "std.h"
+#include "mpconfig.h"
+#include "gc.h"
+
+#if 0
+static uint32_t mem = 0;
+
+void *malloc(size_t n) {
+ if (mem == 0) {
+ extern uint32_t _heap_start;
+ mem = (uint32_t)&_heap_start; // need to use big ram block so we can execute code from it (is it true that we can't execute from CCM?)
+ }
+ void *ptr = (void*)mem;
+ mem = (mem + n + 3) & (~3);
+ if (mem > 0x20000000 + 0x18000) {
+ void __fatal_error(const char*);
+ __fatal_error("out of memory");
+ }
+ return ptr;
+}
+
+void free(void *ptr) {
+}
+
+void *realloc(void *ptr, size_t n) {
+ return malloc(n);
+}
+
+#endif
+
+void __assert_func(void) {
+ printf("\nASSERT FAIL!");
+ for (;;) {
+ }
+}
diff --git a/stmhal/math.c b/stmhal/math.c
new file mode 100644
index 0000000000..8e2c6fc753
--- /dev/null
+++ b/stmhal/math.c
@@ -0,0 +1,407 @@
+#include <stdint.h>
+#include <math.h>
+
+// these 2 functions seem to actually work... no idea why
+// replacing with libgcc does not work (probably due to wrong calling conventions)
+double __aeabi_f2d(float x) {
+ // TODO
+ return 0.0;
+}
+
+float __aeabi_d2f(double x) {
+ // TODO
+ return 0.0;
+}
+
+/*
+double sqrt(double x) {
+ // TODO
+ return 0.0;
+}
+*/
+
+float sqrtf(float x) {
+ asm volatile (
+ "vsqrt.f32 %[r], %[x]\n"
+ : [r] "=t" (x)
+ : [x] "t" (x));
+ return x;
+}
+
+// TODO we need import these functions from some library (eg musl or newlib)
+float powf(float x, float y) { return 0.0; }
+float logf(float x) { return 0.0; }
+float log2f(float x) { return 0.0; }
+float log10f(float x) { return 0.0; }
+float tanhf(float x) { return 0.0; }
+float acoshf(float x) { return 0.0; }
+float asinhf(float x) { return 0.0; }
+float atanhf(float x) { return 0.0; }
+float cosf(float x) { return 0.0; }
+float sinf(float x) { return 0.0; }
+float tanf(float x) { return 0.0; }
+float acosf(float x) { return 0.0; }
+float asinf(float x) { return 0.0; }
+float atanf(float x) { return 0.0; }
+float atan2f(float x, float y) { return 0.0; }
+
+/*****************************************************************************/
+// from musl-0.9.15 libm.h
+
+/* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#define FORCE_EVAL(x) do { \
+ if (sizeof(x) == sizeof(float)) { \
+ volatile float __x; \
+ __x = (x); \
+ (void)__x; \
+ } else if (sizeof(x) == sizeof(double)) { \
+ volatile double __x; \
+ __x = (x); \
+ (void)__x; \
+ } else { \
+ volatile long double __x; \
+ __x = (x); \
+ (void)__x; \
+ } \
+} while(0)
+
+/* Get a 32 bit int from a float. */
+#define GET_FLOAT_WORD(w,d) \
+do { \
+ union {float f; uint32_t i;} __u; \
+ __u.f = (d); \
+ (w) = __u.i; \
+} while (0)
+
+/* Set a float from a 32 bit int. */
+#define SET_FLOAT_WORD(d,w) \
+do { \
+ union {float f; uint32_t i;} __u; \
+ __u.i = (w); \
+ (d) = __u.f; \
+} while (0)
+
+/*****************************************************************************/
+// scalbnf from musl-0.9.15
+
+float scalbnf(float x, int n)
+{
+ union {float f; uint32_t i;} u;
+ float_t y = x;
+
+ if (n > 127) {
+ y *= 0x1p127f;
+ n -= 127;
+ if (n > 127) {
+ y *= 0x1p127f;
+ n -= 127;
+ if (n > 127)
+ n = 127;
+ }
+ } else if (n < -126) {
+ y *= 0x1p-126f;
+ n += 126;
+ if (n < -126) {
+ y *= 0x1p-126f;
+ n += 126;
+ if (n < -126)
+ n = -126;
+ }
+ }
+ u.i = (uint32_t)(0x7f+n)<<23;
+ x = y * u.f;
+ return x;
+}
+
+/*****************************************************************************/
+// expf from musl-0.9.15
+
+/* origin: FreeBSD /usr/src/lib/msun/src/e_expf.c */
+/*
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+static const float
+half[2] = {0.5,-0.5},
+ln2hi = 6.9314575195e-1f, /* 0x3f317200 */
+ln2lo = 1.4286067653e-6f, /* 0x35bfbe8e */
+invln2 = 1.4426950216e+0f, /* 0x3fb8aa3b */
+/*
+ * Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]:
+ * |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74
+ */
+P1 = 1.6666625440e-1f, /* 0xaaaa8f.0p-26 */
+P2 = -2.7667332906e-3f; /* -0xb55215.0p-32 */
+
+float expf(float x)
+{
+ float_t hi, lo, c, xx, y;
+ int k, sign;
+ uint32_t hx;
+
+ GET_FLOAT_WORD(hx, x);
+ sign = hx >> 31; /* sign bit of x */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* special cases */
+ if (hx >= 0x42aeac50) { /* if |x| >= -87.33655f or NaN */
+ if (hx >= 0x42b17218 && !sign) { /* x >= 88.722839f */
+ /* overflow */
+ x *= 0x1p127f;
+ return x;
+ }
+ if (sign) {
+ /* underflow */
+ FORCE_EVAL(-0x1p-149f/x);
+ if (hx >= 0x42cff1b5) /* x <= -103.972084f */
+ return 0;
+ }
+ }
+
+ /* argument reduction */
+ if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */
+ if (hx > 0x3f851592) /* if |x| > 1.5 ln2 */
+ k = invln2*x + half[sign];
+ else
+ k = 1 - sign - sign;
+ hi = x - k*ln2hi; /* k*ln2hi is exact here */
+ lo = k*ln2lo;
+ x = hi - lo;
+ } else if (hx > 0x39000000) { /* |x| > 2**-14 */
+ k = 0;
+ hi = x;
+ lo = 0;
+ } else {
+ /* raise inexact */
+ FORCE_EVAL(0x1p127f + x);
+ return 1 + x;
+ }
+
+ /* x is now in primary range */
+ xx = x*x;
+ c = x - xx*(P1+xx*P2);
+ y = 1 + (x*c/(2-c) - lo + hi);
+ if (k == 0)
+ return y;
+ return scalbnf(y, k);
+}
+
+/*****************************************************************************/
+// expm1f from musl-0.9.15
+
+/* origin: FreeBSD /usr/src/lib/msun/src/s_expm1f.c */
+/*
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+static const float
+o_threshold = 8.8721679688e+01, /* 0x42b17180 */
+ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
+ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
+//invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */
+/*
+ * Domain [-0.34568, 0.34568], range ~[-6.694e-10, 6.696e-10]:
+ * |6 / x * (1 + 2 * (1 / (exp(x) - 1) - 1 / x)) - q(x)| < 2**-30.04
+ * Scaled coefficients: Qn_here = 2**n * Qn_for_q (see s_expm1.c):
+ */
+Q1 = -3.3333212137e-2, /* -0x888868.0p-28 */
+Q2 = 1.5807170421e-3; /* 0xcf3010.0p-33 */
+
+float expm1f(float x)
+{
+ float_t y,hi,lo,c,t,e,hxs,hfx,r1,twopk;
+ union {float f; uint32_t i;} u = {x};
+ uint32_t hx = u.i & 0x7fffffff;
+ int k, sign = u.i >> 31;
+
+ /* filter out huge and non-finite argument */
+ if (hx >= 0x4195b844) { /* if |x|>=27*ln2 */
+ if (hx > 0x7f800000) /* NaN */
+ return x;
+ if (sign)
+ return -1;
+ if (x > o_threshold) {
+ x *= 0x1p127f;
+ return x;
+ }
+ }
+
+ /* argument reduction */
+ if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */
+ if (hx < 0x3F851592) { /* and |x| < 1.5 ln2 */
+ if (!sign) {
+ hi = x - ln2_hi;
+ lo = ln2_lo;
+ k = 1;
+ } else {
+ hi = x + ln2_hi;
+ lo = -ln2_lo;
+ k = -1;
+ }
+ } else {
+ k = invln2*x + (sign ? -0.5f : 0.5f);
+ t = k;
+ hi = x - t*ln2_hi; /* t*ln2_hi is exact here */
+ lo = t*ln2_lo;
+ }
+ x = hi-lo;
+ c = (hi-x)-lo;
+ } else if (hx < 0x33000000) { /* when |x|<2**-25, return x */
+ if (hx < 0x00800000)
+ FORCE_EVAL(x*x);
+ return x;
+ } else
+ k = 0;
+
+ /* x is now in primary range */
+ hfx = 0.5f*x;
+ hxs = x*hfx;
+ r1 = 1.0f+hxs*(Q1+hxs*Q2);
+ t = 3.0f - r1*hfx;
+ e = hxs*((r1-t)/(6.0f - x*t));
+ if (k == 0) /* c is 0 */
+ return x - (x*e-hxs);
+ e = x*(e-c) - c;
+ e -= hxs;
+ /* exp(x) ~ 2^k (x_reduced - e + 1) */
+ if (k == -1)
+ return 0.5f*(x-e) - 0.5f;
+ if (k == 1) {
+ if (x < -0.25f)
+ return -2.0f*(e-(x+0.5f));
+ return 1.0f + 2.0f*(x-e);
+ }
+ u.i = (0x7f+k)<<23; /* 2^k */
+ twopk = u.f;
+ if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */
+ y = x - e + 1.0f;
+ if (k == 128)
+ y = y*2.0f*0x1p127f;
+ else
+ y = y*twopk;
+ return y - 1.0f;
+ }
+ u.i = (0x7f-k)<<23; /* 2^-k */
+ if (k < 23)
+ y = (x-e+(1-u.f))*twopk;
+ else
+ y = (x-(e+u.f)+1)*twopk;
+ return y;
+}
+
+/*****************************************************************************/
+// __expo2f from musl-0.9.15
+
+/* k is such that k*ln2 has minimal relative error and x - kln2 > log(FLT_MIN) */
+static const int k = 235;
+static const float kln2 = 0x1.45c778p+7f;
+
+/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */
+float __expo2f(float x)
+{
+ float scale;
+
+ /* note that k is odd and scale*scale overflows */
+ SET_FLOAT_WORD(scale, (uint32_t)(0x7f + k/2) << 23);
+ /* exp(x - k ln2) * 2**(k-1) */
+ return expf(x - kln2) * scale * scale;
+}
+
+/*****************************************************************************/
+// coshf from musl-0.9.15
+
+float coshf(float x)
+{
+ union {float f; uint32_t i;} u = {.f = x};
+ uint32_t w;
+ float t;
+
+ /* |x| */
+ u.i &= 0x7fffffff;
+ x = u.f;
+ w = u.i;
+
+ /* |x| < log(2) */
+ if (w < 0x3f317217) {
+ if (w < 0x3f800000 - (12<<23)) {
+ FORCE_EVAL(x + 0x1p120f);
+ return 1;
+ }
+ t = expm1f(x);
+ return 1 + t*t/(2*(1+t));
+ }
+
+ /* |x| < log(FLT_MAX) */
+ if (w < 0x42b17217) {
+ t = expf(x);
+ return 0.5f*(t + 1/t);
+ }
+
+ /* |x| > log(FLT_MAX) or nan */
+ t = __expo2f(x);
+ return t;
+}
+
+/*****************************************************************************/
+// sinhf from musl-0.9.15
+
+float sinhf(float x)
+{
+ union {float f; uint32_t i;} u = {.f = x};
+ uint32_t w;
+ float t, h, absx;
+
+ h = 0.5;
+ if (u.i >> 31)
+ h = -h;
+ /* |x| */
+ u.i &= 0x7fffffff;
+ absx = u.f;
+ w = u.i;
+
+ /* |x| < log(FLT_MAX) */
+ if (w < 0x42b17217) {
+ t = expm1f(absx);
+ if (w < 0x3f800000) {
+ if (w < 0x3f800000 - (12<<23))
+ return x;
+ return h*(2*t - t*t/(t+1));
+ }
+ return h*(t + t/(t+1));
+ }
+
+ /* |x| > logf(FLT_MAX) or nan */
+ t = 2*h*__expo2f(absx);
+ return t;
+}
diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h
new file mode 100644
index 0000000000..3f48c43f04
--- /dev/null
+++ b/stmhal/mpconfigport.h
@@ -0,0 +1,51 @@
+#include <stdint.h>
+
+// options to control how Micro Python is built
+
+#define MICROPY_EMIT_THUMB (1)
+#define MICROPY_EMIT_INLINE_THUMB (1)
+#define MICROPY_ENABLE_GC (1)
+#define MICROPY_ENABLE_REPL_HELPERS (1)
+#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
+#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
+#define MICROPY_PATH_MAX (128)
+/* Enable FatFS LFNs
+ 0: Disable LFN feature.
+ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
+ 2: Enable LFN with dynamic working buffer on the STACK.
+ 3: Enable LFN with dynamic working buffer on the HEAP.
+*/
+#define MICROPY_ENABLE_LFN (0)
+#define MICROPY_LFN_CODE_PAGE (1) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
+
+// type definitions for the specific machine
+
+#define BYTES_PER_WORD (4)
+
+#define UINT_FMT "%lu"
+#define INT_FMT "%ld"
+
+typedef int32_t machine_int_t; // must be pointer size
+typedef uint32_t 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
+
+// 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
+
+// board specific definitions
+
+#include "mpconfigboard.h"
+
+#define STM32F40_41xxx
+#define USE_STDPERIPH_DRIVER
+#if !defined(HSE_VALUE)
+#define HSE_VALUE (8000000)
+#endif
+#define USE_DEVICE_MODE
+//#define USE_HOST_MODE
diff --git a/stmhal/pin.c b/stmhal/pin.c
new file mode 100644
index 0000000000..735901c306
--- /dev/null
+++ b/stmhal/pin.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stm32f4xx_hal.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+
+#include "pin.h"
+
+#if 0
+void pin_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ pin_obj_t *self = self_in;
+ print(env, "<Pin %s>", self->name);
+}
+
+mp_obj_t pin_obj_name(mp_obj_t self_in) {
+ pin_obj_t *self = self_in;
+ return MP_OBJ_NEW_QSTR(qstr_from_str(self->name));
+}
+
+mp_obj_t pin_obj_port(mp_obj_t self_in) {
+ pin_obj_t *self = self_in;
+ return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self->port);
+}
+
+mp_obj_t pin_obj_pin(mp_obj_t self_in) {
+ pin_obj_t *self = self_in;
+ return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self->pin);
+}
+
+static MP_DEFINE_CONST_FUN_OBJ_1(pin_obj_name_obj, pin_obj_name);
+static MP_DEFINE_CONST_FUN_OBJ_1(pin_obj_port_obj, pin_obj_port);
+static MP_DEFINE_CONST_FUN_OBJ_1(pin_obj_pin_obj, pin_obj_pin);
+
+static const mp_method_t pin_methods[] = {
+ { "name", &pin_obj_name_obj },
+ { "port", &pin_obj_port_obj },
+ { "pin", &pin_obj_pin_obj },
+ { NULL, NULL },
+};
+#endif
+
+const mp_obj_type_t pin_obj_type = {
+#if 0
+ { &mp_type_type },
+#else
+ { NULL },
+#endif
+ .name = MP_QSTR_Pin,
+#if 0
+ .print = pin_obj_print,
+ .methods = pin_methods,
+#endif
+};
+
+#if 0
+void pin_af_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ pin_af_obj_t *self = self_in;
+ print(env, "<Pin AF %d fn:%d unit:%d typ:%d>", self->idx, self->fn,
+ self->unit, self->type);
+}
+#endif
+
+const mp_obj_type_t pin_af_obj_type = {
+#if 0
+ { &mp_type_type },
+#else
+ { NULL },
+#endif
+ .name = MP_QSTR_PinAF,
+#if 0
+ .print = pin_af_obj_print,
+#endif
+};
+
diff --git a/stmhal/pin.h b/stmhal/pin.h
new file mode 100644
index 0000000000..d5d769058a
--- /dev/null
+++ b/stmhal/pin.h
@@ -0,0 +1,117 @@
+enum {
+ PORT_A,
+ PORT_B,
+ PORT_C,
+ PORT_D,
+ PORT_E,
+ PORT_F,
+ PORT_G,
+ PORT_H,
+ PORT_I,
+ PORT_J,
+};
+
+enum {
+ AF_FN_TIM,
+ AF_FN_I2C,
+ AF_FN_USART,
+ AF_FN_UART = AF_FN_USART,
+ AF_FN_SPI
+};
+
+enum {
+ AF_PIN_TYPE_TIM_CH1 = 0,
+ AF_PIN_TYPE_TIM_CH2,
+ AF_PIN_TYPE_TIM_CH3,
+ AF_PIN_TYPE_TIM_CH4,
+ AF_PIN_TYPE_TIM_CH1N,
+ AF_PIN_TYPE_TIM_CH2N,
+ AF_PIN_TYPE_TIM_CH3N,
+ AF_PIN_TYPE_TIM_CH1_ETR,
+ AF_PIN_TYPE_TIM_ETR,
+ AF_PIN_TYPE_TIM_BKIN,
+
+ AF_PIN_TYPE_I2C_SDA = 0,
+ AF_PIN_TYPE_I2C_SCL,
+
+ AF_PIN_TYPE_USART_TX = 0,
+ AF_PIN_TYPE_USART_RX,
+ AF_PIN_TYPE_USART_CTS,
+ AF_PIN_TYPE_USART_RTS,
+ AF_PIN_TYPE_USART_CK,
+ AF_PIN_TYPE_UART_TX = AF_PIN_TYPE_USART_TX,
+ AF_PIN_TYPE_UART_RX = AF_PIN_TYPE_USART_RX,
+ AF_PIN_TYPE_UART_CTS = AF_PIN_TYPE_USART_CTS,
+ AF_PIN_TYPE_UART_RTS = AF_PIN_TYPE_USART_RTS,
+
+ AF_PIN_TYPE_SPI_MOSI = 0,
+ AF_PIN_TYPE_SPI_MISO,
+ AF_PIN_TYPE_SPI_SCK,
+ AF_PIN_TYPE_SPI_NSS,
+};
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t idx;
+ uint8_t fn;
+ uint8_t unit;
+ uint8_t type;
+
+ union {
+ void *reg;
+ TIM_TypeDef *TIM;
+ I2C_TypeDef *I2C;
+ USART_TypeDef *USART;
+ USART_TypeDef *UART;
+ SPI_TypeDef *SPI;
+ };
+} pin_af_obj_t;
+
+typedef struct {
+ mp_obj_base_t base;
+ const char *name;
+ uint16_t port : 4;
+ uint16_t pin : 4;
+ uint16_t num_af : 4;
+ uint16_t pin_mask;
+ GPIO_TypeDef *gpio;
+ const pin_af_obj_t *af;
+} pin_obj_t;
+
+extern const mp_obj_type_t pin_obj_type;
+extern const mp_obj_type_t pin_af_obj_type;
+
+typedef struct {
+ const char *name;
+ const pin_obj_t *pin;
+} pin_named_pin_t;
+
+extern const pin_named_pin_t pin_board_pins[];
+extern const pin_named_pin_t pin_cpu_pins[];
+
+typedef struct {
+ mp_obj_base_t base;
+ mp_obj_t mapper;
+ mp_obj_t map_dict;
+ bool debug;
+} pin_map_obj_t;
+
+extern pin_map_obj_t pin_map_obj;
+
+typedef struct {
+ mp_obj_base_t base;
+ const char *name;
+ const pin_named_pin_t *named_pins;
+} pin_named_pins_obj_t;
+
+extern const pin_named_pins_obj_t pin_board_pins_obj;
+extern const pin_named_pins_obj_t pin_cpu_pins_obj;
+
+const pin_obj_t *pin_find_named_pin(const pin_named_pin_t *pins, const char *name);
+const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit, uint8_t pin_type);
+
+void pin_map_init(void);
+
+// C function for mapping python pin identifier into an ordinal pin number.
+const pin_obj_t *pin_map_user_obj(mp_obj_t user_obj);
+
diff --git a/stmhal/printf.c b/stmhal/printf.c
new file mode 100644
index 0000000000..acd9816a55
--- /dev/null
+++ b/stmhal/printf.c
@@ -0,0 +1,371 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "std.h"
+#include "misc.h"
+#include "systick.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#if 0
+#include "lcd.h"
+#endif
+#include "usart.h"
+#if 0
+#include "usb.h"
+#endif
+
+#if MICROPY_ENABLE_FLOAT
+#include "formatfloat.h"
+#endif
+
+#define PF_FLAG_LEFT_ADJUST (0x01)
+#define PF_FLAG_SHOW_SIGN (0x02)
+#define PF_FLAG_SPACE_SIGN (0x04)
+#define PF_FLAG_NO_TRAILZ (0x08)
+#define PF_FLAG_ZERO_PAD (0x10)
+
+// tricky; we compute pad string by: pad_chars + (flags & PF_FLAG_ZERO_PAD)
+#define PF_PAD_SIZE PF_FLAG_ZERO_PAD
+static const char *pad_chars = " 0000000000000000";
+
+typedef struct _pfenv_t {
+ void *data;
+ void (*print_strn)(void *, const char *str, unsigned int len);
+} pfenv_t;
+
+static void print_str_dummy(void *data, const char *str, unsigned int len) {
+}
+
+const pfenv_t pfenv_dummy = {0, print_str_dummy};
+
+static int pfenv_print_strn(const pfenv_t *pfenv, const char *str, unsigned int len, int flags, int width) {
+ int pad = width - len;
+ if (pad > 0 && (flags & PF_FLAG_LEFT_ADJUST) == 0) {
+ while (pad > 0) {
+ int p = pad;
+ if (p > PF_PAD_SIZE)
+ p = PF_PAD_SIZE;
+ pfenv->print_strn(pfenv->data, pad_chars + (flags & PF_FLAG_ZERO_PAD), p);
+ pad -= p;
+ }
+ }
+ pfenv->print_strn(pfenv->data, str, len);
+ while (pad > 0) {
+ int p = pad;
+ if (p > PF_PAD_SIZE)
+ p = PF_PAD_SIZE;
+ pfenv->print_strn(pfenv->data, pad_chars, p);
+ pad -= p;
+ }
+ return len;
+}
+
+// enough room for 32 signed number
+#define INT_BUF_SIZE (12)
+
+static int pfenv_print_int(const pfenv_t *pfenv, unsigned int x, int sgn, int base, int base_char, int flags, int width) {
+ char sign = 0;
+ if (sgn) {
+ if ((int)x < 0) {
+ sign = '-';
+ x = -x;
+ } else if (flags & PF_FLAG_SHOW_SIGN) {
+ sign = '+';
+ } else if (flags & PF_FLAG_SPACE_SIGN) {
+ sign = ' ';
+ }
+ }
+
+ char buf[INT_BUF_SIZE];
+ char *b = buf + INT_BUF_SIZE;
+
+ if (x == 0) {
+ *(--b) = '0';
+ } else {
+ do {
+ int c = x % base;
+ x /= base;
+ if (c >= 10) {
+ c += base_char - 10;
+ } else {
+ c += '0';
+ }
+ *(--b) = c;
+ } while (b > buf && x != 0);
+ }
+
+ if (b > buf && sign != 0) {
+ *(--b) = sign;
+ }
+
+ return pfenv_print_strn(pfenv, b, buf + INT_BUF_SIZE - b, flags, width);
+}
+
+void pfenv_prints(const pfenv_t *pfenv, const char *str) {
+ pfenv->print_strn(pfenv->data, str, strlen(str));
+}
+
+int pfenv_printf(const pfenv_t *pfenv, const char *fmt, va_list args) {
+ int chrs = 0;
+ for (;;) {
+ {
+ const char *f = fmt;
+ while (*f != '\0' && *f != '%') {
+ ++f; // XXX UTF8 advance char
+ }
+ if (f > fmt) {
+ pfenv->print_strn(pfenv->data, fmt, f - fmt);
+ chrs += f - fmt;
+ fmt = f;
+ }
+ }
+
+ if (*fmt == '\0') {
+ break;
+ }
+
+ // move past % character
+ ++fmt;
+
+ // parse flags, if they exist
+ int flags = 0;
+ while (*fmt != '\0') {
+ if (*fmt == '-') flags |= PF_FLAG_LEFT_ADJUST;
+ else if (*fmt == '+') flags |= PF_FLAG_SHOW_SIGN;
+ else if (*fmt == ' ') flags |= PF_FLAG_SPACE_SIGN;
+ else if (*fmt == '!') flags |= PF_FLAG_NO_TRAILZ;
+ else if (*fmt == '0') flags |= PF_FLAG_ZERO_PAD;
+ else break;
+ ++fmt;
+ }
+
+ // parse width, if it exists
+ int width = 0;
+ for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
+ width = width * 10 + *fmt - '0';
+ }
+
+ // parse precision, if it exists
+ int prec = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (*fmt == '*') {
+ ++fmt;
+ prec = va_arg(args, int);
+ } else {
+ prec = 0;
+ for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
+ prec = prec * 10 + *fmt - '0';
+ }
+ }
+ if (prec < 0) {
+ prec = 0;
+ }
+ }
+
+ // parse long specifiers (current not used)
+ //bool long_arg = false;
+ if (*fmt == 'l') {
+ ++fmt;
+ //long_arg = true;
+ }
+
+ if (*fmt == '\0') {
+ break;
+ }
+
+ switch (*fmt) {
+ case 'b':
+ if (va_arg(args, int)) {
+ chrs += pfenv_print_strn(pfenv, "true", 4, flags, width);
+ } else {
+ chrs += pfenv_print_strn(pfenv, "false", 5, flags, width);
+ }
+ break;
+ case 'c':
+ {
+ char str = va_arg(args, int);
+ chrs += pfenv_print_strn(pfenv, &str, 1, flags, width);
+ break;
+ }
+ case 's':
+ {
+ const char *str = va_arg(args, const char*);
+ if (str) {
+ if (prec < 0) {
+ prec = strlen(str);
+ }
+ chrs += pfenv_print_strn(pfenv, str, prec, flags, width);
+ } else {
+ chrs += pfenv_print_strn(pfenv, "(null)", 6, flags, width);
+ }
+ break;
+ }
+ case 'u':
+ chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 10, 'a', flags, width);
+ break;
+ case 'd':
+ chrs += pfenv_print_int(pfenv, va_arg(args, int), 1, 10, 'a', flags, width);
+ break;
+ case 'x':
+ case 'p': // ?
+ chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'a', flags, width);
+ break;
+ case 'X':
+ case 'P': // ?
+ chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'A', flags, width);
+ break;
+#if MICROPY_ENABLE_FLOAT
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ {
+ char buf[32];
+ char sign = '\0';
+
+ if (flags & PF_FLAG_SHOW_SIGN) {
+ sign = '+';
+ }
+ else
+ if (flags & PF_FLAG_SPACE_SIGN) {
+ sign = ' ';
+ }
+ float f = va_arg(args, double);
+ int len = format_float(f, buf, sizeof(buf), *fmt, prec, sign);
+ char *s = buf;
+
+ // buf[0] < '0' returns true if the first character is space, + or -
+ // buf[1] < '9' matches a digit, and doesn't match when we get back +nan or +inf
+ if (buf[0] < '0' && buf[1] <= '9' && (flags & PF_FLAG_ZERO_PAD)) {
+ chrs += pfenv_print_strn(pfenv, &buf[0], 1, 0, 1);
+ s++;
+ width--;
+ len--;
+ }
+ if (*s < '0' || *s >= '9') {
+ // For inf or nan, we don't want to zero pad.
+ flags &= ~PF_FLAG_ZERO_PAD;
+ }
+ chrs += pfenv_print_strn(pfenv, s, len, flags, width);
+ break;
+ }
+#endif
+ default:
+ pfenv->print_strn(pfenv->data, fmt, 1);
+ chrs += 1;
+ break;
+ }
+ ++fmt;
+ }
+ return chrs;
+}
+
+void stdout_print_strn(void *data, const char *str, unsigned int len) {
+ // send stdout to USART, USB CDC VCP, and LCD if nothing else
+ bool any = false;
+
+ if (pyb_usart_global_debug != PYB_USART_NONE) {
+ usart_tx_strn_cooked(pyb_usart_global_debug, str, len);
+ any = true;
+ }
+#if 0
+ if (usb_vcp_is_enabled()) {
+ usb_vcp_send_strn_cooked(str, len);
+ any = true;
+ }
+#endif
+ if (!any) {
+#if 0
+#if MICROPY_HW_HAS_LCD
+ lcd_print_strn(str, len);
+#endif
+#endif
+ }
+}
+
+static const pfenv_t pfenv_stdout = {0, stdout_print_strn};
+
+int printf(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ int ret = pfenv_printf(&pfenv_stdout, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+int vprintf(const char *fmt, va_list ap) {
+ return pfenv_printf(&pfenv_stdout, fmt, ap);
+}
+
+#if MICROPY_DEBUG_PRINTERS
+int DEBUG_printf(const char *fmt, ...) {
+ (void)stream;
+ va_list ap;
+ va_start(ap, fmt);
+ int ret = pfenv_printf(&pfenv_stdout, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+#endif
+
+// need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a')
+int putchar(int c) {
+ char chr = c;
+ stdout_print_strn(0, &chr, 1);
+ return chr;
+}
+
+// need this because gcc optimises printf("string\n") -> puts("string")
+int puts(const char *s) {
+ stdout_print_strn(0, s, strlen(s));
+ char chr = '\n';
+ stdout_print_strn(0, &chr, 1);
+ return 1;
+}
+
+typedef struct _strn_pfenv_t {
+ char *cur;
+ size_t remain;
+} strn_pfenv_t;
+
+void strn_print_strn(void *data, const char *str, unsigned int len) {
+ strn_pfenv_t *strn_pfenv = data;
+ if (len > strn_pfenv->remain) {
+ len = strn_pfenv->remain;
+ }
+ memcpy(strn_pfenv->cur, str, len);
+ strn_pfenv->cur += len;
+ strn_pfenv->remain -= len;
+}
+
+int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) {
+ strn_pfenv_t strn_pfenv;
+ strn_pfenv.cur = str;
+ strn_pfenv.remain = size;
+ pfenv_t pfenv;
+ pfenv.data = &strn_pfenv;
+ pfenv.print_strn = strn_print_strn;
+ int len = pfenv_printf(&pfenv, fmt, ap);
+ // add terminating null byte
+ if (size > 0) {
+ if (strn_pfenv.remain == 0) {
+ strn_pfenv.cur[-1] = 0;
+ } else {
+ strn_pfenv.cur[0] = 0;
+ }
+ }
+ return len;
+}
+
+int snprintf(char *str, size_t size, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ int ret = vsnprintf(str, size, fmt, ap);
+ va_end(ap);
+ return ret;
+}
diff --git a/stmhal/pybmodule.c b/stmhal/pybmodule.c
new file mode 100644
index 0000000000..f0a7ebb6dc
--- /dev/null
+++ b/stmhal/pybmodule.c
@@ -0,0 +1,312 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#include <stm32f4xx_hal.h>
+
+#include "misc.h"
+#if 0
+#include "ff.h"
+#endif
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "map.h"
+#include "gc.h"
+#include "gccollect.h"
+#include "systick.h"
+#include "pyexec.h"
+#if 0
+#include "rtc.h"
+#include "servo.h"
+#include "storage.h"
+#include "usb.h"
+#include "usrsw.h"
+#include "sdcard.h"
+#include "accel.h"
+#include "led.h"
+#include "i2c.h"
+#include "usart.h"
+#include "adc.h"
+#include "audio.h"
+#include "pin.h"
+#include "gpio.h"
+#include "exti.h"
+#endif
+#include "pybmodule.h"
+
+// get lots of info about the board
+STATIC mp_obj_t pyb_info(void) {
+ // get and print unique id; 96 bits
+ {
+ byte *id = (byte*)0x1fff7a10;
+ 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
+ // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
+ {
+ printf("S=%lu\nH=%lu\nP1=%lu\nP2=%lu\n",
+ HAL_RCC_GetSysClockFreq(),
+ HAL_RCC_GetHCLKFreq(),
+ HAL_RCC_GetPCLK1Freq(),
+ HAL_RCC_GetPCLK2Freq());
+ }
+
+ // 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(" %lu total\n", info.total);
+ printf(" %lu : %lu\n", info.used, info.free);
+ printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
+ }
+
+#if 0
+ // free space on flash
+ {
+ DWORD nclst;
+ FATFS *fatfs;
+ f_getfree("0:", &nclst, &fatfs);
+ printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512));
+ }
+#endif
+
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_info_obj, pyb_info);
+
+// sync all file systems
+STATIC mp_obj_t pyb_sync(void) {
+#if 0
+ storage_flush();
+#endif
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_sync_obj, pyb_sync);
+
+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);
+
+STATIC mp_obj_t pyb_delay(mp_obj_t count) {
+ sys_tick_delay_ms(mp_obj_get_int(count));
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_delay_obj, pyb_delay);
+
+STATIC mp_obj_t pyb_udelay(mp_obj_t usec) {
+ uint32_t count = 0;
+ const uint32_t utime = (168 * mp_obj_get_int(usec) / 5);
+ for (;;) {
+ if (++count > utime) {
+ return mp_const_none;
+ }
+ }
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay);
+
+STATIC mp_obj_t pyb_rng_get(void) {
+#if 0
+ return mp_obj_new_int(RNG_GetRandomNumber() >> 16);
+#else
+ return mp_obj_new_int(0);
+#endif
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_rng_get_obj, pyb_rng_get);
+
+#if 0
+STATIC void SYSCLKConfig_STOP(void) {
+ /* After wake-up from STOP reconfigure the system clock */
+ /* Enable HSE */
+ RCC_HSEConfig(RCC_HSE_ON);
+
+ /* Wait till HSE is ready */
+ while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET) {
+ }
+
+ /* Enable PLL */
+ RCC_PLLCmd(ENABLE);
+
+ /* Wait till PLL is ready */
+ while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
+ }
+
+ /* Select PLL as system clock source */
+ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
+
+ /* Wait till PLL is used as system clock source */
+ while (RCC_GetSYSCLKSource() != 0x08) {
+ }
+}
+#endif
+
+STATIC mp_obj_t pyb_stop(void) {
+#if 0
+ PWR_EnterSTANDBYMode();
+ //PWR_FlashPowerDownCmd(ENABLE); don't know what the logic is with this
+
+ /* Enter Stop Mode */
+ PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
+
+ /* Configures system clock after wake-up from STOP: enable HSE, PLL and select
+ * PLL as system clock source (HSE and PLL are disabled in STOP mode) */
+ SYSCLKConfig_STOP();
+
+ //PWR_FlashPowerDownCmd(DISABLE);
+#endif
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_stop_obj, pyb_stop);
+
+STATIC mp_obj_t pyb_standby(void) {
+#if 0
+ PWR_EnterSTANDBYMode();
+#endif
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_standby_obj, pyb_standby);
+
+STATIC mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
+#if 0
+ mp_obj_t *items = mp_obj_get_array_fixed_n(arg, 4);
+ 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;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj, pyb_hid_send_report);
+
+#if 0
+MP_DEFINE_CONST_FUN_OBJ_2(pyb_I2C_obj, pyb_I2C); // TODO put this in i2c.c
+#endif
+
+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
+
+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_info), (mp_obj_t)&pyb_info_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_gc), (mp_obj_t)&pyb_gc_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_repl_info), (mp_obj_t)&pyb_set_repl_info_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_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 },
+
+#if MICROPY_HW_ENABLE_RNG
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rand), (mp_obj_t)&pyb_rng_get_obj },
+#endif
+
+#if 0
+#if MICROPY_HW_ENABLE_RTC
+ { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&pyb_rtc_read_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rtc_info), (mp_obj_t)&pyb_rtc_info_obj },
+#endif
+
+#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_obj },
+#endif
+
+#if MICROPY_HW_HAS_SWITCH
+ { MP_OBJ_NEW_QSTR(MP_QSTR_switch), (mp_obj_t)&pyb_switch_obj },
+#endif
+
+#if MICROPY_HW_HAS_SDCARD
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sdcard_obj },
+#endif
+
+#if MICROPY_HW_HAS_MMA7660
+ { MP_OBJ_NEW_QSTR(MP_QSTR_accel), (mp_obj_t)&pyb_accel_read_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_accel_read), (mp_obj_t)&pyb_accel_read_all_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_accel_mode), (mp_obj_t)&pyb_accel_write_mode_obj },
+#endif
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Led), (mp_obj_t)&pyb_Led_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_I2C_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Usart), (mp_obj_t)&pyb_Usart_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ADC_all), (mp_obj_t)&pyb_ADC_all_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_ADC_obj },
+
+#if MICROPY_HW_ENABLE_AUDIO
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Audio), (mp_obj_t)&pyb_Audio_obj },
+#endif
+
+ // pin mapper
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_map_obj },
+
+ // GPIO bindings
+ { MP_OBJ_NEW_QSTR(MP_QSTR_gpio), (mp_obj_t)&pyb_gpio_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_gpio_in), (mp_obj_t)&pyb_gpio_input_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_gpio_out), (mp_obj_t)&pyb_gpio_output_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_NONE), MP_OBJ_NEW_SMALL_INT(GPIO_PuPd_NOPULL) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PuPd_UP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PuPd_DOWN) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PUSH_PULL), MP_OBJ_NEW_SMALL_INT(GPIO_OType_PP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_OType_OD) },
+
+ // EXTI bindings
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Exti), (mp_obj_t)&exti_obj_type },
+#endif
+};
+
+STATIC const mp_map_t pyb_module_globals = {
+ .all_keys_are_qstrs = 1,
+ .table_is_fixed_array = 1,
+ .used = sizeof(pyb_module_globals_table) / sizeof(mp_map_elem_t),
+ .alloc = sizeof(pyb_module_globals_table) / sizeof(mp_map_elem_t),
+ .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_map_t*)&pyb_module_globals,
+};
diff --git a/stmhal/pybmodule.h b/stmhal/pybmodule.h
new file mode 100644
index 0000000000..955aaefe3f
--- /dev/null
+++ b/stmhal/pybmodule.h
@@ -0,0 +1 @@
+extern const mp_obj_module_t pyb_module;
diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c
new file mode 100644
index 0000000000..2eca892a90
--- /dev/null
+++ b/stmhal/pyexec.c
@@ -0,0 +1,347 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <stm32f4xx_hal.h>
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "misc.h"
+#include "lexer.h"
+#include "parse.h"
+#include "obj.h"
+#include "parsehelper.h"
+#include "compile.h"
+#include "runtime.h"
+#include "repl.h"
+#include "gc.h"
+#include "gccollect.h"
+#include "systick.h"
+#include "pyexec.h"
+#if 0
+#include "storage.h"
+#include "usb.h"
+#endif
+#include "usart.h"
+
+static bool repl_display_debugging_info = 0;
+
+void stdout_tx_str(const char *str) {
+ if (pyb_usart_global_debug != PYB_USART_NONE) {
+ usart_tx_str(pyb_usart_global_debug, str);
+ }
+#if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD
+ lcd_print_str(str);
+#endif
+#if 0
+ usb_vcp_send_str(str);
+#endif
+}
+
+int stdin_rx_chr(void) {
+ for (;;) {
+#if 0
+#ifdef USE_HOST_MODE
+ pyb_usb_host_process();
+ int c = pyb_usb_host_get_keyboard();
+ if (c != 0) {
+ return c;
+ }
+#endif
+#endif
+#if 0
+ if (usb_vcp_rx_any() != 0) {
+ return usb_vcp_rx_get();
+ } else
+#endif
+ if (pyb_usart_global_debug != PYB_USART_NONE && usart_rx_any(pyb_usart_global_debug)) {
+ return usart_rx_char(pyb_usart_global_debug);
+ }
+ sys_tick_delay_ms(1);
+#if 0
+ if (storage_needs_flush()) {
+ storage_flush();
+ }
+#endif
+ }
+}
+
+char *str_dup(const char *str) {
+ uint32_t len = strlen(str);
+ char *s2 = m_new(char, len + 1);
+ memcpy(s2, str, len);
+ 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};
+
+#if 0
+#else
+#define VCP_CHAR_CTRL_A (1)
+#define VCP_CHAR_CTRL_C (3)
+#define VCP_CHAR_CTRL_D (4)
+#endif
+
+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 (;;) {
+ int c = stdin_rx_chr();
+ if (escape == 0) {
+ if (VCP_CHAR_CTRL_A <= c && c <= VCP_CHAR_CTRL_D && vstr_len(line) == len) {
+ return c;
+ } 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] = str_dup(vstr_str(line));
+ return 0;
+ } 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;
+ }
+ sys_tick_delay_ms(1);
+ }
+}
+
+// parses, compiles and executes the code in the lexer
+// frees the lexer before returning
+bool parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
+ mp_parse_error_kind_t parse_error_kind;
+ mp_parse_node_t pn = mp_parse(lex, input_kind, &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, is_repl);
+ mp_parse_node_free(pn);
+
+ if (module_fun == mp_const_none) {
+ return false;
+ }
+
+ nlr_buf_t nlr;
+ bool ret;
+ uint32_t start = HAL_GetTick();
+ if (nlr_push(&nlr) == 0) {
+#if 0
+ usb_vcp_set_interrupt_char(VCP_CHAR_CTRL_C); // allow ctrl-C to interrupt us
+#endif
+ rt_call_function_0(module_fun);
+#if 0
+ usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
+#endif
+ nlr_pop();
+ ret = true;
+ } else {
+ // uncaught exception
+ // FIXME it could be that an interrupt happens just before we disable it here
+#if 0
+ usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
+#endif
+ mp_obj_print_exception((mp_obj_t)nlr.ret_val);
+ ret = false;
+ }
+
+ // display debugging info if wanted
+ if (is_repl && repl_display_debugging_info) {
+ uint32_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly
+ printf("took %lu ms\n", ticks);
+ gc_collect();
+ // 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(" %lu total\n", info.total);
+ printf(" %lu : %lu\n", info.used, info.free);
+ printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
+ }
+ }
+
+ return ret;
+}
+
+void pyexec_raw_repl(void) {
+ vstr_t line;
+ vstr_init(&line, 32);
+
+raw_repl_reset:
+ stdout_tx_str("raw REPL; CTRL-C to exit\r\n");
+
+ for (;;) {
+ vstr_reset(&line);
+ stdout_tx_str(">");
+ for (;;) {
+ char c = stdin_rx_chr();
+ if (c == VCP_CHAR_CTRL_A) {
+ goto raw_repl_reset;
+ } else if (c == VCP_CHAR_CTRL_C) {
+ vstr_reset(&line);
+ break;
+ } else if (c == VCP_CHAR_CTRL_D) {
+ break;
+ } else if (c == '\r') {
+ vstr_add_char(&line, '\n');
+ } else if (32 <= c && c <= 126) {
+ vstr_add_char(&line, c);
+ }
+ }
+
+ stdout_tx_str("OK");
+
+ if (vstr_len(&line) == 0) {
+ // finished
+ break;
+ }
+
+ mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0);
+ parse_compile_execute(lex, MP_PARSE_FILE_INPUT, false);
+
+ stdout_tx_str("\004");
+ }
+
+ vstr_clear(&line);
+ stdout_tx_str("\r\n");
+}
+
+void pyexec_repl(void) {
+#if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD
+ // in host mode, we enable the LCD for the repl
+ mp_obj_t lcd_o = rt_call_function_0(rt_load_name(qstr_from_str("LCD")));
+ rt_call_function_1(rt_load_attr(lcd_o, qstr_from_str("light")), mp_const_true);
+#endif
+
+ stdout_tx_str("Micro Python build <git hash> on 25/1/2014; " MICROPY_HW_BOARD_NAME " with STM32F405RG\r\n");
+ stdout_tx_str("Type \"help()\" for more information.\r\n");
+
+ // to test ctrl-C
+ /*
+ {
+ uint32_t x[4] = {0x424242, 0xdeaddead, 0x242424, 0xdeadbeef};
+ for (;;) {
+ nlr_buf_t nlr;
+ printf("pyexec_repl: %p\n", x);
+ usb_vcp_set_interrupt_char(VCP_CHAR_CTRL_C);
+ if (nlr_push(&nlr) == 0) {
+ for (;;) {
+ }
+ } else {
+ printf("break\n");
+ }
+ }
+ }
+ */
+
+ vstr_t line;
+ vstr_init(&line, 32);
+
+ for (;;) {
+ vstr_reset(&line);
+ int ret = readline(&line, ">>> ");
+
+ if (ret == VCP_CHAR_CTRL_A) {
+ pyexec_raw_repl();
+ continue;
+ } else if (ret == VCP_CHAR_CTRL_C) {
+ stdout_tx_str("\r\n");
+ continue;
+ } else if (ret == VCP_CHAR_CTRL_D) {
+ // EOF
+ break;
+ } else if (vstr_len(&line) == 0) {
+ continue;
+ }
+
+ if (mp_repl_is_compound_stmt(vstr_str(&line))) {
+ for (;;) {
+ vstr_add_char(&line, '\n');
+ int len = vstr_len(&line);
+ int ret = readline(&line, "... ");
+ if (ret == VCP_CHAR_CTRL_D || vstr_len(&line) == len) {
+ // done 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);
+ parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, true);
+ }
+
+ stdout_tx_str("\r\n");
+}
+
+bool pyexec_file(const char *filename) {
+ mp_lexer_t *lex = mp_lexer_new_from_file(filename);
+
+ if (lex == NULL) {
+ printf("could not open file '%s' for reading\n", filename);
+ return false;
+ }
+
+ return parse_compile_execute(lex, MP_PARSE_FILE_INPUT, false);
+}
+
+mp_obj_t pyb_set_repl_info(mp_obj_t o_value) {
+ repl_display_debugging_info = mp_obj_get_int(o_value);
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(pyb_set_repl_info_obj, pyb_set_repl_info);
diff --git a/stmhal/pyexec.h b/stmhal/pyexec.h
new file mode 100644
index 0000000000..cad15af6fe
--- /dev/null
+++ b/stmhal/pyexec.h
@@ -0,0 +1,5 @@
+void pyexec_raw_repl(void);
+void pyexec_repl(void);
+bool pyexec_file(const char *filename);
+
+MP_DECLARE_CONST_FUN_OBJ(pyb_set_repl_info_obj);
diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h
new file mode 100644
index 0000000000..13532892a7
--- /dev/null
+++ b/stmhal/qstrdefsport.h
@@ -0,0 +1,57 @@
+// qstrs specific to this port
+
+Q(help)
+Q(pyb)
+Q(info)
+Q(sd_test)
+Q(stop)
+Q(standby)
+Q(source_dir)
+Q(main)
+Q(sync)
+Q(gc)
+Q(repl_info)
+Q(delay)
+Q(udelay)
+Q(switch)
+Q(SW)
+Q(servo)
+Q(pwm)
+Q(accel)
+Q(accel_read)
+Q(accel_mode)
+Q(hid)
+Q(time)
+Q(rand)
+Q(Led)
+Q(LCD)
+Q(Servo)
+Q(SD)
+Q(SDcard)
+Q(I2C)
+Q(gpio)
+Q(gpio_in)
+Q(gpio_out)
+Q(Usart)
+Q(ADC)
+Q(ADC_all)
+Q(Audio)
+Q(open)
+Q(File)
+// Entries for sys.path
+Q(0:/)
+Q(0:/src)
+Q(0:/lib)
+Q(Pin)
+Q(PinMap)
+Q(PinAF)
+Q(PinNamed)
+Q(Exti)
+Q(ExtiMeta)
+Q(rtc_info)
+Q(millis)
+Q(PULL_NONE)
+Q(PULL_UP)
+Q(PULL_DOWN)
+Q(PUSH_PULL)
+Q(OPEN_DRAIN)
diff --git a/stmhal/stm32f4xx_it.c b/stmhal/stm32f4xx_it.c
index 96b12bfe4a..61c4b7172e 100644
--- a/stmhal/stm32f4xx_it.c
+++ b/stmhal/stm32f4xx_it.c
@@ -151,6 +151,7 @@ void PendSV_Handler(void)
{
}
+#if 0 // defined in systick.c
/**
* @brief This function handles SysTick Handler.
* @param None
@@ -160,6 +161,7 @@ void SysTick_Handler(void)
{
HAL_IncTick();
}
+#endif
/******************************************************************************/
/* STM32F4xx Peripherals Interrupt Handlers */
diff --git a/stmhal/string0.c b/stmhal/string0.c
new file mode 100644
index 0000000000..61350bd972
--- /dev/null
+++ b/stmhal/string0.c
@@ -0,0 +1,137 @@
+#include <stdint.h>
+#include "std.h"
+
+void *memcpy(void *dest, const void *src, size_t n) {
+ // TODO align and copy 32 bits at a time
+ uint8_t *d = dest;
+ const uint8_t *s = src;
+ for (; n > 0; n--) {
+ *d++ = *s++;
+ }
+ return dest;
+}
+
+void *memmove(void *dest, const void *src, size_t n) {
+ if (src < dest && dest < src + n) {
+ // need to copy backwards
+ uint8_t *d = dest + n - 1;
+ const uint8_t *s = src + n - 1;
+ for (; n > 0; n--) {
+ *d-- = *s--;
+ }
+ return dest;
+ } else {
+ // can use normal memcpy
+ return memcpy(dest, src, n);
+ }
+}
+
+void *memset(void *s, int c, size_t n) {
+ uint8_t *s2 = s;
+ for (; n > 0; n--) {
+ *s2++ = c;
+ }
+ return s;
+}
+
+int memcmp(const char *s1, const char *s2, size_t n) {
+ while (n--) {
+ char c1 = *s1++;
+ char c2 = *s2++;
+ if (c1 < c2) return -1;
+ else if (c1 > c2) return 1;
+ }
+ return 0;
+}
+
+size_t strlen(const char *str) {
+ int len = 0;
+ for (const char *s = str; *s; s++) {
+ len += 1;
+ }
+ return len;
+}
+
+int strcmp(const char *s1, const char *s2) {
+ while (*s1 && *s2) {
+ char c1 = *s1++; // XXX UTF8 get char, next char
+ char c2 = *s2++; // XXX UTF8 get char, next char
+ if (c1 < c2) return -1;
+ else if (c1 > c2) return 1;
+ }
+ if (*s2) return -1;
+ else if (*s1) return 1;
+ else return 0;
+}
+
+int strncmp(const char *s1, const char *s2, size_t n) {
+ while (*s1 && *s2 && n > 0) {
+ char c1 = *s1++; // XXX UTF8 get char, next char
+ char c2 = *s2++; // XXX UTF8 get char, next char
+ n--;
+ if (c1 < c2) return -1;
+ else if (c1 > c2) return 1;
+ }
+ if (n == 0) return 0;
+ else if (*s2) return -1;
+ else if (*s1) return 1;
+ else return 0;
+}
+
+char *strcpy(char *dest, const char *src) {
+ char *d = dest;
+ while (*src) {
+ *d++ = *src++;
+ }
+ *d = '\0';
+ return dest;
+}
+
+// needed because gcc optimises strcpy + strcat to this
+char *stpcpy(char *dest, const char *src) {
+ while (*src) {
+ *dest++ = *src++;
+ }
+ *dest = '\0';
+ return dest;
+}
+
+char *strcat(char *dest, const char *src) {
+ char *d = dest;
+ while (*d) {
+ d++;
+ }
+ while (*src) {
+ *d++ = *src++;
+ }
+ *d = '\0';
+ return dest;
+}
+
+// Public Domain implementation of strchr from:
+// http://en.wikibooks.org/wiki/C_Programming/Strings#The_strchr_function
+char *strchr(const char *s, int c)
+{
+ /* Scan s for the character. When this loop is finished,
+ s will either point to the end of the string or the
+ character we were looking for. */
+ while (*s != '\0' && *s != (char)c)
+ s++;
+ return ((*s == c) ? (char *) s : 0);
+}
+
+
+// Public Domain implementation of strstr from:
+// http://en.wikibooks.org/wiki/C_Programming/Strings#The_strstr_function
+char *strstr(const char *haystack, const char *needle)
+{
+ size_t needlelen;
+ /* Check for the null needle case. */
+ if (*needle == '\0')
+ return (char *) haystack;
+ needlelen = strlen(needle);
+ for (; (haystack = strchr(haystack, *needle)) != 0; haystack++)
+ if (strncmp(haystack, needle, needlelen) == 0)
+ return (char *) haystack;
+ return 0;
+}
diff --git a/stmhal/system_stm32f4xx.c b/stmhal/system_stm32f4xx.c
index aa9c984731..8d806041c1 100644
--- a/stmhal/system_stm32f4xx.c
+++ b/stmhal/system_stm32f4xx.c
@@ -65,6 +65,8 @@
#include "stm32f4xx_hal.h"
+void __fatal_error(const char *msg);
+
/**
* @}
*/
@@ -257,8 +259,64 @@ void SystemCoreClockUpdate(void)
}
/**
- * @}
+ * @brief System Clock Configuration
+ * The system Clock is configured as follow :
+ * System Clock source = PLL (HSE)
+ * SYSCLK(Hz) = 168000000
+ * HCLK(Hz) = 168000000
+ * AHB Prescaler = 1
+ * APB1 Prescaler = 4
+ * APB2 Prescaler = 2
+ * HSE Frequency(Hz) = 8000000
+ * PLL_M = 8
+ * PLL_N = 336
+ * PLL_P = 2
+ * PLL_Q = 7
+ * VDD(V) = 3.3
+ * Main regulator output voltage = Scale1 mode
+ * Flash Latency(WS) = 5
+ * @param None
+ * @retval None
*/
+void SystemClock_Config(void)
+{
+ RCC_ClkInitTypeDef RCC_ClkInitStruct;
+ RCC_OscInitTypeDef RCC_OscInitStruct;
+
+ /* Enable Power Control clock */
+ __PWR_CLK_ENABLE();
+
+ /* The voltage scaling allows optimizing the power consumption when the device is
+ clocked below the maximum system frequency, to update the voltage scaling value
+ regarding system frequency refer to product datasheet. */
+ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
+
+ /* Enable HSE Oscillator and activate PLL with HSE as source */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+ RCC_OscInitStruct.PLL.PLLM = 8;
+ RCC_OscInitStruct.PLL.PLLN = 336;
+ RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
+ RCC_OscInitStruct.PLL.PLLQ = 7;
+ if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
+ {
+ __fatal_error("HAL_RCC_OscConfig");
+ }
+
+ /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
+ clocks dividers */
+ RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
+ if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
+ {
+ __fatal_error("HAL_RCC_ClockConfig");
+ }
+}
/**
* @}
diff --git a/stmhal/systick.c b/stmhal/systick.c
new file mode 100644
index 0000000000..55c22dab01
--- /dev/null
+++ b/stmhal/systick.c
@@ -0,0 +1,54 @@
+#include <stm32f4xx_hal.h>
+#include "misc.h"
+#include "systick.h"
+
+void sys_tick_init(void) {
+ // SysTick_Config is now called from HAL_RCC_ClockConfig, which is called
+ // from SystemClock_Config
+ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); // make it highest priority
+}
+
+// called on SysTick interrupt
+void SysTick_Handler(void) {
+ HAL_IncTick();
+ HAL_SYSTICK_IRQHandler();
+ // hack!
+ //void audio_drain(void);
+ //audio_drain();
+}
+
+void sys_tick_delay_ms(uint32_t delay_ms) {
+ sys_tick_wait_at_least(HAL_GetTick(), delay_ms);
+}
+
+// waits until at least delay_ms milliseconds have passed from the sampling of stc
+// handles overflow properl
+// assumes stc was taken from HAL_GetTick() some time before calling this function
+// eg stc <= HAL_GetTick() for the case of no wrap around of HAL_GetTick()
+void sys_tick_wait_at_least(uint32_t stc, uint32_t delay_ms) {
+ // stc_wait is the value of HAL_GetTick() that we wait for
+ uint32_t stc_wait = stc + delay_ms;
+ if (stc_wait < stc) {
+ // stc_wait wrapped around
+ while (stc <= HAL_GetTick() || HAL_GetTick() < stc_wait) {
+ __WFI(); // enter sleep mode, waiting for interrupt
+ }
+ } else {
+ // stc_wait did not wrap around
+ while (stc <= HAL_GetTick() && HAL_GetTick() < stc_wait) {
+ __WFI(); // enter sleep mode, waiting for interrupt
+ }
+ }
+}
+
+bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms) {
+ // stc_wait is the value of HAL_GetTick() that we wait for
+ uint32_t stc_wait = stc + delay_ms;
+ if (stc_wait < stc) {
+ // stc_wait wrapped around
+ return !(stc <= HAL_GetTick() || HAL_GetTick() < stc_wait);
+ } else {
+ // stc_wait did not wrap around
+ return !(stc <= HAL_GetTick() && HAL_GetTick() < stc_wait);
+ }
+}
diff --git a/stmhal/systick.h b/stmhal/systick.h
new file mode 100644
index 0000000000..ce33e849b8
--- /dev/null
+++ b/stmhal/systick.h
@@ -0,0 +1,5 @@
+void sys_tick_init(void);
+void SysTick_Handler(void);
+void sys_tick_delay_ms(uint32_t delay_ms);
+void sys_tick_wait_at_least(uint32_t stc, uint32_t delay_ms);
+bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms);
diff --git a/stmhal/usart.c b/stmhal/usart.c
new file mode 100644
index 0000000000..16b23240a8
--- /dev/null
+++ b/stmhal/usart.c
@@ -0,0 +1,269 @@
+#include <stdio.h>
+#include <string.h>
+#include <stm32f4xx_hal.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "usart.h"
+
+pyb_usart_t pyb_usart_global_debug = PYB_USART_NONE;
+
+#if 0
+#else
+// This needs to be fixed. Right now its just a hack to get REPL working
+static UART_HandleTypeDef UartHandle;
+#endif
+
+#if 0
+static USART_TypeDef *usart_get_base(pyb_usart_t usart_id) {
+ USART_TypeDef *USARTx=NULL;
+
+ switch (usart_id) {
+ case PYB_USART_NONE:
+ break;
+ case PYB_USART_1:
+ USARTx = USART1;
+ break;
+ case PYB_USART_2:
+ USARTx = USART2;
+ break;
+ case PYB_USART_3:
+ USARTx = USART3;
+ break;
+ case PYB_USART_6:
+ USARTx = USART6;
+ break;
+ }
+
+ return USARTx;
+}
+#endif
+
+void usart_init(pyb_usart_t usart_id, uint32_t baudrate) {
+ USART_TypeDef *USARTx=NULL;
+
+ uint32_t GPIO_Pin=0;
+ uint8_t GPIO_AF_USARTx=0;
+ GPIO_TypeDef* GPIO_Port=NULL;
+
+ switch (usart_id) {
+ case PYB_USART_NONE:
+ return;
+
+ case PYB_USART_1:
+ USARTx = USART1;
+
+ GPIO_Port = GPIOA;
+ GPIO_AF_USARTx = GPIO_AF7_USART1;
+ GPIO_Pin = GPIO_PIN_9 | GPIO_PIN_10;
+
+ __USART1_CLK_ENABLE();
+ break;
+ case PYB_USART_2:
+ USARTx = USART2;
+
+ GPIO_Port = GPIOD;
+ GPIO_AF_USARTx = GPIO_AF7_USART2;
+ GPIO_Pin = GPIO_PIN_5 | GPIO_PIN_6;
+
+ __USART2_CLK_ENABLE();
+ break;
+ case PYB_USART_3:
+ USARTx = USART3;
+
+#if defined(PYBOARD3) || defined(PYBOARD4)
+ GPIO_Port = GPIOB;
+ GPIO_AF_USARTx = GPIO_AF7_USART3;
+ GPIO_Pin = GPIO_PIN_10 | GPIO_PIN_11;
+#else
+ GPIO_Port = GPIOD;
+ GPIO_AF_USARTx = GPIO_AF7_USART3;
+ GPIO_Pin = GPIO_PIN_8 | GPIO_PIN_9;
+#endif
+ __USART3_CLK_ENABLE();
+ break;
+ case PYB_USART_6:
+ USARTx = USART6;
+
+ GPIO_Port = GPIOC;
+ GPIO_AF_USARTx = GPIO_AF8_USART6;
+ GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7;
+
+ __USART6_CLK_ENABLE();
+ break;
+ }
+
+ /* Initialize USARTx */
+
+ 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_USARTx;
+ HAL_GPIO_Init(GPIO_Port, &GPIO_InitStructure);
+
+ memset(&UartHandle, 0, sizeof(UartHandle));
+ UartHandle.Instance = USARTx;
+ UartHandle.Init.BaudRate = baudrate;
+ UartHandle.Init.WordLength = USART_WORDLENGTH_8B;
+ UartHandle.Init.StopBits = USART_STOPBITS_1;
+ UartHandle.Init.Parity = USART_PARITY_NONE;
+ UartHandle.Init.Mode = USART_MODE_TX_RX;
+ UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
+ HAL_UART_Init(&UartHandle);
+}
+
+bool usart_rx_any(pyb_usart_t usart_id) {
+#if 0
+ USART_TypeDef *USARTx = usart_get_base(usart_id);
+ return USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == SET;
+#else
+ return __HAL_UART_GET_FLAG(&UartHandle, USART_FLAG_RXNE);
+#endif
+}
+
+int usart_rx_char(pyb_usart_t usart_id) {
+#if 0
+ USART_TypeDef *USARTx = usart_get_base(usart_id);
+ return USART_ReceiveData(USARTx);
+#else
+ uint8_t ch;
+ if (HAL_UART_Receive(&UartHandle, &ch, 1, 0) != HAL_OK) {
+ ch = 0;
+ }
+ return ch;
+#endif
+}
+
+void usart_tx_char(pyb_usart_t usart_id, int c) {
+#if 0
+ USART_TypeDef *USARTx = usart_get_base(usart_id);
+ // wait until the end of any previous transmission
+ uint32_t timeout = 100000;
+ while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET && --timeout > 0) {
+ }
+ USART_SendData(USARTx, c);
+#else
+ uint8_t ch = c;
+ HAL_UART_Transmit(&UartHandle, &ch, 1, 100000);
+#endif
+}
+
+void usart_tx_str(pyb_usart_t usart_id, const char *str) {
+ for (; *str; str++) {
+ usart_tx_char(usart_id, *str);
+ }
+}
+
+void usart_tx_bytes(pyb_usart_t usart_id, const char *data, uint len) {
+ for (; len > 0; data++, len--) {
+ usart_tx_char(usart_id, *data);
+ }
+}
+
+void usart_tx_strn_cooked(pyb_usart_t usart_id, const char *str, int len) {
+ for (const char *top = str + len; str < top; str++) {
+ if (*str == '\n') {
+ usart_tx_char(usart_id, '\r');
+ }
+ usart_tx_char(usart_id, *str);
+ }
+}
+
+#if 0
+/******************************************************************************/
+/* Micro Python bindings */
+
+typedef struct _pyb_usart_obj_t {
+ mp_obj_base_t base;
+ pyb_usart_t usart_id;
+ bool is_enabled;
+} pyb_usart_obj_t;
+
+static mp_obj_t usart_obj_status(mp_obj_t self_in) {
+ pyb_usart_obj_t *self = self_in;
+ if (usart_rx_any(self->usart_id)) {
+ return mp_const_true;
+ } else {
+ return mp_const_false;
+ }
+}
+
+static mp_obj_t usart_obj_rx_char(mp_obj_t self_in) {
+ mp_obj_t ret = mp_const_none;
+ pyb_usart_obj_t *self = self_in;
+
+ if (self->is_enabled) {
+ ret = mp_obj_new_int(usart_rx_char(self->usart_id));
+ }
+ return ret;
+}
+
+static mp_obj_t usart_obj_tx_char(mp_obj_t self_in, mp_obj_t c) {
+ pyb_usart_obj_t *self = self_in;
+ uint len;
+ const char *str = mp_obj_str_get_data(c, &len);
+ if (len == 1 && self->is_enabled) {
+ usart_tx_char(self->usart_id, str[0]);
+ }
+ return mp_const_none;
+}
+
+static mp_obj_t usart_obj_tx_str(mp_obj_t self_in, mp_obj_t s) {
+ pyb_usart_obj_t *self = self_in;
+ if (self->is_enabled) {
+ if (MP_OBJ_IS_STR(s)) {
+ uint len;
+ const char *data = mp_obj_str_get_data(s, &len);
+ usart_tx_bytes(self->usart_id, data, len);
+ }
+ }
+ return mp_const_none;
+}
+
+static void usart_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ pyb_usart_obj_t *self = self_in;
+ print(env, "<Usart %lu>", self->usart_id);
+}
+
+static MP_DEFINE_CONST_FUN_OBJ_1(usart_obj_status_obj, usart_obj_status);
+static MP_DEFINE_CONST_FUN_OBJ_1(usart_obj_rx_char_obj, usart_obj_rx_char);
+static MP_DEFINE_CONST_FUN_OBJ_2(usart_obj_tx_char_obj, usart_obj_tx_char);
+static MP_DEFINE_CONST_FUN_OBJ_2(usart_obj_tx_str_obj, usart_obj_tx_str);
+
+STATIC const mp_method_t usart_methods[] = {
+ { "status", &usart_obj_status_obj },
+ { "recv_chr", &usart_obj_rx_char_obj },
+ { "send_chr", &usart_obj_tx_char_obj },
+ { "send", &usart_obj_tx_str_obj },
+ { NULL, NULL },
+};
+
+STATIC const mp_obj_type_t usart_obj_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Usart,
+ .print = usart_obj_print,
+ .methods = usart_methods,
+};
+
+STATIC mp_obj_t pyb_Usart(mp_obj_t usart_id, mp_obj_t baudrate) {
+ if (mp_obj_get_int(usart_id)>PYB_USART_MAX) {
+ return mp_const_none;
+ }
+
+ /* init USART */
+ usart_init(mp_obj_get_int(usart_id), mp_obj_get_int(baudrate));
+
+ pyb_usart_obj_t *o = m_new_obj(pyb_usart_obj_t);
+ o->base.type = &usart_obj_type;
+ o->usart_id = mp_obj_get_int(usart_id);
+ o->is_enabled = true;
+ return o;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_2(pyb_Usart_obj, pyb_Usart);
+#endif
diff --git a/stmhal/usart.h b/stmhal/usart.h
new file mode 100644
index 0000000000..2b1b60bfda
--- /dev/null
+++ b/stmhal/usart.h
@@ -0,0 +1,25 @@
+typedef enum {
+ PYB_USART_NONE = 0,
+ PYB_USART_1 = 1,
+ PYB_USART_2 = 2,
+ PYB_USART_3 = 3,
+ PYB_USART_6 = 4,
+ PYB_USART_MAX = 4,
+
+ //PYB_USART_XA = // USART4 on X1, X2 = PA0, PA1
+ PYB_USART_XB = 1, // USART1 on X9, X10 = PB6, PB7
+ PYB_USART_YA = 4, // USART6 on Y1, Y2 = PC6, PC7
+ PYB_USART_YB = 3, // USART3 on Y9, Y10 = PB10, PB11
+} pyb_usart_t;
+
+extern pyb_usart_t pyb_usart_global_debug;
+
+void usart_init(pyb_usart_t usart_id, uint32_t baudrate);
+bool usart_rx_any(pyb_usart_t usart_id);
+int usart_rx_char(pyb_usart_t usart_id);
+void usart_tx_str(pyb_usart_t usart_id, const char *str);
+void usart_tx_strn_cooked(pyb_usart_t usart_id, const char *str, int len);
+
+#if 0
+MP_DECLARE_CONST_FUN_OBJ(pyb_Usart_obj);
+#endif