diff options
Diffstat (limited to 'cmd/sbc_harness/hw/w5500.c')
-rw-r--r-- | cmd/sbc_harness/hw/w5500.c | 168 |
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) { |