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 <mail@massdriver.space>
This commit is contained in:
@@ -128,6 +128,7 @@ add_dependencies(${MICROPY_TARGET} zephyr_generated_headers)
|
|||||||
target_sources(app PRIVATE
|
target_sources(app PRIVATE
|
||||||
src/zephyr_start.c
|
src/zephyr_start.c
|
||||||
src/zephyr_getchar.c
|
src/zephyr_getchar.c
|
||||||
|
src/usbd.c
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(app PRIVATE ${MICROPY_TARGET})
|
target_link_libraries(app PRIVATE ${MICROPY_TARGET})
|
||||||
|
|||||||
@@ -49,6 +49,14 @@ config MICROPY_FROZEN_MANIFEST
|
|||||||
depends on MICROPY_FROZEN_MODULES
|
depends on MICROPY_FROZEN_MODULES
|
||||||
default "boards/manifest.py"
|
default "boards/manifest.py"
|
||||||
|
|
||||||
|
config MICROPY_USB_DEVICE_VID
|
||||||
|
hex "USB VID"
|
||||||
|
default 0x2fe3
|
||||||
|
|
||||||
|
config MICROPY_USB_DEVICE_PID
|
||||||
|
hex "USB PID"
|
||||||
|
default 0x0001
|
||||||
|
|
||||||
endmenu # MicroPython Options
|
endmenu # MicroPython Options
|
||||||
|
|
||||||
source "Kconfig.zephyr"
|
source "Kconfig.zephyr"
|
||||||
|
|||||||
@@ -63,6 +63,10 @@
|
|||||||
|
|
||||||
static char heap[MICROPY_HEAP_SIZE];
|
static char heap[MICROPY_HEAP_SIZE];
|
||||||
|
|
||||||
|
#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
|
||||||
|
extern int mp_usbd_init(void);
|
||||||
|
#endif // defined(CONFIG_USB_DEVICE_STACK_NEXT)
|
||||||
|
|
||||||
void init_zephyr(void) {
|
void init_zephyr(void) {
|
||||||
// We now rely on CONFIG_NET_APP_SETTINGS to set up bootstrap
|
// We now rely on CONFIG_NET_APP_SETTINGS to set up bootstrap
|
||||||
// network addresses.
|
// network addresses.
|
||||||
@@ -143,6 +147,10 @@ soft_reset:
|
|||||||
usb_enable(NULL);
|
usb_enable(NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_DEVICE_STACK_NEXT
|
||||||
|
mp_usbd_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if MICROPY_VFS
|
#if MICROPY_VFS
|
||||||
vfs_init();
|
vfs_init();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
183
ports/zephyr/src/usbd.c
Normal file
183
ports/zephyr/src/usbd.c
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024-2025 MASSDRIVER EI (massdriver.space)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/usb/usbd.h>
|
||||||
|
#include <zephyr/usb/bos.h>
|
||||||
|
|
||||||
|
#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
|
||||||
|
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(mp_usbd);
|
||||||
|
|
||||||
|
/* By default, do not register the USB DFU class DFU mode instance. */
|
||||||
|
static const char *const blocklist[] = {
|
||||||
|
"dfu_dfu",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
USBD_DEVICE_DEFINE(mp_usbd,
|
||||||
|
DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)),
|
||||||
|
CONFIG_MICROPY_USB_DEVICE_VID, CONFIG_MICROPY_USB_DEVICE_PID);
|
||||||
|
|
||||||
|
USBD_DESC_LANG_DEFINE(mp_lang);
|
||||||
|
USBD_DESC_MANUFACTURER_DEFINE(mp_mfr, "Zephyr Project");
|
||||||
|
USBD_DESC_PRODUCT_DEFINE(mp_product, "Micropython on Zephyr RTOS");
|
||||||
|
USBD_DESC_SERIAL_NUMBER_DEFINE(mp_sn);
|
||||||
|
|
||||||
|
USBD_DESC_CONFIG_DEFINE(fs_cfg_desc, "FS Configuration");
|
||||||
|
USBD_DESC_CONFIG_DEFINE(hs_cfg_desc, "HS Configuration");
|
||||||
|
|
||||||
|
/* not self-powered, no remote wakeup */
|
||||||
|
static const uint8_t attributes = 0;
|
||||||
|
|
||||||
|
/* Full speed configuration
|
||||||
|
* power = 250 * 2 mA = 500mA
|
||||||
|
*/
|
||||||
|
USBD_CONFIGURATION_DEFINE(mp_fs_config,
|
||||||
|
attributes,
|
||||||
|
250, &fs_cfg_desc);
|
||||||
|
|
||||||
|
/* High speed configuration */
|
||||||
|
USBD_CONFIGURATION_DEFINE(mp_hs_config,
|
||||||
|
attributes,
|
||||||
|
250, &hs_cfg_desc);
|
||||||
|
|
||||||
|
static void mp_fix_code_triple(struct usbd_context *uds_ctx,
|
||||||
|
const enum usbd_speed speed) {
|
||||||
|
/* Always use class code information from Interface Descriptors */
|
||||||
|
if (IS_ENABLED(CONFIG_USBD_CDC_ACM_CLASS) ||
|
||||||
|
IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) ||
|
||||||
|
IS_ENABLED(CONFIG_USBD_CDC_NCM_CLASS) ||
|
||||||
|
IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS)) {
|
||||||
|
/*
|
||||||
|
* Class with multiple interfaces have an Interface
|
||||||
|
* Association Descriptor available, use an appropriate triple
|
||||||
|
* to indicate it.
|
||||||
|
*/
|
||||||
|
usbd_device_set_code_triple(uds_ctx, speed,
|
||||||
|
USB_BCC_MISCELLANEOUS, 0x02, 0x01);
|
||||||
|
} else {
|
||||||
|
usbd_device_set_code_triple(uds_ctx, speed, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct usbd_context *mp_usbd_init_device(usbd_msg_cb_t msg_cb) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = usbd_add_descriptor(&mp_usbd, &mp_lang);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to initialize language descriptor (%d)", err);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usbd_add_descriptor(&mp_usbd, &mp_mfr);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to initialize manufacturer descriptor (%d)", err);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usbd_add_descriptor(&mp_usbd, &mp_product);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to initialize product descriptor (%d)", err);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usbd_add_descriptor(&mp_usbd, &mp_sn);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to initialize SN descriptor (%d)", err);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usbd_caps_speed(&mp_usbd) == USBD_SPEED_HS) {
|
||||||
|
err = usbd_add_configuration(&mp_usbd, USBD_SPEED_HS,
|
||||||
|
&mp_hs_config);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to add High-Speed configuration");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usbd_register_all_classes(&mp_usbd, USBD_SPEED_HS, 1, blocklist);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to add register classes");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_fix_code_triple(&mp_usbd, USBD_SPEED_HS);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usbd_add_configuration(&mp_usbd, USBD_SPEED_FS,
|
||||||
|
&mp_fs_config);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to add Full-Speed configuration");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usbd_register_all_classes(&mp_usbd, USBD_SPEED_FS, 1, blocklist);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to add register classes");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_fix_code_triple(&mp_usbd, USBD_SPEED_FS);
|
||||||
|
|
||||||
|
if (msg_cb != NULL) {
|
||||||
|
err = usbd_msg_register_cb(&mp_usbd, msg_cb);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to register message callback");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usbd_init(&mp_usbd);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Failed to initialize device support");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &mp_usbd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usbd_context *mp_usbd_context;
|
||||||
|
|
||||||
|
int mp_usbd_init(void) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
mp_usbd_context = mp_usbd_init_device(NULL);
|
||||||
|
if (mp_usbd_context == NULL) {
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usbd_enable(mp_usbd_context);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(CONFIG_USB_DEVICE_STACK_NEXT)
|
||||||
Reference in New Issue
Block a user