From cf4af09e9a20e9cdaec4b3896eb6d10c27f89eba Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Mon, 26 May 2025 14:58:07 -0400 Subject: No more (static inline) function bodies in headers --- libhw_cr/w5500_ll.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 libhw_cr/w5500_ll.c (limited to 'libhw_cr/w5500_ll.c') diff --git a/libhw_cr/w5500_ll.c b/libhw_cr/w5500_ll.c new file mode 100644 index 0000000..d9f4fc5 --- /dev/null +++ b/libhw_cr/w5500_ll.c @@ -0,0 +1,105 @@ +/* libhw_cr/w5500_ll.c - Low-level library for the WIZnet W5500 chip + * + * Based entirely on the W5500 datasheet, v1.1.0. + * https://docs.wiznet.io/img/products/w5500/W5500_ds_v110e.pdf + * + * Copyright (C) 2024-2025 Luke T. Shumaker + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include /* for stack_alloc() */ +#include + +#include "w5500_ll.h" + +#if CONFIG_W5500_LL_DEBUG +static void fmt_print_ctl_block(lo_interface fmt_dest, uint8_t b) { + static char *strs[] = { + "RES", + "REG", + "TX", + "RX", + }; + fmt_print("CTL_BLOCK_SOCK(", (base10, (((b)>>5) & 0b111)), ", ", strs[((b)>>3)&0b11], ")"); +} +#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) +{ + assert(!LO_IS_NULL(spidev)); + assert((block & ~CTL_MASK_BLOCK) == 0); + assert(iov); + assert(iovcnt > 0); +#if CONFIG_W5500_LL_DEBUG + log_n_debugln(W5500_LL, + func, "(): w5500ll_write(spidev", + ", addr=", (base16_u16_, addr), + ", block=", (ctl_block, block), + ", iov", + ", iovcnt=", iovcnt, + ")"); +#endif + + uint8_t header[] = { + (uint8_t)((addr >> 8) & 0xFF), + (uint8_t)(addr & 0xFF), + (block & CTL_MASK_BLOCK) | CTL_W | CTL_OM_VDM, + }; + int inner_cnt = 1+io_slice_cnt(iov, iovcnt, skip, max); + struct duplex_iovec *inner = stack_alloc(inner_cnt, struct duplex_iovec); + inner[0] = (struct duplex_iovec){ + .iov_read_to = IOVEC_DISCARD, + .iov_write_from = header, + .iov_len = sizeof(header), + }; + io_slice_wr_to_duplex(&inner[1], iov, iovcnt, skip, max); + 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) +{ + assert(!LO_IS_NULL(spidev)); + assert((block & ~CTL_MASK_BLOCK) == 0); + assert(iov); + assert(iovcnt > 0); +#if CONFIG_W5500_LL_DEBUG + log_n_debugln(W5500_LL, + func, "(): w5500ll_read(spidev", + ", addr=", (base16_u16_, addr), + ", block=", (ctl_block, block), + ", iov", + ", iovcnt=", iovcnt, + ")"); +#endif + + uint8_t header[] = { + (uint8_t)((addr >> 8) & 0xFF), + (uint8_t)(addr & 0xFF), + (block & CTL_MASK_BLOCK) | CTL_R | CTL_OM_VDM, + }; + int inner_cnt = 1+io_slice_cnt(iov, iovcnt, 0, max); + struct duplex_iovec *inner = stack_alloc(inner_cnt, struct duplex_iovec); + inner[0] = (struct duplex_iovec){ + .iov_read_to = IOVEC_DISCARD, + .iov_write_from = header, + .iov_len = sizeof(header), + }; + io_slice_rd_to_duplex(&inner[1], iov, iovcnt, 0, max); + LO_CALL(spidev, readwritev, inner, inner_cnt); +} -- cgit v1.2.3-2-g168b From c50edb6000c9ac10f0cc3d5d9f43f82ec2041e56 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Mon, 26 May 2025 18:16:57 -0400 Subject: Try to clean up w5500_ll.h --- libhw_cr/w5500_ll.c | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'libhw_cr/w5500_ll.c') 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 * SPDX-License-Identifier: AGPL-3.0-or-later */ +#include /* for memcmp() and mempy() */ + #include /* for stack_alloc() */ #include @@ -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); + } +} -- cgit v1.2.3-2-g168b