Compare commits
10 Commits
3d20bf4c33
...
f2d98ef4f1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2d98ef4f1 | ||
|
|
8edf8c2d4f | ||
|
|
c961499239 | ||
|
|
0d41f63533 | ||
|
|
394628b8da | ||
|
|
bee0fa3aef | ||
|
|
ff9f9a5c1f | ||
|
|
af308b5aac | ||
|
|
712110aace | ||
|
|
0c11cbb1d1 |
@@ -15,6 +15,7 @@ inline bool operator<(const timer_entry& a, const timer_entry& b) {
|
||||
struct timer_queue {
|
||||
sorted_list<timer_entry, 16> queue;
|
||||
alarm_id_t alarm = -1;
|
||||
volatile bool irq_pending = false;
|
||||
|
||||
void schedule(absolute_time_t when, std::function<void()> fn) {
|
||||
queue.insert({when, std::move(fn)});
|
||||
@@ -26,6 +27,8 @@ struct timer_queue {
|
||||
}
|
||||
|
||||
void run() {
|
||||
if (!irq_pending) return;
|
||||
irq_pending = false;
|
||||
while (!queue.empty()) {
|
||||
auto& front = queue.front();
|
||||
if (absolute_time_diff_us(get_absolute_time(), front.when) > 0) break;
|
||||
@@ -39,12 +42,15 @@ struct timer_queue {
|
||||
bool empty() const { return queue.empty(); }
|
||||
|
||||
private:
|
||||
static int64_t alarm_cb(alarm_id_t, void*) { return 0; }
|
||||
static int64_t alarm_cb(alarm_id_t, void* user_data) {
|
||||
static_cast<timer_queue*>(user_data)->irq_pending = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arm() {
|
||||
if (alarm >= 0) cancel_alarm(alarm);
|
||||
alarm = -1;
|
||||
if (!queue.empty())
|
||||
alarm = add_alarm_at(queue.front().when, alarm_cb, nullptr, false);
|
||||
alarm = add_alarm_at(queue.front().when, alarm_cb, this, false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "timer_queue.h"
|
||||
#include "net.h"
|
||||
#include "debug_log.h"
|
||||
#include "hardware/sync.h"
|
||||
|
||||
static timer_queue timers;
|
||||
|
||||
@@ -39,6 +40,8 @@ void dispatch_schedule_ms(uint32_t ms, std::function<void()> fn) {
|
||||
});
|
||||
|
||||
while (true) {
|
||||
uint32_t save = save_and_disable_interrupts();
|
||||
|
||||
dlog_if_slow("tud_task", 1000, [&]{ tud_task(); });
|
||||
dlog_if_slow("drain", 1000, [&]{ usb.drain(); });
|
||||
dlog_if_slow("timers", 1000, [&]{ timers.run(); });
|
||||
@@ -76,6 +79,7 @@ void dispatch_schedule_ms(uint32_t ms, std::function<void()> fn) {
|
||||
}
|
||||
}
|
||||
|
||||
// __wfi();
|
||||
__wfi();
|
||||
restore_interrupts(save);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,9 +108,7 @@ static bool ip_match_or_broadcast(const ip4_addr& dst) {
|
||||
|
||||
static void send_raw(const void* data, size_t len) {
|
||||
dlog_if_slow("send_raw", 1000, [&]{
|
||||
w6300::ip_address dummy = {};
|
||||
w6300::sendto(raw_socket, std::span<const uint8_t>{static_cast<const uint8_t*>(data), len},
|
||||
dummy, w6300::port_num{0});
|
||||
w6300::send(raw_socket, std::span<const uint8_t>{static_cast<const uint8_t*>(data), len});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -262,7 +260,6 @@ static void process_frame(const uint8_t* frame, size_t len) {
|
||||
|
||||
bool net_init() {
|
||||
w6300::init_spi();
|
||||
w6300::init_critical_section();
|
||||
w6300::reset();
|
||||
w6300::init();
|
||||
if (!w6300::check()) return false;
|
||||
@@ -281,8 +278,8 @@ bool net_init() {
|
||||
state.ip[2] = state.mac[4];
|
||||
state.ip[3] = state.mac[5];
|
||||
|
||||
w6300::open_socket(raw_socket, w6300::protocol::macraw, w6300::port_num{0}, w6300::sock_flag::none);
|
||||
w6300::set_socket_io_mode(raw_socket, w6300::sock_io_mode::nonblock);
|
||||
w6300::open_socket(raw_socket, w6300::protocol::macraw, w6300::sock_flag::none);
|
||||
w6300::set_interrupt_mask(w6300::ik_sock_0);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -296,11 +293,12 @@ void net_set_handler(net_handler handler) {
|
||||
}
|
||||
|
||||
void net_poll() {
|
||||
if (!w6300::irq_pending) return;
|
||||
w6300::irq_pending = false;
|
||||
w6300::clear_interrupt(w6300::ik_int_all);
|
||||
if (w6300::get_socket_recv_buf(raw_socket) == 0) return;
|
||||
static uint8_t rx_buf[1518];
|
||||
w6300::ip_address dummy_addr = {};
|
||||
w6300::port_num dummy_port{0};
|
||||
auto result = w6300::recvfrom(raw_socket, std::span{rx_buf}, dummy_addr, dummy_port);
|
||||
auto result = w6300::recv(raw_socket, std::span{rx_buf});
|
||||
if (!result) return;
|
||||
process_frame(rx_buf, *result);
|
||||
}
|
||||
|
||||
@@ -29,44 +29,34 @@ static ResponseTest test_discovery() {
|
||||
ResponseTest resp;
|
||||
resp.pass = true;
|
||||
|
||||
w6300::ip_address dest = {};
|
||||
std::copy(picomap_discovery_ip.begin(), picomap_discovery_ip.end(), dest.ip.begin());
|
||||
dest.len = 4;
|
||||
|
||||
w6300::set_socket_dest_mac(test_socket, picomap_discovery_mac);
|
||||
|
||||
auto req = encode_request(0, RequestInfo{});
|
||||
auto send_result = w6300::sendto(test_socket, std::span<const uint8_t>{req}, dest,
|
||||
w6300::port_num{PICOMAP_DISCOVERY_PORT});
|
||||
auto send_result = w6300::send(test_socket, std::span<const uint8_t>{req});
|
||||
if (!send_result) {
|
||||
resp.pass = false;
|
||||
resp.messages.push_back("sendto: error " + std::to_string(static_cast<int>(send_result.error())));
|
||||
resp.messages.push_back("send: error " + std::to_string(static_cast<int>(send_result.error())));
|
||||
return resp;
|
||||
}
|
||||
|
||||
uint8_t rx_buf[512];
|
||||
w6300::ip_address src_addr = {};
|
||||
w6300::port_num src_port{0};
|
||||
|
||||
auto deadline = make_timeout_time_ms(5000);
|
||||
std::expected<uint16_t, w6300::sock_error> recv_result = std::unexpected(w6300::sock_error::busy);
|
||||
while (get_absolute_time() < deadline) {
|
||||
recv_result = w6300::recvfrom(test_socket, std::span{rx_buf}, src_addr, src_port);
|
||||
recv_result = w6300::recv(test_socket, std::span{rx_buf});
|
||||
if (recv_result || recv_result.error() != w6300::sock_error::busy) break;
|
||||
}
|
||||
|
||||
if (!recv_result) {
|
||||
resp.pass = false;
|
||||
if (recv_result.error() == w6300::sock_error::busy) {
|
||||
resp.messages.push_back("recvfrom: timed out after 5s");
|
||||
resp.messages.push_back("recv: timed out after 5s");
|
||||
} else {
|
||||
resp.messages.push_back("recvfrom: error " + std::to_string(static_cast<int>(recv_result.error())));
|
||||
resp.messages.push_back("recv: error " + std::to_string(static_cast<int>(recv_result.error())));
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
resp.messages.push_back("received " + std::to_string(*recv_result) + " bytes from port " +
|
||||
std::to_string(static_cast<uint16_t>(src_port)));
|
||||
resp.messages.push_back("received " + std::to_string(*recv_result) + " bytes");
|
||||
|
||||
auto info = decode_response<ResponseInfo>(rx_buf, *recv_result);
|
||||
if (!info) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,267 +2,50 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
|
||||
namespace w6300 {
|
||||
|
||||
constexpr int sock_count = 8;
|
||||
|
||||
enum class socket_id : uint8_t {};
|
||||
enum class port_num : uint16_t {};
|
||||
|
||||
enum class sock_error : int16_t {
|
||||
busy = 0,
|
||||
sock_num = -1,
|
||||
sock_opt = -2,
|
||||
sock_init = -3,
|
||||
sock_closed = -4,
|
||||
sock_mode = -5,
|
||||
sock_flag = -6,
|
||||
sock_status = -7,
|
||||
arg = -10,
|
||||
port_zero = -11,
|
||||
ip_invalid = -12,
|
||||
timeout = -13,
|
||||
data_len = -14,
|
||||
buffer = -15,
|
||||
fatal_packlen = -1001,
|
||||
};
|
||||
|
||||
enum class protocol : uint8_t {
|
||||
tcp = 0x01,
|
||||
udp = 0x02,
|
||||
ipraw = 0x03,
|
||||
macraw = 0x07,
|
||||
tcp6 = 0x09,
|
||||
udp6 = 0x0A,
|
||||
ipraw6 = 0x0B,
|
||||
tcp_dual = 0x0D,
|
||||
udp_dual = 0x0E,
|
||||
};
|
||||
|
||||
enum class sock_flag : uint8_t {
|
||||
none = 0,
|
||||
multi_enable = 1 << 7,
|
||||
ether_own = 1 << 7,
|
||||
broad_block = 1 << 6,
|
||||
tcp_fpsh = 1 << 6,
|
||||
tcp_nodelay = 1 << 5,
|
||||
igmp_ver2 = 1 << 5,
|
||||
solicit_block = 1 << 5,
|
||||
ether_multi4b = 1 << 5,
|
||||
uni_block = 1 << 4,
|
||||
ether_multi6b = 1 << 4,
|
||||
force_arp = 1 << 0,
|
||||
dha_manual = 1 << 1,
|
||||
io_nonblock = 1 << 3,
|
||||
};
|
||||
constexpr sock_flag operator|(sock_flag a, sock_flag b) {
|
||||
return static_cast<sock_flag>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
||||
}
|
||||
constexpr uint8_t operator&(sock_flag a, sock_flag b) {
|
||||
return static_cast<uint8_t>(a) & static_cast<uint8_t>(b);
|
||||
}
|
||||
|
||||
enum class pack_info : uint8_t {
|
||||
none = 0x00,
|
||||
first = 1 << 1,
|
||||
remained = 1 << 2,
|
||||
completed = 1 << 3,
|
||||
ipv6_lla = (1 << 7) | (1 << 4),
|
||||
ipv6_multi = (1 << 7) | (1 << 5),
|
||||
ipv6_allnode = (1 << 7) | (1 << 6),
|
||||
ipv6 = 1 << 7,
|
||||
};
|
||||
constexpr pack_info operator|(pack_info a, pack_info b) {
|
||||
return static_cast<pack_info>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
||||
}
|
||||
constexpr uint8_t operator&(pack_info a, pack_info b) {
|
||||
return static_cast<uint8_t>(a) & static_cast<uint8_t>(b);
|
||||
}
|
||||
|
||||
enum class srcv6_prefer : uint8_t {
|
||||
auto_select = 0x00,
|
||||
lla = 0x02,
|
||||
gua = 0x03,
|
||||
};
|
||||
|
||||
enum class tcp_sock_info : uint8_t {
|
||||
mode = 1 << 2,
|
||||
op = 1 << 1,
|
||||
sip = 1 << 0,
|
||||
};
|
||||
|
||||
enum class sock_io_mode : uint8_t {
|
||||
block = 0,
|
||||
nonblock = 1,
|
||||
};
|
||||
|
||||
enum intr_kind : uint32_t {
|
||||
ik_pppoe_terminated = (1 << 0), ik_dest_unreach = (1 << 1), ik_ip_conflict = (1 << 2),
|
||||
ik_dest_unreach6 = (1 << 4), ik_wol = (1 << 7), ik_net_all = 0x97,
|
||||
ik_sock_0 = (1 << 8), ik_sock_1 = (1 << 9), ik_sock_2 = (1 << 10), ik_sock_3 = (1 << 11),
|
||||
ik_sock_4 = (1 << 12), ik_sock_5 = (1 << 13), ik_sock_6 = (1 << 14), ik_sock_7 = (1 << 15),
|
||||
ik_sock_all = (0xFF << 8),
|
||||
ik_sockl_tout = (1 << 16), ik_sockl_arp4 = (1 << 17), ik_sockl_ping4 = (1 << 18),
|
||||
ik_sockl_arp6 = (1 << 19), ik_sockl_ping6 = (1 << 20), ik_sockl_ns = (1 << 21),
|
||||
ik_sockl_rs = (1 << 22), ik_sockl_ra = (1 << 23), ik_sockl_all = (0xFF << 16),
|
||||
ik_sock_0 = (1 << 8),
|
||||
ik_int_all = 0x00FFFF97
|
||||
};
|
||||
|
||||
struct phy_conf {
|
||||
uint8_t by;
|
||||
uint8_t mode;
|
||||
uint8_t speed;
|
||||
uint8_t duplex;
|
||||
};
|
||||
|
||||
enum ipconf_mode : uint8_t {
|
||||
ipconf_none = 0x00, ipconf_static_v4 = 0x01, ipconf_static_v6 = 0x02,
|
||||
ipconf_static_all = 0x03, ipconf_slaac_v6 = 0x04,
|
||||
ipconf_dhcp_v4 = 0x10, ipconf_dhcp_v6 = 0x20, ipconf_dhcp_all = 0x30
|
||||
};
|
||||
|
||||
enum dhcp_mode : uint8_t { dhcp_static = 1, dhcp_dynamic };
|
||||
|
||||
struct net_info {
|
||||
std::array<uint8_t, 6> mac;
|
||||
std::array<uint8_t, 4> ip;
|
||||
std::array<uint8_t, 4> sn;
|
||||
std::array<uint8_t, 4> gw;
|
||||
std::array<uint8_t, 16> lla;
|
||||
std::array<uint8_t, 16> gua;
|
||||
std::array<uint8_t, 16> sn6;
|
||||
std::array<uint8_t, 16> gw6;
|
||||
std::array<uint8_t, 4> dns;
|
||||
std::array<uint8_t, 16> dns6;
|
||||
ipconf_mode ipmode;
|
||||
dhcp_mode dhcp;
|
||||
};
|
||||
|
||||
enum netmode_type : uint32_t {
|
||||
nm_ipb_v4 = (1 << 0), nm_ipb_v6 = (1 << 1), nm_wol = (1 << 2),
|
||||
nm_pb6_multi = (1 << 4), nm_pb6_allnode = (1 << 5), nm_mr_mask = 0x37,
|
||||
nm_pppoe = (1 << 8), nm_dha_select = (1 << 15), nm_mr2_mask = (0x09 << 8),
|
||||
nm_pb4_all = (1 << 16), nm_trstb_v4 = (1 << 17), nm_parp_v4 = (1 << 18),
|
||||
nm_unrb_v4 = (1 << 19), nm_net4_mask = (0x0F << 16),
|
||||
nm_pb6_all = (1 << 24), nm_trstb_v6 = (1 << 25), nm_parp_v6 = (1 << 26),
|
||||
nm_unrb_v6 = (1 << 27), nm_net6_mask = (0x0F << 24),
|
||||
nm_mask_all = 0x0F0F0937
|
||||
};
|
||||
|
||||
struct net_timeout {
|
||||
uint8_t s_retry_cnt;
|
||||
uint16_t s_time_100us;
|
||||
uint8_t sl_retry_cnt;
|
||||
uint16_t sl_time_100us;
|
||||
};
|
||||
|
||||
struct ip_address {
|
||||
std::array<uint8_t, 16> ip;
|
||||
uint8_t len;
|
||||
};
|
||||
|
||||
struct prefix {
|
||||
uint8_t len;
|
||||
uint8_t flag;
|
||||
uint32_t valid_lifetime;
|
||||
uint32_t preferred_lifetime;
|
||||
std::array<uint8_t, 16> prefix;
|
||||
};
|
||||
|
||||
struct arp_request {
|
||||
ip_address destinfo;
|
||||
std::array<uint8_t, 6> dha;
|
||||
};
|
||||
|
||||
struct ping_request {
|
||||
uint16_t id;
|
||||
uint16_t seq;
|
||||
ip_address destinfo;
|
||||
};
|
||||
|
||||
void init_spi();
|
||||
void init_critical_section();
|
||||
void reset();
|
||||
void init();
|
||||
bool check();
|
||||
void init_net(const net_info& info);
|
||||
|
||||
void soft_reset();
|
||||
int8_t init_buffers(std::span<const uint8_t> txsize, std::span<const uint8_t> rxsize);
|
||||
extern volatile bool irq_pending;
|
||||
|
||||
void clear_interrupt(intr_kind intr);
|
||||
intr_kind get_interrupt();
|
||||
void set_interrupt_mask(intr_kind intr);
|
||||
intr_kind get_interrupt_mask();
|
||||
|
||||
int8_t get_phy_link();
|
||||
int8_t get_phy_power_mode();
|
||||
void reset_phy();
|
||||
void set_phy_conf(const phy_conf& conf);
|
||||
phy_conf get_phy_conf();
|
||||
phy_conf get_phy_status();
|
||||
void set_phy_power_mode(uint8_t pmode);
|
||||
|
||||
void set_net_info(const net_info& info);
|
||||
net_info get_net_info();
|
||||
void set_net_mode(netmode_type mode);
|
||||
netmode_type get_net_mode();
|
||||
void set_timeout(const net_timeout& timeout);
|
||||
net_timeout get_timeout();
|
||||
|
||||
int8_t send_arp(arp_request& arp);
|
||||
int8_t send_ping(const ping_request& ping);
|
||||
int8_t send_dad(std::span<const uint8_t, 16> ipv6);
|
||||
int8_t send_slaac(prefix& pfx);
|
||||
int8_t send_unsolicited();
|
||||
int8_t get_prefix(prefix& pfx);
|
||||
|
||||
std::expected<socket_id, sock_error> open_socket(socket_id sn, protocol proto, port_num port, sock_flag flag);
|
||||
std::expected<void, sock_error> close(socket_id sn);
|
||||
std::expected<void, sock_error> listen(socket_id sn);
|
||||
std::expected<void, sock_error> disconnect(socket_id sn);
|
||||
std::expected<socket_id, sock_error> open_socket(socket_id sn, protocol proto, sock_flag flag);
|
||||
std::expected<uint16_t, sock_error> send(socket_id sn, std::span<const uint8_t> buf);
|
||||
std::expected<uint16_t, sock_error> recv(socket_id sn, std::span<uint8_t> buf);
|
||||
|
||||
std::expected<void, sock_error> connect(socket_id sn, const ip_address& addr, port_num port);
|
||||
std::expected<uint16_t, sock_error> sendto(socket_id sn, std::span<const uint8_t> buf, const ip_address& addr, port_num port);
|
||||
std::expected<uint16_t, sock_error> recvfrom(socket_id sn, std::span<uint8_t> buf, ip_address& addr, port_num& port);
|
||||
|
||||
std::expected<void, sock_error> set_socket_io_mode(socket_id sn, sock_io_mode mode);
|
||||
sock_io_mode get_socket_io_mode(socket_id sn);
|
||||
uint16_t get_socket_max_tx(socket_id sn);
|
||||
uint16_t get_socket_max_rx(socket_id sn);
|
||||
std::expected<void, sock_error> clear_socket_interrupt(socket_id sn, uint8_t flags);
|
||||
uint8_t get_socket_interrupt(socket_id sn);
|
||||
std::expected<void, sock_error> set_socket_interrupt_mask(socket_id sn, uint8_t mask);
|
||||
uint8_t get_socket_interrupt_mask(socket_id sn);
|
||||
std::expected<void, sock_error> set_socket_prefer(socket_id sn, srcv6_prefer pref);
|
||||
srcv6_prefer get_socket_prefer(socket_id sn);
|
||||
|
||||
void set_socket_ttl(socket_id sn, uint8_t ttl);
|
||||
uint8_t get_socket_ttl(socket_id sn);
|
||||
void set_socket_tos(socket_id sn, uint8_t tos);
|
||||
uint8_t get_socket_tos(socket_id sn);
|
||||
void set_socket_mss(socket_id sn, uint16_t mss);
|
||||
uint16_t get_socket_mss(socket_id sn);
|
||||
void set_socket_dest_mac(socket_id sn, const std::array<uint8_t, 6>& mac);
|
||||
void set_socket_dest_ip(socket_id sn, const ip_address& addr);
|
||||
ip_address get_socket_dest_ip(socket_id sn);
|
||||
void set_socket_dest_port(socket_id sn, port_num port);
|
||||
port_num get_socket_dest_port(socket_id sn);
|
||||
std::expected<void, sock_error> send_keepalive(socket_id sn);
|
||||
void set_socket_keepalive_auto(socket_id sn, uint8_t interval);
|
||||
uint8_t get_socket_keepalive_auto(socket_id sn);
|
||||
uint16_t get_socket_send_buf(socket_id sn);
|
||||
uint16_t get_socket_recv_buf(socket_id sn);
|
||||
uint8_t get_socket_status(socket_id sn);
|
||||
uint8_t get_socket_ext_status(socket_id sn);
|
||||
uint8_t get_socket_mode(socket_id sn);
|
||||
uint16_t get_socket_remain_size(socket_id sn);
|
||||
pack_info get_socket_pack_info(socket_id sn);
|
||||
|
||||
std::optional<uint16_t> peek_socket_msg(socket_id sn, std::span<const uint8_t> submsg);
|
||||
|
||||
} // namespace w6300
|
||||
|
||||
Reference in New Issue
Block a user