Skip to content
Snippets Groups Projects
Commit 1b6d94bc authored by Damien George's avatar Damien George
Browse files

stmhal: Refactor to use extmod implementation of software SPI class.

This is a pure refactoring (and simplification) of code so that stmhal
uses the software SPI class provided in extmod, for the machine.SPI
implementation.
parent 1eb3c66e
No related branches found
No related tags found
No related merge requests found
...@@ -105,6 +105,9 @@ ...@@ -105,6 +105,9 @@
#define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hard_i2c_make_new #define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hard_i2c_make_new
#define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SPI (1)
#define MICROPY_PY_MACHINE_SPI_MSB (SPI_FIRSTBIT_MSB)
#define MICROPY_PY_MACHINE_SPI_LSB (SPI_FIRSTBIT_LSB)
#define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hard_spi_make_new
#define MICROPY_PY_MACHINE_SPI_MIN_DELAY (0) #define MICROPY_PY_MACHINE_SPI_MIN_DELAY (0)
#define MICROPY_PY_MACHINE_SPI_MAX_BAUDRATE (HAL_RCC_GetSysClockFreq() / 48) #define MICROPY_PY_MACHINE_SPI_MAX_BAUDRATE (HAL_RCC_GetSysClockFreq() / 48)
#define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_FRAMEBUF (1)
......
...@@ -829,216 +829,7 @@ const mp_obj_type_t pyb_spi_type = { ...@@ -829,216 +829,7 @@ const mp_obj_type_t pyb_spi_type = {
}; };
/******************************************************************************/ /******************************************************************************/
/* MicroPython bindings for machine API */ // Implementation of hard SPI for machine module
// for make_new
enum {
ARG_NEW_id,
ARG_NEW_baudrate,
ARG_NEW_polarity,
ARG_NEW_phase,
ARG_NEW_bits,
ARG_NEW_firstbit,
ARG_NEW_sck,
ARG_NEW_mosi,
ARG_NEW_miso
};
// for init
enum {
ARG_INIT_baudrate,
ARG_INIT_polarity,
ARG_INIT_phase,
ARG_INIT_bits,
ARG_INIT_firstbit
};
STATIC mp_obj_t machine_soft_spi_make_new(mp_arg_val_t *args);
STATIC void machine_soft_spi_init(mp_obj_t self, mp_arg_val_t *args);
STATIC void machine_soft_spi_deinit(mp_obj_t self);
STATIC mp_obj_t machine_hard_spi_make_new(mp_arg_val_t *args);
STATIC void machine_hard_spi_init(mp_obj_t self, mp_arg_val_t *args);
STATIC void machine_hard_spi_deinit(mp_obj_t self);
/* common code for both soft and hard implementations *************************/
STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} },
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_FIRSTBIT_MSB} },
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
if (args[ARG_NEW_id].u_obj == MP_OBJ_NEW_SMALL_INT(-1)) {
// software SPI
return machine_soft_spi_make_new(args);
} else {
// hardware peripheral id given
return machine_hard_spi_make_new(args);
}
}
STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
};
// parse args
mp_obj_t self = pos_args[0];
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// dispatch to specific implementation
if (mp_obj_get_type(self) == &machine_soft_spi_type) {
machine_soft_spi_init(self, args);
} else {
machine_hard_spi_init(self, args);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init);
STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) {
// dispatch to specific implementation
if (mp_obj_get_type(self) == &machine_soft_spi_type) {
machine_soft_spi_deinit(self);
} else {
machine_hard_spi_deinit(self);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit);
STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_spi_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(SPI_FIRSTBIT_MSB) },
{ MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(SPI_FIRSTBIT_LSB) },
};
STATIC MP_DEFINE_CONST_DICT(machine_spi_locals_dict, machine_spi_locals_dict_table);
/* code for soft implementation ***********************************************/
// for the software SPI implementation, this is roughly the max baudrate
#define MAX_BAUDRATE (HAL_RCC_GetSysClockFreq() / 48)
STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) {
if (delay_half == MICROPY_PY_MACHINE_SPI_MIN_DELAY) {
return MAX_BAUDRATE;
} else {
return 500000 / delay_half;
}
}
STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) {
if (baudrate >= MAX_BAUDRATE) {
return MICROPY_PY_MACHINE_SPI_MIN_DELAY;
} else {
uint32_t delay_half = 500000 / baudrate;
// round delay_half up so that: actual_baudrate <= requested_baudrate
if (500000 % baudrate != 0) {
delay_half += 1;
}
return delay_half;
}
}
STATIC void machine_soft_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "SPI(-1, baudrate=%u, polarity=%u, phase=%u, sck=%q, mosi=%q, miso=%q)",
baudrate_from_delay_half(self->delay_half), self->polarity, self->phase,
self->sck->name, self->mosi->name, self->miso->name);
}
STATIC mp_obj_t machine_soft_spi_make_new(mp_arg_val_t *args) {
// create new object
mp_machine_soft_spi_obj_t *self = m_new_obj(mp_machine_soft_spi_obj_t);
self->base.type = &machine_soft_spi_type;
// set parameters
self->delay_half = baudrate_to_delay_half(args[ARG_NEW_baudrate].u_int);
self->polarity = args[ARG_NEW_polarity].u_int;
self->phase = args[ARG_NEW_phase].u_int;
if (args[ARG_NEW_bits].u_int != 8) {
mp_raise_ValueError("bits must be 8");
}
if (args[ARG_NEW_firstbit].u_int != SPI_FIRSTBIT_MSB) {
mp_raise_ValueError("firstbit must be MSB");
}
if (args[ARG_NEW_sck].u_obj == MP_OBJ_NULL
|| args[ARG_NEW_mosi].u_obj == MP_OBJ_NULL
|| args[ARG_NEW_miso].u_obj == MP_OBJ_NULL) {
mp_raise_ValueError("must specify all of sck/mosi/miso");
}
self->sck = mp_hal_get_pin_obj(args[ARG_NEW_sck].u_obj);
self->mosi = mp_hal_get_pin_obj(args[ARG_NEW_mosi].u_obj);
self->miso = mp_hal_get_pin_obj(args[ARG_NEW_miso].u_obj);
// configure pins
mp_hal_pin_write(self->sck, self->polarity);
mp_hal_pin_output(self->sck);
mp_hal_pin_output(self->mosi);
mp_hal_pin_input(self->miso);
return MP_OBJ_FROM_PTR(self);
}
STATIC void machine_soft_spi_init(mp_obj_t self_in, mp_arg_val_t *args) {
mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
// update parameters
if (args[ARG_INIT_baudrate].u_int != -1) {
self->delay_half = baudrate_to_delay_half(args[ARG_INIT_baudrate].u_int);
}
if (args[ARG_INIT_polarity].u_int != -1) {
self->polarity = args[ARG_INIT_polarity].u_int;
}
if (args[ARG_INIT_phase].u_int != -1) {
self->phase = args[ARG_INIT_phase].u_int;
}
}
STATIC void machine_soft_spi_deinit(mp_obj_t self) {
// nothing to do
(void)self;
}
STATIC const mp_machine_spi_p_t machine_soft_spi_p = {
.transfer = mp_machine_soft_spi_transfer,
};
const mp_obj_type_t machine_soft_spi_type = {
{ &mp_type_type },
.name = MP_QSTR_SoftSPI,
.print = machine_soft_spi_print,
.make_new = machine_spi_make_new,
.protocol = &machine_soft_spi_p,
.locals_dict = (mp_obj_t)&machine_spi_locals_dict,
};
/* code for hard implementation ***********************************************/
typedef struct _machine_hard_spi_obj_t { typedef struct _machine_hard_spi_obj_t {
mp_obj_base_t base; mp_obj_base_t base;
...@@ -1055,19 +846,34 @@ STATIC const machine_hard_spi_obj_t machine_hard_spi_obj[] = { ...@@ -1055,19 +846,34 @@ STATIC const machine_hard_spi_obj_t machine_hard_spi_obj[] = {
}; };
STATIC void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_hard_spi_obj_t *self = self_in; machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in;
spi_print(print, self->pyb->spi, false); spi_print(print, self->pyb->spi, false);
} }
STATIC mp_obj_t machine_hard_spi_make_new(mp_arg_val_t *args) { mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} },
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_FIRSTBIT_MSB} },
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get static peripheral object // get static peripheral object
int spi_id = spi_find(args[ARG_NEW_id].u_obj); int spi_id = spi_find(args[ARG_id].u_obj);
const machine_hard_spi_obj_t *self = &machine_hard_spi_obj[spi_id - 1]; const machine_hard_spi_obj_t *self = &machine_hard_spi_obj[spi_id - 1];
// here we would check the sck/mosi/miso pins and configure them, but it's not implemented // here we would check the sck/mosi/miso pins and configure them, but it's not implemented
if (args[ARG_NEW_sck].u_obj != MP_OBJ_NULL if (args[ARG_sck].u_obj != MP_OBJ_NULL
|| args[ARG_NEW_mosi].u_obj != MP_OBJ_NULL || args[ARG_mosi].u_obj != MP_OBJ_NULL
|| args[ARG_NEW_miso].u_obj != MP_OBJ_NULL) { || args[ARG_miso].u_obj != MP_OBJ_NULL) {
mp_raise_ValueError("explicit choice of sck/mosi/miso is not implemented"); mp_raise_ValueError("explicit choice of sck/mosi/miso is not implemented");
} }
...@@ -1083,9 +889,9 @@ STATIC mp_obj_t machine_hard_spi_make_new(mp_arg_val_t *args) { ...@@ -1083,9 +889,9 @@ STATIC mp_obj_t machine_hard_spi_make_new(mp_arg_val_t *args) {
init->CRCPolynomial = 0; init->CRCPolynomial = 0;
// set configurable paramaters // set configurable paramaters
spi_set_params(self->pyb->spi, 0xffffffff, args[ARG_NEW_baudrate].u_int, spi_set_params(self->pyb->spi, 0xffffffff, args[ARG_baudrate].u_int,
args[ARG_NEW_polarity].u_int, args[ARG_NEW_phase].u_int, args[ARG_NEW_bits].u_int, args[ARG_polarity].u_int, args[ARG_phase].u_int, args[ARG_bits].u_int,
args[ARG_NEW_firstbit].u_int); args[ARG_firstbit].u_int);
// init the SPI bus // init the SPI bus
spi_init(self->pyb->spi, false); spi_init(self->pyb->spi, false);
...@@ -1093,20 +899,31 @@ STATIC mp_obj_t machine_hard_spi_make_new(mp_arg_val_t *args) { ...@@ -1093,20 +899,31 @@ STATIC mp_obj_t machine_hard_spi_make_new(mp_arg_val_t *args) {
return MP_OBJ_FROM_PTR(self); return MP_OBJ_FROM_PTR(self);
} }
STATIC void machine_hard_spi_init(mp_obj_t self_in, mp_arg_val_t *args) { STATIC void machine_hard_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
machine_hard_spi_obj_t *self = self_in; machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in;
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// set the SPI configuration values // set the SPI configuration values
spi_set_params(self->pyb->spi, 0xffffffff, args[ARG_INIT_baudrate].u_int, spi_set_params(self->pyb->spi, 0xffffffff, args[ARG_baudrate].u_int,
args[ARG_INIT_polarity].u_int, args[ARG_INIT_phase].u_int, args[ARG_INIT_bits].u_int, args[ARG_polarity].u_int, args[ARG_phase].u_int, args[ARG_bits].u_int,
args[ARG_INIT_firstbit].u_int); args[ARG_firstbit].u_int);
// re-init the SPI bus // re-init the SPI bus
spi_init(self->pyb->spi, false); spi_init(self->pyb->spi, false);
} }
STATIC void machine_hard_spi_deinit(mp_obj_t self_in) { STATIC void machine_hard_spi_deinit(mp_obj_base_t *self_in) {
machine_hard_spi_obj_t *self = self_in; machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in;
spi_deinit(self->pyb->spi); spi_deinit(self->pyb->spi);
} }
...@@ -1116,6 +933,8 @@ STATIC void machine_hard_spi_transfer(mp_obj_base_t *self_in, size_t len, const ...@@ -1116,6 +933,8 @@ STATIC void machine_hard_spi_transfer(mp_obj_base_t *self_in, size_t len, const
} }
STATIC const mp_machine_spi_p_t machine_hard_spi_p = { STATIC const mp_machine_spi_p_t machine_hard_spi_p = {
.init = machine_hard_spi_init,
.deinit = machine_hard_spi_deinit,
.transfer = machine_hard_spi_transfer, .transfer = machine_hard_spi_transfer,
}; };
...@@ -1123,7 +942,7 @@ const mp_obj_type_t machine_hard_spi_type = { ...@@ -1123,7 +942,7 @@ const mp_obj_type_t machine_hard_spi_type = {
{ &mp_type_type }, { &mp_type_type },
.name = MP_QSTR_SPI, .name = MP_QSTR_SPI,
.print = machine_hard_spi_print, .print = machine_hard_spi_print,
.make_new = machine_spi_make_new, .make_new = mp_machine_spi_make_new, // delegate to master constructor
.protocol = &machine_hard_spi_p, .protocol = &machine_hard_spi_p,
.locals_dict = (mp_obj_t)&machine_spi_locals_dict, .locals_dict = (mp_obj_t)&mp_machine_spi_locals_dict,
}; };
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment