summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/sbc_harness/CMakeLists.txt5
-rw-r--r--cmd/sbc_harness/hw/rp2040_hwspi.c24
-rw-r--r--cmd/sbc_harness/hw/rp2040_hwspi.h12
-rw-r--r--cmd/sbc_harness/hw/w5500.c168
-rw-r--r--cmd/sbc_harness/hw/w5500.h10
-rw-r--r--cmd/sbc_harness/main.c7
-rw-r--r--libnet/include/libnet/libnet.h4
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;