Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite of NCM device driver #2227

Merged
merged 20 commits into from May 7, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/device/net_lwip_webserver/CMakeLists.txt
Expand Up @@ -74,6 +74,7 @@ target_sources(${PROJECT} PUBLIC
${LWIP}/src/netif/slipif.c
${LWIP}/src/apps/http/httpd.c
${LWIP}/src/apps/http/fs.c
${LWIP}/src/apps/lwiperf/lwiperf.c
)

# due to warnings from other net source, we need to prevent error from some of the warnings options
Expand Down
1 change: 1 addition & 0 deletions examples/device/net_lwip_webserver/Makefile
Expand Up @@ -63,6 +63,7 @@ SRC_C += \
lib/lwip/src/netif/slipif.c \
lib/lwip/src/apps/http/httpd.c \
lib/lwip/src/apps/http/fs.c \
lib/lwip/src/apps/lwiperf/lwiperf.c \
lib/networking/dhserver.c \
lib/networking/dnserver.c \
lib/networking/rndis_reports.c
Expand Down
6 changes: 3 additions & 3 deletions examples/device/net_lwip_webserver/src/lwipopts.h
Expand Up @@ -48,8 +48,8 @@
#define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67))

#define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/)
#define TCP_SND_BUF (2 * TCP_MSS)
#define TCP_WND (TCP_MSS)
#define TCP_SND_BUF (4 * TCP_MSS)
#define TCP_WND (4 * TCP_MSS)

#define ETHARP_SUPPORT_STATIC_ENTRIES 1

Expand All @@ -59,7 +59,7 @@

#define LWIP_SINGLE_NETIF 1

#define PBUF_POOL_SIZE 2
#define PBUF_POOL_SIZE 4

#define HTTPD_USE_CUSTOM_FSDATA 0

Expand Down
121 changes: 54 additions & 67 deletions examples/device/net_lwip_webserver/src/main.c
Expand Up @@ -48,12 +48,17 @@ try changing the first byte of tud_network_mac_address[] below from 0x02 to 0x00

#include "dhserver.h"
#include "dnserver.h"
#include "httpd.h"
#include "lwip/ethip6.h"
#include "lwip/init.h"
#include "lwip/timeouts.h"
#include "lwip/ethip6.h"
#include "httpd.h"

#define INIT_IP4(a,b,c,d) { PP_HTONL(LWIP_MAKEU32(a,b,c,d)) }
#ifdef INCLUDE_IPERF
#include "lwip/apps/lwiperf.h"
#endif

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

/* lwip context */
static struct netif netif_data;
Expand All @@ -64,44 +69,40 @@ 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};
uint8_t tud_network_mac_address[6] = {0x02, 0x02, 0x84, 0x6A, 0x96, 0x00};

/* network parameters of this MCU */
static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 1);
static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 1);
static const ip4_addr_t netmask = INIT_IP4(255, 255, 255, 0);
static const ip4_addr_t gateway = INIT_IP4(0, 0, 0, 0);

/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */
static dhcp_entry_t entries[] =
{
/* mac ip address lease time */
{ {0}, INIT_IP4(192, 168, 7, 2), 24 * 60 * 60 },
{ {0}, INIT_IP4(192, 168, 7, 3), 24 * 60 * 60 },
{ {0}, INIT_IP4(192, 168, 7, 4), 24 * 60 * 60 },
static dhcp_entry_t entries[] = {
/* mac ip address lease time */
{{0}, INIT_IP4(192, 168, 7, 2), 24 * 60 * 60},
{{0}, INIT_IP4(192, 168, 7, 3), 24 * 60 * 60},
{{0}, INIT_IP4(192, 168, 7, 4), 24 * 60 * 60},
};

static const dhcp_config_t dhcp_config =
{
.router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */
.port = 67, /* listen port */
.dns = INIT_IP4(192, 168, 7, 1), /* dns server (if any) */
"usb", /* dns suffix */
TU_ARRAY_SIZE(entries), /* num entry */
entries /* entries */
static const dhcp_config_t dhcp_config = {
.router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */
.port = 67, /* listen port */
.dns = INIT_IP4(192, 168, 7, 1), /* dns server (if any) */
"usb", /* dns suffix */
TU_ARRAY_SIZE(entries), /* num entry */
entries /* entries */
};
static err_t linkoutput_fn(struct netif *netif, struct pbuf *p)
{
(void)netif;

for (;;)
{
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))
{
if (tud_network_can_xmit(p->tot_len)) {
tud_network_xmit(p, 0 /* unused for this example */);
return ERR_OK;
}
Expand All @@ -111,20 +112,17 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p)
}
}

static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr)
{
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)
{
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)
{
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_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
Expand All @@ -139,8 +137,7 @@ static err_t netif_init_cb(struct netif *netif)
return ERR_OK;
}

