Skip to content

Commit 6601d4d

Browse files
VynDragondpgeorge
authored andcommitted
zephyr: Create ability to use device_next with CDC ACM as REPL.
This enables using the newer USB stack and its CDC ACM for the REPL. To switch to it, board file must contain `CONFIG_USB_DEVICE_STACK_NEXT=y` and `CONFIG_USBD_CDC_ACM_CLASS=y`. In the case of a board that is a platform that supports the older device stack, `CONFIG_USB_DEVICE_STACK=n` may be necessary. Signed-off-by: Vdragon <[email protected]>
1 parent e53f262 commit 6601d4d

File tree

4 files changed

+200
-0
lines changed

4 files changed

+200
-0
lines changed

ports/zephyr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ add_dependencies(${MICROPY_TARGET} zephyr_generated_headers)
128128
target_sources(app PRIVATE
129129
src/zephyr_start.c
130130
src/zephyr_getchar.c
131+
src/usbd.c
131132
)
132133

133134
target_link_libraries(app PRIVATE ${MICROPY_TARGET})

ports/zephyr/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ config MICROPY_FROZEN_MANIFEST
4949
depends on MICROPY_FROZEN_MODULES
5050
default "boards/manifest.py"
5151

52+
config MICROPY_USB_DEVICE_VID
53+
hex "USB VID"
54+
default 0x2fe3
55+
56+
config MICROPY_USB_DEVICE_PID
57+
hex "USB PID"
58+
default 0x0001
59+
5260
endmenu # MicroPython Options
5361

5462
source "Kconfig.zephyr"

ports/zephyr/main.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@
6363

6464
static char heap[MICROPY_HEAP_SIZE];
6565

