Skip to content

Commit 79b57c2

Browse files
author
Sylwester
committed
Add dirty work folder for ongoing USB Ethernet experimentation.
1 parent 59bc6c9 commit 79b57c2

File tree

7 files changed

+293
-8
lines changed

7 files changed

+293
-8
lines changed

CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ project(main C CXX ASM)
3636

3737
pico_sdk_init()
3838

39-
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR} ".")
39+
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/lib/pico-sdk/lib/tinyusb/lib/networking ${CMAKE_CURRENT_BINARY_DIR} ".")
4040

4141
if (USE_PRECOMPILED_LIBS)
4242
add_library(audio STATIC IMPORTED)
@@ -68,6 +68,8 @@ add_executable(main
6868
src/picoadk_hw.cpp
6969
src/midi_input_usb.cpp
7070
src/get_serial.c
71+
${CMAKE_CURRENT_SOURCE_DIR}/lib/pico-sdk/lib/tinyusb/lib/networking/dhserver.c
72+
${CMAKE_CURRENT_SOURCE_DIR}/lib/pico-sdk/lib/tinyusb/lib/networking/dnserver.c
7173
# src/psram.cpp
7274
lib/FreeRTOS-Kernel/portable/MemMang/heap_3.c
7375
)
@@ -106,6 +108,7 @@ if (USE_PRECOMPILED_LIBS)
106108
audio
107109
FreeRTOS-Kernel
108110
heavy
111+
lwip
109112
)
110113
else()
111114
target_link_libraries(main
@@ -131,6 +134,7 @@ else()
131134
Audio
132135
FreeRTOS-Kernel
133136
heavy
137+
lwip
134138
)
135139
endif()
136140

include/lwipopts.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without modification,
6+
* are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
* 2. Redistributions in binary form must reproduce the above copyright notice,
11+
* this list of conditions and the following disclaimer in the documentation
12+
* and/or other materials provided with the distribution.
13+
* 3. The name of the author may not be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19+
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21+
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24+
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25+
* OF SUCH DAMAGE.
26+
*
27+
* This file is part of the lwIP TCP/IP stack.
28+
*
29+
* Author: Simon Goldschmidt
30+
*
31+
*/
32+
#ifndef __LWIPOPTS_H__
33+
#define __LWIPOPTS_H__
34+
35+
/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */
36+
#define NO_SYS 1
37+
#define MEM_ALIGNMENT 4
38+
#define LWIP_RAW 0
39+
#define LWIP_NETCONN 0
40+
#define LWIP_SOCKET 0
41+
#define LWIP_DHCP 0
42+
#define LWIP_ICMP 1
43+
#define LWIP_UDP 1
44+
#define LWIP_TCP 1
45+
#define LWIP_IPV4 1
46+
#define LWIP_IPV6 0
47+
#define ETH_PAD_SIZE 0
48+
#define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67))
49+
50+
#define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/)
51+
#define TCP_SND_BUF (4 * TCP_MSS)
52+
#define TCP_WND (4 * TCP_MSS)
53+
54+
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
55+
56+
#define LWIP_HTTPD_CGI 0
57+
#define LWIP_HTTPD_SSI 0
58+
#define LWIP_HTTPD_SSI_INCLUDE_TAG 0
59+
60+
#define LWIP_SINGLE_NETIF 1
61+
62+
#define PBUF_POOL_SIZE 4
63+
64+
#define HTTPD_USE_CUSTOM_FSDATA 0
65+
66+
#define LWIP_MULTICAST_PING 1
67+
#define LWIP_BROADCAST_PING 1
68+
#define LWIP_IPV6_MLD 0
69+
#define LWIP_IPV6_SEND_ROUTER_SOLICIT 0
70+
71+
#endif /* __LWIPOPTS_H__ */

include/tusb_config.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
#error CFG_TUSB_MCU must be defined
4343
#endif
4444

45+
#define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/)
46+
#define TCP_SND_BUF (4 * TCP_MSS)
47+
#define TCP_WND (4 * TCP_MSS)
4548

4649
// RHPort number used for device can be defined by board.mk, default to port 0
4750
#ifndef BOARD_DEVICE_RHPORT_NUM
@@ -98,12 +101,37 @@
98101
#define CFG_TUD_ENDPOINT0_SIZE 64
99102
#endif
100103

