summaryrefslogtreecommitdiff
path: root/libhw/w5500.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-30 10:30:42 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-30 10:33:27 -0700
commite8f09fdd0e0aa7e17317a58474058b9272a12f93 (patch)
tree255e43c5d4f9a2a3974af2f8764ee93cbd975bb2 /libhw/w5500.c
parent4258cb9dc66296e2222e706df8924878867b8a23 (diff)
w5500: Verify that the INTR line goes high before blocking
Diffstat (limited to 'libhw/w5500.c')
-rw-r--r--libhw/w5500.c60
1 files changed, 31 insertions, 29 deletions
diff --git a/libhw/w5500.c b/libhw/w5500.c
index 563fd8b..c1607f1 100644
--- a/libhw/w5500.c
+++ b/libhw/w5500.c
@@ -206,37 +206,39 @@ static COROUTINE w5500_irq_cr(void *_chip) {
cr_begin();
for (;;) {
- cr_sema_wait(&chip->intr);
- if (w5500ll_read_common_reg(chip->spidev, chip_interrupt))
- w5500ll_write_common_reg(chip->spidev, chip_interrupt, 0xFF);
-
- uint8_t sockmask = w5500ll_read_common_reg(chip->spidev, sock_interrupt);
- for (uint8_t socknum = 0; socknum < 8; socknum++) {
- if (!(sockmask & (1<<socknum)))
- continue;
- struct _w5500_socket *socket = &chip->sockets[socknum];
-
- uint8_t sockintr = w5500ll_read_sock_reg(chip->spidev, socknum, interrupt);
-
- switch (socket->mode) {
- case W5500_MODE_NONE:
- break;
- case W5500_MODE_TCP: case W5500_MODE_UDP:
- uint8_t listen_bits = sockintr & SOCKINTR_CONN,
- send_bits = sockintr & (SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT),
- recv_bits = sockintr & (SOCKINTR_RECV_DAT|SOCKINTR_RECV_FIN);
-
- if (listen_bits)
- cr_sema_signal(&socket->listen_sema);
- if (recv_bits)
- cr_sema_signal(&socket->read_sema);
- if (send_bits)
- _w5500_sockintr_ch_send(&socket->write_ch, send_bits);
- break;
+ while (!gpio_get(chip->pin_intr)) {
+ if (w5500ll_read_common_reg(chip->spidev, chip_interrupt))
+ w5500ll_write_common_reg(chip->spidev, chip_interrupt, 0xFF);
+
+ uint8_t sockmask = w5500ll_read_common_reg(chip->spidev, sock_interrupt);
+ for (uint8_t socknum = 0; socknum < 8; socknum++) {
+ if (!(sockmask & (1<<socknum)))
+ continue;
+ struct _w5500_socket *socket = &chip->sockets[socknum];
+
+ uint8_t sockintr = w5500ll_read_sock_reg(chip->spidev, socknum, interrupt);
+
+ switch (socket->mode) {
+ case W5500_MODE_NONE:
+ break;
+ case W5500_MODE_TCP: case W5500_MODE_UDP:
+ uint8_t listen_bits = sockintr & SOCKINTR_CONN,
+ send_bits = sockintr & (SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT),
+ recv_bits = sockintr & (SOCKINTR_RECV_DAT|SOCKINTR_RECV_FIN);
+
+ if (listen_bits)
+ cr_sema_signal(&socket->listen_sema);
+ if (recv_bits)
+ cr_sema_signal(&socket->read_sema);
+ if (send_bits)
+ _w5500_sockintr_ch_send(&socket->write_ch, send_bits);
+ break;
+ }
+
+ w5500ll_write_sock_reg(chip->spidev, socknum, interrupt, sockintr);
}
-
- w5500ll_write_sock_reg(chip->spidev, socknum, interrupt, sockintr);
}
+ cr_sema_wait(&chip->intr);
}
cr_end();