summaryrefslogtreecommitdiff
path: root/cmd/sbc_harness/hw/w5500.c
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/sbc_harness/hw/w5500.c')
-rw-r--r--cmd/sbc_harness/hw/w5500.c168
1 files changed, 86 insertions, 82 deletions
diff --git a/cmd/sbc_harness/hw/w5500.c b/cmd/sbc_harness/hw/w5500.c
index 7470401..d896480 100644
--- a/cmd/sbc_harness/hw/w5500.c
+++ b/cmd/sbc_harness/hw/w5500.c
@@ -32,8 +32,10 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <pico/time.h> /* for sleep_ms() */
+#include <pico/time.h> /* for sleep_ms() */
+#include <hardware/gpio.h> /* pico-sdk:hardware_gpio5 */
+#include <libcr/coroutine.h>
#include "hw/w5500.h"
#include "config.h"
@@ -53,18 +55,18 @@
* operating-mode. */
/* Part 1: Block ID. */
-#define CTL_MASK_BLOCK 0b11111'000
-#define _CTL_BLOCK_RES (0b00'000)
-#define _CTL_BLOCK_REG (0b01'000)
-#define _CTL_BLOCK_TX (0b10'000)
-#define _CTL_BLOCK_RX (0b11'000)
+#define CTL_MASK_BLOCK 0b11111000
+#define _CTL_BLOCK_RES (0b00000)
+#define _CTL_BLOCK_REG (0b01000)
+#define _CTL_BLOCK_TX (0b10000)
+#define _CTL_BLOCK_RX (0b11000)
#define CTL_BLOCK_SOCK(n,part) (((n)<<5)|(_CTL_BLOCK_##part))
#define CTL_BLOCK_COMMON_REG CTL_BLOCK_SOCK(0,RES)
/* Part 2: R/W. */
-#define CTL_MASK_RW 0b1'00
-#define CTL_R 0b0'00
-#define CTL_W 0b1'00
+#define CTL_MASK_RW 0b100
+#define CTL_R 0b000
+#define CTL_W 0b100
/* Part 3: Operating mode. */
#define CTL_MASK_OM 0b11
@@ -228,11 +230,11 @@ static_assert(sizeof(struct w5500_block_sock_reg) == 0x30);
* - Writing data is valid in ESTABLISHED and CLOSE_WAIT.
* - Reading data is valid in ESTABLISHED and FIN_WAIT.
*
- * │ CLOSED │
- * └────────┘
- * V
- * (CMD_OPEN)
- * V
+ * TCP state diagram, showing the flow of │ CLOSED │ ━━ role separator ┌───────┐
+ * SYN, FIN, and their assocaited ACKs. └────────┘ ══ state transition │ state │
+ * V ┈┈ packet flow └───────┘
+ * (CMD_OPEN) ║
+ * V (action/event)
* ┌────────┐
* ┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━│ INIT │━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
* ┃ server ┃ └────────┘ ┃ client ┃
@@ -260,14 +262,14 @@ static_assert(sizeof(struct w5500_block_sock_reg) == 0x30);
* ┃ ║ V ┃┃ V ┃
* ┃ ╠═══════════╝ ┃┃ ╚═══════════╗ ┃
* ┃ (CMD_DISCON) ┃┃ ║ ┃
- * ┃ ┌┈┈┈<(send FIN)>┈┈┈┈┈┈┐┃┃ ║ ┃
- * ┃ ┊ V └┃┃┈┈┈┈┈┈┈┈>(recv FIN) ┃
- * ┃ ┊ ┌────────────┐ ┌┃┃┈┈┈┈┈┈┈┈<(send ACK) ┃
- * ┃ ┊ │ FIN_WAIT_1 │ ┊┃┃ V ┃
- * ┃ ┊ └────────────┘ ┊┃┃ ┌────────────┐ ┃
- * ┃ ┊ V V ┊┃┃ │ CLOSE_WAIT │ ┃
- * ┃ ╔════════════════╝ ╔══╝ ┊┃┃ └────────────┘ ┃
- * ┃ (recv FIN)<┈┈┈┈┤ ║ ┊┃┃ V ┃
+ * ┃ Both sides sent ┌┈┈┈<(send FIN)>┈┈┈┈┈┈┐┃┃ ║ ┃
+ * ┃ FIN at the "same" ┊ V └┃┃┈┈┈┈┈┈┈┈>(recv FIN) ┃
+ * ┃ time; both are ┊ ┌────────────┐ ┌┃┃┈┈┈┈┈┈┈┈<(send ACK) ┃
+ * ┃ active closers ┊ │ FIN_WAIT_1 │ ┊┃┃ V ┃
+ * ┃ / \ ┊ └────────────┘ ┊┃┃ ┌────────────┐ ┃
+ * ┃ ,-----' '-----, ┊ V V ┊┃┃ │ CLOSE_WAIT │ ┃
+ * ┃ ╔════════════════╝ ║ ┊┃┃ └────────────┘ ┃
+ * ┃ (recv FIN)<┈┈┈┈┤ ╔══╝ ┊┃┃ V ┃
* ┃ ┌┈┈<(send ACK)>┈┈┐ ┊ ║ ┊┃┃ ║ ┃
* ┃ ┊ ║ └┈┈┈┈┈>(recv ACK)<┈┈┈┈┈┈┘┃┃ ║ ┃
* ┃ ┊ V ┊ V ┃┃ ║ ┃
@@ -277,18 +279,18 @@ static_assert(sizeof(struct w5500_block_sock_reg) == 0x30);
* ┃ ┊ V ┊ V ┌┃┃┈┈┈┈┈┈┈┈<(send FIN) ┃
* ┃ ┊ ║ └┈┈┈>(recv FIN)<┈┈┈┈┈┈┘┃┃ ║ ┃
* ┃ ┊ ║ ┌┈┈┈┈┈<(send ACK)>┈┈┈┈┈┈┐┃┃ V ┃
- * ┃ └┈┈>(recv ACK)<┈┈┘ ║ ┊┃┃ ┌──────────┐ ┃
- * ┃ ╚════════════════╗ ╚═╗ ┊┃┃ │ LAST_ACK │ ┃
- * ┃ `------, ,-------' V V ┊┃┃ └──────────┘ ┃
- * ┃ \/ ┌───────────┐ ┊┃┃ V ┃
- * ┃ Both sides sent │ TIME_WAIT │ ┊┃┃ ║ ┃
- * ┃ FIN at the "same" └───────────┘ └┃┃┈┈┈┈┈┈┈┈>(recv ACK) ┃
- * ┃ time; both are V ┃┃ ║ ┃
- * ┃ active closers (2*MSL has elapsed) ┃┃ ║ ┃
- * ┃ ╚═══════════╗ ┃┃ ╔══════════╝ ┃
- * ┣━━━━━━━━━━━━━━━━┓ V ┃┃ V ┏━━━━━━━━━━━━━━━━┫
- * ┃ active closer ┃ ┌────────┐ ┃ passive closer ┃
- * ┗━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━│ CLOSED │━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┛
+ * ┃ └┈┈>(recv ACK)<┈┈┘ ╚═╗ ┊┃┃ ┌──────────┐ ┃
+ * ┃ ╚════════════════╗ ║ ┊┃┃ │ LAST_ACK │ ┃
+ * ┃ V V ┊┃┃ └──────────┘ ┃
+ * ┃ ┌───────────┐ ┊┃┃ V ┃
+ * ┃ │ TIME_WAIT │ ┊┃┃ ║ ┃
+ * ┃ └───────────┘ └┃┃┈┈┈┈┈┈┈┈>(recv ACK) ┃
+ * ┃ V ┃┃ ║ ┃
+ * ┣━━━━━━━━━━━━━━━━┓ (2*MSL has elapsed) ┃┃ ║ ┏━━━━━━━━━━━━━━━━┫
+ * ┃ active closer ┃ ╚═══════════╗ ┃┃ ╔═══════════╝ ┃ passive closer ┃
+ * ┗━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━V━┛┗━V━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┛
+ * ┌────────┐
+ * │ CLOSED │
*/
#define STATE_TCP_INIT ((uint8_t)0x13)
#define STATE_TCP_LISTEN ((uint8_t)0x14) /* server */
@@ -305,44 +307,46 @@ static_assert(sizeof(struct w5500_block_sock_reg) == 0x30);
#define STATE_MACRAW ((uint8_t)0x42)
-#define REGWRITE_COMMON(spidev, field, val) do { \
- assert(sizeof(val) == sizeof((struct w5500_block_common_reg).field)); \
- w5500_spiframe_write(spidev, \
- offsetof(struct w5500_block_common_reg, field), \
- CTL_BLOCK_COMMON_REG, \
- &(val), \
- sizeof(struct w5500_block_common_reg, field)); \
+#define REGWRITE_COMMON(spidev, field, val) do { \
+ assert(sizeof(val) == sizeof(((struct w5500_block_common_reg){}).field)); \
+ typeof(val) lval = val; \
+ w5500_spiframe_write(spidev, \
+ offsetof(struct w5500_block_common_reg, field), \
+ CTL_BLOCK_COMMON_REG, \
+ &lval, \
+ sizeof(lval)); \
} while (0)
-#define REGREAD_COMMON(spidev, field, typ) ({ \
- typ val; \
- assert(sizeof(val) == sizeof((struct w5500_block_sock_reg).field)); \
- w5500_spiframe_read(spidev, \
- offsetof(struct w5500_block_sock_reg, field), \
- CTL_BLOCK_COMMON, \
- &(val), \
- sizeof(struct w5500_block_sock_reg, field)); \
- val; \
+#define REGREAD_COMMON(spidev, field, typ) ({ \
+ typ val; \
+ assert(sizeof(val) == sizeof(((struct w5500_block_sock_reg){}).field)); \
+ w5500_spiframe_read(spidev, \
+ offsetof(struct w5500_block_sock_reg, field), \
+ CTL_BLOCK_COMMON, \
+ &(val), \
+ sizeof(val)); \
+ val; \
})
-#define REGWRITE_SOCK(spidev, socknum, field, val) do { \
- assert(sizeof(val) == sizeof((struct w5500_block_sock_reg).field)); \
- w5500_spiframe_write(spidev, \
- offsetof(struct w5500_block_sock_reg, field), \
- CTL_BLOCK_SOCK(socknum, REG), \
- &(val), \
- sizeof(struct w5500_block_sock_reg, field)); \
+#define REGWRITE_SOCK(spidev, socknum, field, val) do { \
+ assert(sizeof(val) == sizeof(((struct w5500_block_sock_reg){}).field)); \
+ typeof(val) lval = val; \
+ w5500_spiframe_write(spidev, \
+ offsetof(struct w5500_block_sock_reg, field), \
+ CTL_BLOCK_SOCK(socknum, REG), \
+ &lval, \
+ sizeof(lval)); \
} while (0)
-#define REGREAD_SOCK(spidev, socknum, field, typ) ({ \
- typ val; \
- assert(sizeof(val) == sizeof((struct w5500_block_sock_reg).field)); \
- w5500_spiframe_read(spidev, \
- offsetof(struct w5500_block_sock_reg, field), \
- CTL_BLOCK_SOCK(socknum, REG), \
- &(val), \
- sizeof(struct w5500_block_sock_reg, field)); \
- val; \
+#define REGREAD_SOCK(spidev, socknum, field, typ) ({ \
+ typ val; \
+ assert(sizeof(val) == sizeof(((struct w5500_block_sock_reg){}).field)); \
+ w5500_spiframe_read(spidev, \
+ offsetof(struct w5500_block_sock_reg, field), \
+ CTL_BLOCK_SOCK(socknum, REG), \
+ &(val), \
+ sizeof(val)); \
+ val; \
})
/* init() *********************************************************************/
@@ -383,7 +387,7 @@ void _w5500_init(struct w5500 *chip,
}
chip->_next_local_port = CONFIG_W5500_LOCAL_PORT_MIN;
- gpio_set_irq_enabled_with_callback(pin_intr, GPIO_IRQ_EDGE_FALL, true, cbfn);
+ gpio_set_irq_enabled_with_callback(pin_intr, GPIO_IRQ_EDGE_FALL, true, TODO_cbfn);
gpio_set_dir(chip->pin_reset, GPIO_OUT);
w5500_reset(chip);
@@ -394,9 +398,9 @@ void _w5500_init(struct w5500 *chip,
void w5500_reset(struct w5500 *chip) {
/* TODO: Replace blocking sleep_ms() with something libcr-friendly. */
- gpio_put(chip->pin_reset, 0)
+ gpio_put(chip->pin_reset, 0);
sleep_ms(1); /* minimum of 500us */
- gpio_put(chip->pin_reset, 1)
+ gpio_put(chip->pin_reset, 1);
sleep_ms(2); /* minimum of 1ms */
}
@@ -413,13 +417,13 @@ struct libnet_listener *w5500_listen(struct w5500 *chip, uint8_t socknum, uint16
assert(socknum < 8);
assert(port);
- w5500_close(&chip->_listeners[socknum].active_socket, true, true);
+ w5500_close((struct libnet_conn *)&chip->_listeners[socknum].active_conn, true, true);
REGWRITE_SOCK(chip->spidev, socknum, mode, MODE_TCP);
- REGWRITE_SOCK(chip->spidev, socknum, local_port, (uint8_t[2]){port>>8, port});
+ REGWRITE_SOCK(chip->spidev, socknum, local_port, ((uint8_t[2]){port>>8, port}));
REGWRITE_SOCK(chip->spidev, socknum, command, CMD_OPEN);
while (REGREAD_SOCK(chip->spidev, socknum, command, uint8_t) != 0x00)
cr_yield();
- while (REGREAD_SOCK(spidev, socknum, state, uint8_t) != STATE_TCP_INIT)
+ while (REGREAD_SOCK(chip->spidev, socknum, state, uint8_t) != STATE_TCP_INIT)
cr_yield();
return (struct libnet_listener *)&chip->_listeners[socknum];
@@ -428,7 +432,7 @@ struct libnet_listener *w5500_listen(struct w5500 *chip, uint8_t socknum, uint16
/* accept() *******************************************************************/
#define ASSERT_LISTENER() \
- struct w5500_listener *self = (struct w5500_listener *)_self; \
+ struct _w5500_listener *self = (struct _w5500_listener *)_self; \
assert(self); \
\
struct w5500 *chip = self->chip; \
@@ -443,14 +447,14 @@ static struct libnet_conn *w5500_accept(struct libnet_listener *_self) {
while (REGREAD_SOCK(chip->spidev, socknum, command, uint8_t) != 0x00)
cr_yield();
for (;;) {
- uint8_t mode = REGREAD_SOCK(spidev, socknum, state, uint8_t);
+ uint8_t mode = REGREAD_SOCK(chip->spidev, socknum, state, uint8_t);
switch (mode) {
case STATE_TCP_LISTEN:
case STATE_TCP_SYNRECV:
cr_yield();
break;
default:
- return &self->active_conn;
+ return (struct libnet_conn *)&self->active_conn;
}
}
}
@@ -458,12 +462,12 @@ static struct libnet_conn *w5500_accept(struct libnet_listener *_self) {
/* write() ********************************************************************/
#define ASSERT_CONN() \
- struct w5500_conn *self = (struct w5500_conn *)_self; \
- assert(self); \
- \
- struct w5500 *chip = self->parent_listener->chip; \
- uint8_t socknum = self->parent_listener->socknum; \
- assert(chip); \
+ struct _w5500_conn *self = (struct _w5500_conn *)_self; \
+ assert(self); \
+ \
+ struct w5500 *chip = self->parent_listener->chip; \
+ uint8_t socknum = self->parent_listener->socknum; \
+ assert(chip); \
assert(socknum < 8)
@@ -472,7 +476,7 @@ static ssize_t w5500_write(struct libnet_conn *_self, void *buf, size_t count) {
assert(buf);
assert(count);
-
+ // TODO
}
static int w5500_close(struct libnet_conn *_self, bool rd, bool wr) {