104+
//--------------------------------------------------------------------
105+
// NCM CLASS CONFIGURATION, SEE "ncm.h" FOR PERFORMANCE TUNING
106+
//--------------------------------------------------------------------
107+
108+
// Must be >> MTU
109+
// Can be set to 2048 without impact
110+
#define CFG_TUD_NCM_IN_NTB_MAX_SIZE (2 * TCP_MSS + 100)
111+
112+
// Must be >> MTU
113+
// Can be set to smaller values if wNtbOutMaxDatagrams==1
114+
#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE (2 * TCP_MSS + 100)
115+
116+
// Number of NCM transfer blocks for reception side
117+
#ifndef CFG_TUD_NCM_OUT_NTB_N
118+
#define CFG_TUD_NCM_OUT_NTB_N 1
119+
#endif
120+
121+
// Number of NCM transfer blocks for transmission side
122+
#ifndef CFG_TUD_NCM_IN_NTB_N
123+
#define CFG_TUD_NCM_IN_NTB_N 1
124+
#endif
125+
126+
101127
//------------- CLASS -------------//
102128
#define CFG_TUD_CDC 0
103129
#define CFG_TUD_MSC 0
104130
#define CFG_TUD_HID 0
105131
#define CFG_TUD_MIDI 1
106132
#define CFG_TUD_VENDOR 0
133+
#define CFG_TUD_ECM_RNDIS USE_ECM
134+
#define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS)
107135

108136
#define CFG_TUH_MIDI CFG_TUD_MIDI
109137

libpico.a

1.42 MB
Binary file not shown.

src/main.cpp

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@
1919

2020
#include "arduino_compat.h"
2121

22+
#include <dhserver.h>
23+
#include <dnserver.h>
24+
#include <httpd.h>
25+
#include <lwip/ethip6.h>
26+
#include <lwip/init.h>
27+
#include <lwip/timeouts.h>
28+
29+
30+
#ifdef INCLUDE_IPERF
31+
#include "lwip/apps/lwiperf.h"
32+
#endif
33+
2234
// Audio Buffer (Size is set in lib/audio/include/audio_subsystem.h)
2335
audio_buffer_pool_t *audio_pool;
2436

