Merge pull request #342 from dhylands/stmhal-repl
REPL working on UART6 with STMHAL
This commit is contained in:
commit
659c19c67c
@ -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
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
#include <stm32f4xx_hal.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
|
56
stmhal/gccollect.c
Normal file
56
stmhal/gccollect.c
Normal file
@ -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);
|
17
stmhal/gccollect.h
Normal file
17
stmhal/gccollect.h
Normal file
@ -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);
|
62
stmhal/gchelper.s
Normal file
62
stmhal/gchelper.s
Normal file
@ -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
|
24
stmhal/import.c
Normal file
24
stmhal/import.c
Normal file
@ -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;
|
||||
}
|
133
stmhal/led.c
Normal file
133
stmhal/led.c
Normal file
@ -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
|
25
stmhal/led.h
Normal file
25
stmhal/led.h
Normal file
@ -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
|
61
stmhal/lexerfatfs.c
Normal file
61
stmhal/lexerfatfs.c
Normal file
@ -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
|
||||
}
|
1
stmhal/lexerfatfs.h
Normal file
1
stmhal/lexerfatfs.h
Normal file
@ -0,0 +1 @@
|
||||
mp_lexer_t *mp_lexer_new_from_file(const char *filename);
|
158
stmhal/main.c
158
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
|
||||
@ -328,29 +239,57 @@ int main(void) {
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
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()) {
|
||||
@ -591,16 +539,18 @@ soft_reset:
|
||||
// wifi
|
||||
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
|
||||
}
|
||||
|
36
stmhal/malloc0.c
Normal file
36
stmhal/malloc0.c
Normal file
@ -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 (;;) {
|
||||
}
|
||||
}
|
407
stmhal/math.c
Normal file
407
stmhal/math.c
Normal file
@ -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;
|
||||
}
|
51
stmhal/mpconfigport.h
Normal file
51
stmhal/mpconfigport.h
Normal file
@ -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
|
78
stmhal/pin.c
Normal file
78
stmhal/pin.c
Normal file
@ -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
|
||||
};
|
||||
|
117
stmhal/pin.h
Normal file
117
stmhal/pin.h
Normal file
@ -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);
|
||||
|
371
stmhal/printf.c
Normal file
371
stmhal/printf.c
Normal file
@ -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;
|
||||
}
|
312
stmhal/pybmodule.c
Normal file
312
stmhal/pybmodule.c
Normal file
@ -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,
|
||||
};
|
1
stmhal/pybmodule.h
Normal file
1
stmhal/pybmodule.h
Normal file
@ -0,0 +1 @@
|
||||
extern const mp_obj_module_t pyb_module;
|
347
stmhal/pyexec.c
Normal file
347
stmhal/pyexec.c
Normal file
@ -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);
|
5
stmhal/pyexec.h
Normal file
5
stmhal/pyexec.h
Normal file
@ -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);
|
57
stmhal/qstrdefsport.h
Normal file
57
stmhal/qstrdefsport.h
Normal file
@ -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)
|
@ -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 */
|
||||
|
137
stmhal/string0.c
Normal file
137
stmhal/string0.c
Normal file
@ -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;
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
54
stmhal/systick.c
Normal file
54
stmhal/systick.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
5
stmhal/systick.h
Normal file
5
stmhal/systick.h
Normal file
@ -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);
|
269
stmhal/usart.c
Normal file
269
stmhal/usart.c
Normal file
@ -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
|
25
stmhal/usart.h
Normal file
25
stmhal/usart.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user