From 3f4898456bb1a451e5e6d45cb62c9c718f2b8a76 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 Apr 2014 22:46:40 +0100 Subject: [PATCH] stmhal: Add stm module, which contains some constants for the MCU. Also contains raw memory read/write functions, read8, read16, read32, write8, write16, write32. Can now do: stm.write16(stm.GPIOA + stm.GPIO_BSRRL, 1 << 13) This turns on the red LED. With the new constant folding, the above constants for the GPIO address are actually compiled to constants (and the addition done) at compile time. For viper code and inline assembler, this optimisation will make a big difference. In the inline assembler, using these constants would not be possible without this constant folding. --- stmhal/Makefile | 3 +- stmhal/modstm.c | 120 ++++++++++++++++++++++++++++++++++++++++++ stmhal/modstm.h | 1 + stmhal/mpconfigport.h | 7 +++ stmhal/qstrdefsport.h | 16 ++++++ 5 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 stmhal/modstm.c create mode 100644 stmhal/modstm.h diff --git a/stmhal/Makefile b/stmhal/Makefile index 064db23c35..9789189946 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -77,8 +77,9 @@ SRC_C = \ pyexec.c \ help.c \ input.c \ - modpyb.c \ modos.c \ + modpyb.c \ + modstm.c \ modtime.c \ import.c \ lexerfatfs.c \ diff --git a/stmhal/modstm.c b/stmhal/modstm.c new file mode 100644 index 0000000000..5e72a75bb2 --- /dev/null +++ b/stmhal/modstm.c @@ -0,0 +1,120 @@ +#include +#include + +#include + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "modstm.h" + +STATIC uint32_t get_read_addr(mp_obj_t addr_o, uint align) { + uint32_t addr = mp_obj_get_int(addr_o) & 0x7fffffff; + if (addr < 0x10000000) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "cannot read from address %08x", addr)); + } + if ((addr & (align - 1)) != 0) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align)); + } + return addr; +} + +STATIC uint32_t get_write_addr(mp_obj_t addr_o, uint align) { + uint32_t addr = mp_obj_get_int(addr_o) & 0x7fffffff; + if (addr < 0x10000000) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "cannot write to address %08x", addr)); + } + if ((addr & (align - 1)) != 0) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align)); + } + return addr; +} + +STATIC mp_obj_t stm_read8(mp_obj_t addr) { + uint32_t a = get_read_addr(addr, 1); + uint32_t v = *(uint8_t*)a; + return mp_obj_new_int(v); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(stm_read8_obj, stm_read8); + +STATIC mp_obj_t stm_read16(mp_obj_t addr) { + uint32_t a = get_read_addr(addr, 2); + uint32_t v = *(uint16_t*)a; + return mp_obj_new_int(v); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(stm_read16_obj, stm_read16); + +STATIC mp_obj_t stm_read32(mp_obj_t addr) { + uint32_t a = get_read_addr(addr, 4); + uint32_t v = *(uint32_t*)a; + return mp_obj_new_int(v); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(stm_read32_obj, stm_read32); + +STATIC mp_obj_t stm_write8(mp_obj_t addr, mp_obj_t val) { + uint32_t a = get_write_addr(addr, 1); + uint32_t v = mp_obj_get_int(val); + *(uint8_t*)a = v; + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_2(stm_write8_obj, stm_write8); + +STATIC mp_obj_t stm_write16(mp_obj_t addr, mp_obj_t val) { + uint32_t a = get_write_addr(addr, 2); + uint32_t v = mp_obj_get_int(val); + *(uint16_t*)a = v; + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_2(stm_write16_obj, stm_write16); + +STATIC mp_obj_t stm_write32(mp_obj_t addr, mp_obj_t val) { + uint32_t a = get_write_addr(addr, 4); + uint32_t v = mp_obj_get_int(val); + *(uint32_t*)a = v; + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_2(stm_write32_obj, stm_write32); + +STATIC const mp_map_elem_t stm_module_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_stm) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_read8), (mp_obj_t)&stm_read8_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_read16), (mp_obj_t)&stm_read16_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_read32), (mp_obj_t)&stm_read32_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_write8), (mp_obj_t)&stm_write8_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_write16), (mp_obj_t)&stm_write16_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_write32), (mp_obj_t)&stm_write32_obj }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIOA), MP_OBJ_NEW_SMALL_INT(GPIOA_BASE) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIOB), MP_OBJ_NEW_SMALL_INT(GPIOB_BASE) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIOC), MP_OBJ_NEW_SMALL_INT(GPIOC_BASE) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIOD), MP_OBJ_NEW_SMALL_INT(GPIOD_BASE) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO_IDR), MP_OBJ_NEW_SMALL_INT(0x10) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO_BSRRL), MP_OBJ_NEW_SMALL_INT(0x18) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO_BSRRH), MP_OBJ_NEW_SMALL_INT(0x1a) }, +}; + +STATIC const mp_obj_dict_t stm_module_globals = { + .base = {&mp_type_dict}, + .map = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = sizeof(stm_module_globals_table) / sizeof(mp_map_elem_t), + .alloc = sizeof(stm_module_globals_table) / sizeof(mp_map_elem_t), + .table = (mp_map_elem_t*)stm_module_globals_table, + }, +}; + +const mp_obj_module_t stm_module = { + .base = { &mp_type_module }, + .name = MP_QSTR_stm, + .globals = (mp_obj_dict_t*)&stm_module_globals, +}; diff --git a/stmhal/modstm.h b/stmhal/modstm.h new file mode 100644 index 0000000000..205cdd2a18 --- /dev/null +++ b/stmhal/modstm.h @@ -0,0 +1 @@ +extern const mp_obj_module_t stm_module; diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 08ba923e40..5529101425 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -31,12 +31,19 @@ extern const struct _mp_obj_fun_native_t mp_builtin_open_obj; // extra built in modules to add to the list of known ones extern const struct _mp_obj_module_t os_module; extern const struct _mp_obj_module_t pyb_module; +extern const struct _mp_obj_module_t stm_module; extern const struct _mp_obj_module_t time_module; #define MICROPY_EXTRA_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&os_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_stm), (mp_obj_t)&stm_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \ +// extra constants +#define MICROPY_EXTRA_CONSTANTS \ + { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_stm), (mp_obj_t)&stm_module }, \ + // type definitions for the specific machine #define BYTES_PER_WORD (4) diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h index 4eb6ea12a0..546b5b1430 100644 --- a/stmhal/qstrdefsport.h +++ b/stmhal/qstrdefsport.h @@ -130,3 +130,19 @@ Q(sleep) // for input Q(input) + +// for stm module +Q(stm) +Q(read8) +Q(read16) +Q(read32) +Q(write8) +Q(write16) +Q(write32) +Q(GPIOA) +Q(GPIOB) +Q(GPIOC) +Q(GPIOD) +Q(GPIO_IDR) +Q(GPIO_BSRRL) +Q(GPIO_BSRRH)