From 4933fa1c27f987be558a33b1736089b04e880a03 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 29 Nov 2016 15:49:50 -0800 Subject: [PATCH] shared-bindings: Ensure pin objects are actually pins. Fixes #12 --- atmel-samd/common-hal/nativeio/AnalogOut.c | 4 +- shared-bindings/bitbangio/I2C.c | 71 +++++++++++----------- shared-bindings/bitbangio/SPI.c | 6 +- shared-bindings/microcontroller/Pin.c | 9 +++ shared-bindings/microcontroller/Pin.h | 2 + shared-bindings/nativeio/AnalogIn.c | 2 + shared-bindings/nativeio/AnalogOut.c | 6 +- shared-bindings/nativeio/DigitalInOut.c | 2 + shared-bindings/nativeio/I2C.c | 37 +++++------ shared-bindings/nativeio/PWMOut.c | 2 + shared-bindings/nativeio/SPI.c | 48 ++++++++------- 11 files changed, 111 insertions(+), 78 deletions(-) diff --git a/atmel-samd/common-hal/nativeio/AnalogOut.c b/atmel-samd/common-hal/nativeio/AnalogOut.c index 5540cb37d6..ac2eada423 100644 --- a/atmel-samd/common-hal/nativeio/AnalogOut.c +++ b/atmel-samd/common-hal/nativeio/AnalogOut.c @@ -36,8 +36,8 @@ void common_hal_nativeio_analogout_construct(nativeio_analogout_obj_t* self, const mcu_pin_obj_t *pin) { if (pin->pin != PIN_PA02) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, - "DAC only supported on pin PA02.")); + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, + "AnalogOut only supported on pin PA02.")); return; } struct dac_config config_dac; diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c index d92b0db821..9b2dc4f2c2 100644 --- a/shared-bindings/bitbangio/I2C.c +++ b/shared-bindings/bitbangio/I2C.c @@ -28,6 +28,7 @@ // bitbangio.I2C class. #include "shared-bindings/bitbangio/I2C.h" +#include "shared-bindings/microcontroller/Pin.h" #include "py/runtime.h" //| .. currentmodule:: bitbangio @@ -46,23 +47,25 @@ //| :param int freq: The clock frequency //| STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { - mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); - bitbangio_i2c_obj_t *self = m_new_obj(bitbangio_i2c_obj_t); - self->base.type = &bitbangio_i2c_type; - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_scl, ARG_sda, ARG_freq }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, - }; - 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); - const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj); - const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj); - shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_freq].u_int); - return (mp_obj_t)self; + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + bitbangio_i2c_obj_t *self = m_new_obj(bitbangio_i2c_obj_t); + self->base.type = &bitbangio_i2c_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_scl, ARG_sda, ARG_freq }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + }; + 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); + assert_pin(args[ARG_scl].u_obj, false); + assert_pin(args[ARG_sda].u_obj, false); + const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj); + const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj); + shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_freq].u_int); + return (mp_obj_t)self; } //| .. method:: I2C.deinit() @@ -70,9 +73,9 @@ STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, //| Releases control of the underlying hardware so other classes can use it. //| STATIC mp_obj_t bitbangio_i2c_obj_deinit(mp_obj_t self_in) { - bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - shared_module_bitbangio_i2c_deinit(self); - return mp_const_none; + bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + shared_module_bitbangio_i2c_deinit(self); + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_deinit_obj, bitbangio_i2c_obj_deinit); @@ -81,7 +84,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_deinit_obj, bitbangio_i2c_obj_deinit); //| No-op used in Context Managers. //| STATIC mp_obj_t bitbangio_i2c_obj___enter__(mp_obj_t self_in) { - return self_in; + return self_in; } MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c___enter___obj, bitbangio_i2c_obj___enter__); @@ -103,16 +106,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_i2c_obj___exit___obj, 4, 4, //| its address (including a read bit) is sent on the bus. //| STATIC mp_obj_t bitbangio_i2c_scan(mp_obj_t self_in) { - bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_t list = mp_obj_new_list(0, NULL); - // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved - for (int addr = 0x08; addr < 0x78; ++addr) { - bool success = shared_module_bitbangio_i2c_probe(self, addr); - if (success) { + bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t list = mp_obj_new_list(0, NULL); + // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved + for (int addr = 0x08; addr < 0x78; ++addr) { + bool success = shared_module_bitbangio_i2c_probe(self, addr); + if (success) { mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); - } - } - return list; + } + } + return list; } MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_scan_obj, bitbangio_i2c_scan); @@ -174,8 +177,8 @@ STATIC const mp_rom_map_elem_t bitbangio_i2c_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(bitbangio_i2c_locals_dict, bitbangio_i2c_locals_dict_table); const mp_obj_type_t bitbangio_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .make_new = bitbangio_i2c_make_new, - .locals_dict = (mp_obj_dict_t*)&bitbangio_i2c_locals_dict, + { &mp_type_type }, + .name = MP_QSTR_I2C, + .make_new = bitbangio_i2c_make_new, + .locals_dict = (mp_obj_dict_t*)&bitbangio_i2c_locals_dict, }; diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c index 560834ac8a..4b6b1bacb9 100644 --- a/shared-bindings/bitbangio/SPI.c +++ b/shared-bindings/bitbangio/SPI.c @@ -30,6 +30,7 @@ #include #include "shared-bindings/bitbangio/SPI.h" +#include "shared-bindings/microcontroller/Pin.h" #include "py/runtime.h" @@ -76,8 +77,11 @@ STATIC mp_obj_t bitbangio_spi_make_new(const mp_obj_type_t *type, size_t n_args, }; 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); + assert_pin(args[ARG_clock].u_obj, false); + assert_pin(args[ARG_MOSI].u_obj, true); + assert_pin(args[ARG_MISO].u_obj, true); const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(args[ARG_clock].u_obj); - const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(args[ARG_MOSI].u_obj); + const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(args[ARG_MOSI].u_obj); const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(args[ARG_MISO].u_obj); shared_module_bitbangio_spi_construct(self, clock, mosi, miso, args[ARG_baudrate].u_int); return (mp_obj_t)self; diff --git a/shared-bindings/microcontroller/Pin.c b/shared-bindings/microcontroller/Pin.c index 733fa29ec9..c691a9a17e 100644 --- a/shared-bindings/microcontroller/Pin.c +++ b/shared-bindings/microcontroller/Pin.c @@ -26,6 +26,9 @@ #include "shared-bindings/microcontroller/Pin.h" +#include "py/nlr.h" +#include "py/obj.h" + //| .. currentmodule:: microcontroller //| //| :class:`Pin` --- Pin reference @@ -44,3 +47,9 @@ const mp_obj_type_t mcu_pin_type = { { &mp_type_type }, .name = MP_QSTR_Pin, }; + +void assert_pin(mp_obj_t obj, bool none_ok) { + if ((obj != mp_const_none || !none_ok) && !MP_OBJ_IS_TYPE(obj, &mcu_pin_type)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Expected a Pin")); + } +} diff --git a/shared-bindings/microcontroller/Pin.h b/shared-bindings/microcontroller/Pin.h index 96df67ef86..d31ba040c1 100644 --- a/shared-bindings/microcontroller/Pin.h +++ b/shared-bindings/microcontroller/Pin.h @@ -32,4 +32,6 @@ // Type object used in Python. Should be shared between ports. extern const mp_obj_type_t mcu_pin_type; +void assert_pin(mp_obj_t obj, bool none_ok); + #endif // __MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PIN_H__ diff --git a/shared-bindings/nativeio/AnalogIn.c b/shared-bindings/nativeio/AnalogIn.c index 9c5a601da2..fb3d1c5b25 100644 --- a/shared-bindings/nativeio/AnalogIn.c +++ b/shared-bindings/nativeio/AnalogIn.c @@ -31,6 +31,7 @@ #include "py/nlr.h" #include "py/objproperty.h" #include "py/runtime.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/nativeio/AnalogIn.h" //| .. currentmodule:: nativeio @@ -60,6 +61,7 @@ STATIC mp_obj_t nativeio_analogin_make_new(const mp_obj_type_t *type, // 1st argument is the pin mp_obj_t pin_obj = args[0]; + assert_pin(pin_obj, false); nativeio_analogin_obj_t *self = m_new_obj(nativeio_analogin_obj_t); self->base.type = &nativeio_analogin_type; diff --git a/shared-bindings/nativeio/AnalogOut.c b/shared-bindings/nativeio/AnalogOut.c index 7de336a6a3..7ea7678433 100644 --- a/shared-bindings/nativeio/AnalogOut.c +++ b/shared-bindings/nativeio/AnalogOut.c @@ -29,6 +29,7 @@ #include "py/objproperty.h" #include "py/runtime.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/nativeio/AnalogOut.h" //| .. currentmodule:: nativeio @@ -57,11 +58,12 @@ STATIC mp_obj_t nativeio_analogout_make_new(const mp_obj_type_t *type, mp_uint_t // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + assert_pin(args[0], false); + const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(args[0]); + nativeio_analogout_obj_t *self = m_new_obj(nativeio_analogout_obj_t); self->base.type = &nativeio_analogout_type; - const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(args[0]); - common_hal_nativeio_analogout_construct(self, pin); return self; diff --git a/shared-bindings/nativeio/DigitalInOut.c b/shared-bindings/nativeio/DigitalInOut.c index ce1e129861..7ef06152a9 100644 --- a/shared-bindings/nativeio/DigitalInOut.c +++ b/shared-bindings/nativeio/DigitalInOut.c @@ -33,6 +33,7 @@ #include "py/runtime.h" #include "py/mphal.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/nativeio/DigitalInOut.h" //| .. currentmodule:: nativeio @@ -60,6 +61,7 @@ STATIC mp_obj_t nativeio_digitalinout_make_new(const mp_obj_type_t *type, nativeio_digitalinout_obj_t *self = m_new_obj(nativeio_digitalinout_obj_t); self->base.type = &nativeio_digitalinout_type; + assert_pin(args[0], false); mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(args[0]); common_hal_nativeio_digitalinout_construct(self, pin); diff --git a/shared-bindings/nativeio/I2C.c b/shared-bindings/nativeio/I2C.c index 667b832b0e..081936cb5d 100644 --- a/shared-bindings/nativeio/I2C.c +++ b/shared-bindings/nativeio/I2C.c @@ -27,6 +27,7 @@ // This file contains all of the Python API definitions for the // nativeio.I2C class. +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/nativeio/I2C.h" #include "py/runtime.h" @@ -46,23 +47,25 @@ //| :param int freq: The clock frequency //| STATIC mp_obj_t nativeio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { - mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); - nativeio_i2c_obj_t *self = m_new_obj(nativeio_i2c_obj_t); - self->base.type = &nativeio_i2c_type; - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_scl, ARG_sda, ARG_freq }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, - }; - 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); - const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj); - const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj); - common_hal_nativeio_i2c_construct(self, scl, sda, args[ARG_freq].u_int); - return (mp_obj_t)self; + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + nativeio_i2c_obj_t *self = m_new_obj(nativeio_i2c_obj_t); + self->base.type = &nativeio_i2c_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_scl, ARG_sda, ARG_freq }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + }; + 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); + assert_pin(args[ARG_scl].u_obj, false); + assert_pin(args[ARG_sda].u_obj, false); + const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj); + const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj); + common_hal_nativeio_i2c_construct(self, scl, sda, args[ARG_freq].u_int); + return (mp_obj_t)self; } //| .. method:: I2C.deinit() diff --git a/shared-bindings/nativeio/PWMOut.c b/shared-bindings/nativeio/PWMOut.c index 13897ad1d4..33084be0cb 100644 --- a/shared-bindings/nativeio/PWMOut.c +++ b/shared-bindings/nativeio/PWMOut.c @@ -28,6 +28,7 @@ #include "py/objproperty.h" #include "py/runtime.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/nativeio/PWMOut.h" //| .. currentmodule:: nativeio @@ -48,6 +49,7 @@ STATIC mp_obj_t nativeio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); mp_obj_t pin_obj = args[0]; + assert_pin(pin_obj, false); const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj); // create PWM object from the given pin diff --git a/shared-bindings/nativeio/SPI.c b/shared-bindings/nativeio/SPI.c index f17814ffa9..e285655afe 100644 --- a/shared-bindings/nativeio/SPI.c +++ b/shared-bindings/nativeio/SPI.c @@ -29,6 +29,7 @@ #include +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/nativeio/SPI.h" #include "py/runtime.h" @@ -59,28 +60,31 @@ // TODO(tannewt): Support LSB SPI. // TODO(tannewt): Support phase, polarity and bit order. STATIC mp_obj_t nativeio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { - mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); - nativeio_spi_obj_t *self = m_new_obj(nativeio_spi_obj_t); - self->base.type = &nativeio_spi_type; - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_MOSI, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_MISO, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, - { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, - { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, - { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, - }; - 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); - const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(args[ARG_clock].u_obj); - const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(args[ARG_MOSI].u_obj); - const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(args[ARG_MISO].u_obj); - common_hal_nativeio_spi_construct(self, clock, mosi, miso, args[ARG_baudrate].u_int); - return (mp_obj_t)self; + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + nativeio_spi_obj_t *self = m_new_obj(nativeio_spi_obj_t); + self->base.type = &nativeio_spi_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MOSI, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MISO, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, + { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, + }; + 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); + assert_pin(args[ARG_clock].u_obj, false); + assert_pin(args[ARG_MOSI].u_obj, true); + assert_pin(args[ARG_MISO].u_obj, true); + const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(args[ARG_clock].u_obj); + const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(args[ARG_MOSI].u_obj); + const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(args[ARG_MISO].u_obj); + common_hal_nativeio_spi_construct(self, clock, mosi, miso, args[ARG_baudrate].u_int); + return (mp_obj_t)self; } //| .. method:: SPI.deinit()