Skip to content

Commit

Permalink
WIP: usbd_net & mimx
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Leech <[email protected]>
  • Loading branch information
pi-anl committed Dec 18, 2024
1 parent 377e274 commit f98bf4b
Show file tree
Hide file tree
Showing 16 changed files with 392 additions and 57 deletions.
19 changes: 11 additions & 8 deletions ports/mimxrt/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,9 @@ INC += -I$(TOP)/lib/tinyusb/src
INC += -I$(TOP)/shared/tinyusb
INC += -I.
INC += -Ihal

# All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP
ifeq ($(MICROPY_PY_LWIP),1)
INC += -Ilwip_inc

ifeq ($(MICROPY_HW_ETHERNET),1)
INC += -Ihal/phy
endif

Expand All @@ -106,8 +105,10 @@ SRC_TINYUSB_C += \
lib/tinyusb/src/portable/chipidea/ci_hs/dcd_ci_hs.c \
lib/tinyusb/src/tusb.c

# All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP
ifeq ($(MICROPY_PY_LWIP),1)
# All settings for Ethernet support are controlled by the value of MICROPY_HW_ETHERNET
ifeq ($(MICROPY_HW_ETHERNET),1)
MICROPY_PY_LWIP = 1

SRC_ETH_C += \
$(MCUX_SDK_DIR)/drivers/enet/fsl_enet.c \
hal/phy/device/phydp83825/fsl_phydp83825.c \
Expand Down Expand Up @@ -281,6 +282,7 @@ SHARED_SRC_C += \
shared/timeutils/timeutils.c \
shared/tinyusb/mp_usbd.c \
shared/tinyusb/mp_usbd_cdc.c \
shared/tinyusb/mp_usbd_net.c \
shared/tinyusb/mp_usbd_descriptor.c \

# Set flash driver name, base address and internal flash flag, based on the flash type.
Expand Down Expand Up @@ -447,8 +449,8 @@ else
endif


# All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP
ifeq ($(MICROPY_PY_LWIP),1)
# All settings for Ethernet support are controlled by the value of MICROPY_HW_ETHERNET
ifeq ($(MICROPY_HW_ETHERNET),1)
CFLAGS += \
-DFSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE=1
endif
Expand All @@ -470,7 +472,8 @@ LDFLAGS += \
--gc-sections \
--print-memory-usage \
-Map=$@.map \
--wrap=LPUART_TransferHandleIRQ
--wrap=LPUART_TransferHandleIRQ \
--wrap=dcd_event_handler

# LDDEFINES are used for link time adaptation of linker scripts, utilizing
# the C preprocessor. Therefore keep LDDEFINES separated from LDFLAGS!
Expand Down
2 changes: 2 additions & 0 deletions ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ MICROPY_FLOAT_IMPL = single
MICROPY_HW_FLASH_TYPE = qspi_nor_flash
MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB

MICROPY_PY_LWIP = 0

JLINK_PATH ?= /media/RT1010-EVK/
JLINK_COMMANDER_SCRIPT = $(BUILD)/script.jlink

Expand Down
3 changes: 2 additions & 1 deletion ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB

MICROPY_PY_LWIP = 1
MICROPY_HW_ETHERNET = 1

MICROPY_PY_SSL = 1
MICROPY_SSL_MBEDTLS = 1

Expand Down
2 changes: 1 addition & 1 deletion ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ MICROPY_HW_FLASH_SIZE = 0x4000000 # 64MB
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB

MICROPY_PY_LWIP = 1
MICROPY_HW_ETHERNET = 1
MICROPY_PY_SSL = 1
MICROPY_SSL_MBEDTLS = 1

Expand Down
2 changes: 1 addition & 1 deletion ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB

MICROPY_PY_LWIP = 1
MICROPY_HW_ETHERNET = 1
MICROPY_PY_SSL = 1
MICROPY_SSL_MBEDTLS = 1

Expand Down
2 changes: 1 addition & 1 deletion ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ MICROPY_HW_FLASH_SIZE = 0x400000 # 4MB
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB

MICROPY_PY_LWIP = 1
MICROPY_HW_ETHERNET = 1
MICROPY_PY_SSL = 1
MICROPY_SSL_MBEDTLS = 1

Expand Down
2 changes: 1 addition & 1 deletion ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ MICROPY_HW_FLASH_RESERVED ?= 0x100000 # 1MB CM4 Code address space
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x4000000 # 64MB

MICROPY_PY_LWIP = 1
MICROPY_HW_ETHERNET = 1
MICROPY_PY_SSL = 1
MICROPY_SSL_MBEDTLS = 1
MICROPY_PY_OPENAMP = 1
Expand Down
2 changes: 1 addition & 1 deletion ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB

MICROPY_PY_LWIP = 1
MICROPY_HW_ETHERNET = 1
MICROPY_PY_SSL = 1
MICROPY_SSL_MBEDTLS = 1

Expand Down
2 changes: 1 addition & 1 deletion ports/mimxrt/boards/TEENSY41/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ MICROPY_HW_FLASH_TYPE = qspi_nor_flash
MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB
MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB

MICROPY_PY_LWIP = 1
MICROPY_HW_ETHERNET = 1
MICROPY_PY_SSL = 1
MICROPY_SSL_MBEDTLS = 1

Expand Down
5 changes: 4 additions & 1 deletion ports/mimxrt/modules/_boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import vfs
import sys
import mimxrt
from machine import Pin
from machine import Pin, UART

bdev = mimxrt.Flash()
try:
Expand All @@ -19,6 +19,9 @@
sys.path.append("/flash")
sys.path.append("/flash/lib")

os.dupterm(UART(0))


# do not mount the SD card if SKIPSD exists.
try:
os.stat("SKIPSD")
Expand Down
1 change: 1 addition & 0 deletions ports/mimxrt/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ uint32_t trng_random_u32(void);

#define MICROPY_HW_ENABLE_USBDEV (1)
#define MICROPY_HW_USB_CDC (1)
// #define MICROPY_HW_USB_NET (1)

// Hooks to add builtins

Expand Down
20 changes: 17 additions & 3 deletions shared/tinyusb/mp_usbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
#include "py/objarray.h"
#include "py/runtime.h"

#if MICROPY_HW_USB_NET
#include "mp_usbd_net.h"
#endif

#ifndef NO_QSTR
#include "tusb.h"
#include "device/dcd.h"
Expand All @@ -45,6 +49,10 @@ static inline void mp_usbd_init_tud(void) {
tusb_init();
tud_cdc_configure_fifo_t cfg = { .rx_persistent = 0, .tx_persistent = 1 };
tud_cdc_configure_fifo(&cfg);

#if MICROPY_HW_USB_NET
mp_usbd_net_init();
#endif
}

// Run the TinyUSB device task
Expand All @@ -64,9 +72,15 @@ void mp_usbd_hex_str(char *out_str, const uint8_t *bytes, size_t bytes_len);

// Length of built-in configuration descriptor
#define MP_USBD_BUILTIN_DESC_CFG_LEN (TUD_CONFIG_DESC_LEN + \
(CFG_TUD_CDC ? (TUD_CDC_DESC_LEN) : 0) + \
(CFG_TUD_MSC ? (TUD_MSC_DESC_LEN) : 0) \
)
(CFG_TUD_CDC ? (TUD_CDC_DESC_LEN) : 0) + \
(CFG_TUD_MSC ? (TUD_MSC_DESC_LEN) : 0) + \
(CFG_TUD_NCM ? (TUD_CDC_NCM_DESC_LEN) : 0) + \
(CFG_TUD_ECM_RNDIS ? (TUD_RNDIS_DESC_LEN) : 0) \
)


// Alternate config length used by ETH / ECM-RNDIS
#define MP_USBD_ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN)

// Built-in USB device and configuration descriptor values
extern const tusb_desc_device_t mp_usbd_builtin_desc_dev;
Expand Down
25 changes: 24 additions & 1 deletion shared/tinyusb/mp_usbd_descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#define USBD_CDC_CMD_MAX_SIZE (8)
#define USBD_CDC_IN_OUT_MAX_SIZE ((CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED) ? 512 : 64)
#define USBD_MSC_IN_OUT_MAX_SIZE ((CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED) ? 512 : 64)
#define USBD_NET_IN_OUT_MAX_SIZE ((CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED) ? 512 : 64)

const tusb_desc_device_t mp_usbd_builtin_desc_dev = {
.bLength = sizeof(tusb_desc_device_t),
Expand Down Expand Up @@ -62,7 +63,16 @@ const uint8_t mp_usbd_builtin_desc_cfg[MP_USBD_BUILTIN_DESC_CFG_LEN] = {
USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE),
#endif
#if CFG_TUD_MSC
TUD_MSC_DESCRIPTOR(USBD_ITF_MSC, USBD_STR_MSC, EPNUM_MSC_OUT, EPNUM_MSC_IN, USBD_MSC_IN_OUT_MAX_SIZE),
TUD_MSC_DESCRIPTOR(USBD_ITF_MSC, USBD_STR_MSC, USBD_MSC_EP_OUT, USBD_MSC_EP_IN, USBD_MSC_IN_OUT_MAX_SIZE),
#endif
#if CFG_TUD_ECM_RNDIS
TUD_CONFIG_DESCRIPTOR(2, USBD_ITF_BUILTIN_MAX, USBD_STR_0, ALT_CONFIG_TOTAL_LEN, 0, USBD_MAX_POWER_MA),
// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size.
TUD_CDC_ECM_DESCRIPTOR(USBD_ITF_ETH, USBD_STR_ETH, USBD_STR_ETH_MAC, USBD_NET_EP_CMD, 64, USBD_NET_EP_OUT, USBD_NET_EP_IN, USBD_NET_IN_OUT_MAX_SIZE, CFG_TUD_NET_MTU),
#endif
#if CFG_TUD_NCM
// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size.
TUD_CDC_NCM_DESCRIPTOR(USBD_ITF_ETH, USBD_STR_ETH, USBD_STR_ETH_MAC, USBD_NET_EP_CMD, 64, USBD_NET_EP_OUT, USBD_NET_EP_IN, USBD_NET_IN_OUT_MAX_SIZE, CFG_TUD_NET_MTU),
#endif
};

