REPl working on UART6 with STMHAL

This commit is contained in:
Dave Hylands 2014-03-12 18:06:26 -07:00
parent 19438fd30a
commit f14b92b9e1
29 changed files with 2793 additions and 125 deletions

View File

@ -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

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1 @@
mp_lexer_t *mp_lexer_new_from_file(const char *filename);

View File

@ -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
View 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
View 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
View 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
View 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
View 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;