66+
#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
67+
extern int mp_usbd_init(void);
68+
#endif // defined(CONFIG_USB_DEVICE_STACK_NEXT)
69+
6670
void init_zephyr(void) {
6771
// We now rely on CONFIG_NET_APP_SETTINGS to set up bootstrap
6872
// network addresses.
@@ -143,6 +147,10 @@ int real_main(void) {
143147
usb_enable(NULL);
144148
#endif
145149

150+
#ifdef CONFIG_USB_DEVICE_STACK_NEXT
151+
mp_usbd_init();
152+
#endif
153+
146154
#if MICROPY_VFS
147155
vfs_init();
148156
#endif

ports/zephyr/src/usbd.c

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2024-2025 MASSDRIVER EI (massdriver.space)
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
#include <stdint.h>
27+
28+
#include <zephyr/device.h>
29+
#include <zephyr/usb/usbd.h>
30+
#include <zephyr/usb/bos.h>
31+
32+
#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
33+
34+
#include <zephyr/logging/log.h>
35+
LOG_MODULE_REGISTER(mp_usbd);
36+
37+
/* By default, do not register the USB DFU class DFU mode instance. */
38+
static const char *const blocklist[] = {
39+
"dfu_dfu",
40+
NULL,
41+
};
42+
43+
USBD_DEVICE_DEFINE(mp_usbd,
44+
DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)),
45+
CONFIG_MICROPY_USB_DEVICE_VID, CONFIG_MICROPY_USB_DEVICE_PID);
46+
47+
USBD_DESC_LANG_DEFINE(mp_lang);
48+
USBD_DESC_MANUFACTURER_DEFINE(mp_mfr, "Zephyr Project");
49+
USBD_DESC_PRODUCT_DEFINE(mp_product, "Micropython on Zephyr RTOS");
50+
USBD_DESC_SERIAL_NUMBER_DEFINE(mp_sn);
51+
52+
USBD_DESC_CONFIG_DEFINE(fs_cfg_desc, "FS Configuration");
53+
USBD_DESC_CONFIG_DEFINE(hs_cfg_desc, "HS Configuration");
54+
55+
/* not self-powered, no remote wakeup */
56+
static const uint8_t attributes = 0;
57+
58+
/* Full speed configuration
59+
* power = 250 * 2 mA = 500mA
60+
*/
61+
USBD_CONFIGURATION_DEFINE(mp_fs_config,
62+
attributes,
63+
250, &fs_cfg_desc);
64+
65+
/* High speed configuration */
66+
USBD_CONFIGURATION_DEFINE(mp_hs_config,
67+
attributes,
68+
250, &hs_cfg_desc);
69+
70+
static void mp_fix_code_triple(struct usbd_context *uds_ctx,
71+
const enum usbd_speed speed) {
72+
/* Always use class code information from Interface Descriptors */
73+
if (IS_ENABLED(CONFIG_USBD_CDC_ACM_CLASS) ||
74+
IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) ||
75+
IS_ENABLED(CONFIG_USBD_CDC_NCM_CLASS) ||
76+
IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS)) {
77+
/*
78+
* Class with multiple interfaces have an Interface
79+
* Association Descriptor available, use an appropriate triple
80+
* to indicate it.
81+
*/
82+
usbd_device_set_code_triple(uds_ctx, speed,
83+
USB_BCC_MISCELLANEOUS, 0x02, 0x01);
84+
} else {
85+
usbd_device_set_code_triple(uds_ctx, speed, 0, 0, 0);
86+
}
87+
}
88+
89+
struct usbd_context *mp_usbd_init_device(usbd_msg_cb_t msg_cb) {
90+
int err;
91+
92+
err = usbd_add_descriptor(&mp_usbd, &mp_lang);
93+
if (err) {
94+
LOG_ERR("Failed to initialize language descriptor (%d)", err);
95+
return NULL;
96+
}
97+
98+
err = usbd_add_descriptor(&mp_usbd, &mp_mfr);
99+
if (err) {
100+
LOG_ERR("Failed to initialize manufacturer descriptor (%d)", err);
101+
return NULL;
102+
}
103+
104+
err = usbd_add_descriptor(&mp_usbd, &mp_product);
105+
if (err) {
106+
LOG_ERR("Failed to initialize product descriptor (%d)", err);
107+
return NULL;
108+
}
109+
110+
err = usbd_add_descriptor(&mp_usbd, &mp_sn);
111+
if (err) {
112+
LOG_ERR("Failed to initialize SN descriptor (%d)", err);
113+
return NULL;
114+
}
115+
116+
if (usbd_caps_speed(&mp_usbd) == USBD_SPEED_HS) {
117+
err = usbd_add_configuration(&mp_usbd, USBD_SPEED_HS,
118+
&mp_hs_config);
119+
if (err) {
120+
LOG_ERR("Failed to add High-Speed configuration");
121+
return NULL;
122+
}
123+
124+
err = usbd_register_all_classes(&mp_usbd, USBD_SPEED_HS, 1, blocklist);
125+
if (err) {
126+
LOG_ERR("Failed to add register classes");
127+
return NULL;
128+
}
129+
130+
mp_fix_code_triple(&mp_usbd, USBD_SPEED_HS);
131+
}
132+
133+
err = usbd_add_configuration(&mp_usbd, USBD_SPEED_FS,
134+
&mp_fs_config);
135+
if (err) {
136+
LOG_ERR("Failed to add Full-Speed configuration");
137+
return NULL;
138+
}
139+
140+
err = usbd_register_all_classes(&mp_usbd, USBD_SPEED_FS, 1, blocklist);
141+
if (err) {
142+
LOG_ERR("Failed to add register classes");
143+
return NULL;
144+
}
145+
146+
mp_fix_code_triple(&mp_usbd, USBD_SPEED_FS);
147+
148+
if (msg_cb != NULL) {
149+
err = usbd_msg_register_cb(&mp_usbd, msg_cb);
150+
if (err) {
151+
LOG_ERR("Failed to register message callback");
152+
return NULL;
153+
}
154+
}
155+
156+
err = usbd_init(&mp_usbd);
157+
if (err) {
158+
LOG_ERR("Failed to initialize device support");
159+
return NULL;
160+
}
161+
162+
return &mp_usbd;
163+
}
164+
165+
static struct usbd_context *mp_usbd_context;
166+
167+
int mp_usbd_init(void) {
168+
int err;
169+
170+
mp_usbd_context = mp_usbd_init_device(NULL);
171+
if (mp_usbd_context == NULL) {
172+
return -ENODEV;
173+
}
174+
175+
err = usbd_enable(mp_usbd_context);
176+
if (err) {
177+
return err;
178+
}
179+
180+
return 0;
181+
}
182+
183+
#endif // defined(CONFIG_USB_DEVICE_STACK_NEXT)

0 commit comments

Comments
 (0)