Expand Down Expand Up @@ -115,6 +125,19 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
desc_str = MICROPY_HW_USB_MSC_INTERFACE_STRING;
break;
#endif
#if CFG_TUD_NCM || CFG_TUD_ECM_RNDIS
case USBD_STR_ETH:
desc_str = MICROPY_HW_USB_ETH_INTERFACE_STRING;
break;
case USBD_STR_ETH_MAC:
// Convert MAC address into UTF-16
mp_usbd_hex_str(desc_str, (uint8_t *)tud_network_mac_address, sizeof(tud_network_mac_address));
// for (unsigned i=0; i<sizeof(tud_network_mac_address); i++) {
// desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 4) & 0xf];
// desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf];
// }
break;
#endif
default:
break;
}
Expand Down
149 changes: 149 additions & 0 deletions shared/tinyusb/mp_usbd_net.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@


#include "py/runtime.h"
#include "py/mphal.h"

#if MICROPY_HW_USB_NET

#include "tusb.h"
// #include "lwip/ethip6.h"
// #include "lwip/init.h"
// #include "lwip/timeouts.h"
#include "shared/netutils/netutils.h"
#include "extmod/modnetwork.h"

#include "lwip/etharp.h"
#include "lwip/dns.h"
#include "lwip/dhcp.h"
#include "netif/ethernet.h"

// typedef struct _eth_t {
// uint32_t trace_flags;
// struct netif netif_data;
// struct dhcp dhcp_struct;
// } eth_t;

#define INIT_IP4(a, b, c, d) \
{ PP_HTONL(LWIP_MAKEU32(a, b, c, d)) }

/* lwip context */
static struct netif netif_data;

/* shared between tud_network_recv_cb() and service_traffic() */
static struct pbuf *received_frame;

/* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */
/* ideally speaking, this should be generated from the hardware's unique ID (if available) */
/* it is suggested that the first byte is 0x02 to indicate a link-local address */
uint8_t tud_network_mac_address[6] = {0x02, 0x02, 0x84, 0x6A, 0x96, 0x00};


static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) {
(void) netif;

for (;;) {
/* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */
if (!tud_ready())
return ERR_USE;

/* if the network driver can accept another packet, we make it happen */
if (tud_network_can_xmit(p->tot_len)) {
tud_network_xmit(p, 0 /* unused for this example */);
return ERR_OK;
}

/* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */
tud_task();
}
}

static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) {
return etharp_output(netif, p, addr);
}

#if LWIP_IPV6
static err_t ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) {
return ethip6_output(netif, p, addr);
}
#endif

static err_t netif_init_cb(struct netif *netif) {
LWIP_ASSERT("netif != NULL", (netif != NULL));
netif->mtu = CFG_TUD_NET_MTU;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_NETARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
netif->state = NULL;
netif->name[0] = 'E';
netif->name[1] = 'X';
netif->linkoutput = linkoutput_fn;
netif->output = ip4_output_fn;
#if LWIP_IPV6
netif->output_ip6 = ip6_output_fn;
#endif
return ERR_OK;
}


bool tud_network_recv_cb(const uint8_t *src, uint16_t size) {
/* this shouldn't happen, but if we get another packet before
parsing the previous, we must signal our inability to accept it */
if (received_frame) return false;

if (size) {
struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL);

if (p) {
/* pbuf_alloc() has already initialized struct; all we need to do is copy the data */
memcpy(p->payload, src, size);

/* store away the pointer for service_traffic() to later handle */
received_frame = p;
}
}

return true;
}

uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) {
struct pbuf *p = (struct pbuf *) ref;

(void) arg; /* unused for this example */

return pbuf_copy_partial(p, dst, p->tot_len, 0);
}

static void service_traffic(void) {
/* handle any packet received by tud_network_recv_cb() */
if (received_frame) {
ethernet_input(received_frame, &netif_data);
pbuf_free(received_frame);
received_frame = NULL;
tud_network_recv_renew();
}

sys_check_timeouts();
}

void tud_network_init_cb(void) {
/* if the network is re-initializing and we have a leftover packet, we must do a cleanup */
if (received_frame) {
pbuf_free(received_frame);
received_frame = NULL;
}
}

void mp_usbd_net_init(void) {
MICROPY_PY_LWIP_ENTER
netif->hwaddr_len = sizeof(tud_network_mac_address);
memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address));
netif->hwaddr[5] ^= 0x01;

netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input);
#if LWIP_IPV6
netif_create_ip6_linklocal_address(netif, 1);
#endif
netif_set_default(netif);
MICROPY_PY_LWIP_EXIT

}

#endif
Loading

0 comments on commit f98bf4b

Please sign in to comment.