cherry-embedded / CherryUSB

CherryUSB is a tiny and portable USB Stack (device & host) for embedded system with USB IP
https://cherryusb.readthedocs.io/
Apache License 2.0
1.14k stars 245 forks source link

stm32f107 dwc2 rndis device #78

Closed alexpa940 closed 1 year ago

alexpa940 commented 1 year ago

I tried to run rndis with lwip on stm32f107. The device is detected, windows receives an ip address and a gateway via dhcp, but network manager freezes and it is impossible to turn on the network interface. What am I doing wrong?

ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE

define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 128

endif

ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE

define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1536

endif

ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID

define CONFIG_USBDEV_RNDIS_VENDOR_ID 0x0000ffff

endif

ifndef CONFIG_USBDEV_RNDIS_VENDOR_DESC

define CONFIG_USBDEV_RNDIS_VENDOR_DESC "CherryUSB"

endif


- Wrote initialization functions:

static struct usbd_interface intf0; static struct usbd_interface intf1; static uint8_t mac[6] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };

void cdc_rndis_init(void) { usbd_desc_register(cdc_descriptor); usbd_add_interface(usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac)); usbd_add_interface(usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac)); usbd_initialize(); }

void usb_dc_low_level_init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0};

GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

__HAL_RCC_USB_OTG_FS_CLK_ENABLE();

HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0); HAL_NVIC_EnableIRQ(OTG_FS_IRQn); }

void usb_dc_low_level_deinit(void) { __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); HAL_NVIC_DisableIRQ(OTG_FS_IRQn); }


- And lwip initialization:

static struct netif rndis_netif; //network interface

static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); static const ip_addr_t netmask = IPADDR4_INIT_BYTES(NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); static const ip_addr_t gateway = IPADDR4_INIT_BYTES(GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);

err_t output_fn(struct netif netif, struct pbuf p, const ip_addr_t *ipaddr) { return etharp_output(netif, p, ipaddr); }

err_t linkoutput_fn(struct netif netif, struct pbuf p) { static int ret; ret = usbd_rndis_eth_tx(p);

if(ret == 0)
    return ERR_OK;
else
    return ERR_BUF;

}

err_t rndisif_init(struct netif *netif) { LWIP_ASSERT("netif != NULL", (netif != NULL)); netif->mtu = 1500; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; netif->state = NULL; netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; netif->output = output_fn; netif->linkoutput = linkoutput_fn; return ERR_OK; }

err_t rndisif_input(struct netif netif) { static err_t err; static struct pbuf p; p = usbd_rndis_eth_rx(); if(p != NULL) { err = netif->input(p, netif); if(err != ERR_OK) { pbuf_free(p); } } else { return ERR_BUF; } return err; }

define NUM_DHCP_ENTRY 3

static dhcp_entry_t entries[NUM_DHCP_ENTRY] = { / mac ip address subnet mask lease time / { {0}, {192, 168, 17, 2}, {255, 255, 255, 0}, 24 60 60 }, { {0}, {192, 168, 17, 3}, {255, 255, 255, 0}, 24 60 60 }, { {0}, {192, 168, 17, 4}, {255, 255, 255, 0}, 24 60 60 } };

static dhcp_config_t dhcp_config = { {192, 168, 17, 1}, 67, / server address, port / {192, 168, 17, 1}, / dns server / "stm", / dns suffix / NUM_DHCP_ENTRY, / num entry / entries / entries / };

uint32_t dns_query_proc(const char name, ip_addr_t addr) { if (strcmp(name, "run.stm") == 0 || strcmp(name, "www.run.stm") == 0) { addr->addr = ipaddr.addr; return 1; } return 0; }

void LwIP_Init(void) { struct netif *netif = &rndis_netif;

lwip_init();

netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, rndisif_init, ethernet_input);
netif_set_default(netif);
dhserv_init(&dhcp_config);
dnserv_init(&ipaddr, PORT_DNS, dns_query_proc);

}

/**

alexpa940 commented 1 year ago

PXL_20221221_065057277~2

sakumisu commented 1 year ago

From those , i dont know what happened. Maybe you can try in rt-thread os with lwip, it works.

alexpa940 commented 1 year ago

How can I create a project under stm32f1 with rt thread?

sakumisu commented 1 year ago

If you have no experience of rt-thread, maybe you can print some logs in rndis_bulk_out to watch g_rndis_rx_data_buffer and g_rndis_rx_data_length, usbd_rndis_eth_tx also does the same.From your log, it means control transfer does not work well when get OID_802_3_PERMANENT_ADDRESS.

alexpa940 commented 1 year ago

I only see that the endpoints are periodically reset.

[D/USB] Start reading 12 bytes from ep0
[D/USB] Start reading 12 bytes from ep0
[D/USB] Start reading 12 bytes from ep0
[E/USB] ep:81 clear halt
[E/USB] ep:81 clear halt
[D/USB] EP0 send 0 bytes, 0 remained
[E/USB] ep:02 clear halt
[D/USB] EP0 send 0 bytes, 0 remained
[E/USB] ep:83 clear halt
sakumisu commented 1 year ago

Enable CONFIG_USBDEV_SETUP_LOG_PRINT to see setup packet.

sakumisu commented 1 year ago

12 bytes means it is keepalive msg, it works. So you should check if rndis_bulk_out enters and print log in it.

sakumisu commented 1 year ago

How about try another port? With dma mode.

Fishwaldo commented 1 year ago

FYI, you should use netif_input(p, &netif_data); to pass data to the lwip network interface instead of err = netif->input(p, netif); then it should work (at least does for me on the bl808 chip) With your example, netif->input doesn't take account of the ethernet frame so it drops the packet as its "invalid"

alexpa940 commented 1 year ago

FYI, you should use netif_input(p, &netif_data); to pass data to the lwip network interface instead of err = netif->input(p, netif); then it should work (at least does for me on the bl808 chip) With your example, netif->input doesn't take account of the ethernet frame so it drops the packet as its "invalid"

Thanks. It works.