diff --git a/atmel-samd/common-hal/nativeio/SPI.c b/atmel-samd/common-hal/nativeio/SPI.c index 7600766f77..8216524751 100644 --- a/atmel-samd/common-hal/nativeio/SPI.c +++ b/atmel-samd/common-hal/nativeio/SPI.c @@ -44,6 +44,8 @@ void common_hal_nativeio_spi_construct(nativeio_spi_obj_t *self, Sercom* sercom = NULL; uint32_t clock_pinmux = 0; + bool mosi_none = mosi == mp_const_none; + bool miso_none = miso == mp_const_none; uint32_t mosi_pinmux = 0; uint32_t miso_pinmux = 0; uint8_t clock_pad = 0; @@ -58,16 +60,27 @@ void common_hal_nativeio_spi_construct(nativeio_spi_obj_t *self, clock_pinmux = clock->sercom[i].pinmux; clock_pad = clock->sercom[i].pad; for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { - mosi_pinmux = mosi->sercom[j].pinmux; - mosi_pad = mosi->sercom[j].pad; - for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) { - if (potential_sercom == miso->sercom[k].sercom) { - miso_pinmux = miso->sercom[k].pinmux; - miso_pad = miso->sercom[k].pad; - sercom = potential_sercom; + if (!mosi_none) { + if(potential_sercom == mosi->sercom[j].sercom) { + mosi_pinmux = mosi->sercom[j].pinmux; + mosi_pad = mosi->sercom[j].pad; + if (miso_none) { + sercom = potential_sercom; + } + } else { break; } } + if (!miso_none) { + for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) { + if (potential_sercom == miso->sercom[k].sercom) { + miso_pinmux = miso->sercom[k].pinmux; + miso_pad = miso->sercom[k].pad; + sercom = potential_sercom; + break; + } + } + } if (sercom != NULL) { break; } @@ -77,7 +90,7 @@ void common_hal_nativeio_spi_construct(nativeio_spi_obj_t *self, } } if (sercom == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "No hardware support available with those pins.")); } @@ -109,8 +122,12 @@ void common_hal_nativeio_spi_construct(nativeio_spi_obj_t *self, &config_spi_master.pinmux_pad2, &config_spi_master.pinmux_pad3}; *pinmuxes[clock_pad] = clock_pinmux; - *pinmuxes[mosi_pad] = mosi_pinmux; - *pinmuxes[miso_pad] = miso_pinmux; + if (!mosi_none) { + *pinmuxes[mosi_pad] = mosi_pinmux; + } + if (!miso_none) { + *pinmuxes[miso_pad] = miso_pinmux; + } config_spi_master.mode_specific.master.baudrate = baudrate; diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c index 4b6b1bacb9..ea8c2f255e 100644 --- a/shared-bindings/bitbangio/SPI.c +++ b/shared-bindings/bitbangio/SPI.c @@ -68,8 +68,8 @@ STATIC mp_obj_t bitbangio_spi_make_new(const mp_obj_type_t *type, size_t 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_MOSI, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_MISO, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { 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} }, diff --git a/shared-module/bitbangio/SPI.c b/shared-module/bitbangio/SPI.c index 5d77efaf97..07322abd78 100644 --- a/shared-module/bitbangio/SPI.c +++ b/shared-module/bitbangio/SPI.c @@ -26,6 +26,7 @@ #include "mpconfigport.h" +#include "py/nlr.h" #include "py/obj.h" #include "common-hal/microcontroller/types.h" @@ -40,18 +41,29 @@ extern void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, const mcu_pin_obj_t * miso, uint32_t baudrate) { digitalinout_result_t result = common_hal_nativeio_digitalinout_construct(&self->clock, clock); if (result != DIGITALINOUT_OK) { - return; + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, + "Clock pin init failed.")); } - result = common_hal_nativeio_digitalinout_construct(&self->mosi, mosi); - if (result != DIGITALINOUT_OK) { - common_hal_nativeio_digitalinout_deinit(&self->clock); - return; + if (mosi != mp_const_none) { + result = common_hal_nativeio_digitalinout_construct(&self->mosi, mosi); + if (result != DIGITALINOUT_OK) { + common_hal_nativeio_digitalinout_deinit(&self->clock); + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, + "MOSI pin init failed.")); + } + self->has_mosi = true; } - result = common_hal_nativeio_digitalinout_construct(&self->miso, miso); - if (result != DIGITALINOUT_OK) { - common_hal_nativeio_digitalinout_deinit(&self->clock); - common_hal_nativeio_digitalinout_deinit(&self->mosi); - return; + if (miso != mp_const_none) { + result = common_hal_nativeio_digitalinout_construct(&self->miso, miso); + if (result != DIGITALINOUT_OK) { + common_hal_nativeio_digitalinout_deinit(&self->clock); + if (mosi != mp_const_none) { + common_hal_nativeio_digitalinout_deinit(&self->mosi); + } + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, + "MISO pin init failed.")); + } + self->has_miso = true; } self->delay_half = 500000 / baudrate; @@ -66,13 +78,25 @@ extern void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, extern void shared_module_bitbangio_spi_deinit(bitbangio_spi_obj_t *self) { common_hal_nativeio_digitalinout_deinit(&self->clock); - common_hal_nativeio_digitalinout_deinit(&self->mosi); - common_hal_nativeio_digitalinout_deinit(&self->miso); + if (self->has_mosi) { + common_hal_nativeio_digitalinout_deinit(&self->mosi); + } + if (self->has_miso) { + common_hal_nativeio_digitalinout_deinit(&self->miso); + } } bool shared_module_bitbangio_spi_transfer(bitbangio_spi_obj_t *self, const uint8_t *write_buffer, size_t write_buffer_len, uint8_t *read_buffer, size_t read_buffer_len) { + if (write_buffer_len > 0 && !self->has_mosi) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, + "Cannot write without MOSI pin.")); + } + if (read_buffer_len > 0 && !self->has_miso) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, + "Cannot read without MISO pin.")); + } uint32_t delay_half = self->delay_half; // only MSB transfer is implemented @@ -95,7 +119,9 @@ bool shared_module_bitbangio_spi_transfer(bitbangio_spi_obj_t *self, } // Clock out zeroes while we read. - common_hal_nativeio_digitalinout_set_value(&self->mosi, false); + if (self->has_mosi) { + common_hal_nativeio_digitalinout_set_value(&self->mosi, false); + } for (size_t i = 0; i < read_buffer_len; ++i) { uint8_t data_in = 0; for (int j = 0; j < 8; ++j, data_out <<= 1) { @@ -135,7 +161,9 @@ bool shared_module_bitbangio_spi_transfer(bitbangio_spi_obj_t *self, MICROPY_EVENT_POLL_HOOK; #endif } - common_hal_nativeio_digitalinout_set_value(&self->mosi, false); + if (self->has_mosi) { + common_hal_nativeio_digitalinout_set_value(&self->mosi, false); + } for (size_t i = 0; i < read_buffer_len; ++i) { uint8_t data_in = 0; for (int j = 0; j < 8; ++j) { diff --git a/shared-module/bitbangio/types.h b/shared-module/bitbangio/types.h index e6a29ab54c..e7fd95498b 100644 --- a/shared-module/bitbangio/types.h +++ b/shared-module/bitbangio/types.h @@ -41,7 +41,9 @@ typedef struct { typedef struct { mp_obj_base_t base; nativeio_digitalinout_obj_t clock; + bool has_mosi; nativeio_digitalinout_obj_t mosi; + bool has_miso; nativeio_digitalinout_obj_t miso; uint32_t delay_half; uint8_t polarity;