@@ -66,6 +78,168 @@ TaskHandle_t usb_task_handle;
6678
extern "C" {
6779
#endif
6880

81+
82+
// IP
83+
84+
85+
86+
#define INIT_IP4(a, b, c, d) \
87+
{ PP_HTONL(LWIP_MAKEU32(a, b, c, d)) }
88+
89+
/* lwip context */
90+
static struct netif netif_data;
91+
92+
/* shared between tud_network_recv_cb() and service_traffic() */
93+
static struct pbuf *received_frame;
94+
95+
/* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */
96+
/* ideally speaking, this should be generated from the hardware's unique ID (if available) */
97+
/* it is suggested that the first byte is 0x02 to indicate a link-local address */
98+
uint8_t tud_network_mac_address[6] = {0x02, 0x02, 0x84, 0x6A, 0x96, 0x00};
99+
100+
/* network parameters of this MCU */
101+
static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 1);
102+
static const ip4_addr_t netmask = INIT_IP4(255, 255, 255, 0);
103+
static const ip4_addr_t gateway = INIT_IP4(0, 0, 0, 0);
104+
105+
/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */
106+
static dhcp_entry_t entries[] = {
107+
/* mac ip address lease time */
108+
{{0}, INIT_IP4(192, 168, 7, 2), 24 * 60 * 60},
109+
{{0}, INIT_IP4(192, 168, 7, 3), 24 * 60 * 60},
110+
{{0}, INIT_IP4(192, 168, 7, 4), 24 * 60 * 60},
111+
};
112+
113+
static const dhcp_config_t dhcp_config = {
114+
.router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */
115+
.port = 67, /* listen port */
116+
.dns = INIT_IP4(192, 168, 7, 1), /* dns server (if any) */
117+
"usb", /* dns suffix */
118+
TU_ARRAY_SIZE(entries), /* num entry */
119+
entries /* entries */
120+
};
121+
122+
static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) {
123+
(void) netif;
124+
125+
for (;;) {
126+
/* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */
127+
if (!tud_ready())
128+
return ERR_USE;
129+
130+
/* if the network driver can accept another packet, we make it happen */
131+
if (tud_network_can_xmit(p->tot_len)) {
132+
tud_network_xmit(p, 0 /* unused for this example */);
133+
return ERR_OK;
134+
}
135+
136+
/* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */
137+
tud_task();
138+
}
139+
}
140+
141+
static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) {
142+
return etharp_output(netif, p, addr);
143+
}
144+
145+
#if LWIP_IPV6
146+
static err_t ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) {
147+
return ethip6_output(netif, p, addr);
148+
}
149+
#endif
150+
151+
static err_t netif_init_cb(struct netif *netif) {
152+
LWIP_ASSERT("netif != NULL", (netif != NULL));
153+
netif->mtu = CFG_TUD_NET_MTU;
154+
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
155+
netif->state = NULL;
156+
netif->name[0] = 'E';
157+
netif->name[1] = 'X';
158+
netif->linkoutput = linkoutput_fn;
159+
netif->output = ip4_output_fn;
160+
#if LWIP_IPV6
161+
netif->output_ip6 = ip6_output_fn;
162+
#endif
163+
return ERR_OK;
164+
}
165+
166+
static void init_lwip(void) {
167+
struct netif *netif = &netif_data;
168+
169+
lwip_init();
170+
171+
/* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */
172+
netif->hwaddr_len = sizeof(tud_network_mac_address);
173+
memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address));
174+
netif->hwaddr[5] ^= 0x01;
175+
176+
netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input);
177+
#if LWIP_IPV6
178+
netif_create_ip6_linklocal_address(netif, 1);
179+
#endif
180+
netif_set_default(netif);
181+
}
182+
183+
/* handle any DNS requests from dns-server */
184+
bool dns_query_proc(const char *name, ip4_addr_t *addr) {
185+
if (0 == strcmp(name, "tiny.usb")) {
186+
*addr = ipaddr;
187+
return true;
188+
}
189+
return false;
190+
}
191+
192+
bool tud_network_recv_cb(const uint8_t *src, uint16_t size) {
193+
/* this shouldn't happen, but if we get another packet before
194+
parsing the previous, we must signal our inability to accept it */
195+
if (received_frame) return false;
196+
197+
if (size) {
198+
struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL);
199+
200+
if (p) {
201+
/* pbuf_alloc() has already initialized struct; all we need to do is copy the data */
202+
memcpy(p->payload, src, size);
203+
204+
/* store away the pointer for service_traffic() to later handle */
205+
received_frame = p;
206+
}
207+
}
208+
209+
return true;
210+
}
211+
212+
uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) {
213+
struct pbuf *p = (struct pbuf *) ref;
214+
215+
(void) arg; /* unused for this example */
216+
217+
return pbuf_copy_partial(p, dst, p->tot_len, 0);
218+
}
219+
220+
static void service_traffic(void) {
221+
/* handle any packet received by tud_network_recv_cb() */
222+
if (received_frame) {
223+
ethernet_input(received_frame, &netif_data);
224+
pbuf_free(received_frame);
225+
received_frame = NULL;
226+
tud_network_recv_renew();
227+
}
228+
229+
sys_check_timeouts();
230+
}
231+
232+
void tud_network_init_cb(void) {
233+
/* if the network is re-initializing and we have a leftover packet, we must do a cleanup */
234+
if (received_frame) {
235+
pbuf_free(received_frame);
236+
received_frame = NULL;
237+
}
238+
}
239+
240+
241+
// IP END
242+
69243
/**
70244
* Task to handle USB MIDI input processing.
71245
*
@@ -155,9 +329,22 @@ extern "C" {
155329
// Start the FreeRTOS scheduler
156330
vTaskStartScheduler();
157331

332+
/* initialize lwip, dhcp-server, dns-server, and http */
333+
init_lwip();
334+
while (!netif_is_up(&netif_data));
335+
while (dhserv_init(&dhcp_config) != ERR_OK);
336+
while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK);
337+
httpd_init();
338+
339+
#ifdef INCLUDE_IPERF
340+
// test with: iperf -c 192.168.7.1 -e -i 1 -M 5000 -l 8192 -r
341+
lwiperf_start_tcp_server_default(NULL, NULL);
342+
#endif
343+
158344
// Idle loop (this is fine for Cortex-M33)
159345
while (1)
160346
{
347+
service_traffic();
161348
__wfi();
162349
}
163350
}

src/picoadk_hw.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,7 @@ void picoadk_init()
1010
// Initialize TinyUSB
1111
board_init();
1212

13-
// tusb_init(0, TUSB_ROLE_DEVICE);
14-
#if TUSB_VERSION_NUMBER >= 1700
15-
tusb_init(0, TUSB_ROLE_DEVICE);
16-
#else
17-
tusb_init();
18-
#endif
19-
13+
tusb_init();
2014
stdio_init_all();
2115

2216
// set gpio 25 (soft mute) to output and set to 1 (unmute)

src/usb_descriptors.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ enum
7676
{
7777
ITF_NUM_MIDI = 0,
7878
ITF_NUM_MIDI_STREAMING,
79+
ITF_NUM_NET,
7980
ITF_NUM_TOTAL
8081
};
8182

0 commit comments

Comments
 (0)