diff --git a/README.md b/README.md index b124e0e0..f989d5e8 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,7 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr |Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term | |Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term | |NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term | +|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term | |AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb | |Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb | |Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD | diff --git a/README_zh.md b/README_zh.md index 95bc8317..719a4b0f 100644 --- a/README_zh.md +++ b/README_zh.md @@ -188,6 +188,7 @@ CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和 |Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term | |Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term | |NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term | +|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term | |AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb | |Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb | |Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD | diff --git a/docs/source/demo/usbd_webusb.rst b/docs/source/demo/usbd_webusb.rst index 51e25511..74a22101 100644 --- a/docs/source/demo/usbd_webusb.rst +++ b/docs/source/demo/usbd_webusb.rst @@ -1,2 +1,21 @@ usbd_webusb =============== + +本 demo 主要演示 webusb 功能,webusb 主要用于弹出网页并对 USB 设备进行访问。示例使用 webusb_hid_template.c。 + +- 在注册描述符时注册 BOS, MSOSV2, WEBUSB 描述符即可。 + +.. code-block:: C + + usbd_bos_desc_register(busid, &bos_desc); + usbd_msosv2_desc_register(busid, &msosv2_desc); + usbd_webusb_desc_register(busid, &webusb_url_desc); + +- 增加一个接口描述符用于 webusb + +.. code-block:: C + +USB_INTERFACE_DESCRIPTOR_INIT(USBD_WEBUSB_INTF_NUM, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00) + +- 其余使用 hid 描述符,不再赘述 +- 枚举完成后,电脑右下角会弹出网页信息,点击即可打开网页 \ No newline at end of file diff --git a/docs/source/demo/usbd_winusb.rst b/docs/source/demo/usbd_winusb.rst index bc698ea5..a3d02852 100644 --- a/docs/source/demo/usbd_winusb.rst +++ b/docs/source/demo/usbd_winusb.rst @@ -1,2 +1,32 @@ usbd_winusb =============== + +本节主要介绍 winusb 驱动。winusb 是 windows 为了让用户友好的访问 USB 自定义类设备提供的一套通用驱动,其实本质就是 CDC ACM。 +WINUSB 版本根据 USB 版本分为 V1/V2 版本,V2 版本需要包含 BOS 描述符,V1 版本不需要。V2 版本需要在设备描述符中设置为 USB2.1 的版本号。 + +- V1 版本注册描述符 + +.. code-block:: C + + usbd_msosv1_desc_register(busid, &msosv1_desc); + +- V2 版本注册描述符 + +.. code-block:: C + + usbd_bos_desc_register(busid, &bos_desc); + usbd_msosv2_desc_register(busid, &msosv2_desc); + + +- 接口描述符注册 + +.. code-block:: C + + /* Interface 0 */ + USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02), + /* Endpoint OUT 2 */ + USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00), + /* Endpoint IN 1 */ + USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00), + +- 其余操作与 CDC ACM 相同,不再赘述 \ No newline at end of file diff --git a/docs/source/demo/usbh_hid.rst b/docs/source/demo/usbh_hid.rst index 508c9cae..79a5f247 100644 --- a/docs/source/demo/usbh_hid.rst +++ b/docs/source/demo/usbh_hid.rst @@ -1,2 +1,51 @@ usbh_hid =============== + +本节主要介绍 HID 类的使用。 + +- HID 枚举完成回调中创建一次性线程 + +.. code-block:: C + + + void usbh_hid_run(struct usbh_hid *hid_class) + { + usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, hid_class); + } + + void usbh_hid_stop(struct usbh_hid *hid_class) + { + } + + +- 这里我们使用 usbh_submit_urb 的异步操作,在中断中处理数据并继续接收下一次数据。 + +.. code-block:: C + + static void usbh_hid_thread(void *argument) + { + int ret; + struct usbh_hid *hid_class = (struct usbh_hid *)argument; + ; + + /* test with only one buffer, if you have more hid class, modify by yourself */ + + /* Suggest you to use timer for int transfer and use ep interval */ + usbh_int_urb_fill(&hid_class->intin_urb, hid_class->hport, hid_class->intin, hid_buffer, hid_class->intin->wMaxPacketSize, 0, usbh_hid_callback, hid_class); + ret = usbh_submit_urb(&hid_class->intin_urb); + if (ret < 0) { + goto delete; + } + // clang-format off + delete: + usb_osal_thread_delete(NULL); + // clang-format on + } + +- 当然,也可以不使用异步操作,而是使用 timeout 的同步操作。 +- HID 使用的是中断传输,因此正常来说,我们需要根据 **bInterval** 来设置定时器,定时触发中断传输,demo 这里没有使用,如果对时间有精确要求,可以选择使用定时器来触发异步发送。 +- 以 hub 通信为例,采用的是一次性定时器,也可以使用周期性定时器。 + +.. code-block:: C + + hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed), hub_int_timeout, hub, 0); diff --git a/docs/source/demo/usbh_msc.rst b/docs/source/demo/usbh_msc.rst index 3d4b89c7..7df6ed95 100644 --- a/docs/source/demo/usbh_msc.rst +++ b/docs/source/demo/usbh_msc.rst @@ -1,2 +1,56 @@ usbh_msc =============== + +本节主要介绍主机 MSC 使用。借助 FATFS 实现读写功能。 + +- 在 msc 枚举完成的回调中注册一个线程,用于读写操作。 + +.. code-block:: C + + void usbh_msc_run(struct usbh_msc *msc_class) + { + usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class); + } + + void usbh_msc_stop(struct usbh_msc *msc_class) + { + } + + +- 不使用 fatfs,则直接使用 usbh_msc_scsi_read10 或者 usbh_msc_scsi_write10 函数进行读写操作。 +- 如果使用 fatfs,则需要在 usbh_msc_thread 中调用 fatfs 的接口进行读写操作。msc读写适配fatfs 参考 `platform/none/usbh_fatfs.c` + +.. code-block:: C + + static void usbh_msc_thread(void *argument) + { + int ret; + struct usbh_msc *msc_class = (struct usbh_msc *)argument; + + /* test with only one buffer, if you have more msc class, modify by yourself */ + #if 1 + /* get the partition table */ + ret = usbh_msc_scsi_read10(msc_class, 0, partition_table, 1); + if (ret < 0) { + USB_LOG_RAW("scsi_read10 error,ret:%d\r\n", ret); + goto delete; + } + for (uint32_t i = 0; i < 512; i++) { + if (i % 16 == 0) { + USB_LOG_RAW("\r\n"); + } + USB_LOG_RAW("%02x ", partition_table[i]); + } + USB_LOG_RAW("\r\n"); + #endif + + #if TEST_USBH_MSC_FATFS + usb_msc_fatfs_test(); + #endif + // clang-format off + delete: + usb_osal_thread_delete(NULL); + // clang-format on + } + +- 最后处理完成或者失败后,删除线程。 \ No newline at end of file diff --git a/docs/source/demo/usbh_net.rst b/docs/source/demo/usbh_net.rst index be61628d..9602dec7 100644 --- a/docs/source/demo/usbh_net.rst +++ b/docs/source/demo/usbh_net.rst @@ -1,2 +1,106 @@ usbh_net =============== + +本节主要介绍 USB 网卡的使用,USB 网卡推荐采用 AIR780(RNDIS),EC20(ECM/RNDIS), 手机(RNDIS),RTL8152 USB 网卡,AX88772 USB 网卡。 + +USB 网卡传输层面已经对接好了 LWIP 的收发接口,因此,用户只需要包含 **platform/XXX/usbh_lwip.c** 并根据需要开启对应的网卡类的宏即可。 + +- 当前支持以下网卡类: + +.. code-block:: C + + // #define CONFIG_USBHOST_PLATFORM_CDC_ECM + // #define CONFIG_USBHOST_PLATFORM_CDC_RNDIS + // #define CONFIG_USBHOST_PLATFORM_CDC_NCM + // #define CONFIG_USBHOST_PLATFORM_ASIX + // #define CONFIG_USBHOST_PLATFORM_RTL8152 + // #define CONFIG_USBHOST_PLATFORM_BL616 + +- 包含了对接 LWIP 的输入输出接口,举例如下 + +.. code-block:: C + + static err_t usbh_cdc_ecm_linkoutput(struct netif *netif, struct pbuf *p) + { + int ret; + (void)netif; + + usbh_lwip_eth_output_common(p, usbh_cdc_ecm_get_eth_txbuf()); + ret = usbh_cdc_ecm_eth_output(p->tot_len); + if (ret < 0) { + return ERR_BUF; + } else { + return ERR_OK; + } + } + + void usbh_cdc_ecm_eth_input(uint8_t *buf, uint32_t buflen) + { + usbh_lwip_eth_input_common(&g_cdc_ecm_netif, buf, buflen); + } + + +- 网卡类枚举完成后,注册 netif,并且创建网卡接收线程(因此使用 RTTHREAD 时不需要使用 RTT 的接收线程模块)。 +- 必须开启 DHCP client 服务,用于从 USB 网卡获取 IP 地址。 + +.. code-block:: C + + void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class) + { + struct netif *netif = &g_cdc_ecm_netif; + + netif->hwaddr_len = 6; + memcpy(netif->hwaddr, cdc_ecm_class->mac, 6); + + IP4_ADDR(&g_ipaddr, 0, 0, 0, 0); + IP4_ADDR(&g_netmask, 0, 0, 0, 0); + IP4_ADDR(&g_gateway, 0, 0, 0, 0); + + netif = netif_add(netif, &g_ipaddr, &g_netmask, &g_gateway, NULL, usbh_cdc_ecm_if_init, tcpip_input); + netif_set_default(netif); + while (!netif_is_up(netif)) { + } + + dhcp_handle = usb_osal_timer_create("dhcp", 200, dhcp_timeout, netif, true); + if (dhcp_handle == NULL) { + USB_LOG_ERR("timer creation failed! \r\n"); + while (1) { + } + } + + usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, NULL); + #if LWIP_DHCP + dhcp_start(netif); + usb_osal_timer_start(dhcp_handle); + #endif + } + +- 获取到 IP 以后,就与 USB 没有关系了,直接使用 LWIP 的接口即可。 + +- 需要注意以下参数 + +LWIP_TCPIP_CORE_LOCKING_INPUT 用于不使用 lwip 内置的 tcpip 线程,而使用 USB 自己的处理线程。 + +LWIP_TCPIP_CORE_LOCKING 在现在 lwip 版本中默认是打开的,也推荐必须打开。 + +PBUF_POOL_BUFSIZE 推荐大于1600,搭配 LWIP_TCPIP_CORE_LOCKING_INPUT 使用,因为我们提供了使用 zero mempy 的方式,使用静态 pbuf,而不是把数据 copy 到 pbuf 中。 + +TCPIP_THREAD_STACKSIZE 推荐大于 1K,防止栈溢出。 + +.. code-block:: C + + #if LWIP_TCPIP_CORE_LOCKING_INPUT != 1 + #warning suggest you to set LWIP_TCPIP_CORE_LOCKING_INPUT to 1, usb handles eth input with own thread + #endif + + #if LWIP_TCPIP_CORE_LOCKING != 1 + #error must set LWIP_TCPIP_CORE_LOCKING to 1 + #endif + + #if PBUF_POOL_BUFSIZE < 1600 + #error PBUF_POOL_BUFSIZE must be larger than 1600 + #endif + + #if TCPIP_THREAD_STACKSIZE < 1024 + #error TCPIP_THREAD_STACKSIZE must be >= 1024 + #endif