summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-12 16:29:37 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-12-08 08:27:23 -0700
commitd07ade8014628930057f5398fc26b06a527bb4d0 (patch)
tree492e5a416bd2d6a9d701dde323e7643f397b3f37
parent957931e0f585b5132bf16e28b7eb3e68aec70d9a (diff)
w5500: Add DEBUG logging
-rw-r--r--cmd/sbc_harness/config/config.h2
-rw-r--r--libhw/w5500.c132
-rw-r--r--libhw_generic/include/libhw/generic/net.h15
-rw-r--r--libmisc/include/libmisc/log.h4
-rw-r--r--libmisc/log.c266
5 files changed, 394 insertions, 25 deletions
diff --git a/cmd/sbc_harness/config/config.h b/cmd/sbc_harness/config/config.h
index 6d2ea89..3f7a0bf 100644
--- a/cmd/sbc_harness/config/config.h
+++ b/cmd/sbc_harness/config/config.h
@@ -25,6 +25,8 @@
#define CONFIG_W5500_LOCAL_PORT_MIN 32768
#define CONFIG_W5500_LOCAL_PORT_MAX 60999
+#define CONFIG_W5500_DEBUG 1 /* bool */
+
/* 9P *************************************************************************/
#define CONFIG_9P_PORT 564
diff --git a/libhw/w5500.c b/libhw/w5500.c
index c1607f1..e675ae9 100644
--- a/libhw/w5500.c
+++ b/libhw/w5500.c
@@ -67,6 +67,8 @@
* SPDX-License-Identifier: MIT
*/
+#include <inttypes.h> /* for PRIu{n} */
+
/* TODO: Write a <libhw/generic/gpio.h> to avoid w5500.c being
* pico-sdk-specific. */
#include <hardware/gpio.h> /* pico-sdk:hardware_gpio */
@@ -77,7 +79,7 @@
#include <libhw/generic/alarmclock.h> /* for sleep_*() */
#define LOG_NAME W5500
-#include <libmisc/log.h> /* for errorf() */
+#include <libmisc/log.h> /* for errorf(), debugf(), const_byte_str() */
#define IMPLEMENTATION_FOR_LIBHW_W5500_H YES
#include <libhw/w5500.h>
@@ -88,26 +90,43 @@
#include "config.h"
-/* These are the default values of the Linux kernel's
- * net.ipv4.ip_local_port_range, so I figure they're probably good
- * values to use. */
#ifndef CONFIG_W5500_LOCAL_PORT_MIN
#error config.h must define CONFIG_W5500_LOCAL_PORT_MIN
#endif
-
#ifndef CONFIG_W5500_LOCAL_PORT_MAX
#error config.h must define CONFIG_W5500_LOCAL_PORT_MAX
#endif
-
#ifndef CONFIG_W5500_NUM
#error config.h must define CONFIG_W5500_NUM
#endif
+#ifndef CONFIG_W5500_DEBUG
+ #error config.h must define CONFIG_W5500_DEBUG
+#endif
/* C language *****************************************************************/
#define UNUSED(name)
#define ARRAY_LEN(ary) (sizeof(ary)/sizeof((ary)[0]))
+static const char *w5500_state_str(uint8_t state) {
+ switch (state) {
+ case STATE_CLOSED: return "STATE_CLOSED";
+ case STATE_TCP_INIT: return "STATE_TCP_INIT";
+ case STATE_TCP_LISTEN: return "STATE_TCP_LISTEN";
+ case STATE_TCP_SYNSENT: return "STATE_TCP_SYNSENT";
+ case STATE_TCP_SYNRECV: return "STATE_TCP_SYNRECV";
+ case STATE_TCP_ESTABLISHED: return "STATE_TCP_ESTABLISHED";
+ case STATE_TCP_FIN_WAIT: return "STATE_TCP_FIN_WAIT";
+ case STATE_TCP_CLOSING: return "STATE_TCP_CLOSING";
+ case STATE_TCP_TIME_WAIT: return "STATE_TCP_TIME_WAIT";
+ case STATE_TCP_CLOSE_WAIT: return "STATE_TCP_CLOSE_WAIT";
+ case STATE_TCP_LAST_ACK: return "STATE_TCP_LAST_ACK";
+ case STATE_UDP: return "STATE_UDP";
+ case STATE_MACRAW: return "STATE_MACRAW";
+ default: return const_byte_str(state);
+ }
+}
+
/* vtables ********************************************************************/
/* iface */
@@ -207,7 +226,10 @@ static COROUTINE w5500_irq_cr(void *_chip) {
for (;;) {
while (!gpio_get(chip->pin_intr)) {
- if (w5500ll_read_common_reg(chip->spidev, chip_interrupt))
+ debugf("w5500_irq_cr(): gpio low");
+
+ uint8_t chipintr = w5500ll_read_common_reg(chip->spidev, chip_interrupt);
+ if (chipintr)
w5500ll_write_common_reg(chip->spidev, chip_interrupt, 0xFF);
uint8_t sockmask = w5500ll_read_common_reg(chip->spidev, sock_interrupt);
@@ -226,12 +248,18 @@ static COROUTINE w5500_irq_cr(void *_chip) {
send_bits = sockintr & (SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT),
recv_bits = sockintr & (SOCKINTR_RECV_DAT|SOCKINTR_RECV_FIN);
- if (listen_bits)
+ if (listen_bits) {
+ debugf("w5500_irq_cr(): signal sock[%"PRIu8"]->listen_sema", socknum);
cr_sema_signal(&socket->listen_sema);
- if (recv_bits)
+ }
+ if (recv_bits) {
+ debugf("w5500_irq_cr(): signal sock[%"PRIu8"]->read_sema", socknum);
cr_sema_signal(&socket->read_sema);
- if (send_bits)
+ }
+ if (send_bits) {
+ debugf("w5500_irq_cr(): signal sock[%"PRIu8"]->write_ch", socknum);
_w5500_sockintr_ch_send(&socket->write_ch, send_bits);
+ }
break;
}
@@ -239,6 +267,7 @@ static COROUTINE w5500_irq_cr(void *_chip) {
}
}
cr_sema_wait(&chip->intr);
+ debugf("w5500_irq_cr(): sema signalled");
}
cr_end();
@@ -296,6 +325,7 @@ static inline void w5500_socket_close(struct _w5500_socket *socket) {
static struct w5500 *w5500_chips[CONFIG_W5500_NUM] = {0};
static void w5500_intrhandler(uint gpio, uint32_t UNUSED(event_mask)) {
+ debugf("w5500_intrhandler(): interrupt on pin %u", gpio);
for (size_t i = 0; i < ARRAY_LEN(w5500_chips); i++)
if (w5500_chips[i] && w5500_chips[i]->pin_intr == gpio)
cr_sema_signal_from_intrhandler(&w5500_chips[i]->intr);
@@ -328,8 +358,8 @@ void _w5500_init(struct w5500 *chip,
.socknum = i,
/* mutable */
.next_free = (i + 1 < 8) ? &chip->sockets[i+1] : NULL,
- /* the rest of the mutable members get
- * initialized to the zero values */
+ /* The rest of the mutable members get
+ * initialized to the zero values. */
};
}
@@ -361,7 +391,7 @@ void _w5500_init(struct w5500 *chip,
/* chip methods ***************************************************************/
-static inline void w5500_post_reset(struct w5500 *chip) {
+static void w5500_post_reset(struct w5500 *chip) {
/* The W5500 does not have a built-in MAC address, we must
* provide one. */
w5500ll_write_common_reg(chip->spidev, eth_addr, chip->hwaddr);
@@ -426,7 +456,7 @@ static struct net_eth_addr w5500_if_hwaddr(implements_net_iface *_chip) {
return chip->hwaddr;
}
-static void w5500_if_up(implements_net_iface *_chip, struct net_iface_config cfg) {
+static void _w5500_if_up(implements_net_iface *_chip, struct net_iface_config cfg) {
struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
assert(chip);
@@ -435,8 +465,17 @@ static void w5500_if_up(implements_net_iface *_chip, struct net_iface_config cfg
w5500ll_write_common_reg(chip->spidev, ip_addr, cfg.addr);
}
+static void w5500_if_up(implements_net_iface *_chip, struct net_iface_config cfg) {
+ debugf("if_up()");
+ debugf(":: addr = "PRI_net_ip4_addr, ARG_net_ip4_addr(cfg.addr));
+ debugf(":: gateway_addr = "PRI_net_ip4_addr, ARG_net_ip4_addr(cfg.gateway_addr));
+ debugf(":: subnet_mask = "PRI_net_ip4_addr, ARG_net_ip4_addr(cfg.subnet_mask));
+ _w5500_if_up(_chip, cfg);
+}
+
static void w5500_if_down(implements_net_iface *_chip) {
- w5500_if_up(_chip, (struct net_iface_config){0});
+ debugf("if_down()");
+ _w5500_if_up(_chip, (struct net_iface_config){0});
}
static implements_net_stream_listener *w5500_if_tcp_listen(implements_net_iface *_chip, uint16_t local_port) {
@@ -444,8 +483,11 @@ static implements_net_stream_listener *w5500_if_tcp_listen(implements_net_iface
assert(chip);
struct _w5500_socket *sock = w5500_alloc_socket(chip);
- if (!sock)
+ if (!sock) {
+ debugf("tcp_listen() => no sock");
return NULL;
+ }
+ debugf("tcp_listen() => sock[%"PRIu8"]", sock->socknum);
if (!local_port)
local_port = w5500_alloc_local_port(chip);
@@ -468,9 +510,12 @@ static implements_net_stream_conn *w5500_if_tcp_dial(implements_net_iface *_chip
assert(port);
struct _w5500_socket *socket = w5500_alloc_socket(chip);
- if (!socket)
+ if (!socket) {
+ debugf("tcp_dial() => no sock");
return NULL;
+ }
uint8_t socknum = socket->socknum;
+ debugf("tcp_dial() => sock[%"PRIu8"]", socknum);
uint16_t local_port = w5500_alloc_local_port(chip);
@@ -495,6 +540,7 @@ static implements_net_stream_conn *w5500_if_tcp_dial(implements_net_iface *_chip
w5500_socket_cmd(socket, CMD_CONNECT);
for (;;) {
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
+ debugf("tcp_dial(): state=%s", w5500_state_str(state));
switch (state) {
case STATE_TCP_SYNSENT:
cr_yield();
@@ -507,14 +553,17 @@ static implements_net_stream_conn *w5500_if_tcp_dial(implements_net_iface *_chip
}
}
-implements_net_packet_conn *w5500_if_udp_conn(implements_net_iface *_chip, uint16_t local_port) {
+static implements_net_packet_conn *w5500_if_udp_conn(implements_net_iface *_chip, uint16_t local_port) {
struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
assert(chip);
struct _w5500_socket *socket = w5500_alloc_socket(chip);
- if (!socket)
+ if (!socket) {
+ debugf("udp_conn() => no sock");
return NULL;
+ }
uint8_t socknum = socket->socknum;
+ debugf("udp_conn() => sock[%"PRIu8"]", socknum);
if (!local_port)
local_port = w5500_alloc_local_port(chip);
@@ -541,8 +590,10 @@ static implements_net_stream_conn *w5500_tcplist_accept(implements_net_stream_li
ASSERT_SELF(stream_listener, TCP);
restart:
- if (!socket->list_open)
+ if (!socket->list_open) {
+ debugf("tcp_listener.accept() => already closed");
return NULL;
+ }
/* Mimics socket.c:socket(). */
w5500_socket_close(socket);
@@ -556,6 +607,7 @@ static implements_net_stream_conn *w5500_tcplist_accept(implements_net_stream_li
w5500_socket_cmd(socket, CMD_LISTEN);
for (;;) {
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
+ debugf("tcp_listener.accept() => state=%s", w5500_state_str(state));
switch (state) {
case STATE_TCP_LISTEN:
case STATE_TCP_SYNRECV:
@@ -574,6 +626,7 @@ static implements_net_stream_conn *w5500_tcplist_accept(implements_net_stream_li
}
static int w5500_tcplist_close(implements_net_stream_listener *_socket) {
+ debugf("tcp_listener.close()");
ASSERT_SELF(stream_listener, TCP);
socket->list_open = false;
@@ -584,6 +637,7 @@ static int w5500_tcplist_close(implements_net_stream_listener *_socket) {
/* tcp_conn methods ***********************************************************/
static ssize_t w5500_tcp_write(implements_net_stream_conn *_socket, void *buf, size_t count) {
+ debugf("tcp_conn.write(%zu)", count);
ASSERT_SELF(stream_conn, TCP);
assert(buf);
assert(count);
@@ -610,11 +664,15 @@ static ssize_t w5500_tcp_write(implements_net_stream_conn *_socket, void *buf, s
size_t done = 0;
while (done < count) {
- if (!socket->write_open)
+ if (!socket->write_open) {
+ debugf(" => soft closed");
return -NET_ECLOSED;
+ }
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
- if (state != STATE_TCP_ESTABLISHED && state != STATE_TCP_CLOSE_WAIT)
+ if (state != STATE_TCP_ESTABLISHED && state != STATE_TCP_CLOSE_WAIT) {
+ debugf(" => hard closed");
return -NET_ECLOSED;
+ }
uint16_t freesize = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_free_size));
if (freesize < count-done && freesize < min_free_space) {
@@ -634,9 +692,11 @@ static ssize_t w5500_tcp_write(implements_net_stream_conn *_socket, void *buf, s
w5500_socket_cmd(socket, CMD_SEND);
switch (_w5500_sockintr_ch_recv(&socket->write_ch)) {
case SOCKINTR_SEND_OK:
+ debugf(" => sent %zu", freesize);
done += freesize;
break;
case SOCKINTR_SEND_TIMEOUT:
+ debugf(" => ACK timeout");
return -NET_EACK_TIMEOUT;
case SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT:
assert_notreached("send both OK and timed out?");
@@ -644,10 +704,12 @@ static ssize_t w5500_tcp_write(implements_net_stream_conn *_socket, void *buf, s
assert_notreached("invalid write_ch bits");
}
}
+ debugf(" => send finished");
return done;
}
static void w5500_tcp_set_read_deadline(implements_net_stream_conn *_socket, uint64_t ns) {
+ debugf("tcp_conn.set_read_deadline(%"PRIu64")", ns);
ASSERT_SELF(stream_conn, TCP);
socket->read_deadline_ns = ns;
}
@@ -658,6 +720,7 @@ static void w5500_tcp_alarm_handler(void *_arg) {
}
static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, size_t count) {
+ debugf("tcp_conn.read()");
ASSERT_SELF(stream_conn, TCP);
assert(buf);
assert(count);
@@ -674,10 +737,12 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
for (;;) {
if (!socket->read_open) {
VCALL(bootclock, del_trigger, &trigger);
+ debugf(" => soft closed");
return -NET_ECLOSED;
}
if (socket->read_deadline_ns && socket->read_deadline_ns <= VCALL(bootclock, get_time_ns)) {
VCALL(bootclock, del_trigger, &trigger);
+ debugf(" => recv timeout");
return -NET_ERECV_TIMEOUT;
}
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
@@ -688,6 +753,7 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
break; /* OK */
default:
VCALL(bootclock, del_trigger, &trigger);
+ debugf(" => hard closed");
return -NET_ECLOSED;
}
@@ -697,12 +763,14 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
break;
if (state == STATE_TCP_CLOSE_WAIT) {
VCALL(bootclock, del_trigger, &trigger);
- return 0; /* EOF */
+ debugf(" => EOF");
+ return 0;
}
cr_sema_wait(&socket->read_sema);
}
assert(avail);
+ debugf(" => received %"PRIu16" bytes", avail);
uint16_t ptr = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, rx_read_pointer));
/* Read the data. */
if ((size_t)avail > count)
@@ -717,6 +785,7 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
}
static int w5500_tcp_close(implements_net_stream_conn *_socket, bool rd, bool wr) {
+ debugf("tcp_conn.close(rd=%s, wr=%s)", rd ? "true" : "false", wr ? "true" : "false");
ASSERT_SELF(stream_conn, TCP);
if (rd)
@@ -748,18 +817,23 @@ static int w5500_tcp_close(implements_net_stream_conn *_socket, bool rd, bool wr
static ssize_t w5500_udp_sendto(implements_net_packet_conn *_socket, void *buf, size_t count,
struct net_ip4_addr node, uint16_t port) {
+ debugf("udp_conn.sendto()");
ASSERT_SELF(packet_conn, UDP);
assert(buf);
assert(count);
uint16_t bufsize = ((uint16_t)w5500ll_read_sock_reg(chip->spidev, socknum, tx_buf_size))*1024;
- if (count > bufsize)
+ if (count > bufsize) {
+ debugf(" => msg too large");
return -NET_EMSGSIZE;
+ }
for (;;) {
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
- if (state != STATE_UDP)
+ if (state != STATE_UDP) {
+ debugf(" => closed");
return -NET_ECLOSED;
+ }
uint16_t freesize = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_free_size));
if (freesize >= count)
@@ -782,8 +856,10 @@ static ssize_t w5500_udp_sendto(implements_net_packet_conn *_socket, void *buf,
switch (_w5500_sockintr_ch_recv(&socket->write_ch)) {
case SOCKINTR_SEND_OK:
+ debugf(" => sent");
return count;
case SOCKINTR_SEND_TIMEOUT:
+ debugf(" => ARP timeout");
return -NET_EARP_TIMEOUT;
case SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT:
assert_notreached("send both OK and timed out?");
@@ -793,6 +869,7 @@ static ssize_t w5500_udp_sendto(implements_net_packet_conn *_socket, void *buf,
}
static void w5500_udp_set_read_deadline(implements_net_packet_conn *_socket, uint64_t ns) {
+ debugf("udp_conn.set_read_deadline(%"PRIu64")", ns);
ASSERT_SELF(packet_conn, UDP);
socket->read_deadline_ns = ns;
}
@@ -804,6 +881,7 @@ static void w5500_udp_alarm_handler(void *_arg) {
static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf, size_t count,
struct net_ip4_addr *ret_node, uint16_t *ret_port) {
+ debugf("udp_conn.recvfrom()");
ASSERT_SELF(packet_conn, UDP);
assert(buf);
assert(count);
@@ -820,11 +898,13 @@ static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf
for (;;) {
if (socket->read_deadline_ns && socket->read_deadline_ns <= VCALL(bootclock, get_time_ns)) {
VCALL(bootclock, del_trigger, &trigger);
+ debugf(" => recv timeout");
return -NET_ERECV_TIMEOUT;
}
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
if (state != STATE_UDP) {
VCALL(bootclock, del_trigger, &trigger);
+ debugf(" => hard closed");
return -NET_ECLOSED;
}
@@ -851,6 +931,7 @@ static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf
if (ret_port)
*ret_port = uint16be_decode(&hdr[4]);
uint16_t len = uint16be_decode(&hdr[6]);
+ debugf(" => received %"PRIu16" bytes%s", len, len < avail-8 ? " (plus more messages)" : "");
/* Now read the actual data. */
if (count > len)
count = len;
@@ -864,6 +945,7 @@ static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf
}
static int w5500_udp_close(implements_net_packet_conn *_socket) {
+ debugf("udp_conn.close()");
ASSERT_SELF(packet_conn, UDP);
w5500_socket_close(socket);
diff --git a/libhw_generic/include/libhw/generic/net.h b/libhw_generic/include/libhw/generic/net.h
index 150d199..a016d51 100644
--- a/libhw_generic/include/libhw/generic/net.h
+++ b/libhw_generic/include/libhw/generic/net.h
@@ -7,6 +7,7 @@
#ifndef _LIBHW_GENERIC_NET_H_
#define _LIBHW_GENERIC_NET_H_
+#include <inttypes.h> /* for PRI{u,x}{n} */
#include <stdbool.h> /* for bool */
#include <stddef.h> /* for size_t */
#include <stdint.h> /* for uint{n}_t} */
@@ -31,10 +32,24 @@ struct net_ip4_addr {
static const struct net_ip4_addr net_ip4_addr_broadcast = {{255, 255, 255, 255}};
static const struct net_ip4_addr net_ip4_addr_zero = {{0, 0, 0, 0}};
+#define PRI_net_ip4_addr "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8
+#define ARG_net_ip4_addr(addr) (addr).octets[0], \
+ (addr).octets[1], \
+ (addr).octets[2], \
+ (addr).octets[3]
+
struct net_eth_addr {
unsigned char octets[6];
};
+#define PRI_net_eth_addr "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8
+#define ARG_net_eth_addr(addr) (addr).octets[0], \
+ (addr).octets[1], \
+ (addr).octets[2], \
+ (addr).octets[3], \
+ (addr).octets[4], \
+ (addr).octets[5]
+
/* Streams (e.g. TCP) *********************************************************/
struct net_stream_listener_vtable;
diff --git a/libmisc/include/libmisc/log.h b/libmisc/include/libmisc/log.h
index 37da20b..c1e4a05 100644
--- a/libmisc/include/libmisc/log.h
+++ b/libmisc/include/libmisc/log.h
@@ -7,6 +7,8 @@
#ifndef _LIBMISC_LOG_H_
#define _LIBMISC_LOG_H_
+#include <stdint.h> /* for uint8_t */
+
#ifndef LOG_NAME
#error "each compilation unit that includes <libmisc/log.h> must define LOG_NAME"
#endif
@@ -28,4 +30,6 @@
#define debugf(fmt, ...) do { if (_LOG_CAT3(CONFIG_, LOG_NAME, _DEBUG) && !_LOG_NDEBUG) \
_log_printf("debug: " _LOG_STR(LOG_NAME) ": " fmt "\n" __VA_OPT__(,) __VA_ARGS__); } while (0)
+const char *const_byte_str(uint8_t b);
+
#endif /* _LIBMISC_LOG_H_ */
diff --git a/libmisc/log.c b/libmisc/log.c
index a1ec10f..9bf5366 100644
--- a/libmisc/log.c
+++ b/libmisc/log.c
@@ -7,6 +7,8 @@
#include <stdio.h> /* for vprintf() */
#include <stdarg.h> /* for va_list, va_start(), va_end() */
+#include <libmisc/assert.h>
+
#define LOG_NAME
#include <libmisc/log.h>
@@ -17,3 +19,267 @@ int _log_printf(const char *format, ...) {
va_end(va);
return ret;
}
+
+static const char *byte_strs[] = {
+ "0x00",
+ "0x01",
+ "0x02",
+ "0x03",
+ "0x04",
+ "0x05",
+ "0x06",
+ "0x07",
+ "0x08",
+ "0x09",
+ "0x0A",
+ "0x0B",
+ "0x0C",
+ "0x0D",
+ "0x0E",
+ "0x0F",
+ "0x10",
+ "0x11",
+ "0x12",
+ "0x13",
+ "0x14",
+ "0x15",
+ "0x16",
+ "0x17",
+ "0x18",
+ "0x19",
+ "0x1A",
+ "0x1B",
+ "0x1C",
+ "0x1D",
+ "0x1E",
+ "0x1F",
+ "0x20",
+ "0x21",
+ "0x22",
+ "0x23",
+ "0x24",
+ "0x25",
+ "0x26",
+ "0x27",
+ "0x28",
+ "0x29",
+ "0x2A",
+ "0x2B",
+ "0x2C",
+ "0x2D",
+ "0x2E",
+ "0x2F",
+ "0x30",
+ "0x31",
+ "0x32",
+ "0x33",
+ "0x34",
+ "0x35",
+ "0x36",
+ "0x37",
+ "0x38",
+ "0x39",
+ "0x3A",
+ "0x3B",
+ "0x3C",
+ "0x3D",
+ "0x3E",
+ "0x3F",
+ "0x40",
+ "0x41",
+ "0x42",
+ "0x43",
+ "0x44",
+ "0x45",
+ "0x46",
+ "0x47",
+ "0x48",
+ "0x49",
+ "0x4A",
+ "0x4B",
+ "0x4C",
+ "0x4D",
+ "0x4E",
+ "0x4F",
+ "0x50",
+ "0x51",
+ "0x52",
+ "0x53",
+ "0x54",
+ "0x55",
+ "0x56",
+ "0x57",
+ "0x58",
+ "0x59",
+ "0x5A",
+ "0x5B",
+ "0x5C",
+ "0x5D",
+ "0x5E",
+ "0x5F",
+ "0x60",
+ "0x61",
+ "0x62",
+ "0x63",
+ "0x64",
+ "0x65",
+ "0x66",
+ "0x67",
+ "0x68",
+ "0x69",
+ "0x6A",
+ "0x6B",
+ "0x6C",
+ "0x6D",
+ "0x6E",
+ "0x6F",
+ "0x70",
+ "0x71",
+ "0x72",
+ "0x73",
+ "0x74",
+ "0x75",
+ "0x76",
+ "0x77",
+ "0x78",
+ "0x79",
+ "0x7A",
+ "0x7B",
+ "0x7C",
+ "0x7D",
+ "0x7E",
+ "0x7F",
+ "0x80",
+ "0x81",
+ "0x82",
+ "0x83",
+ "0x84",
+ "0x85",
+ "0x86",
+ "0x87",
+ "0x88",
+ "0x89",
+ "0x8A",
+ "0x8B",
+ "0x8C",
+ "0x8D",
+ "0x8E",
+ "0x8F",
+ "0x90",
+ "0x91",
+ "0x92",
+ "0x93",
+ "0x94",
+ "0x95",
+ "0x96",
+ "0x97",
+ "0x98",
+ "0x99",
+ "0x9A",
+ "0x9B",
+ "0x9C",
+ "0x9D",
+ "0x9E",
+ "0x9F",
+ "0xA0",
+ "0xA1",
+ "0xA2",
+ "0xA3",
+ "0xA4",
+ "0xA5",
+ "0xA6",
+ "0xA7",
+ "0xA8",
+ "0xA9",
+ "0xAA",
+ "0xAB",
+ "0xAC",
+ "0xAD",
+ "0xAE",
+ "0xAF",
+ "0xB0",
+ "0xB1",
+ "0xB2",
+ "0xB3",
+ "0xB4",
+ "0xB5",
+ "0xB6",
+ "0xB7",
+ "0xB8",
+ "0xB9",
+ "0xBA",
+ "0xBB",
+ "0xBC",
+ "0xBD",
+ "0xBE",
+ "0xBF",
+ "0xC0",
+ "0xC1",
+ "0xC2",
+ "0xC3",
+ "0xC4",
+ "0xC5",
+ "0xC6",
+ "0xC7",
+ "0xC8",
+ "0xC9",
+ "0xCA",
+ "0xCB",
+ "0xCC",
+ "0xCD",
+ "0xCE",
+ "0xCF",
+ "0xD0",
+ "0xD1",
+ "0xD2",
+ "0xD3",
+ "0xD4",
+ "0xD5",
+ "0xD6",
+ "0xD7",
+ "0xD8",
+ "0xD9",
+ "0xDA",
+ "0xDB",
+ "0xDC",
+ "0xDD",
+ "0xDE",
+ "0xDF",
+ "0xE0",
+ "0xE1",
+ "0xE2",
+ "0xE3",
+ "0xE4",
+ "0xE5",
+ "0xE6",
+ "0xE7",
+ "0xE8",
+ "0xE9",
+ "0xEA",
+ "0xEB",
+ "0xEC",
+ "0xED",
+ "0xEE",
+ "0xEF",
+ "0xF0",
+ "0xF1",
+ "0xF2",
+ "0xF3",
+ "0xF4",
+ "0xF5",
+ "0xF6",
+ "0xF7",
+ "0xF8",
+ "0xF9",
+ "0xFA",
+ "0xFB",
+ "0xFC",
+ "0xFD",
+ "0xFE",
+ "0xFF",
+};
+static_assert(sizeof(byte_strs)/sizeof(byte_strs[0]) == 0x100);
+
+const char *const_byte_str(uint8_t b) {
+ return byte_strs[b];
+}