diff options
Diffstat (limited to 'libhw/w5500.c')
-rw-r--r-- | libhw/w5500.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/libhw/w5500.c b/libhw/w5500.c index 5678ffd..79fc10e 100644 --- a/libhw/w5500.c +++ b/libhw/w5500.c @@ -67,6 +67,8 @@ * SPDX-License-Identifier: MIT */ +#include <stdio.h> + /* TODO: Write a <libhw/generic/gpio.h> to avoid w5500.c being * pico-sdk-specific. */ #include <hardware/gpio.h> /* pico-sdk:hardware_gpio */ @@ -273,12 +275,6 @@ static inline void w5500_socket_close(struct _w5500_socket *socket) { /* Wait for it to transition to STATE_CLOSED. */ while (w5500ll_read_sock_reg(chip->spidev, socknum, state) != STATE_CLOSED) cr_yield(); - - /* Update our MCU-side bookkeeping. */ - socket->mode = W5500_MODE_NONE; - socket->port = 0; - socket->read_deadline_ns = 0; - socket->read_open = socket->write_open = false; } #define ASSERT_SELF(_iface, _mode) \ @@ -339,6 +335,15 @@ void _w5500_init(struct w5500 *chip, gpio_set_dir(chip->pin_reset, GPIO_OUT); w5500_hard_reset(chip); + /* Validate that SPI works correctly. */ + for (uint16_t a = 0; a < 0x100; a++) { + w5500ll_write_sock_reg(chip->spidev, 0, mode, a); + uint8_t b = w5500ll_read_sock_reg(chip->spidev, 0, mode); + if (b != a) + printf("SPI to W5500 does not appear to be functional: wrote:%d != read:%d\n", a, b); + } + w5500ll_write_sock_reg(chip->spidev, 0, mode, 0); + /* Finally, wire in the interrupt handler. */ bool saved = cr_save_and_disable_interrupts(); for (size_t i = 0; i < ARRAY_LEN(w5500_chips); i++) { @@ -506,6 +511,7 @@ implements_net_packet_conn *w5500_if_udp_conn(implements_net_iface *_chip, uint1 struct _w5500_socket *socket = w5500_alloc_socket(chip); if (!socket) return NULL; + uint8_t socknum = socket->socknum; if (!local_port) local_port = w5500_alloc_local_port(chip); @@ -515,6 +521,14 @@ implements_net_packet_conn *w5500_if_udp_conn(implements_net_iface *_chip, uint1 socket->port = local_port; socket->read_deadline_ns = 0; + /* Mimics socket.c:socket(). */ + w5500_socket_close(socket); + w5500ll_write_sock_reg(chip->spidev, socknum, mode, SOCKMODE_UDP); + w5500ll_write_sock_reg(chip->spidev, socknum, local_port, uint16be_marshal(socket->port)); + w5500_socket_cmd(socket, CMD_OPEN); + while (w5500ll_read_sock_reg(chip->spidev, socknum, state) != STATE_UDP) + cr_yield(); + return &socket->implements_net_packet_conn; } @@ -627,7 +641,7 @@ static void w5500_tcp_set_read_deadline(implements_net_stream_conn *_socket, uin static void w5500_tcp_alarm_handler(void *_arg) { struct _w5500_socket *socket = _arg; - cr_sema_signal(&socket->read_sema); + cr_sema_signal_from_intrhandler(&socket->read_sema); } static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, size_t count) { @@ -649,7 +663,7 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si VCALL(bootclock, del_trigger, &trigger); return -NET_ECLOSED; } - if (socket->read_deadline_ns && socket->read_deadline_ns >= VCALL(bootclock, get_time_ns)) { + if (socket->read_deadline_ns && socket->read_deadline_ns <= VCALL(bootclock, get_time_ns)) { VCALL(bootclock, del_trigger, &trigger); return -NET_ETIMEDOUT; } @@ -726,7 +740,7 @@ static ssize_t w5500_udp_sendto(implements_net_packet_conn *_socket, void *buf, assert(count); uint16_t bufsize = ((uint16_t)w5500ll_read_sock_reg(chip->spidev, socknum, tx_buf_size))*1024; - if (count < bufsize) + if (count > bufsize) return -NET_EMSGSIZE; for (;;) { @@ -763,7 +777,7 @@ static void w5500_udp_set_read_deadline(implements_net_packet_conn *_socket, uin static void w5500_udp_alarm_handler(void *_arg) { struct _w5500_socket *socket = _arg; - cr_sema_signal(&socket->read_sema); + cr_sema_signal_from_intrhandler(&socket->read_sema); } static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf, size_t count, @@ -782,7 +796,7 @@ static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf /* Wait until there is data to read. */ uint16_t avail = 0; for (;;) { - if (socket->read_deadline_ns && socket->read_deadline_ns >= VCALL(bootclock, get_time_ns)) { + if (socket->read_deadline_ns && socket->read_deadline_ns <= VCALL(bootclock, get_time_ns)) { VCALL(bootclock, del_trigger, &trigger); return -NET_ETIMEDOUT; } |