diff options
Diffstat (limited to 'libhw_cr')
-rw-r--r-- | libhw_cr/CMakeLists.txt | 4 | ||||
-rw-r--r-- | libhw_cr/host_alarmclock.c | 2 | ||||
-rw-r--r-- | libhw_cr/host_include/libhw/host_alarmclock.h | 6 | ||||
-rw-r--r-- | libhw_cr/host_include/libhw/host_net.h | 18 | ||||
-rw-r--r-- | libhw_cr/host_net.c | 24 | ||||
-rw-r--r-- | libhw_cr/host_util.c | 2 | ||||
-rw-r--r-- | libhw_cr/host_util.h | 2 | ||||
-rw-r--r-- | libhw_cr/rp2040_dma.h | 3 | ||||
-rw-r--r-- | libhw_cr/rp2040_hwspi.c | 49 | ||||
-rw-r--r-- | libhw_cr/rp2040_include/libhw/rp2040_hwspi.h | 8 | ||||
-rw-r--r-- | libhw_cr/rp2040_include/libhw/w5500.h | 32 | ||||
-rw-r--r-- | libhw_cr/w5500.c | 26 |
12 files changed, 103 insertions, 73 deletions
diff --git a/libhw_cr/CMakeLists.txt b/libhw_cr/CMakeLists.txt index caeac21..ba20b26 100644 --- a/libhw_cr/CMakeLists.txt +++ b/libhw_cr/CMakeLists.txt @@ -14,7 +14,7 @@ target_sources(libhw_cr INTERFACE ) if (PICO_PLATFORM STREQUAL "rp2040") - target_include_directories(libhw_cr SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/rp2040_include) + target_include_directories(libhw_cr PUBLIC INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/rp2040_include) target_link_libraries(libhw_cr INTERFACE libcr_ipc ) @@ -34,7 +34,7 @@ if (PICO_PLATFORM STREQUAL "rp2040") endif() if (PICO_PLATFORM STREQUAL "host") - target_include_directories(libhw_cr SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/host_include) + target_include_directories(libhw_cr PUBLIC INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/host_include) target_sources(libhw_cr INTERFACE host_util.c host_alarmclock.c diff --git a/libhw_cr/host_alarmclock.c b/libhw_cr/host_alarmclock.c index 2f255e0..9eedec2 100644 --- a/libhw_cr/host_alarmclock.c +++ b/libhw_cr/host_alarmclock.c @@ -19,7 +19,7 @@ #include "host_util.h" /* for host_sigrt_alloc(), ns_to_host_ns_time() */ -LO_IMPLEMENTATION_C(alarmclock, struct hostclock, hostclock, static) +LO_IMPLEMENTATION_C(alarmclock, struct hostclock, hostclock, static); static uint64_t hostclock_get_time_ns(struct hostclock *alarmclock) { assert(alarmclock); diff --git a/libhw_cr/host_include/libhw/host_alarmclock.h b/libhw_cr/host_include/libhw/host_alarmclock.h index 89df68a..0cb8d30 100644 --- a/libhw_cr/host_include/libhw/host_alarmclock.h +++ b/libhw_cr/host_include/libhw/host_alarmclock.h @@ -16,12 +16,12 @@ struct hostclock { clockid_t clock_id; - BEGIN_PRIVATE(LIBHW_HOST_ALARMCLOCK_H) + BEGIN_PRIVATE(LIBHW_HOST_ALARMCLOCK_H); bool initialized; timer_t timer_id; struct alarmclock_trigger *queue; - END_PRIVATE(LIBHW_HOST_ALARMCLOCK_H) + END_PRIVATE(LIBHW_HOST_ALARMCLOCK_H); }; -LO_IMPLEMENTATION_H(alarmclock, struct hostclock, hostclock) +LO_IMPLEMENTATION_H(alarmclock, struct hostclock, hostclock); #endif /* _LIBHW_HOST_ALARMCLOCK_H_ */ diff --git a/libhw_cr/host_include/libhw/host_net.h b/libhw_cr/host_include/libhw/host_net.h index fced229..a16ed01 100644 --- a/libhw_cr/host_include/libhw/host_net.h +++ b/libhw_cr/host_include/libhw/host_net.h @@ -14,30 +14,30 @@ #include <libhw/generic/net.h> struct _hostnet_tcp_conn { - BEGIN_PRIVATE(LIBHW_HOST_NET_H) + BEGIN_PRIVATE(LIBHW_HOST_NET_H); int fd; uint64_t read_deadline_ns; - END_PRIVATE(LIBHW_HOST_NET_H) + END_PRIVATE(LIBHW_HOST_NET_H); }; -LO_IMPLEMENTATION_H(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp) +LO_IMPLEMENTATION_H(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp); struct hostnet_tcp_listener { - BEGIN_PRIVATE(LIBHW_HOST_NET_H) + BEGIN_PRIVATE(LIBHW_HOST_NET_H); int fd; struct _hostnet_tcp_conn active_conn; - END_PRIVATE(LIBHW_HOST_NET_H) + END_PRIVATE(LIBHW_HOST_NET_H); }; -LO_IMPLEMENTATION_H(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist) +LO_IMPLEMENTATION_H(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist); void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port); struct hostnet_udp_conn { - BEGIN_PRIVATE(LIBHW_HOST_NET_H) + BEGIN_PRIVATE(LIBHW_HOST_NET_H); int fd; uint64_t read_deadline_ns; - END_PRIVATE(LIBHW_HOST_NET_H) + END_PRIVATE(LIBHW_HOST_NET_H); }; -LO_IMPLEMENTATION_H(net_packet_conn, struct hostnet_udp_conn, hostnet_udp) +LO_IMPLEMENTATION_H(net_packet_conn, struct hostnet_udp_conn, hostnet_udp); void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port); diff --git a/libhw_cr/host_net.c b/libhw_cr/host_net.c index f1c988c..6ed6e46 100644 --- a/libhw_cr/host_net.c +++ b/libhw_cr/host_net.c @@ -30,18 +30,18 @@ #include "host_util.h" /* for host_sigrt_alloc(), ns_to_host_us_time() */ -LO_IMPLEMENTATION_C(io_closer, struct hostnet_tcp_listener, hostnet_tcplist, static) -LO_IMPLEMENTATION_C(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist, static) - -LO_IMPLEMENTATION_C(io_reader, struct _hostnet_tcp_conn, hostnet_tcp, static) -LO_IMPLEMENTATION_C(io_writer, struct _hostnet_tcp_conn, hostnet_tcp, static) -LO_IMPLEMENTATION_C(io_readwriter, struct _hostnet_tcp_conn, hostnet_tcp, static) -LO_IMPLEMENTATION_C(io_closer, struct _hostnet_tcp_conn, hostnet_tcp, static) -LO_IMPLEMENTATION_C(io_bidi_closer, struct _hostnet_tcp_conn, hostnet_tcp, static) -LO_IMPLEMENTATION_C(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp, static) - -LO_IMPLEMENTATION_C(io_closer, struct hostnet_udp_conn, hostnet_udp, static) -LO_IMPLEMENTATION_C(net_packet_conn, struct hostnet_udp_conn, hostnet_udp, static) +LO_IMPLEMENTATION_C(io_closer, struct hostnet_tcp_listener, hostnet_tcplist, static); +LO_IMPLEMENTATION_C(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist, static); + +LO_IMPLEMENTATION_C(io_reader, struct _hostnet_tcp_conn, hostnet_tcp, static); +LO_IMPLEMENTATION_C(io_writer, struct _hostnet_tcp_conn, hostnet_tcp, static); +LO_IMPLEMENTATION_C(io_readwriter, struct _hostnet_tcp_conn, hostnet_tcp, static); +LO_IMPLEMENTATION_C(io_closer, struct _hostnet_tcp_conn, hostnet_tcp, static); +LO_IMPLEMENTATION_C(io_bidi_closer, struct _hostnet_tcp_conn, hostnet_tcp, static); +LO_IMPLEMENTATION_C(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp, static); + +LO_IMPLEMENTATION_C(io_closer, struct hostnet_udp_conn, hostnet_udp, static); +LO_IMPLEMENTATION_C(net_packet_conn, struct hostnet_udp_conn, hostnet_udp, static); /* common *********************************************************************/ diff --git a/libhw_cr/host_util.c b/libhw_cr/host_util.c index 958ed9c..7b3200c 100644 --- a/libhw_cr/host_util.c +++ b/libhw_cr/host_util.c @@ -1,6 +1,6 @@ /* libhw_cr/host_util.c - Utilities for GNU/Linux hosts * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ diff --git a/libhw_cr/host_util.h b/libhw_cr/host_util.h index 8c53fab..02c04dc 100644 --- a/libhw_cr/host_util.h +++ b/libhw_cr/host_util.h @@ -1,6 +1,6 @@ /* libhw_cr/host_util.h - Utilities for GNU/Linux hosts * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ diff --git a/libhw_cr/rp2040_dma.h b/libhw_cr/rp2040_dma.h index e295adf..c7f5a8f 100644 --- a/libhw_cr/rp2040_dma.h +++ b/libhw_cr/rp2040_dma.h @@ -11,6 +11,7 @@ #define _LIBHW_CR_RP2040_DMA_H_ #include <assert.h> +#include <stddef.h> /* for offsetof() */ #include <stdint.h> /* for uint32_t */ #include <hardware/regs/dreq.h> /* for DREQ_* for use with DMA_CTRL_TREQ_SEL() */ @@ -105,6 +106,8 @@ struct dma_alias3_short3 { READ_ADDR ; }; struct dma_alias2_short3: &dma_channel_hw_addr(CH)->al2_write_addr_trig, \ struct dma_alias3_short3: &dma_channel_hw_addr(CH)->al3_read_addr_trig)) +#define DMA_IS_TRIGGER(TYP, FIELD) (offsetof(TYP, FIELD) == 0xC) + #define DMA_CHAN_WR_TRANS_COUNT(TYP) \ (sizeof(TYP)/4) diff --git a/libhw_cr/rp2040_hwspi.c b/libhw_cr/rp2040_hwspi.c index d4adb11..d181650 100644 --- a/libhw_cr/rp2040_hwspi.c +++ b/libhw_cr/rp2040_hwspi.c @@ -30,8 +30,8 @@ #error config.h must define CONFIG_RP2040_SPI_DEBUG (bool) #endif -LO_IMPLEMENTATION_C(io_duplex_readwriter, struct rp2040_hwspi, rp2040_hwspi, static) -LO_IMPLEMENTATION_C(spi, struct rp2040_hwspi, rp2040_hwspi, static) +LO_IMPLEMENTATION_C(io_duplex_readwriter, struct rp2040_hwspi, rp2040_hwspi, static); +LO_IMPLEMENTATION_C(spi, struct rp2040_hwspi, rp2040_hwspi, static); static void rp2040_hwspi_intrhandler(void *_self, enum dmairq LM_UNUSED(irq), uint LM_UNUSED(channel)) { struct rp2040_hwspi *self = _self; @@ -130,9 +130,11 @@ void _rp2040_hwspi_init(struct rp2040_hwspi *self, self->dma_tx_data = dma3; self->dma_rx_data = dma4; self->dead_until_ns = 0; - self->sema = (cr_sema_t){0}; + self->sema = (cr_sema_t){}; /* Initialize the interrupt handler. */ + /* We do this on (just) the rx channel, because the way the + * SSP works reads necessarily complete *after* writes. */ dmairq_set_and_enable_exclusive_handler(DMAIRQ_0, self->dma_rx_data, rp2040_hwspi_intrhandler, self); } @@ -163,23 +165,43 @@ static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct dupl if (!pruned_iovcnt) return; - /* For tx_data_blocks, it doesn't really matter which aliases - * we choose: + /* It doesn't *really* matter which aliases we choose: + * * - None of our fields can be NULL (so no * false-termination). + * * - Moving const fields first so they don't have to be - * re-programmed each time isn't possible for us there need - * to be at least 2 const fields, and we only have 1 + * re-programmed each time isn't possible for us; there + * need to be at least 2 const fields, and we only have 1 * (read_addr for rx_data_blocks, and write_addr for * tx_data_blocks). * - * But for rx_data_blocks, we need ctrl to be the trigger - * register so that the DMA_CTRL_IRQ_QUIET flag isn't cleared - * before we get to the trigger; and while for tx_data_blocks - * it doesn't really matter, the inverse would be nice. + * The code following this initial declaration is generic to + * the alias, so changing which alias is used is easy. + * + * Since we have no hard requirements, here are some mild + * preferences: + * + * - I like the aliases being different for each channel, + * because it helps prevent alias-specific code from + * sneaking in. + * + * - I like the rx channel (the channel the interrupt handler + * is wired to) having ctrl be the trigger, so that we + * don't have to worry about DMA_CTRL_IRQ_QUIET being + * cleared before the trigger, and at the end the control + * block is clean and zeroed-out. + * + * - Conversely, I like the tx channel (the non-interrupt + * channel) having ctrl *not* be the trigger, so that + * DMA_CTRL_IRQ_QUIET is cleared by the time the trigger + * happens, so the IRQ machinery doesn't need to be engaged + * at all. */ struct dma_alias1 *tx_data_blocks = alloca(sizeof(struct dma_alias1)*(pruned_iovcnt+1)); struct dma_alias0 *rx_data_blocks = alloca(sizeof(struct dma_alias0)*(pruned_iovcnt+1)); + static_assert(!DMA_IS_TRIGGER(typeof(tx_data_blocks[0]), ctrl)); + static_assert(DMA_IS_TRIGGER(typeof(rx_data_blocks[0]), ctrl)); for (int i = 0, j = 0; i < iovcnt; i++) { if (!iov[i].iov_len) @@ -210,6 +232,11 @@ static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct dupl } tx_data_blocks[pruned_iovcnt] = (typeof(tx_data_blocks[0])){0}; rx_data_blocks[pruned_iovcnt] = (typeof(rx_data_blocks[0])){0}; + /* If ctrl isn't the trigger then we need to make sure that + * DMA_CTRL_IRQ_QUIET isn't cleared before the trigger + * happens. */ + if (!DMA_IS_TRIGGER(typeof(rx_data_blocks[0]), ctrl)) + rx_data_blocks[pruned_iovcnt].ctrl = DMA_CTRL_IRQ_QUIET; /* Set up ctrl. */ DMA_NONTRIGGER(self->dma_tx_ctrl, read_addr) = tx_data_blocks; diff --git a/libhw_cr/rp2040_include/libhw/rp2040_hwspi.h b/libhw_cr/rp2040_include/libhw/rp2040_hwspi.h index 9d99f7b..4951136 100644 --- a/libhw_cr/rp2040_include/libhw/rp2040_hwspi.h +++ b/libhw_cr/rp2040_include/libhw/rp2040_hwspi.h @@ -20,7 +20,7 @@ enum rp2040_hwspi_instance { }; struct rp2040_hwspi { - BEGIN_PRIVATE(LIBHW_RP2040_HWSPI_H) + BEGIN_PRIVATE(LIBHW_RP2040_HWSPI_H); /* const */ LM_IF(IS_IMPLEMENTATION_FOR(LIBHW_RP2040_HWSPI_H))(spi_inst_t)(void) *inst; uint64_t min_delay_ns; @@ -34,10 +34,10 @@ struct rp2040_hwspi { /* mutable */ uint64_t dead_until_ns; cr_sema_t sema; - END_PRIVATE(LIBHW_RP2040_HWSPI_H) + END_PRIVATE(LIBHW_RP2040_HWSPI_H); }; -LO_IMPLEMENTATION_H(io_duplex_readwriter, struct rp2040_hwspi, rp2040_hwspi) -LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi) +LO_IMPLEMENTATION_H(io_duplex_readwriter, struct rp2040_hwspi, rp2040_hwspi); +LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi); /** * Initialize an instance of `struct rp2040_hwspi`. diff --git a/libhw_cr/rp2040_include/libhw/w5500.h b/libhw_cr/rp2040_include/libhw/w5500.h index 51effba..8dda1a1 100644 --- a/libhw_cr/rp2040_include/libhw/w5500.h +++ b/libhw_cr/rp2040_include/libhw/w5500.h @@ -17,10 +17,10 @@ #include <libhw/generic/net.h> #include <libhw/generic/spi.h> -CR_CHAN_DECLARE(_w5500_sockintr_ch, uint8_t) +CR_CHAN_DECLARE(_w5500_sockintr_ch, uint8_t); struct _w5500_socket { - BEGIN_PRIVATE(LIBHW_W5500_H) + BEGIN_PRIVATE(LIBHW_W5500_H); /* const-after-init */ uint8_t socknum; @@ -38,24 +38,24 @@ struct _w5500_socket { _w5500_sockintr_ch_t write_ch; /* MODE_{TCP,UDP} */ bool list_open, read_open, write_open; /* MODE_TCP */ - END_PRIVATE(LIBHW_W5500_H) + END_PRIVATE(LIBHW_W5500_H); }; -LO_IMPLEMENTATION_H(io_closer, struct _w5500_socket, w5500_tcplist) -LO_IMPLEMENTATION_H(net_stream_listener, struct _w5500_socket, w5500_tcplist) +LO_IMPLEMENTATION_H(io_closer, struct _w5500_socket, w5500_tcplist); +LO_IMPLEMENTATION_H(net_stream_listener, struct _w5500_socket, w5500_tcplist); -LO_IMPLEMENTATION_H(io_reader, struct _w5500_socket, w5500_tcp) -LO_IMPLEMENTATION_H(io_writer, struct _w5500_socket, w5500_tcp) -LO_IMPLEMENTATION_H(io_readwriter, struct _w5500_socket, w5500_tcp) -LO_IMPLEMENTATION_H(io_closer, struct _w5500_socket, w5500_tcp) -LO_IMPLEMENTATION_H(io_bidi_closer, struct _w5500_socket, w5500_tcp) -LO_IMPLEMENTATION_H(net_stream_conn, struct _w5500_socket, w5500_tcp) +LO_IMPLEMENTATION_H(io_reader, struct _w5500_socket, w5500_tcp); +LO_IMPLEMENTATION_H(io_writer, struct _w5500_socket, w5500_tcp); +LO_IMPLEMENTATION_H(io_readwriter, struct _w5500_socket, w5500_tcp); +LO_IMPLEMENTATION_H(io_closer, struct _w5500_socket, w5500_tcp); +LO_IMPLEMENTATION_H(io_bidi_closer, struct _w5500_socket, w5500_tcp); +LO_IMPLEMENTATION_H(net_stream_conn, struct _w5500_socket, w5500_tcp); -LO_IMPLEMENTATION_H(io_closer, struct _w5500_socket, w5500_udp) -LO_IMPLEMENTATION_H(net_packet_conn, struct _w5500_socket, w5500_udp) +LO_IMPLEMENTATION_H(io_closer, struct _w5500_socket, w5500_udp); +LO_IMPLEMENTATION_H(net_packet_conn, struct _w5500_socket, w5500_udp); struct w5500 { - BEGIN_PRIVATE(LIBHW_W5500_H) + BEGIN_PRIVATE(LIBHW_W5500_H); /* const-after-init */ lo_interface spi spidev; uint pin_intr; @@ -68,9 +68,9 @@ struct w5500 { struct _w5500_socket *free; cr_sema_t intr; cr_mutex_t mu; - END_PRIVATE(LIBHW_W5500_H) + END_PRIVATE(LIBHW_W5500_H); }; -LO_IMPLEMENTATION_H(net_iface, struct w5500, w5500_if) +LO_IMPLEMENTATION_H(net_iface, struct w5500, w5500_if); /** * Initialize a WIZnet W5500 Ethernet-and-TCP/IP-offload chip. diff --git a/libhw_cr/w5500.c b/libhw_cr/w5500.c index 295add2..fa427d9 100644 --- a/libhw_cr/w5500.c +++ b/libhw_cr/w5500.c @@ -126,20 +126,20 @@ static const char *w5500_state_str(uint8_t state) { /* libobj *********************************************************************/ -LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_tcplist, static) -LO_IMPLEMENTATION_C(net_stream_listener, struct _w5500_socket, w5500_tcplist, static) +LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_tcplist, static); +LO_IMPLEMENTATION_C(net_stream_listener, struct _w5500_socket, w5500_tcplist, static); -LO_IMPLEMENTATION_C(io_reader, struct _w5500_socket, w5500_tcp, static) -LO_IMPLEMENTATION_C(io_writer, struct _w5500_socket, w5500_tcp, static) -LO_IMPLEMENTATION_C(io_readwriter, struct _w5500_socket, w5500_tcp, static) -LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_tcp, static) -LO_IMPLEMENTATION_C(io_bidi_closer, struct _w5500_socket, w5500_tcp, static) -LO_IMPLEMENTATION_C(net_stream_conn, struct _w5500_socket, w5500_tcp, static) +LO_IMPLEMENTATION_C(io_reader, struct _w5500_socket, w5500_tcp, static); +LO_IMPLEMENTATION_C(io_writer, struct _w5500_socket, w5500_tcp, static); +LO_IMPLEMENTATION_C(io_readwriter, struct _w5500_socket, w5500_tcp, static); +LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_tcp, static); +LO_IMPLEMENTATION_C(io_bidi_closer, struct _w5500_socket, w5500_tcp, static); +LO_IMPLEMENTATION_C(net_stream_conn, struct _w5500_socket, w5500_tcp, static); -LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_udp, static) -LO_IMPLEMENTATION_C(net_packet_conn, struct _w5500_socket, w5500_udp, static) +LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_udp, static); +LO_IMPLEMENTATION_C(net_packet_conn, struct _w5500_socket, w5500_udp, static); -LO_IMPLEMENTATION_C(net_iface, struct w5500, w5500_if, static) +LO_IMPLEMENTATION_C(net_iface, struct w5500, w5500_if, static); /* mid-level utilities ********************************************************/ @@ -706,7 +706,7 @@ static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec if (count == 0) return 0; - struct alarmclock_trigger trigger = {0}; + struct alarmclock_trigger trigger = {}; if (socket->read_deadline_ns) LO_CALL(bootclock, add_trigger, &trigger, socket->read_deadline_ns, @@ -885,7 +885,7 @@ static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_ assert(buf); assert(count); - struct alarmclock_trigger trigger = {0}; + struct alarmclock_trigger trigger = {}; if (socket->read_deadline_ns) LO_CALL(bootclock, add_trigger, &trigger, socket->read_deadline_ns, |