From bd7abcda970e4e6ecd0f64621536870b49185594 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 25 Oct 2017 14:28:23 -0700 Subject: shared-bindings: Check that I2C and SPI reads and writes are given a buffer of at least 1. (#370) Fixes #358 --- shared-bindings/busio/I2C.c | 8 ++++++++ shared-bindings/busio/SPI.c | 8 ++++++++ 2 files changed, 16 insertions(+) (limited to 'shared-bindings/busio') diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index cdc960f80..dc1997034 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -201,6 +201,10 @@ STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, int32_t start = args[ARG_start].u_int; uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + if (length == 0) { + mp_raise_ValueError("Buffer must be at least length 1"); + } + uint8_t status = common_hal_busio_i2c_read(self, args[ARG_address].u_int, ((uint8_t*)bufinfo.buf) + start, length); if (status != 0) { mp_raise_OSError(status); @@ -250,6 +254,10 @@ STATIC mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_ma uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + if (length == 0) { + mp_raise_ValueError("Buffer must be at least length 1"); + } + // do the transfer uint8_t status = common_hal_busio_i2c_write(self, args[ARG_address].u_int, ((uint8_t*) bufinfo.buf) + start, length, args[ARG_stop].u_bool); diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index 12f888f23..dc136564d 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -231,6 +231,10 @@ STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_ uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + if (length == 0) { + mp_raise_ValueError("Buffer must be at least length 1"); + } + bool ok = common_hal_busio_spi_write(self, ((uint8_t*)bufinfo.buf) + start, length); if (!ok) { mp_raise_OSError(MP_EIO); @@ -269,6 +273,10 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + if (length == 0) { + mp_raise_ValueError("Buffer must be at least length 1"); + } + bool ok = common_hal_busio_spi_read(self, ((uint8_t*)bufinfo.buf) + start, length, args[ARG_write_value].u_int); if (!ok) { mp_raise_OSError(MP_EIO); -- cgit v1.2.3 From f738996164fc270015fdb53ee38b24f7823cbbd8 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 30 Oct 2017 19:32:03 -0400 Subject: Allow writing buffer of length zero to I2C device; it can be used to poll for existence. --- shared-bindings/busio/I2C.c | 8 ++++---- shared-bindings/busio/SPI.c | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'shared-bindings/busio') diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index dc1997034..b0954d6c8 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -171,6 +171,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock); //| //| Read into ``buffer`` from the slave specified by ``address``. //| The number of bytes read will be the length of ``buffer``. +//| At least one byte must be read. //| //| If ``start`` or ``end`` is provided, then the buffer will be sliced //| as if ``buffer[start:end]``. This will not cause an allocation like @@ -223,6 +224,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_in //| as if ``buffer[start:end]``. This will not cause an allocation like //| ``buffer[start:end]`` will so it saves memory. //| +//| Writing a buffer or slice of length zero is permitted, as it can be used +//| to poll for the existence of a device. +//| //| :param int address: 7-bit device address //| :param bytearray buffer: buffer containing the bytes to write //| :param int start: Index to start writing from @@ -254,10 +258,6 @@ STATIC mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_ma uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); - if (length == 0) { - mp_raise_ValueError("Buffer must be at least length 1"); - } - // do the transfer uint8_t status = common_hal_busio_i2c_write(self, args[ARG_address].u_int, ((uint8_t*) bufinfo.buf) + start, length, args[ARG_stop].u_bool); diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index dc136564d..add541aa7 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -207,6 +207,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock); //| .. method:: SPI.write(buffer, \*, start=0, end=len(buffer)) //| //| Write the data contained in ``buf``. Requires the SPI being locked. +//| At least one byte must be written. //| //| :param bytearray buffer: buffer containing the bytes to write //| :param int start: Index to start writing from @@ -247,6 +248,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write); //| .. method:: SPI.readinto(buffer, \*, start=0, end=len(buffer), write_value=0) //| //| Read into the buffer specified by ``buf`` while writing zeroes. Requires the SPI being locked. +//| At least one byte must be read. //| //| :param bytearray buffer: buffer to write into //| :param int start: Index to start writing at -- cgit v1.2.3 From 78f6c2232ca08f80ed96d2f1ef365f5f749fec1c Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Fri, 3 Nov 2017 15:44:13 +0100 Subject: Allow empty reads and writes for busio.SPI This is mostly for convenience, so that user code doesn't need to add additional checks. Also, bring the bitbangio into compatibility with busio wrt. empty buffers. --- shared-bindings/bitbangio/I2C.c | 7 +++++++ shared-bindings/bitbangio/SPI.c | 11 ++++++++++- shared-bindings/busio/SPI.c | 11 ++++++----- 3 files changed, 23 insertions(+), 6 deletions(-) (limited to 'shared-bindings/busio') diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c index 80718090a..f8f60210e 100644 --- a/shared-bindings/bitbangio/I2C.c +++ b/shared-bindings/bitbangio/I2C.c @@ -157,6 +157,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock); //| //| Read into ``buffer`` from the slave specified by ``address``. //| The number of bytes read will be the length of ``buffer``. +//| At least one byte must be read. //| //| If ``start`` or ``end`` is provided, then the buffer will be sliced //| as if ``buffer[start:end]``. This will not cause an allocation like @@ -186,6 +187,9 @@ STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_a int32_t start = args[ARG_start].u_int; uint32_t length = bufinfo.len; normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + if (length == 0) { + mp_raise_ValueError("Buffer must be at least length 1"); + } uint8_t status = shared_module_bitbangio_i2c_read(self, args[ARG_address].u_int, ((uint8_t*)bufinfo.buf) + start, @@ -206,6 +210,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_rea //| as if ``buffer[start:end]``. This will not cause an allocation like //| ``buffer[start:end]`` will so it saves memory. //| +//| Writing a buffer or slice of length zero is permitted, as it can be used +//| to poll for the existence of a device. +//| //| :param int address: 7-bit device address //| :param bytearray buffer: buffer containing the bytes to write //| :param int start: Index to start writing from diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c index 6c7bac3e5..5442b9ea2 100644 --- a/shared-bindings/bitbangio/SPI.c +++ b/shared-bindings/bitbangio/SPI.c @@ -191,6 +191,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_unlock_obj, bitbangio_spi_obj_unlock); //| .. method:: SPI.write(buf) //| //| Write the data contained in ``buf``. Requires the SPI being locked. +//| If the buffer is empty, nothing happens. //| // TODO(tannewt): Add support for start and end kwargs. STATIC mp_obj_t bitbangio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) { @@ -198,6 +199,9 @@ STATIC mp_obj_t bitbangio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) { raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self)); mp_buffer_info_t src; mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); + if (src.len == 0) { + return mp_const_none; + } check_lock(self); bool ok = shared_module_bitbangio_spi_write(self, src.buf, src.len); if (!ok) { @@ -210,7 +214,9 @@ MP_DEFINE_CONST_FUN_OBJ_2(bitbangio_spi_write_obj, bitbangio_spi_write); //| .. method:: SPI.readinto(buf) //| -//| Read into the buffer specified by ``buf`` while writing zeroes. Requires the SPI being locked. +//| Read into the buffer specified by ``buf`` while writing zeroes. +//| Requires the SPI being locked. +//| If the number of bytes to read is 0, nothing happens. //| // TODO(tannewt): Add support for start and end kwargs. STATIC mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *args) { @@ -218,6 +224,9 @@ STATIC mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *args) { raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self)); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); + if (bufinfo.len == 0) { + return mp_const_none; + } check_lock(args[0]); bool ok = shared_module_bitbangio_spi_read(self, bufinfo.buf, bufinfo.len); if (!ok) { diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index add541aa7..72787af30 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -207,7 +207,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock); //| .. method:: SPI.write(buffer, \*, start=0, end=len(buffer)) //| //| Write the data contained in ``buf``. Requires the SPI being locked. -//| At least one byte must be written. +//| If the buffer is empty, nothing happens. //| //| :param bytearray buffer: buffer containing the bytes to write //| :param int start: Index to start writing from @@ -233,7 +233,7 @@ STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_ normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); if (length == 0) { - mp_raise_ValueError("Buffer must be at least length 1"); + return mp_const_none; } bool ok = common_hal_busio_spi_write(self, ((uint8_t*)bufinfo.buf) + start, length); @@ -247,8 +247,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write); //| .. method:: SPI.readinto(buffer, \*, start=0, end=len(buffer), write_value=0) //| -//| Read into the buffer specified by ``buf`` while writing zeroes. Requires the SPI being locked. -//| At least one byte must be read. +//| Read into the buffer specified by ``buf`` while writing zeroes. +//| Requires the SPI being locked. +//| If the number of bytes to read is 0, nothing happens. //| //| :param bytearray buffer: buffer to write into //| :param int start: Index to start writing at @@ -276,7 +277,7 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); if (length == 0) { - mp_raise_ValueError("Buffer must be at least length 1"); + return mp_const_none; } bool ok = common_hal_busio_spi_read(self, ((uint8_t*)bufinfo.buf) + start, length, args[ARG_write_value].u_int); -- cgit v1.2.3 From e75fd0e166375727fbb4c054478c9c8d329477c4 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 4 Dec 2017 21:49:31 -0500 Subject: add SPI.write_readinto() - bidirectional SPI --- atmel-samd/common-hal/busio/SPI.c | 13 ++++++ atmel-samd/shared_dma.c | 18 ++++++--- atmel-samd/shared_dma.h | 1 + shared-bindings/busio/SPI.c | 83 ++++++++++++++++++++++++++++++++++----- shared-bindings/busio/SPI.h | 3 ++ 5 files changed, 103 insertions(+), 15 deletions(-) (limited to 'shared-bindings/busio') diff --git a/atmel-samd/common-hal/busio/SPI.c b/atmel-samd/common-hal/busio/SPI.c index c1b13cec8..e5a945df2 100644 --- a/atmel-samd/common-hal/busio/SPI.c +++ b/atmel-samd/common-hal/busio/SPI.c @@ -257,3 +257,16 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, } return status == STATUS_OK; } + +bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) { + if (len == 0) { + return true; + } + enum status_code status; + if (len >= 16) { + status = shared_dma_transfer(self->spi_master_instance.hw, data_out, data_in, len, 0 /*ignored*/); + } else { + status = spi_transceive_buffer_wait(&self->spi_master_instance, data_out, data_in, len); + } + return status == STATUS_OK; +} diff --git a/atmel-samd/shared_dma.c b/atmel-samd/shared_dma.c index 461798366..c0f0d4672 100644 --- a/atmel-samd/shared_dma.c +++ b/atmel-samd/shared_dma.c @@ -103,7 +103,7 @@ enum status_code shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_ } dma_configure(general_dma_tx.channel_id, sercom_index(sercom) * 2 + 2, false); - // Set up TX second. + // Set up TX. There is no RX job. struct dma_descriptor_config descriptor_config; dma_descriptor_get_config_defaults(&descriptor_config); descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE; @@ -137,6 +137,12 @@ enum status_code shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_ } enum status_code shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx) { + return shared_dma_transfer(sercom, NULL, buffer, length, tx); +} + +// Do write and read simultaneously. If buffer_out is NULL, write the tx byte over and over. +// If buffer_out is a real buffer, ignore tx. +enum status_code shared_dma_transfer(Sercom* sercom, uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length, uint8_t tx) { if (general_dma_tx.job_status != STATUS_OK) { return general_dma_tx.job_status; } @@ -153,17 +159,19 @@ enum status_code shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t lengt descriptor_config.block_transfer_count = length; // DATA register is consistently addressed across all SERCOM modes. descriptor_config.source_address = ((uint32_t)&sercom->SPI.DATA.reg); - descriptor_config.destination_address = ((uint32_t)buffer + length); + descriptor_config.destination_address = ((uint32_t)buffer_in + length); dma_descriptor_create(general_dma_rx.descriptor, &descriptor_config); - // Set up TX to retransmit the same byte over and over. + // Set up TX second. dma_descriptor_get_config_defaults(&descriptor_config); descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE; - descriptor_config.src_increment_enable = false; + // Increment write address only if we have a real buffer. + descriptor_config.src_increment_enable = buffer_out != NULL; descriptor_config.dst_increment_enable = false; descriptor_config.block_transfer_count = length; - descriptor_config.source_address = ((uint32_t)&tx); + // + descriptor_config.source_address = ((uint32_t) (buffer_out != NULL ? buffer_out + length : &tx)); // DATA register is consistently addressed across all SERCOM modes. descriptor_config.destination_address = ((uint32_t)&sercom->SPI.DATA.reg); diff --git a/atmel-samd/shared_dma.h b/atmel-samd/shared_dma.h index 7aa45547d..251b8357b 100644 --- a/atmel-samd/shared_dma.h +++ b/atmel-samd/shared_dma.h @@ -39,6 +39,7 @@ void init_shared_dma(void); enum status_code shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length); enum status_code shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx); +enum status_code shared_dma_transfer(Sercom* sercom, uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length, uint8_t tx); // Allocate a counter to track how far along we are in a DMA double buffer. bool allocate_block_counter(void); diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index 72787af30..c4c139105 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -206,12 +206,12 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock); //| .. method:: SPI.write(buffer, \*, start=0, end=len(buffer)) //| -//| Write the data contained in ``buf``. Requires the SPI being locked. +//| Write the data contained in ``buffer``. The SPI object must be locked. //| If the buffer is empty, nothing happens. //| -//| :param bytearray buffer: buffer containing the bytes to write -//| :param int start: Index to start writing from -//| :param int end: Index to read up to but not include +//| :param bytearray buffer: Write out the data in this buffer +//| :param int start: Start of the slice of ``buffer`` to write out: ``buffer[start:end]`` +//| :param int end: End of the slice; this index is not included //| STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end }; @@ -247,14 +247,14 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write); //| .. method:: SPI.readinto(buffer, \*, start=0, end=len(buffer), write_value=0) //| -//| Read into the buffer specified by ``buf`` while writing zeroes. -//| Requires the SPI being locked. +//| Read into ``buffer`` while writing ``write_value`` for each byte read. +//| The SPI object must be locked. //| If the number of bytes to read is 0, nothing happens. //| -//| :param bytearray buffer: buffer to write into -//| :param int start: Index to start writing at -//| :param int end: Index to write up to but not include -//| :param int write_value: Value to write reading. (Usually ignored.) +//| :param bytearray buffer: Read data into this buffer +//| :param int start: Start of the slice of ``buffer`` to read into: ``buffer[start:end]`` +//| :param int end: End of the slice; this index is not included +//| :param int write_value: Value to write while reading. (Usually ignored.) //| STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value }; @@ -288,6 +288,68 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m } MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_readinto_obj, 2, busio_spi_readinto); +//| .. method:: SPI.write_readinto(buffer_out, buffer_in, \*, out_start=0, out_end=len(buffer_out), in_start=0, in_end=len(buffer_in)) +//| +//| Write out the data in ``buffer_out`` while simultaneously reading data into ``buffer_in``. +//| The SPI object must be locked. +//| The lengths of the slices defined by ``buffer_out[out_start:out_end]`` and ``buffer_in[in_start:in_end]`` +//| must be equal. +//| If buffer slice lengths are both 0, nothing happens. +//| +//| :param bytearray buffer_out: Write out the data in this buffer +//| :param bytearray buffer_in: Read data into this buffer +//| :param int out_start: Start of the slice of buffer_out to write out: ``buffer_out[out_start:out_end]`` +//| :param int out_end: End of the slice; this index is not included +//| :param int in_start: Start of the slice of ``buffer_in`` to read into: ``buffer_in[in_start:in_end]`` +//| :param int in_end: End of the slice; this index is not included +//| +STATIC mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_buffer_out, ARG_buffer_in, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_buffer_out, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_buffer_in, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + }; + busio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + raise_error_if_deinited(common_hal_busio_spi_deinited(self)); + check_lock(self); + 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); + + mp_buffer_info_t buf_out_info; + mp_get_buffer_raise(args[ARG_buffer_out].u_obj, &buf_out_info, MP_BUFFER_READ); + int32_t out_start = args[ARG_out_start].u_int; + uint32_t out_length = buf_out_info.len; + normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length); + + mp_buffer_info_t buf_in_info; + mp_get_buffer_raise(args[ARG_buffer_in].u_obj, &buf_in_info, MP_BUFFER_WRITE); + int32_t in_start = args[ARG_in_start].u_int; + uint32_t in_length = buf_in_info.len; + normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length); + + if (out_length != in_length) { + mp_raise_ValueError("buffer slices must be of equal length"); + } + + if (out_length == 0) { + return mp_const_none; + } + + bool ok = common_hal_busio_spi_transfer(self, + ((uint8_t*)buf_out_info.buf) + out_start, + ((uint8_t*)buf_in_info.buf) + in_start, + out_length); + if (!ok) { + mp_raise_OSError(MP_EIO); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_readinto_obj, 2, busio_spi_write_readinto); + STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_spi_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, @@ -299,6 +361,7 @@ STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&busio_spi_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&busio_spi_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&busio_spi_write_readinto_obj) }, }; STATIC MP_DEFINE_CONST_DICT(busio_spi_locals_dict, busio_spi_locals_dict_table); diff --git a/shared-bindings/busio/SPI.h b/shared-bindings/busio/SPI.h index ac31d5060..b6e5c9b1b 100644 --- a/shared-bindings/busio/SPI.h +++ b/shared-bindings/busio/SPI.h @@ -55,4 +55,7 @@ extern bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *dat // Reads in len bytes while outputting zeroes. extern bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value); +// Reads and write len bytes simultaneously. +extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H -- cgit v1.2.3