summaryrefslogtreecommitdiffstatshomepage
path: root/ports
diff options
context:
space:
mode:
Diffstat (limited to 'ports')
-rw-r--r--ports/zephyr/CMakeLists.txt1
-rw-r--r--ports/zephyr/Kconfig8
-rw-r--r--ports/zephyr/boards/beagleconnect_freedom.conf1
-rw-r--r--ports/zephyr/boards/nrf9151dk_nrf9151.conf7
-rw-r--r--ports/zephyr/boards/nrf9151dk_nrf9151.overlay22
-rw-r--r--ports/zephyr/main.c8
-rw-r--r--ports/zephyr/src/usbd.c183
-rw-r--r--ports/zephyr/zephyr_storage.c19
8 files changed, 246 insertions, 3 deletions
diff --git a/ports/zephyr/CMakeLists.txt b/ports/zephyr/CMakeLists.txt
index 4f457f4a58..debf2bd2c1 100644
--- a/ports/zephyr/CMakeLists.txt
+++ b/ports/zephyr/CMakeLists.txt
@@ -128,6 +128,7 @@ add_dependencies(${MICROPY_TARGET} zephyr_generated_headers)
target_sources(app PRIVATE
src/zephyr_start.c
src/zephyr_getchar.c
+ src/usbd.c
)
target_link_libraries(app PRIVATE ${MICROPY_TARGET})
diff --git a/ports/zephyr/Kconfig b/ports/zephyr/Kconfig
index f8d1543155..6db0133f4f 100644
--- a/ports/zephyr/Kconfig
+++ b/ports/zephyr/Kconfig
@@ -49,6 +49,14 @@ config MICROPY_FROZEN_MANIFEST
depends on MICROPY_FROZEN_MODULES
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
source "Kconfig.zephyr"
diff --git a/ports/zephyr/boards/beagleconnect_freedom.conf b/ports/zephyr/boards/beagleconnect_freedom.conf
index 1e3f6037bd..8fe2583205 100644
--- a/ports/zephyr/boards/beagleconnect_freedom.conf
+++ b/ports/zephyr/boards/beagleconnect_freedom.conf
@@ -1,4 +1,5 @@
# Hardware features
+CONFIG_ADC=y
CONFIG_PWM=y
CONFIG_I2C=y
CONFIG_SPI=y
diff --git a/ports/zephyr/boards/nrf9151dk_nrf9151.conf b/ports/zephyr/boards/nrf9151dk_nrf9151.conf
new file mode 100644
index 0000000000..e89f332ba1
--- /dev/null
+++ b/ports/zephyr/boards/nrf9151dk_nrf9151.conf
@@ -0,0 +1,7 @@
+# Enable external flash
+CONFIG_SPI=y
+CONFIG_SPI_NOR=y
+CONFIG_SPI_NOR_SFDP_DEVICETREE=y
+
+CONFIG_FLASH=y
+CONFIG_FLASH_MAP=y
diff --git a/ports/zephyr/boards/nrf9151dk_nrf9151.overlay b/ports/zephyr/boards/nrf9151dk_nrf9151.overlay
new file mode 100644
index 0000000000..85cab57414
--- /dev/null
+++ b/ports/zephyr/boards/nrf9151dk_nrf9151.overlay
@@ -0,0 +1,22 @@
+/ {
+ /* Configure partition manager to use gd25wb256 as the external flash */
+ chosen {
+ nordic,pm-ext-flash = &gd25wb256;
+ };
+};
+
+/delete-node/ &storage_partition;
+
+&gd25wb256 {
+ status = "okay";
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ storage_partition: partition@0 {
+ reg = <0x00000000 0x2000000>;
+ label = "storage";
+ };
+ };
+};
diff --git a/ports/zephyr/main.c b/ports/zephyr/main.c
index 206b7f92d3..d4498c1079 100644
--- a/ports/zephyr/main.c
+++ b/ports/zephyr/main.c
@@ -63,6 +63,10 @@
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) {
// We now rely on CONFIG_NET_APP_SETTINGS to set up bootstrap
// network addresses.
@@ -143,6 +147,10 @@ soft_reset:
usb_enable(NULL);
#endif
+ #ifdef CONFIG_USB_DEVICE_STACK_NEXT
+ mp_usbd_init();
+ #endif
+
#if MICROPY_VFS
vfs_init();
#endif
diff --git a/ports/zephyr/src/usbd.c b/ports/zephyr/src/usbd.c
new file mode 100644
index 0000000000..2444706cbe
--- /dev/null
+++ b/ports/zephyr/src/usbd.c
@@ -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)
diff --git a/ports/zephyr/zephyr_storage.c b/ports/zephyr/zephyr_storage.c
index 484feb1130..40bcef7338 100644
--- a/ports/zephyr/zephyr_storage.c
+++ b/ports/zephyr/zephyr_storage.c
@@ -139,6 +139,20 @@ MP_DEFINE_CONST_OBJ_TYPE(
#endif // CONFIG_DISK_ACCESS
#ifdef CONFIG_FLASH_MAP
+
+#define FLASH_AREA_DEFINE_LABEL(part) CONCAT(MP_QSTR_ID_, DT_STRING_TOKEN(part, label))
+#define FLASH_AREA_DEFINE_NB(part) CONCAT(MP_QSTR_ID_, DT_FIXED_PARTITION_ID(part))
+
+#define FLASH_AREA_DEFINE_GETNAME(part) COND_CODE_1(DT_NODE_HAS_PROP(part, label), \
+ (FLASH_AREA_DEFINE_LABEL(part)), (FLASH_AREA_DEFINE_NB(part)))
+
+#define FLASH_AREA_DEFINE_DEFINE(part) { MP_ROM_QSTR(FLASH_AREA_DEFINE_GETNAME(part)), MP_ROM_INT(DT_FIXED_PARTITION_ID(part)) },
+
+#define FLASH_AREA_DEFINE(part) COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_MTD_FROM_FIXED_PARTITION(part)), \
+ (FLASH_AREA_DEFINE_DEFINE(part)), ())
+
+#define FOREACH_PARTITION(n) DT_FOREACH_CHILD(n, FLASH_AREA_DEFINE)
+
const mp_obj_type_t zephyr_flash_area_type;
typedef struct _zephyr_flash_area_obj_t {
@@ -244,9 +258,8 @@ static const mp_rom_map_elem_t zephyr_flash_area_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&zephyr_flash_area_readblocks_obj) },
{ MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&zephyr_flash_area_writeblocks_obj) },
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&zephyr_flash_area_ioctl_obj) },
- #if FIXED_PARTITION_EXISTS(storage_partition)
- { MP_ROM_QSTR(MP_QSTR_STORAGE), MP_ROM_INT(FIXED_PARTITION_ID(storage_partition)) },
- #endif
+ /* Generate list of partition IDs from Zephyr Devicetree */
+ DT_FOREACH_STATUS_OKAY(fixed_partitions, FOREACH_PARTITION)
};
static MP_DEFINE_CONST_DICT(zephyr_flash_area_locals_dict, zephyr_flash_area_locals_dict_table);