static void init_lwip(void)
{
static void init_lwip(void) {
struct netif *netif = &netif_data;

lwip_init();
Expand All @@ -158,28 +155,23 @@ static void init_lwip(void)
}

/* handle any DNS requests from dns-server */
bool dns_query_proc(const char *name, ip4_addr_t *addr)
{
if (0 == strcmp(name, "tiny.usb"))
{
bool dns_query_proc(const char *name, ip4_addr_t *addr) {
if (0 == strcmp(name, "tiny.usb")) {
*addr = ipaddr;
return true;
}
return false;
}

bool tud_network_recv_cb(const uint8_t *src, uint16_t size)
{
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)
{
if (size) {
struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL);

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

Expand All @@ -191,20 +183,17 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size)
return true;
}

uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg)
{
struct pbuf *p = (struct pbuf *)ref;
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 */
(void) arg; /* unused for this example */

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

static void service_traffic(void)
{
static void service_traffic(void) {
/* handle any packet received by tud_network_recv_cb() */
if (received_frame)
{
if (received_frame) {
ethernet_input(received_frame, &netif_data);
pbuf_free(received_frame);
received_frame = NULL;
Expand All @@ -214,18 +203,15 @@ static void service_traffic(void)
sys_check_timeouts();
}

void tud_network_init_cb(void)
{
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)
{
if (received_frame) {
pbuf_free(received_frame);
received_frame = NULL;
}
}

int main(void)
{
int main(void) {
/* initialize TinyUSB */
board_init();

Expand All @@ -243,8 +229,12 @@ int main(void)
while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK);
httpd_init();

while (1)
{
#ifdef INCLUDE_IPERF
// test with: iperf -c 192.168.7.1 -e -i 1 -M 5000 -l 8192 -r
lwiperf_start_tcp_server_default(NULL, NULL);
#endif

while (1) {
tud_task();
service_traffic();
}
Expand All @@ -253,17 +243,14 @@ int main(void)
}

/* lwip has provision for using a mutex, when applicable */
sys_prot_t sys_arch_protect(void)
{
sys_prot_t sys_arch_protect(void) {
return 0;
}
void sys_arch_unprotect(sys_prot_t pval)
{
(void)pval;
void sys_arch_unprotect(sys_prot_t pval) {
(void) pval;
}

/* lwip needs a millisecond time source, and the TinyUSB board support code has one available */
uint32_t sys_now(void)
{
uint32_t sys_now(void) {
return board_millis();
}
64 changes: 50 additions & 14 deletions examples/device/net_lwip_webserver/src/tusb_config.h
Expand Up @@ -27,21 +27,23 @@
#define _TUSB_CONFIG_H_

#ifdef __cplusplus
extern "C" {
extern "C" {
#endif

#include "lwipopts.h"

//--------------------------------------------------------------------+
// Board Specific Configuration
//--------------------------------------------------------------------+

// RHPort number used for device can be defined by board.mk, default to port 0
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT 0
#define BOARD_TUD_RHPORT 0
#endif

// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUD_MAX_SPEED
#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
#endif

//--------------------------------------------------------------------
Expand All @@ -50,22 +52,22 @@

// defined by compiler flags for flexibility
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#error CFG_TUSB_MCU must be defined
#endif

#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#define CFG_TUSB_OS OPT_OS_NONE
#endif

#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#define CFG_TUSB_DEBUG 0
#endif

// Enable Device stack
#define CFG_TUD_ENABLED 1
#define CFG_TUD_ENABLED 1

// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED
#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED

/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
Expand All @@ -75,30 +77,64 @@
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_SECTION
#endif

#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#define CFG_TUSB_MEM_ALIGN __attribute__((aligned(4)))
#endif

// Use different configurations to test all net devices (also due to resource limitations)
#if TU_CHECK_MCU(OPT_MCU_LPC15XX, OPT_MCU_LPC40XX, OPT_MCU_LPC51UXX, OPT_MCU_LPC54)
#define USE_ECM 1
#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAML21, OPT_MCU_SAML22)
#define USE_ECM 1
#elif TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F1)
#define USE_ECM 1
#else
#define USE_ECM 0
#define INCLUDE_IPERF
#endif

//--------------------------------------------------------------------
// NCM CLASS CONFIGURATION, SEE "ncm.h" FOR PERFORMANCE TUNNING
//--------------------------------------------------------------------

// Must be >> MTU
// Can be set to 2048 without impact
#define CFG_TUD_NCM_IN_NTB_MAX_SIZE (2 * TCP_MSS + 100)

// Must be >> MTU
// Can be set to smaller values if wNtbOutMaxDatagrams==1
#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE (2 * TCP_MSS + 100)

// Number of NCM transfer blocks for reception side
#ifndef CFG_TUD_NCM_OUT_NTB_N
#define CFG_TUD_NCM_OUT_NTB_N 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example build I reduced both NTBs to 1 for less RAM usage, users can read ncm.h for tuning details.

#endif

// Number of NCM transfer blocks for transmission side
#ifndef CFG_TUD_NCM_IN_NTB_N
#define CFG_TUD_NCM_IN_NTB_N 1
#endif

//--------------------------------------------------------------------
// DEVICE CONFIGURATION
//--------------------------------------------------------------------

#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif

//------------- CLASS -------------//

// Network class has 2 drivers: ECM/RNDIS and NCM.
// Only one of the drivers can be enabled
#define CFG_TUD_ECM_RNDIS 1
#define CFG_TUD_NCM (1-CFG_TUD_ECM_RNDIS)
#define CFG_TUD_ECM_RNDIS USE_ECM
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#2242 is included

#define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS)

#ifdef __cplusplus
}
}
#endif

#endif /* _TUSB_CONFIG_H_ */