-
Notifications
You must be signed in to change notification settings - Fork 5
feat(port/cherryusb): add cherryusb for usb usage, based on cdc acm #6
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Note | ||
|
|
||
| You need to configure CherryUSB by yourself first. | ||
|
|
||
| This port is modified from CherryUSB cdc acm template. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,242 @@ | ||
| /* | ||
| * Copyright (c) 2024, sakumisu | ||
| * Copyright (c) 2026, MDLZCOOL | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
| #include "usbd_core.h" | ||
| #include "usbd_cdc_acm.h" | ||
| #include "ctshell_cherryusb.h" | ||
|
|
||
| static ctshell_ctx_t shell_ctx; | ||
|
|
||
| /*!< endpoint address */ | ||
| #define CDC_IN_EP 0x81 | ||
| #define CDC_OUT_EP 0x02 | ||
| #define CDC_INT_EP 0x83 | ||
|
|
||
| #define USBD_VID 0xFFFF | ||
| #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) | ||
|
|
||
| #ifdef CONFIG_USB_HS | ||
| #define CDC_MAX_MPS 512 | ||
| #else | ||
| #define CDC_MAX_MPS 64 | ||
| #endif | ||
|
|
||
| /*!< 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, CDC_MAX_MPS, 0x02), | ||
| /////////////////////////////////////// | ||
| /// string0 descriptor | ||
| /////////////////////////////////////// | ||
| USB_LANGID_INIT(USBD_LANGID_STRING), | ||
| /////////////////////////////////////// | ||
| /// string1 descriptor | ||
| /////////////////////////////////////// | ||
| 0x14, /* bLength */ | ||
| USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ | ||
| 'C', 0x00, /* wcChar0 */ | ||
| 'h', 0x00, /* wcChar1 */ | ||
| 'e', 0x00, /* wcChar2 */ | ||
| 'r', 0x00, /* wcChar3 */ | ||
| 'r', 0x00, /* wcChar4 */ | ||
| 'y', 0x00, /* wcChar5 */ | ||
| 'U', 0x00, /* wcChar6 */ | ||
| 'S', 0x00, /* wcChar7 */ | ||
| 'B', 0x00, /* wcChar8 */ | ||
| /////////////////////////////////////// | ||
| /// string2 descriptor | ||
| /////////////////////////////////////// | ||
| 0x26, /* bLength */ | ||
| USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ | ||
| 'C', 0x00, /* wcChar0 */ | ||
| 'h', 0x00, /* wcChar1 */ | ||
| 'e', 0x00, /* wcChar2 */ | ||
| 'r', 0x00, /* wcChar3 */ | ||
| 'r', 0x00, /* wcChar4 */ | ||
| 'y', 0x00, /* wcChar5 */ | ||
| 'U', 0x00, /* wcChar6 */ | ||
| 'S', 0x00, /* wcChar7 */ | ||
| 'B', 0x00, /* wcChar8 */ | ||
| ' ', 0x00, /* wcChar9 */ | ||
| 'C', 0x00, /* wcChar10 */ | ||
| 'D', 0x00, /* wcChar11 */ | ||
| 'C', 0x00, /* wcChar12 */ | ||
| ' ', 0x00, /* wcChar13 */ | ||
| 'D', 0x00, /* wcChar14 */ | ||
| 'E', 0x00, /* wcChar15 */ | ||
| 'M', 0x00, /* wcChar16 */ | ||
| 'O', 0x00, /* wcChar17 */ | ||
| /////////////////////////////////////// | ||
| /// 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, | ||
| 0x02, | ||
| 0x02, | ||
| 0x01, | ||
| 0x40, | ||
| 0x00, | ||
| 0x00, | ||
| #endif | ||
| 0x00 | ||
| }; | ||
|
|
||
| USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048]; /* 2048 is only for test speed , please use CDC_MAX_MPS for common*/ | ||
| USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048]; | ||
|
|
||
| volatile bool ep_tx_busy_flag = false; | ||
|
|
||
| static void usbd_event_handler(uint8_t busid, uint8_t event) | ||
| { | ||
| switch (event) { | ||
| case USBD_EVENT_RESET: | ||
| break; | ||
| case USBD_EVENT_CONNECTED: | ||
| break; | ||
| case USBD_EVENT_DISCONNECTED: | ||
| break; | ||
| case USBD_EVENT_RESUME: | ||
| break; | ||
| case USBD_EVENT_SUSPEND: | ||
| break; | ||
| case USBD_EVENT_CONFIGURED: | ||
| ep_tx_busy_flag = false; | ||
| /* setup first out ep read transfer */ | ||
| usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048); | ||
| break; | ||
| case USBD_EVENT_SET_REMOTE_WAKEUP: | ||
| break; | ||
| case USBD_EVENT_CLR_REMOTE_WAKEUP: | ||
| break; | ||
|
|
||
| default: | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) | ||
| { | ||
| for (uint32_t i = 0; i < nbytes; i++) { | ||
| ctshell_input(&shell_ctx, read_buffer[i]); | ||
| } | ||
| /* setup next out ep read transfer */ | ||
| usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048); | ||
| } | ||
|
|
||
| void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) | ||
| { | ||
| //USB_LOG_RAW("actual in len:%d\r\n", nbytes); | ||
|
|
||
| if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) { | ||
| /* send zlp */ | ||
| usbd_ep_start_write(busid, 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 | ||
| }; | ||
|
|
||
| static struct usbd_interface intf0; | ||
| static struct usbd_interface intf1; | ||
|
|
||
| void cdc_acm_init(uint8_t busid, uintptr_t reg_base) | ||
| { | ||
| const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 }; | ||
|
|
||
| memcpy(&write_buffer[0], data, 10); | ||
| memset(&write_buffer[10], 'a', 2038); | ||
|
|
||
| usbd_desc_register(busid, cdc_descriptor); | ||
| usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0)); | ||
| usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1)); | ||
| usbd_add_endpoint(busid, &cdc_out_ep); | ||
| usbd_add_endpoint(busid, &cdc_in_ep); | ||
| usbd_initialize(busid, reg_base, usbd_event_handler); | ||
|
Comment on lines
+179
to
+191
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make Line 228 hard-codes bus Proposed fix+static uint8_t cdc_busid;
+
void cdc_acm_init(uint8_t busid, uintptr_t reg_base)
{
+ cdc_busid = busid;
const uint8_t data[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
memcpy(&write_buffer[0], data, 10);
memset(&write_buffer[10], 'a', 2038);
@@
void shell_usb_write(const char *buf, uint16_t len, void *priv)
{
if (!dtr_enable || len == 0) {
return;
}
- uint16_t send_len = (len > 2048) ? 2048 : len;
- uint32_t timeout = 0xFFFFF;
- while (ep_tx_busy_flag && timeout > 0) {
- timeout--;
- }
- if (timeout == 0) return;
- memcpy(write_buffer, buf, send_len);
- ep_tx_busy_flag = true;
- usbd_ep_start_write(0, CDC_IN_EP, write_buffer, send_len);
+ while (len > 0) {
+ uint16_t send_len = (len > sizeof(write_buffer)) ? sizeof(write_buffer) : len;
+ uint32_t timeout = 0xFFFFF;
+
+ while (ep_tx_busy_flag && timeout > 0) {
+ timeout--;
+ }
+ if (timeout == 0) {
+ return;
+ }
+
+ memcpy(write_buffer, buf, send_len);
+ ep_tx_busy_flag = true;
+ usbd_ep_start_write(cdc_busid, CDC_IN_EP, write_buffer, send_len);
+
+ buf += send_len;
+ len -= send_len;
+ }
}Also applies to: 215-228 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| volatile uint8_t dtr_enable = 0; | ||
|
|
||
| void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr) | ||
| { | ||
| if (dtr) { | ||
| dtr_enable = 1; | ||
| } else { | ||
| dtr_enable = 0; | ||
| } | ||
| } | ||
|
|
||
| void cdc_acm_data_send_with_dtr_test(uint8_t busid) | ||
| { | ||
| if (dtr_enable) { | ||
| ep_tx_busy_flag = true; | ||
| usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048); | ||
| while (ep_tx_busy_flag) { | ||
| } | ||
| } | ||
| } | ||
|
|
||
| static uint8_t priv_busid; | ||
|
|
||
| void shell_usb_write(const char *buf, uint16_t len, void *priv) | ||
| { | ||
| if (!dtr_enable || len == 0) { | ||
| return; | ||
| } | ||
| uint16_t send_len = (len > 2048) ? 2048 : len; | ||
| uint32_t timeout = 0xFFFFF; | ||
| while (ep_tx_busy_flag && timeout > 0) { | ||
| timeout--; | ||
| } | ||
| if (timeout == 0) return; | ||
| memcpy(write_buffer, buf, send_len); | ||
| ep_tx_busy_flag = true; | ||
| usbd_ep_start_write(priv_busid, CDC_IN_EP, write_buffer, send_len); | ||
| } | ||
|
|
||
| void ctshell_port_cherryusb_init(ctshell_ctx_t *ctx, uint8_t busid, uintptr_t reg_base) | ||
| { | ||
| ctshell_io_t shell_io = { | ||
| .write = shell_usb_write, | ||
| }; | ||
| priv_busid = busid; | ||
|
|
||
| ctshell_init(ctx, shell_io, NULL); | ||
| cdc_acm_init(busid, reg_base); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| /* | ||
| * Copyright (c) 2026, MDLZCOOL | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
| #pragma once | ||
|
|
||
| #include "ctshell.h" | ||
| #include <stdint.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| void ctshell_port_cherryusb_init(ctshell_ctx_t *ctx, uint8_t busid, uintptr_t reg_base); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clear the session flags on reset/disconnect.
dtr_enableis only driven fromusbd_cdc_acm_set_dtr(). If the host drops off the bus after setting DTR, later writes still enter the transmit path and spin until timeout because the link state was never invalidated.Proposed fix
Also applies to: 194-203
🤖 Prompt for AI Agents