diff options
-rw-r--r-- | cmd/sbc_harness/CMakeLists.txt | 5 | ||||
-rw-r--r-- | cmd/sbc_harness/hw/rp2040_hwspi.c | 24 | ||||
-rw-r--r-- | cmd/sbc_harness/hw/rp2040_hwspi.h | 12 | ||||
-rw-r--r-- | cmd/sbc_harness/hw/w5500.c | 168 | ||||
-rw-r--r-- | cmd/sbc_harness/hw/w5500.h | 10 | ||||
-rw-r--r-- | cmd/sbc_harness/main.c | 7 | ||||
-rw-r--r-- | libnet/include/libnet/libnet.h | 4 |
7 files changed, 122 insertions, 108 deletions
diff --git a/cmd/sbc_harness/CMakeLists.txt b/cmd/sbc_harness/CMakeLists.txt index 0dc77a5..04f231d 100644 --- a/cmd/sbc_harness/CMakeLists.txt +++ b/cmd/sbc_harness/CMakeLists.txt @@ -8,13 +8,18 @@ pico_sdk_init() add_executable(sbc_harness main.c usb_keyboard.c + hw/rp2040_hwspi.c + hw/w5500.c ) target_include_directories(sbc_harness PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/config) target_include_directories(sbc_harness PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(sbc_harness pico_stdlib + hardware_spi + hardware_gpio libusb + libnet ) pico_enable_stdio_usb(sbc_harness 0) diff --git a/cmd/sbc_harness/hw/rp2040_hwspi.c b/cmd/sbc_harness/hw/rp2040_hwspi.c index 2f0bec4..7019954 100644 --- a/cmd/sbc_harness/hw/rp2040_hwspi.c +++ b/cmd/sbc_harness/hw/rp2040_hwspi.c @@ -3,7 +3,8 @@ #include <assert.h> -#include <hardware/spi.h> /* pico-sdk:hardware_spi */ +#include <hardware/spi.h> /* pico-sdk:hardware_spi */ +#include <hardware/gpio.h> /* pico-sdk:hardware_gpio5 */ #include "hw/rp2040_hwspi.h" @@ -13,13 +14,14 @@ struct spi_vtable rp2040_hwspi_vtable = { .readwritev = rp2040_hwspi_readwritev, }; -static inline void _rp2040_hwspi_init(struct rp2040_hwspi *self, - enum rp2040_hwspi_instance inst_num, - uint baudrate_hz; - uint pin_miso, - uint pin_mosi, - uint pin_clk, - uint pin_cs) { +void _rp2040_hwspi_init(struct rp2040_hwspi *self, + enum rp2040_hwspi_instance inst_num, + enum spi_mode mode, + uint baudrate_hz, + uint pin_miso, + uint pin_mosi, + uint pin_clk, + uint pin_cs) { /* Be not weary: This is but 12 lines of actual code; and many * lines of comments and assert()s. */ spi_inst_t *inst; @@ -90,8 +92,8 @@ static inline void _rp2040_hwspi_init(struct rp2040_hwspi *self, self->pin_cs = pin_cs; } -static void rp2040_hwspi_readwritev(struct spi *_self, const struct bidi_iovec *iov, int iovcnt); { - struct rp2040_hwspi* self = _self; +static void rp2040_hwspi_readwritev(struct spi *_self, const struct bidi_iovec *iov, int iovcnt) { + struct rp2040_hwspi *self = (struct rp2040_hwspi *)_self; assert(self); spi_inst_t *inst = self->inst; @@ -107,7 +109,7 @@ static void rp2040_hwspi_readwritev(struct spi *_self, const struct bidi_iovec * else if (iov[i].iov_write_src) spi_write_blocking(inst, iov[i].iov_write_src, iov[i].iov_len); else if (iov[i].iov_read_dst) - spi_read_blocking(inst, iov[i].iov_read_dst, iov[i].iov_len); + spi_read_blocking(inst, 0, iov[i].iov_read_dst, iov[i].iov_len); else assert(false); } diff --git a/cmd/sbc_harness/hw/rp2040_hwspi.h b/cmd/sbc_harness/hw/rp2040_hwspi.h index 22ef6fa..55a6759 100644 --- a/cmd/sbc_harness/hw/rp2040_hwspi.h +++ b/cmd/sbc_harness/hw/rp2040_hwspi.h @@ -1,6 +1,8 @@ #ifndef _RP2040_HWSPI_H_ #define _RP2040_HWSPI_H_ +#include <pico/binary_info.h> /* for bi_* */ + #include "hw/spi.h" enum rp2040_hwspi_instance { @@ -34,13 +36,13 @@ struct rp2040_hwspi { inst_num, mode, baudrate_hz, \ pin_miso, pin_mosi, pin_clk, pin_cs) \ do { \ - bi_decl(bi_4_pins_with_names(pin_miso, name" SPI MISO", \ - pin_mosi, name" SPI MOSI", \ - pin_mosi, name" SPI CLK", \ - pin_mosi, name" SPI CS")); \ + bi_decl(bi_4pins_with_names(pin_miso, name" SPI MISO", \ + pin_mosi, name" SPI MOSI", \ + pin_mosi, name" SPI CLK", \ + pin_mosi, name" SPI CS")); \ _rp2040_hwspi_init(self, \ inst_num, mode, baudrate_hz, \ - pin_miso, pin_mosi, pin_c;k, pin_cs); \ + pin_miso, pin_mosi, pin_clk, pin_cs); \ } while(0) void _rp2040_hwspi_init(struct rp2040_hwspi *self, enum rp2040_hwspi_instance inst_num, 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) { diff --git a/cmd/sbc_harness/hw/w5500.h b/cmd/sbc_harness/hw/w5500.h index 90d4130..967a436 100644 --- a/cmd/sbc_harness/hw/w5500.h +++ b/cmd/sbc_harness/hw/w5500.h @@ -43,13 +43,13 @@ struct w5500 { * happened.) * - A reset pin that the MCU can pull low to reset the W5500. */ -#define w5500_init(self, name, spi, pin_intr, pin_reset, eth_addr) do { \ - bi_decl(bi_2_pins_with_names(pin_intr, name" interrupt"), \ - pin_reset, name" reset"); \ - _w5500_init(self, spi, pin_intr, pin_reset, eth_addr); \ +#define w5500_init(self, name, spi, pin_intr, pin_reset, eth_addr) do { \ + bi_decl(bi_2pins_with_names(pin_intr, name" interrupt", \ + pin_reset, name" reset")); \ + _w5500_init(self, spi, pin_intr, pin_reset, eth_addr); \ } while (0) void _w5500_init(struct w5500 *self, - struct spi* spi, uint pin_intr, + struct spi* spi, uint pin_intr, uint pin_reset, struct eth_addr addr); /** diff --git a/cmd/sbc_harness/main.c b/cmd/sbc_harness/main.c index 1200608..b120d46 100644 --- a/cmd/sbc_harness/main.c +++ b/cmd/sbc_harness/main.c @@ -44,9 +44,10 @@ int main() { 19, /* PIN_MOSI */ 18, /* PIN_CLK */ 17); /* PIN_CS */ - w5500_init(&dev_w5500, "W5500", &dev_spi, - 21, /* PIN_INTR */ - 20); /* PIN_RESET */ + w5500_init(&dev_w5500, "W5500", (struct spi *)&dev_spi, + 21, /* PIN_INTR */ + 20, /* PIN_RESET */ + ((struct eth_addr){{0xDE,0xAD,0xBE,0xEF,0x01,0x02}})); usb_common_earlyinit(); usb_keyboard_init(); diff --git a/libnet/include/libnet/libnet.h b/libnet/include/libnet/libnet.h index c56b61d..4145f8b 100644 --- a/libnet/include/libnet/libnet.h +++ b/libnet/include/libnet/libnet.h @@ -7,11 +7,11 @@ struct ip4_addr { unsigned char bytes[4]; -} +}; struct eth_addr { unsigned char bytes[6]; -} +}; struct libnet_conn; struct libnet_listener; |