summaryrefslogtreecommitdiff
path: root/libhw_cr/w5500_ll.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhw_cr/w5500_ll.c')
-rw-r--r--libhw_cr/w5500_ll.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/libhw_cr/w5500_ll.c b/libhw_cr/w5500_ll.c
index d9f4fc5..c60e045 100644
--- a/libhw_cr/w5500_ll.c
+++ b/libhw_cr/w5500_ll.c
@@ -1,12 +1,14 @@
/* libhw_cr/w5500_ll.c - Low-level library for the WIZnet W5500 chip
*
- * Based entirely on the W5500 datasheet, v1.1.0.
+ * Based entirely on the W5500 datasheet (v1.1.0), not on reference code.
* https://docs.wiznet.io/img/products/w5500/W5500_ds_v110e.pdf
*
* Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+#include <string.h> /* for memcmp() and mempy() */
+
#include <libmisc/alloc.h> /* for stack_alloc() */
#include <libmisc/fmt.h>
@@ -24,15 +26,10 @@ static void fmt_print_ctl_block(lo_interface fmt_dest, uint8_t b) {
}
#endif
-void
-#if CONFIG_W5500_LL_DEBUG
-_w5500ll_writev(const char *func,
-#else
-w5500ll_writev(
-#endif
- lo_interface spi spidev, uint16_t addr, uint8_t block,
- const struct iovec *iov, int iovcnt,
- size_t skip, size_t max)
+void _w5500ll_n_writev(const char *func,
+ lo_interface spi spidev, uint16_t addr, uint8_t block,
+ const struct iovec *iov, int iovcnt,
+ size_t skip, size_t max)
{
assert(!LO_IS_NULL(spidev));
assert((block & ~CTL_MASK_BLOCK) == 0);
@@ -64,15 +61,11 @@ w5500ll_writev(
LO_CALL(spidev, readwritev, inner, inner_cnt);
}
-void
-#if CONFIG_W5500_LL_DEBUG
-_w5500ll_readv(const char *func,
-#else
-w5500ll_readv(
-#endif
- lo_interface spi spidev, uint16_t addr, uint8_t block,
- const struct iovec *iov, int iovcnt,
- size_t max)
+
+void _w5500ll_n_readv(const char *func,
+ lo_interface spi spidev, uint16_t addr, uint8_t block,
+ const struct iovec *iov, int iovcnt,
+ size_t max)
{
assert(!LO_IS_NULL(spidev));
assert((block & ~CTL_MASK_BLOCK) == 0);
@@ -103,3 +96,20 @@ w5500ll_readv(
io_slice_rd_to_duplex(&inner[1], iov, iovcnt, 0, max);
LO_CALL(spidev, readwritev, inner, inner_cnt);
}
+
+void _w5500ll_n_read_repeated(const char *func,
+ lo_interface spi spidev, uint16_t addr, uint8_t block,
+ void *buf, void *buf_scratch, size_t len)
+{
+ _w5500ll_n_readv(func, spidev, addr, block,
+ &((struct iovec){.iov_base=buf, .iov_len=len}), 1,
+ 0);
+ for (;;) {
+ _w5500ll_n_readv(func, spidev, addr, block,
+ &((struct iovec){.iov_base=buf_scratch, .iov_len=len}), 1,
+ 0);
+ if (memcmp(buf, buf_scratch, len) == 0)
+ break;
+ memcpy(buf, buf_scratch, len);
+ }
+}