hathach / tinyusb

An open source cross-platform USB stack for embedded system
https://www.tinyusb.org
MIT License
4.93k stars 1.03k forks source link

webserver NCM mode can't work #2660

Closed ymj-123 closed 3 months ago

ymj-123 commented 4 months ago

Operating System

Windows 11

Board

MIMXRT11XX

Firmware

My project use the tinyusb repository a068b81674e8b47d6fb78ab6a06abb7decc2e644, refer to examples/device/net_lwip_webserver.

What happened ?

NCM enable: PC(win11) can detect the driver named TinyUSB Network Interface, with event device(UsbNcm) not start, problem status 0xC00000E5. Can't ping the board and can't open the web. ECM_RNDIS enable: Everything is ok, I can open the default web.

How to reproduce ?

In my project, lwip and tinyusb both use rtos. Here are some important changes:

  1. in linkoutput_fn, use vTaskDelay(1) to replace tud_task().
  2. in service_traffic, use tcpip_input to replace ethernet_input() and not do pbuf_free if retval is not ERR_OK.
  3. in ncm_device.c, remove const of ntb_parameters. for compile problem. It can work rightly when USE_ECM=0.

Debug Log as txt file (LOG/CFG_TUSB_DEBUG=2)

tinyusb_ncm_log_1.txt

Screenshots

No response

I have checked existing issues, dicussion and documentation

HiFiPhile commented 4 months ago

Please use stock example for testing, otherwise it's impossible to diagnostic.

ymj-123 commented 4 months ago

Unfortunately I can't use this routine directly on my board. But I found that if I change the CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB and CFG_TUD_NCM_OUT_MAX_DATAGRAMS_PER_NTB to 1, I can use NCM rightly and open the default web.

HiFiPhile commented 4 months ago

@rgrr do you have any thoughts?

rgrr commented 4 months ago

So this example uses the most recent NCM driver? (you can identify it with my name in the copyright (Hardy Griech))

What is on the host side?

rgrr commented 4 months ago

One more thing: @HiFiPhile introduced one significant change during reformat. CFG_TUD_NCM_IN_NTB_MAX_SIZE/CFG_TUD_NCM_OUT_NTB_MAX_SIZE was changed from "(2 * TCP_MSS + 100)" to "3200". Could you please test with the old values?

ymj-123 commented 4 months ago

I have tested CFG_TUD_NCM_IN_NTB_MAX_SIZE/CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200, but not work. Something may be important. CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB/CFG_TUD_NCM_OUT_MAX_DATAGRAMS_PER_NTB default 8/6, and CFG_TUD_NCM_OUT_NTB_N/CFG_TUD_NCM_IN_NTB_N also set to 8/6, that can work. But when I pin the board, the first 6 counts pin will have lot delay ms.

ymj-123 commented 4 months ago

This example use the released version 0.17.0 and has the Copyright (c) 2024 Hardy Griech.

rgrr commented 4 months ago

I have tested CFG_TUD_NCM_IN_NTB_MAX_SIZE/CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200, but not work.

Please set those values to "(2 * TCP_MSS + 100)" and try again.

Something may be important. CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB/CFG_TUD_NCM_OUT_MAX_DATAGRAMS_PER_NTB default 8/6,

ok

and CFG_TUD_NCM_OUT_NTB_N/CFG_TUD_NCM_IN_NTB_N also set to 8/6, that can work.

Thats a lot of buffers. Set those to 2/2

But when I pin the board, the first 6 counts pin will have lot delay ms.

Sorry, not getting that point

HiFiPhile commented 4 months ago

In your customization, how about to use taskYIELD() instead of vTaskDelay() to avoid blocking?

ymj-123 commented 3 months ago

In tud_network_xmit_cb, just process one datagram and will call tud_network_recv_cb to alloc data of this one datagram. I didn't notice that in my previous tests. So in my test, CFG_TUD_NCM_OUT_MAX_DATAGRAMS_PER_NTB must be 1.

ymj-123 commented 3 months ago

I think the recv data flow is not very suitable for rtos. Do you have any good ideas?

rgrr commented 3 months ago

In tud_network_xmit_cb, just process one datagram and will call tud_network_recv_cb to alloc data of this one datagram. I didn't notice that in my previous tests. So in my test, CFG_TUD_NCM_OUT_MAX_DATAGRAMS_PER_NTB must be 1.

Which means that your problem is solved?

rgrr commented 3 months ago

I think the recv data flow is not very suitable for rtos. Do you have any good ideas?

Perhaps this glue code helps?: https://github.com/rgrr/yapicoprobe/blob/master/src/net/net_glue.c

ymj-123 commented 3 months ago

There are servial ways.

  1. not use rtos mode of tinyusb.
  2. 1) not use service_traffic(), input data into lwip directly in tud_network_recv_cb() 2) modify tud_network_recv_renew(), do a while(1) process of datagrams, and end by recv_glue_ntb==null, end process call recv_try_to_start_new_reception()
rgrr commented 3 months ago

There are servial ways. ...

Sorry, I cannot follow... to whom are you responding? The glue code above also uses FreeRTOS. Why not use it? Tested and works (at least in my project ;-)).

ymj-123 commented 3 months ago

There are servial ways. ...

Sorry, I cannot follow... to whom are you responding? The glue code above also uses FreeRTOS. Why not use it? Tested and works (at least in my project ;-)).

Thanks.

ymj-123 commented 3 months ago

There are servial ways. ...

Sorry, I cannot follow... to whom are you responding? The glue code above also uses FreeRTOS. Why not use it? Tested and works (at least in my project ;-)).

Thanks.

The glue code is useful to me. I want more details but I don't know how to get lwip and tinyusb code in your project.

rgrr commented 3 months ago

The glue code is useful to me. I want more details but I don't know how to get lwip and tinyusb code in your project.

Check other parts of the code, esp CMakeLists.txt in the project root