hw/bus/spi_hal: Add bus_spi_write_read
This implements new bus driver write_read function for
spi_hal bus driver implementation.
For short transactions (up to 16) bytes, function performs
single SPI transfer that can reduce transaction time by half
or more depending on hal_spi MCU implementation.
diff --git a/hw/bus/drivers/spi_hal/src/spi_hal.c b/hw/bus/drivers/spi_hal/src/spi_hal.c
index 26c6db7..26e30a2 100644
--- a/hw/bus/drivers/spi_hal/src/spi_hal.c
+++ b/hw/bus/drivers/spi_hal/src/spi_hal.c
@@ -191,6 +191,66 @@
return rc;
}
+static int
+bus_spi_write_read(struct bus_dev *bdev, struct bus_node *bnode,
+ const uint8_t *wbuf, uint16_t wlength,
+ uint8_t *rbuf, uint16_t rlength,
+ os_time_t timeout, uint16_t flags)
+{
+ struct bus_spi_hal_dev *dev = (struct bus_spi_hal_dev *)bdev;
+ struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+ int rc;
+ uint8_t buf[16];
+
+ BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+ BUS_DEBUG_VERIFY_NODE(node);
+
+ hal_gpio_write(node->pin_cs, 0);
+
+ /* XXX update HAL to accept const instead */
+
+#if MYNEWT_VAL(SPI_HAL_USE_NOBLOCK)
+ if (wlength + rlength <= sizeof(buf)) {
+ memcpy(buf, wbuf, wlength);
+ memset(buf + wlength, 0, rlength);
+ rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+ if (rc == 0) {
+ os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+ memcpy(rbuf, buf + wlength, rlength);
+ }
+ } else {
+ rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+ if (rc == 0) {
+ os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+ memset(rbuf, 0, rlength);
+ rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, rbuf, rbuf, rlength);
+ if (rc == 0) {
+ os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+ }
+ }
+ }
+#else
+ if (wlength + rlength <= sizeof(buf)) {
+ memcpy(buf, wbuf, wlength);
+ rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+ if (rc == 0) {
+ memcpy(rbuf, buf + wlength, rlength);
+ }
+ } else {
+ rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+ if (rc == 0) {
+ rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, NULL, rbuf, rlength);
+ }
+ }
+#endif
+
+ if (!(flags & BUS_F_NOSTOP)) {
+ hal_gpio_write(node->pin_cs, 1);
+ }
+
+ return rc;
+}
+
static int bus_spi_disable(struct bus_dev *bdev)
{
struct bus_spi_dev *spi_dev = (struct bus_spi_dev *)bdev;
@@ -213,6 +273,7 @@
.read = bus_spi_read,
.write = bus_spi_write,
.disable = bus_spi_disable,
+ .write_read = bus_spi_write_read,
};
int