From aae3a2892cb9f2731aa4013efa433b26ce74b2a3 Mon Sep 17 00:00:00 2001 From: muzkr Date: Fri, 7 Nov 2025 20:31:45 +0800 Subject: [PATCH] Add USB support --- App/CMakeLists.txt | 6 +- App/driver/vcp.c | 6 + App/driver/vcp.h | 7 ++ App/main.c | 4 + App/usb/usb_config.h | 93 +++++++++++++++ App/usb/usbd_cdc_if.c | 168 +++++++++++++++++++++++++++ CMakeLists.txt | 1 + Middlewares/CMakeLists.txt | 2 + Middlewares/CherryUSB/CMakeLists.txt | 14 +++ 9 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 App/driver/vcp.c create mode 100644 App/driver/vcp.h create mode 100644 App/usb/usb_config.h create mode 100644 App/usb/usbd_cdc_if.c create mode 100644 Middlewares/CMakeLists.txt create mode 100644 Middlewares/CherryUSB/CMakeLists.txt diff --git a/App/CMakeLists.txt b/App/CMakeLists.txt index d0aa844e..7efb1cd6 100644 --- a/App/CMakeLists.txt +++ b/App/CMakeLists.txt @@ -1,7 +1,7 @@ add_library(App INTERFACE) target_include_directories(App INTERFACE .) -target_link_libraries(App INTERFACE PY32F071_Driver) +target_link_libraries(App INTERFACE PY32F071_Driver CherryUSB) target_compile_definitions(App INTERFACE PRINTF_INCLUDE_CONFIG_H) target_sources(App INTERFACE @@ -15,6 +15,7 @@ target_sources(App INTERFACE driver/st7565.c driver/system.c driver/systick.c + driver/vcp.c # Main app/action.c app/app.c @@ -52,6 +53,9 @@ target_sources(App INTERFACE external/printf/printf.c ) +target_include_directories(App INTERFACE usb) +target_sources(App INTERFACE usb/usbd_cdc_if.c) + macro(enable_feature feature) if(${feature}) target_compile_definitions(App INTERFACE ${feature}) diff --git a/App/driver/vcp.c b/App/driver/vcp.c new file mode 100644 index 00000000..7ab79c3a --- /dev/null +++ b/App/driver/vcp.c @@ -0,0 +1,6 @@ + +#include "driver/vcp.h" + +void VCP_Init() +{ +} diff --git a/App/driver/vcp.h b/App/driver/vcp.h new file mode 100644 index 00000000..7a7e84c4 --- /dev/null +++ b/App/driver/vcp.h @@ -0,0 +1,7 @@ + +#ifndef _DRIVER_VCP_H +#define _DRIVER_VCP_H + +void VCP_Init(); + +#endif // _DRIVER_VCP_H diff --git a/App/main.c b/App/main.c index 094055a8..856acd69 100644 --- a/App/main.c +++ b/App/main.c @@ -53,6 +53,8 @@ #include "driver/uart.h" #endif +#include "driver/vcp.h" + #include "helper/battery.h" #include "helper/boot.h" @@ -83,6 +85,8 @@ void Main(void) UART_Send(UART_Version, strlen(UART_Version)); #endif + VCP_Init(); + // Not implementing authentic device checks memset(gDTMF_String, '-', sizeof(gDTMF_String)); diff --git a/App/usb/usb_config.h b/App/usb/usb_config.h new file mode 100644 index 00000000..c2cec4e1 --- /dev/null +++ b/App/usb/usb_config.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2022, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef CHERRYUSB_CONFIG_H +#define CHERRYUSB_CONFIG_H + +/* ================ USB common Configuration ================ */ + +#define CONFIG_USB_PRINTF(...) //printf(__VA_ARGS__) + +#define usb_malloc(size) malloc(size) +#define usb_free(ptr) free(ptr) + +#ifndef CONFIG_USB_DBG_LEVEL +#define CONFIG_USB_DBG_LEVEL USB_DBG_ERROR +#endif + +/* Enable print with color */ +#define CONFIG_USB_PRINTF_COLOR_ENABLE + +/* data align size when use dma */ +#ifndef CONFIG_USB_ALIGN_SIZE +#define CONFIG_USB_ALIGN_SIZE 4 +#endif + +/* attribute data into no cache ram */ +#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) + +/* ================= USB Device Stack Configuration ================ */ + +/* Ep0 max transfer buffer, specially for receiving data from ep0 out */ +#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256 + +/* Setup packet log for debug */ +// #define CONFIG_USBDEV_SETUP_LOG_PRINT + +/* Check if the input descriptor is correct */ +// #define CONFIG_USBDEV_DESC_CHECK + +/* Enable test mode */ +// #define CONFIG_USBDEV_TEST_MODE + +#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE +#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512 +#endif + +#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING +#define CONFIG_USBDEV_MSC_MANUFACTURER_STRING "" +#endif + +#ifndef CONFIG_USBDEV_MSC_PRODUCT_STRING +#define CONFIG_USBDEV_MSC_PRODUCT_STRING "" +#endif + +#ifndef CONFIG_USBDEV_MSC_VERSION_STRING +#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01" +#endif + +// #define CONFIG_USBDEV_MSC_THREAD + +#ifdef CONFIG_USBDEV_MSC_THREAD +#ifndef CONFIG_USBDEV_MSC_STACKSIZE +#define CONFIG_USBDEV_MSC_STACKSIZE 2048 +#endif + +#ifndef CONFIG_USBDEV_MSC_PRIO +#define CONFIG_USBDEV_MSC_PRIO 4 +#endif +#endif + +#ifndef CONFIG_USBDEV_AUDIO_VERSION +#define CONFIG_USBDEV_AUDIO_VERSION 0x0100 +#endif + +#ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL +#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8 +#endif + + +/* ================ USB Device Port Configuration ================*/ +#include "py32f0xx.h" + +#define USBD_IRQn USB_IRQn + +#define USBD_IRQHandler USB_IRQHandler + +void cdc_acm_init(void); +void cdc_acm_data_send_with_dtr_test(void); + + +#endif diff --git a/App/usb/usbd_cdc_if.c b/App/usb/usbd_cdc_if.c new file mode 100644 index 00000000..f7407d3c --- /dev/null +++ b/App/usb/usbd_cdc_if.c @@ -0,0 +1,168 @@ +#include "usbd_core.h" +#include "usbd_cdc.h" + +/*!< endpoint address */ +#define CDC_IN_EP 0x81 +#define CDC_OUT_EP 0x02 +#define CDC_INT_EP 0x83 + +#define USBD_VID 0x36b7 +#define USBD_PID 0xFFFF +#define USBD_MAX_POWER 100 +#define USBD_LANGID_STRING 1033 + +/*!< config descriptor size */ +#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN) + +uint8_t dma_in_ep_idx = (CDC_IN_EP & 0x7f); +uint8_t dma_out_ep_idx = CDC_OUT_EP; + +/*!< global descriptor */ +static const uint8_t cdc_descriptor[] = { + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), + USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), + CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02), + /////////////////////////////////////// + /// string0 descriptor + /////////////////////////////////////// + USB_LANGID_INIT(USBD_LANGID_STRING), + /////////////////////////////////////// + /// string1 descriptor + /////////////////////////////////////// + 0x0A, /* bLength */ + USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ + 'P', 0x00, /* wcChar0 */ + 'U', 0x00, /* wcChar1 */ + 'Y', 0x00, /* wcChar2 */ + 'A', 0x00, /* wcChar3 */ + /////////////////////////////////////// + /// string2 descriptor + /////////////////////////////////////// + 0x1C, /* bLength */ + USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ + 'P', 0x00, /* wcChar0 */ + 'U', 0x00, /* wcChar1 */ + 'Y', 0x00, /* wcChar2 */ + 'A', 0x00, /* wcChar3 */ + ' ', 0x00, /* wcChar4 */ + 'C', 0x00, /* wcChar5 */ + 'D', 0x00, /* wcChar6 */ + 'C', 0x00, /* wcChar7 */ + ' ', 0x00, /* wcChar8 */ + 'D', 0x00, /* wcChar9 */ + 'E', 0x00, /* wcChar10 */ + 'M', 0x00, /* wcChar11 */ + 'O', 0x00, /* wcChar12 */ + /////////////////////////////////////// + /// string3 descriptor + /////////////////////////////////////// + 0x16, /* bLength */ + USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ + '2', 0x00, /* wcChar0 */ + '0', 0x00, /* wcChar1 */ + '2', 0x00, /* wcChar2 */ + '2', 0x00, /* wcChar3 */ + '1', 0x00, /* wcChar4 */ + '2', 0x00, /* wcChar5 */ + '3', 0x00, /* wcChar6 */ + '4', 0x00, /* wcChar7 */ + '5', 0x00, /* wcChar8 */ + '6', 0x00, /* wcChar9 */ +#ifdef CONFIG_USB_HS + /////////////////////////////////////// + /// device qualifier descriptor + /////////////////////////////////////// + 0x0a, + USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, +#endif + 0x00 +}; + +USB_MEM_ALIGNX uint8_t read_buffer[128]; +USB_MEM_ALIGNX uint8_t write_buffer[128] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 }; + +volatile bool ep_tx_busy_flag = false; + +#ifdef CONFIG_USB_HS +#define CDC_MAX_MPS 512 +#else +#define CDC_MAX_MPS 64 +#endif + +void usbd_configure_done_callback(void) +{ + /* setup first out ep read transfer */ + usbd_ep_start_read(CDC_OUT_EP, read_buffer, 128); +} + +void usbd_cdc_acm_bulk_out(uint8_t ep, uint32_t nbytes) +{ + /* setup next out ep read transfer */ + usbd_ep_start_read(CDC_OUT_EP, read_buffer, 128); +} + +void usbd_cdc_acm_bulk_in(uint8_t ep, uint32_t nbytes) +{ + if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) { + /* send zlp */ + usbd_ep_start_write(CDC_IN_EP, NULL, 0); + } else { + ep_tx_busy_flag = false; + } +} + +/*!< endpoint call back */ +struct usbd_endpoint cdc_out_ep = { + .ep_addr = CDC_OUT_EP, + .ep_cb = usbd_cdc_acm_bulk_out +}; + +struct usbd_endpoint cdc_in_ep = { + .ep_addr = CDC_IN_EP, + .ep_cb = usbd_cdc_acm_bulk_in +}; + +struct usbd_interface intf0; +struct usbd_interface intf1; + +void cdc_acm_init(void) +{ + usbd_desc_register(cdc_descriptor); + usbd_add_interface(usbd_cdc_acm_init_intf(&intf0)); + usbd_add_interface(usbd_cdc_acm_init_intf(&intf1)); + usbd_add_endpoint(&cdc_out_ep); + usbd_add_endpoint(&cdc_in_ep); + usbd_initialize(); +} + +volatile uint8_t dtr_enable = 0; + +void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr) +{ + if (dtr) { + dtr_enable = 1; + } else { + dtr_enable = 0; + } +} + +void cdc_acm_data_send_with_dtr_test(void) +{ + if (dtr_enable) { + memset(&write_buffer[10], 'a', 118); + ep_tx_busy_flag = true; + usbd_ep_start_write(CDC_IN_EP, write_buffer, 128); + while (ep_tx_busy_flag) { + } + } +} + + diff --git a/CMakeLists.txt b/CMakeLists.txt index 23bf8fcb..cfb19696 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,7 @@ message("EXE_NAME = " ${EXE_NAME}) add_executable(${EXE_NAME}) add_subdirectory(Drivers) +add_subdirectory(Middlewares) add_subdirectory(Core) add_subdirectory(App) diff --git a/Middlewares/CMakeLists.txt b/Middlewares/CMakeLists.txt new file mode 100644 index 00000000..4f71018e --- /dev/null +++ b/Middlewares/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_subdirectory(CherryUSB) diff --git a/Middlewares/CherryUSB/CMakeLists.txt b/Middlewares/CherryUSB/CMakeLists.txt new file mode 100644 index 00000000..b3ebdfe2 --- /dev/null +++ b/Middlewares/CherryUSB/CMakeLists.txt @@ -0,0 +1,14 @@ + +add_library(CherryUSB INTERFACE) +target_include_directories(CherryUSB INTERFACE + core + port + common + class/cdc +) +target_sources(CherryUSB INTERFACE + core/usbd_core.c + port/usb_dc_py32.c + class/cdc/usbd_cdc.c +) +target_link_libraries(CherryUSB INTERFACE CMSIS)