diff --git a/embed/embed.mk b/embed/embed.mk new file mode 100644 index 0000000000000..edcb9a5c23ff5 --- /dev/null +++ b/embed/embed.mk @@ -0,0 +1,31 @@ +# where embed object files go (they have a name prefix to prevent filename clashes) +EMBED_BUILD = $(BUILD)/embed + +# embed object files +EMBED_O_BASENAME = \ + hal_gpio.o \ + +# prepend the build destination prefix to the embed object files +EMBED_O = $(addprefix $(EMBED_BUILD)/, $(EMBED_O_BASENAME)) + +# Relative to the top of the mbed tree + +MBED_TOP = $(TOP)/../mbed/libraries/mbed +MBED_API = $(MBED_TOP)/api +MBED_COMMON = $(MBED_TOP)/common +MBED_HAL_INC = $(MBED_TOP)/hal +MBED_HAL_SRC = $(MBED_TOP)/targets/hal/TARGET_STM/TARGET_STM32F4XX + +CFLAGS_EMBED = -I$(TOP)/embed -I$(MBED_API) -I$(MBED_HAL_INC) -I$(MBED_HAL_SRC) + +vpath %.c $(MBED_HAL_SRC) +SRC_HAL = \ + pinmap.c \ + analogin_api.c \ + gpio_api.c \ + +vpath %.c $(MBED_COMMON) +SRC_HAL += \ + pinmap_common.c \ + exit.c \ + diff --git a/embed/hal.h b/embed/hal.h new file mode 100644 index 0000000000000..33c7b99a57dfa --- /dev/null +++ b/embed/hal.h @@ -0,0 +1,7 @@ +typedef struct { + const char *const_name; + machine_int_t const_val; +} hal_int_const; + +void hal_target_init_Gpio_class(mp_obj_t gpio_class_type); + diff --git a/embed/hal_gpio.c b/embed/hal_gpio.c new file mode 100644 index 0000000000000..59422d0d385ff --- /dev/null +++ b/embed/hal_gpio.c @@ -0,0 +1,83 @@ +#include +#include +#include + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "runtime.h" +#include "map.h" + +#include "gpio_api.h" +#include "hal.h" +#include "hal_gpio.h" + +static mp_obj_t gpio_obj_mode(mp_obj_t self_in, mp_obj_t mode_obj) { + hal_gpio_obj_t *self = self_in; + int mode = mp_obj_get_int(mode_obj); + gpio_mode(&self->gpio, mode); + return mp_const_none; +} + +static mp_obj_t gpio_obj_dir(mp_obj_t self_in, mp_obj_t dir_obj) { + hal_gpio_obj_t *self = self_in; + int dir = mp_obj_get_int(dir_obj); + gpio_dir(&self->gpio, dir); + return mp_const_none; +} + +static mp_obj_t gpio_obj_read(mp_obj_t self_in) { + hal_gpio_obj_t *self = self_in; + return MP_OBJ_NEW_SMALL_INT(gpio_read(&self->gpio)); +} + +static mp_obj_t gpio_obj_write(mp_obj_t self_in, mp_obj_t value_obj) { + hal_gpio_obj_t *self = self_in; + int value = mp_obj_get_int(value_obj); + gpio_dir(&self->gpio, value); + return mp_const_none; +} + +static void gpio_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { + hal_gpio_obj_t *self = self_in; + print(env, "", self->pin); +} + +static MP_DEFINE_CONST_FUN_OBJ_2(gpio_obj_mode_obj, gpio_obj_mode); +static MP_DEFINE_CONST_FUN_OBJ_2(gpio_obj_dir_obj, gpio_obj_dir); +static MP_DEFINE_CONST_FUN_OBJ_1(gpio_obj_read_obj, gpio_obj_read); +static MP_DEFINE_CONST_FUN_OBJ_2(gpio_obj_write_obj, gpio_obj_write); + +static bool gpio_call_kwarg(mp_obj_t param, mp_obj_t key, mp_obj_t value) { + hal_gpio_obj_t *self = param; + mp_obj_t fn = rt_load_attr(self, mp_obj_str_get_qstr(key)); + if (fn != MP_OBJ_NULL) { + rt_call_function_1(fn, value); + } + return true; +} + +mp_obj_t hal_Gpio_init(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) { + hal_gpio_obj_t *self = args[0]; + int pin = mp_obj_get_int(args[1]); + gpio_init(&self->gpio, pin, PIN_INPUT); + mp_map_walk(kwargs, gpio_call_kwarg, self); + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN_KW(hal_Gpio_init_obj, 2, 2, hal_Gpio_init); + +void hal_init_Gpio_class(mp_obj_t module_obj) { + mp_obj_t gpio_class_type = mp_obj_new_type("Gpio", mp_const_empty_tuple, mp_obj_new_dict(0)); + ((mp_obj_type_t *)gpio_class_type)->print = gpio_obj_print; + rt_store_attr(gpio_class_type, QSTR_FROM_STR_STATIC("__init__"), (mp_obj_t)&hal_Gpio_init_obj); + rt_store_attr(gpio_class_type, QSTR_FROM_STR_STATIC("dir"), (mp_obj_t)&gpio_obj_dir_obj); + rt_store_attr(gpio_class_type, QSTR_FROM_STR_STATIC("mode"), (mp_obj_t)&gpio_obj_mode_obj); + rt_store_attr(gpio_class_type, QSTR_FROM_STR_STATIC("read"), (mp_obj_t)&gpio_obj_read_obj); + rt_store_attr(gpio_class_type, QSTR_FROM_STR_STATIC("write"), (mp_obj_t)&gpio_obj_write_obj); + rt_store_attr(module_obj, QSTR_FROM_STR_STATIC("Gpio"), gpio_class_type); + + // Allow the target to add its own constants and methods + hal_target_init_Gpio_class(gpio_class_type); +} diff --git a/embed/hal_gpio.h b/embed/hal_gpio.h new file mode 100644 index 0000000000000..d68ed40945081 --- /dev/null +++ b/embed/hal_gpio.h @@ -0,0 +1,8 @@ +typedef struct { + mp_obj_base_t base; + PinName pin; + gpio_t gpio; +} hal_gpio_obj_t; + +void hal_init_Gpio_class(mp_obj_t module_obj); + diff --git a/py/map.c b/py/map.c index 2bae8b28d74bb..44ec84752ed27 100644 --- a/py/map.c +++ b/py/map.c @@ -135,6 +135,21 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t } } +void mp_map_walk(mp_map_t *map, bool (*fn)(void *param, mp_obj_t key, mp_obj_t value), void *param) { + uint pos; + if (!map) { + return; + } + for (pos = 0; pos < map->alloc; pos++) { + mp_map_elem_t *elem = &map->table[pos]; + if (elem->key != NULL) { + if (!fn(param, elem->key, elem->value)) { + return; + } + } + } +} + /******************************************************************************/ /* set */ diff --git a/py/map.h b/py/map.h index 7acb5a98a7469..294876e9d8a5e 100644 --- a/py/map.h +++ b/py/map.h @@ -31,6 +31,7 @@ mp_map_t *mp_map_new(int n); void mp_map_deinit(mp_map_t *map); void mp_map_free(mp_map_t *map); mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind); +void mp_map_walk(mp_map_t *map, bool (*fn)(mp_obj_t param, mp_obj_t key, mp_obj_t value), mp_obj_t param); void mp_map_clear(mp_map_t *map); void mp_set_init(mp_set_t *set, int n); diff --git a/py/obj.h b/py/obj.h index 9c6a354220861..2025fba7fed22 100644 --- a/py/obj.h +++ b/py/obj.h @@ -61,6 +61,7 @@ typedef struct _mp_obj_base_t mp_obj_base_t; #define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, 3, 3, (mp_fun_3_t)fun_name) #define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, n_args_min, (~((machine_uint_t)0)), (mp_fun_var_t)fun_name) #define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, n_args_min, n_args_max, (mp_fun_var_t)fun_name) +#define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN_KW(obj_name, n_args_min, n_args_max, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, n_args_min, n_args_max, (mp_fun_var_t)fun_name) #define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, n_args_min, (~((machine_uint_t)0)), (mp_fun_kw_t)fun_name) // These macros are used to declare and define constant staticmethond and classmethod objects diff --git a/stm/Makefile b/stm/Makefile index 12fd0d9662a7e..6dc6bf61d7c65 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -5,6 +5,7 @@ QSTR_DEFS = qstrdefsport.h # include py core make definitions include ../py/py.mk +include ../embed/embed.mk CMSIS_DIR=cmsis STMPERIPH_DIR=stmperiph @@ -23,6 +24,7 @@ CFLAGS += -I$(STMUSBD_DIR) CFLAGS += -I$(STMUSBH_DIR) CFLAGS += -I$(FATFS_DIR) #CFLAGS += -I$(CC3K_DIR) +CFLAGS += $(CFLAGS_EMBED) #Debugging/Optimization ifeq ($(DEBUG), 1) @@ -63,6 +65,7 @@ SRC_C = \ adc.c \ rtc.c \ file.c \ + hal_target_gpio.c \ # pybwlan.c \ SRC_S = \ @@ -145,11 +148,16 @@ SRC_CC3K = $(addprefix $(CC3K_DIR)/,\ pybcc3k.c \ ) -OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o) $(SRC_STMPERIPH:.c=.o) $(SRC_STMUSB:.c=.o)) +OBJ = $(PY_O) $(EMBED_O) +OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o) $(SRC_STMPERIPH:.c=.o) $(SRC_STMUSB:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_STMUSBD:.c=.o)) #OBJ += $(addprefix $(BUILD)/, $(SRC_STMUSBH:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_FATFS:.c=.o)) #OBJ += $(addprefix $(BUILD)/, $(SRC_CC3K:.c=.o)) +OBJ += $(addprefix $(BUILD)/hal/, $(SRC_HAL:.c=.o)) + +$(BUILD)/hal/%.o: %.c + $(compile_c) all: $(BUILD) $(BUILD)/flash.dfu diff --git a/stm/cmsis/cmsis.h b/stm/cmsis/cmsis.h new file mode 100644 index 0000000000000..863efb3794f01 --- /dev/null +++ b/stm/cmsis/cmsis.h @@ -0,0 +1,14 @@ +/* mbed Microcontroller Library - CMSIS + * Copyright (C) 2009-2011 ARM Limited. All rights reserved. + * + * A generic CMSIS include header, pulling in STM32F407 specifics + */ + +#ifndef MBED_CMSIS_H +#define MBED_CMSIS_H + +#include "stm32f4xx.h" +#include "cmsis_nvic.h" + +#endif + diff --git a/stm/cmsis/cmsis_nvic.h b/stm/cmsis/cmsis_nvic.h new file mode 100644 index 0000000000000..c259328d4ed04 --- /dev/null +++ b/stm/cmsis/cmsis_nvic.h @@ -0,0 +1,26 @@ +/* mbed Microcontroller Library - cmsis_nvic + * Copyright (c) 2009-2011 ARM Limited. All rights reserved. + * + * CMSIS-style functionality to support dynamic vectors + */ + +#ifndef MBED_CMSIS_NVIC_H +#define MBED_CMSIS_NVIC_H + +#define NVIC_NUM_VECTORS (16 + 81) // CORE + MCU Peripherals +#define NVIC_USER_IRQ_OFFSET 16 + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector); +uint32_t NVIC_GetVector(IRQn_Type IRQn); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stm/hal_target_gpio.c b/stm/hal_target_gpio.c new file mode 100644 index 0000000000000..ee18d6f0512e3 --- /dev/null +++ b/stm/hal_target_gpio.c @@ -0,0 +1,50 @@ +#include + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "runtime.h" + +#include "gpio_api.h" +#include "hal.h" +#include "hal_gpio.h" + +const static hal_int_const target_gpio_const[] = { + { "DIR_INPUT", 0 }, + { "DIR_OUTPUT", 1 }, + + { "PUD_NONE", 0 }, + { "PUD_UP", 1 }, + { "PUD_DOWN", 2 }, + { "PUD_OPEN_DRAIN", 3 }, + + { "SPEED_LOW", 0 }, + { "SPEED_MEDIUM", 1 }, + { "SPEED_FAST", 2 }, + { "SPEED_HIGH", 3 }, + + { NULL, 0 } +}; + +static mp_obj_t gpio_obj_speed(mp_obj_t self_in, mp_obj_t speed_obj) { + hal_gpio_obj_t *self = self_in; + int speed = mp_obj_get_int(speed_obj) & 3; + + uint32_t port_index = (uint32_t) self->pin >> 4; + GPIO_TypeDef *port_reg = (GPIO_TypeDef *) (GPIOA_BASE + (port_index << 10)); + + int pin_shift = (self->pin & 0x0f) << 1; + port_reg->OSPEEDR = (port_reg->OSPEEDR & ~(3 << pin_shift)) | (speed << pin_shift); + + return mp_const_none; +} + +static MP_DEFINE_CONST_FUN_OBJ_2(gpio_obj_speed_obj, gpio_obj_speed); + +void hal_target_init_Gpio_class(mp_obj_t gpio_class_type) { + for (const hal_int_const *c = target_gpio_const; c->const_name != NULL; c++) { + rt_store_attr(gpio_class_type, qstr_from_str(c->const_name), MP_OBJ_NEW_SMALL_INT(c->const_val)); + } + rt_store_attr(gpio_class_type, QSTR_FROM_STR_STATIC("speed"), (mp_obj_t)&gpio_obj_speed_obj); +} diff --git a/stm/main.c b/stm/main.c index 90fdab3d22375..2ae607ee35b2a 100644 --- a/stm/main.c +++ b/stm/main.c @@ -45,6 +45,9 @@ #include "adc.h" #include "rtc.h" #include "file.h" +#include "gpio_api.h" +#include "hal.h" +#include "hal_gpio.h" int errno; @@ -72,6 +75,11 @@ void __fatal_error(const char *msg) { } } +// mbed_die is provided for the mbed hal routines +void mbed_die(void) { + __fatal_error("mbed_die"); +} + static mp_obj_t pyb_config_source_dir = MP_OBJ_NULL; static mp_obj_t pyb_config_main = MP_OBJ_NULL; @@ -319,7 +327,7 @@ int readline(vstr_t *line, const char *prompt) { return 1; } else if (c == 27) { escape = true; - } else if (c == 127) { + } else if (c == 127 || c == 8) { if (vstr_len(line) > len) { vstr_cut_tail(line, 1); stdout_tx_str("\b \b"); @@ -670,6 +678,7 @@ int main(void) { rt_store_attr(m, MP_QSTR_Usart, rt_make_function_n(2, pyb_Usart)); rt_store_attr(m, qstr_from_str("ADC_all"), (mp_obj_t)&pyb_ADC_all_obj); rt_store_attr(m, MP_QSTR_ADC, (mp_obj_t)&pyb_ADC_obj); + hal_target_init_Gpio_class(m); rt_store_name(MP_QSTR_pyb, m); rt_store_name(MP_QSTR_open, rt_make_function_n(2, pyb_io_open)); diff --git a/stm/qstrdefsport.h b/stm/qstrdefsport.h index 4fbcb1e5a4e42..7c4af293515d4 100644 --- a/stm/qstrdefsport.h +++ b/stm/qstrdefsport.h @@ -23,7 +23,9 @@ Q(rand) Q(Led) Q(Servo) Q(I2C) +Q(Gpio) Q(gpio) Q(Usart) Q(ADC) +Q(Adc) Q(open)