diff options
Diffstat (limited to 'libhw_cr')
-rw-r--r-- | libhw_cr/rp2040_hwspi.c | 8 | ||||
-rw-r--r-- | libhw_cr/rp2040_include/libhw/rp2040_hwspi.h | 2 | ||||
-rw-r--r-- | libhw_cr/w5500_ll.h | 63 |
3 files changed, 19 insertions, 54 deletions
diff --git a/libhw_cr/rp2040_hwspi.c b/libhw_cr/rp2040_hwspi.c index 7b57792..d4adb11 100644 --- a/libhw_cr/rp2040_hwspi.c +++ b/libhw_cr/rp2040_hwspi.c @@ -185,23 +185,23 @@ static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct dupl if (!iov[i].iov_len) continue; tx_data_blocks[j] = (typeof(tx_data_blocks[0])){ - .read_addr = iov[i].iov_write_src ?: &self->bogus_data, + .read_addr = (iov[i].iov_write_from != IOVEC_DISCARD) ? iov[i].iov_write_from : &self->bogus_data, .write_addr = &spi_get_hw(self->inst)->dr, .trans_count = iov[i].iov_len, .ctrl = (DMA_CTRL_ENABLE | DMA_CTRL_DATA_SIZE(DMA_SIZE_8) - | (iov[i].iov_write_src ? DMA_CTRL_INCR_READ : 0) + | ((iov[i].iov_write_from != IOVEC_DISCARD) ? DMA_CTRL_INCR_READ : 0) | DMA_CTRL_CHAIN_TO(self->dma_tx_ctrl) | DMA_CTRL_TREQ_SEL(SPI_DREQ_NUM(self->inst, true)) | DMA_CTRL_IRQ_QUIET), }; rx_data_blocks[j] = (typeof(rx_data_blocks[0])){ .read_addr = &spi_get_hw(self->inst)->dr, - .write_addr = iov[i].iov_read_dst ?: &bogus_rx_dst, + .write_addr = (iov[i].iov_read_to != IOVEC_DISCARD) ? iov[i].iov_read_to : &bogus_rx_dst, .trans_count = iov[i].iov_len, .ctrl = (DMA_CTRL_ENABLE | DMA_CTRL_DATA_SIZE(DMA_SIZE_8) - | (iov[i].iov_read_dst ? DMA_CTRL_INCR_WRITE : 0) + | ((iov[i].iov_read_to != IOVEC_DISCARD) ? DMA_CTRL_INCR_WRITE : 0) | DMA_CTRL_CHAIN_TO(self->dma_rx_ctrl) | DMA_CTRL_TREQ_SEL(SPI_DREQ_NUM(self->inst, false)) | DMA_CTRL_IRQ_QUIET), diff --git a/libhw_cr/rp2040_include/libhw/rp2040_hwspi.h b/libhw_cr/rp2040_include/libhw/rp2040_hwspi.h index eb54cdc..9d99f7b 100644 --- a/libhw_cr/rp2040_include/libhw/rp2040_hwspi.h +++ b/libhw_cr/rp2040_include/libhw/rp2040_hwspi.h @@ -48,7 +48,7 @@ LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi) * @param mode : enum spi_mode : the SPI mode; SPI_MODE_{0..3} * @param baudrate_hz : uint : baudrate in Hz * @param min_delay_ns: uint64_t : minimum time for pin_cs to be high between messages - * @param bogus_data : uint8_t : bogus data to write when .iov_write_src is NULL + * @param bogus_data : uint8_t : bogus data to write when .iov_write_from is IOVEC_DISCARD * @param pin_miso : uint : pin number; 0, 4, 16, or 20 for _HWSPI_0; 8, 12, 24, or 28 for _HWSPI_1 * @param pin_mosi : uint : pin number; 3, 7, 19, or 23 for _HWSPI_0; 11, 15, or 27 for _HWSPI_1 * @param pin_clk : uint : pin number; 2, 6, 18, or 22 for _HWSPI_0; 10, 14, or 26 for _HWSPI_1 diff --git a/libhw_cr/w5500_ll.h b/libhw_cr/w5500_ll.h index 8f5f9ec..2506cd2 100644 --- a/libhw_cr/w5500_ll.h +++ b/libhw_cr/w5500_ll.h @@ -93,39 +93,15 @@ w5500ll_writev( (uint8_t)(addr & 0xFF), (block & CTL_MASK_BLOCK) | CTL_W | CTL_OM_VDM, }; - struct duplex_iovec *inner = alloca(sizeof(struct duplex_iovec)*(iovcnt+1)); + int inner_cnt = 1+io_slice_cnt(iov, iovcnt, skip, max); + struct duplex_iovec *inner = alloca(sizeof(struct duplex_iovec)*inner_cnt); inner[0] = (struct duplex_iovec){ - .iov_read_dst = NULL, - .iov_write_src = header, - .iov_len = sizeof(header), + .iov_read_to = IOVEC_DISCARD, + .iov_write_from = header, + .iov_len = sizeof(header), }; - int j = 1; - size_t skipped = 0, done = 0; - for (int i = 0; i < iovcnt && (max == 0 || done < max); i++) { - if (skipped < skip) { - if (skip - skipped >= iov[i].iov_len) { - skipped += iov[i].iov_len; - continue; - } - inner[j] = (struct duplex_iovec){ - .iov_read_dst = NULL, - .iov_write_src = iov[i].iov_base+(skip-skipped), - .iov_len = iov[i].iov_len-(skip-skipped), - }; - skipped = skip; - } else { - inner[j] = (struct duplex_iovec){ - .iov_read_dst = NULL, - .iov_write_src = iov[i].iov_base, - .iov_len = iov[i].iov_len, - }; - } - done += inner[j].iov_len; - if (max > 0 && done > max) - inner[j].iov_len -= done - max; - j++; - }; - LO_CALL(spidev, readwritev, inner, j); + io_slice_wr_to_duplex(&inner[1], iov, iovcnt, skip, max); + LO_CALL(spidev, readwritev, inner, inner_cnt); } static inline void @@ -154,26 +130,15 @@ w5500ll_readv( (uint8_t)(addr & 0xFF), (block & CTL_MASK_BLOCK) | CTL_R | CTL_OM_VDM, }; - struct duplex_iovec *inner = alloca(sizeof(struct duplex_iovec)*(iovcnt+1)); + int inner_cnt = 1+io_slice_cnt(iov, iovcnt, 0, max); + struct duplex_iovec *inner = alloca(sizeof(struct duplex_iovec)*inner_cnt); inner[0] = (struct duplex_iovec){ - .iov_read_dst = NULL, - .iov_write_src = header, - .iov_len = sizeof(header), - }; - int j = 1; - size_t done = 0; - for (int i = 0; i < iovcnt && (max == 0 || done < max); i++) { - inner[j] = (struct duplex_iovec){ - .iov_read_dst = iov[i].iov_base, - .iov_write_src = NULL, - .iov_len = iov[i].iov_len, - }; - done += inner[j].iov_len; - if (max > 0 && done > max) - inner[j].iov_len -= done - max; - j++; + .iov_read_to = IOVEC_DISCARD, + .iov_write_from = header, + .iov_len = sizeof(header), }; - LO_CALL(spidev, readwritev, inner, j); + io_slice_rd_to_duplex(&inner[1], iov, iovcnt, 0, max); + LO_CALL(spidev, readwritev, inner, inner_cnt); } /* Common chip-wide registers. ***********************************************/ |