diff --git a/ports/stm32/main.c b/ports/stm32/main.c
index ff4589f9d4a08fc4fc1bc11e682b8108feff9fbb..02449a1b806a349d706e6759908b34d771859242 100644
--- a/ports/stm32/main.c
+++ b/ports/stm32/main.c
@@ -558,10 +558,6 @@ soft_reset:
 
     #if MICROPY_HW_ENABLE_USB
     pyb_usb_init0();
-
-    // Activate USB_VCP(0) on dupterm slot 1 for the REPL
-    MP_STATE_VM(dupterm_objs[1]) = MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj);
-    usb_vcp_attach_to_repl(&pyb_usb_vcp_obj, true);
     #endif
 
     // Initialise the local flash filesystem.
diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h
index b9fa3833ecafd752852a18bf1ed56f2642af53d2..036e1f6ccdce75a2dce729d13cd6fb1df2becad5 100644
--- a/ports/stm32/mpconfigboard_common.h
+++ b/ports/stm32/mpconfigboard_common.h
@@ -264,6 +264,10 @@
 #define MICROPY_HW_MAX_CAN (1)
 #endif
 
+// Configure maximum number of CDC VCP interfaces
+#ifndef MICROPY_HW_USB_CDC_NUM
+#define MICROPY_HW_USB_CDC_NUM (1)
+#endif
 
 // Pin definition header file
 #define MICROPY_PIN_DEFS_PORT_H "pin_defs_stm32.h"
diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c
index 8b7608a15023182bbdc61bf9bb1e1a42dda9a386..c9c22d5d2bbcaf2a93f096017fac144e817348d0 100644
--- a/ports/stm32/usb.c
+++ b/ports/stm32/usb.c
@@ -55,6 +55,8 @@
 #endif
 #endif
 
+STATIC void pyb_usb_vcp_init0(void);
+
 // this will be persistent across a soft-reset
 mp_uint_t pyb_usb_flags = 0;
 
@@ -62,10 +64,7 @@ typedef struct _usb_device_t {
     uint32_t enabled;
     USBD_HandleTypeDef hUSBDDevice;
     usbd_cdc_msc_hid_state_t usbd_cdc_msc_hid_state;
-    usbd_cdc_itf_t usbd_cdc_itf;
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    usbd_cdc_itf_t usbd_cdc2_itf;
-    #endif
+    usbd_cdc_itf_t usbd_cdc_itf[MICROPY_HW_USB_CDC_NUM];
     usbd_hid_itf_t usbd_hid_itf;
 } usb_device_t;
 
@@ -111,16 +110,15 @@ const mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj = {
 };
 
 void pyb_usb_init0(void) {
-    usb_device.usbd_cdc_itf.attached_to_repl = false;
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    usb_device.usbd_cdc2_itf.attached_to_repl = false;
-    #endif
+    for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+        usb_device.usbd_cdc_itf[i].attached_to_repl = false;
+    }
     MP_STATE_PORT(pyb_hid_report_desc) = MP_OBJ_NULL;
+
+    pyb_usb_vcp_init0();
 }
 
-bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_HID_ModeInfoTypeDef *hid_info) {
-    bool high_speed = (mode & USBD_MODE_HIGH_SPEED) != 0;
-    mode &= 0x7f;
+bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInfoTypeDef *hid_info) {
     usb_device_t *usb_dev = &usb_device;
     if (!usb_dev->enabled) {
         // only init USB once in the device's power-lifetime
@@ -132,15 +130,15 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H
         usbd->pDesc = (USBD_DescriptorsTypeDef*)&USBD_Descriptors;
         usbd->pClass = &USBD_CDC_MSC_HID;
         usb_dev->usbd_cdc_msc_hid_state.pdev = usbd;
-        usb_dev->usbd_cdc_msc_hid_state.cdc = &usb_dev->usbd_cdc_itf.base;
-        #if MICROPY_HW_USB_ENABLE_CDC2
-        usb_dev->usbd_cdc_msc_hid_state.cdc2 = &usb_dev->usbd_cdc2_itf.base;
-        #endif
+        for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+            usb_dev->usbd_cdc_msc_hid_state.cdc[i] = &usb_dev->usbd_cdc_itf[i].base;
+        }
         usb_dev->usbd_cdc_msc_hid_state.hid = &usb_dev->usbd_hid_itf.base;
         usbd->pClassData = &usb_dev->usbd_cdc_msc_hid_state;
 
         // configure the VID, PID and the USBD mode (interfaces it will expose)
-        USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, mode == USBD_MODE_CDC);
+        int cdc_only = (mode & USBD_MODE_IFACE_MASK) == USBD_MODE_CDC;
+        USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, cdc_only);
         if (USBD_SelectMode(&usb_dev->usbd_cdc_msc_hid_state, mode, hid_info) != 0) {
             return false;
         }
@@ -157,7 +155,7 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H
         }
 
         // start the USB device
-        USBD_LL_Init(usbd, high_speed);
+        USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0);
         USBD_LL_Start(usbd);
         usb_dev->enabled = true;
     }
@@ -179,22 +177,17 @@ bool usb_vcp_is_enabled(void) {
 }
 
 int usb_vcp_recv_byte(uint8_t *c) {
-    return usbd_cdc_rx(&usb_device.usbd_cdc_itf, c, 1, 0);
+    return usbd_cdc_rx(&usb_device.usbd_cdc_itf[0], c, 1, 0);
 }
 
 void usb_vcp_send_strn(const char *str, int len) {
     if (usb_device.enabled) {
-        usbd_cdc_tx_always(&usb_device.usbd_cdc_itf, (const uint8_t*)str, len);
+        usbd_cdc_tx_always(&usb_device.usbd_cdc_itf[0], (const uint8_t*)str, len);
     }
 }
 
 usbd_cdc_itf_t *usb_vcp_get(int idx) {
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    if (idx == 1) {
-        return &usb_device.usbd_cdc2_itf;
-    }
-    #endif
-    return &usb_device.usbd_cdc_itf;
+    return &usb_device.usbd_cdc_itf[idx];
 }
 
 /******************************************************************************/
@@ -243,7 +236,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
         return MP_OBJ_NEW_QSTR(MP_QSTR_host);
     #else
         uint8_t mode = USBD_GetMode(&usb_device.usbd_cdc_msc_hid_state);
-        switch (mode) {
+        switch (mode & USBD_MODE_IFACE_MASK) {
             case USBD_MODE_CDC:
                 return MP_OBJ_NEW_QSTR(MP_QSTR_VCP);
             case USBD_MODE_MSC:
@@ -298,13 +291,13 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
     // note: we support CDC as a synonym for VCP for backward compatibility
     uint16_t vid = args[1].u_int;
     uint16_t pid = args[2].u_int;
-    usb_device_mode_t mode;
+    uint8_t mode;
     if (strcmp(mode_str, "CDC+MSC") == 0 || strcmp(mode_str, "VCP+MSC") == 0) {
         if (args[2].u_int == -1) {
             pid = USBD_PID_CDC_MSC;
         }
         mode = USBD_MODE_CDC_MSC;
-    #if MICROPY_HW_USB_ENABLE_CDC2
+    #if MICROPY_HW_USB_CDC_NUM >= 2
     } else if (strcmp(mode_str, "VCP+VCP") == 0) {
         if (args[2].u_int == -1) {
             pid = USBD_PID_CDC2;
@@ -337,7 +330,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
 
     // get hid info if user selected such a mode
     USBD_HID_ModeInfoTypeDef hid_info;
-    if (mode & USBD_MODE_HID) {
+    if (mode & USBD_MODE_IFACE_HID) {
         mp_obj_t *items;
         mp_obj_get_array_fixed_n(args[3].u_obj, 5, &items);
         hid_info.subclass = mp_obj_get_int(items[0]);
@@ -388,13 +381,21 @@ typedef struct _pyb_usb_vcp_obj_t {
     usbd_cdc_itf_t *cdc_itf;
 } pyb_usb_vcp_obj_t;
 
-const pyb_usb_vcp_obj_t pyb_usb_vcp_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf};
-#if MICROPY_HW_USB_ENABLE_CDC2
-STATIC const pyb_usb_vcp_obj_t pyb_usb_vcp2_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc2_itf};
-#endif
+const pyb_usb_vcp_obj_t pyb_usb_vcp_obj[MICROPY_HW_USB_CDC_NUM] = {
+    {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[0]},
+    #if MICROPY_HW_USB_CDC_NUM >= 2
+    {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[1]},
+    #endif
+};
+
+STATIC void pyb_usb_vcp_init0(void) {
+    // Activate USB_VCP(0) on dupterm slot 1 for the REPL
+    MP_STATE_VM(dupterm_objs[1]) = MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[0]);
+    usb_vcp_attach_to_repl(&pyb_usb_vcp_obj[0], true);
+}
 
 STATIC void pyb_usb_vcp_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
-    int id = ((pyb_usb_vcp_obj_t*)MP_OBJ_TO_PTR(self_in))->cdc_itf - &usb_device.usbd_cdc_itf;
+    int id = ((pyb_usb_vcp_obj_t*)MP_OBJ_TO_PTR(self_in))->cdc_itf - &usb_device.usbd_cdc_itf[0];
     mp_printf(print, "USB_VCP(%u)", id);
 }
 
@@ -411,12 +412,8 @@ STATIC mp_obj_t pyb_usb_vcp_make_new(const mp_obj_type_t *type, size_t n_args, s
     // TODO raise exception if USB is not configured for VCP
 
     int id = (n_args == 0) ? 0 : mp_obj_get_int(args[0]);
-    if (id == 0) {
-        return MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj);
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    } else if (id == 1) {
-        return MP_OBJ_FROM_PTR(&pyb_usb_vcp2_obj);
-    #endif
+    if (0 <= id && id < MICROPY_HW_USB_CDC_NUM) {
+        return MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[id]);
     } else {
         mp_raise_ValueError(NULL);
     }
@@ -457,7 +454,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_vcp_isconnected_obj, pyb_usb_vcp_isconn
 
 // deprecated in favour of USB_VCP.isconnected
 STATIC mp_obj_t pyb_have_cdc(void) {
-    return pyb_usb_vcp_isconnected(MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj));
+    return pyb_usb_vcp_isconnected(MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[0]));
 }
 MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc);
 
diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h
index 3d57bf9129cda195ac2dd6f5514257f41d98d8e0..6678e1e17372f8de738eec119533bcaa9806f19a 100644
--- a/ports/stm32/usb.h
+++ b/ports/stm32/usb.h
@@ -58,14 +58,13 @@ extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_mouse_obj;
 extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj;
 extern const mp_obj_type_t pyb_usb_vcp_type;
 extern const mp_obj_type_t pyb_usb_hid_type;
-extern const pyb_usb_vcp_obj_t pyb_usb_vcp_obj;
 
 MP_DECLARE_CONST_FUN_OBJ_KW(pyb_usb_mode_obj);
 MP_DECLARE_CONST_FUN_OBJ_0(pyb_have_cdc_obj); // deprecated
 MP_DECLARE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj); // deprecated
 
 void pyb_usb_init0(void);
-bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_HID_ModeInfoTypeDef *hid_info);
+bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInfoTypeDef *hid_info);
 void pyb_usb_dev_deinit(void);
 bool usb_vcp_is_enabled(void);
 int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0
diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c
index 4a4a8beb8500ed250974b4e8734135c181b7bc21..49f0deec71242f4790564504087d71c65d08cf24 100644
--- a/ports/stm32/usbd_cdc_interface.c
+++ b/ports/stm32/usbd_cdc_interface.c
@@ -217,18 +217,13 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
     } else {
         usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData;
         hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM;
-        usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc;
-        if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) {
-            cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED;
-            usbd_cdc_try_tx(cdc);
-        }
-        #if MICROPY_HW_USB_ENABLE_CDC2
-        cdc = (usbd_cdc_itf_t*)usbd->cdc2;
-        if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) {
-            cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED;
-            usbd_cdc_try_tx(cdc);
+        for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+            usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc[i];
+            if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) {
+                cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED;
+                usbd_cdc_try_tx(cdc);
+            }
         }
-        #endif
     }
 }
 
diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c
index b7c1665f0a214ff18b2d16c6aba2342ca05be659..c2e86ccb5b21dbabdbec68e5c29bb9dc2103f69e 100644
--- a/ports/stm32/usbd_conf.c
+++ b/ports/stm32/usbd_conf.c
@@ -334,7 +334,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
     if (pdev->id ==  USB_PHY_FS_ID) {
         // Set LL Driver parameters
         pcd_fs_handle.Instance = USB_OTG_FS;
-        #if MICROPY_HW_USB_ENABLE_CDC2
+        #if MICROPY_HW_USB_CDC_NUM == 2
         pcd_fs_handle.Init.dev_endpoints = 6;
         #else
         pcd_fs_handle.Init.dev_endpoints = 4;
@@ -364,7 +364,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
         HAL_PCD_Init(&pcd_fs_handle);
 
         // We have 320 32-bit words in total to use here
-        #if MICROPY_HW_USB_ENABLE_CDC2
+        #if MICROPY_HW_USB_CDC_NUM == 2
         HAL_PCD_SetRxFiFo(&pcd_fs_handle, 128);
         HAL_PCD_SetTxFiFo(&pcd_fs_handle, 0, 32); // EP0
         HAL_PCD_SetTxFiFo(&pcd_fs_handle, 1, 64); // MSC / HID
diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h
index 1857273e0725e3e37127624e8bcbade45344852b..f20485a7c0c4f4135a0081a8f09dc6dc8ce8a328 100644
--- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h
+++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h
@@ -18,12 +18,13 @@
 #define USBD_SUPPORT_HS_MODE (0)
 #endif
 
-// Needed for the CDC+MSC+HID state and should be maximum of all template
-// config descriptors defined in usbd_cdc_msc_hid.c
-#if MICROPY_HW_USB_ENABLE_CDC2
+// Should be maximum of possible config descriptors that might be configured
+#if MICROPY_HW_USB_CDC_NUM == 2
+// Maximum is MSC+CDC+CDC
 #define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58))
 #else
-#define MAX_TEMPLATE_CONFIG_DESC_SIZE (107)
+// Maximum is HID+CDC
+#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 32 + (8 + 58))
 #endif
 
 // CDC, MSC and HID packet sizes
@@ -124,10 +125,7 @@ typedef struct _usbd_cdc_msc_hid_state_t {
     __ALIGN_BEGIN uint8_t usbd_str_desc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
     __ALIGN_BEGIN uint8_t usbd_config_desc[MAX_TEMPLATE_CONFIG_DESC_SIZE] __ALIGN_END;
 
-    usbd_cdc_state_t *cdc;
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    usbd_cdc_state_t *cdc2;
-    #endif
+    usbd_cdc_state_t *cdc[MICROPY_HW_USB_CDC_NUM];
     usbd_hid_state_t *hid;
 } usbd_cdc_msc_hid_state_t;
 
diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h
index c876dcf2987b2d99c65e41f0696aa11df1e79642..1cb879180d102b890986fbd9fd75d4ba5b5cbe64 100644
--- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h
+++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h
@@ -29,18 +29,22 @@
 // these are exports for the CDC/MSC/HID interface that are independent
 // from any other definitions/declarations
 
-// only CDC_MSC and CDC_HID are available
-typedef enum {
-    USBD_MODE_CDC = 0x01,
-    USBD_MODE_MSC = 0x02,
-    USBD_MODE_HID = 0x04,
-    USBD_MODE_CDC2 = 0x08,
-    USBD_MODE_CDC_MSC = USBD_MODE_CDC | USBD_MODE_MSC,
-    USBD_MODE_CDC_HID = USBD_MODE_CDC | USBD_MODE_HID,
-    USBD_MODE_MSC_HID = USBD_MODE_MSC | USBD_MODE_HID,
-    USBD_MODE_CDC2_MSC = USBD_MODE_CDC | USBD_MODE_MSC | USBD_MODE_CDC2,
-    USBD_MODE_HIGH_SPEED = 0x80, // or with one of the above
-} usb_device_mode_t;
+// These can be or'd together (but not all combinations may be available)
+#define USBD_MODE_IFACE_MASK    (0x7f)
+#define USBD_MODE_IFACE_CDC(i)  (0x01 << (i))
+#define USBD_MODE_IFACE_HID     (0x10)
+#define USBD_MODE_IFACE_MSC     (0x20)
+#define USBD_MODE_HIGH_SPEED    (0x80)
+
+// Convenience macros for supported mode combinations
+#define USBD_MODE_CDC       (USBD_MODE_IFACE_CDC(0))
+#define USBD_MODE_CDC2      (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1))
+#define USBD_MODE_CDC_HID   (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_HID)
+#define USBD_MODE_CDC_MSC   (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_MSC)
+#define USBD_MODE_CDC2_MSC  (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_MSC)
+#define USBD_MODE_HID       (USBD_MODE_IFACE_HID)
+#define USBD_MODE_MSC       (USBD_MODE_IFACE_MSC)
+#define USBD_MODE_MSC_HID   (USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID)
 
 typedef struct _USBD_HID_ModeInfoTypeDef {
     uint8_t subclass; // 0=no sub class, 1=boot
diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c
index 47436a4b6349748c8360f44f52c568df75412136..bfb5d3058a2d4d9e78887cde52c06fa5de6aa32f 100644
--- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c
+++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c
@@ -38,6 +38,8 @@
 #define MSC_TEMPLATE_MSC_DESC_OFFSET (9)
 #define CDC_MSC_TEMPLATE_MSC_DESC_OFFSET (9)
 #define CDC_MSC_TEMPLATE_CDC_DESC_OFFSET (40)
+#define CDC2_TEMPLATE_CDC_DESC_OFFSET (9 + 8)
+#define CDC2_TEMPLATE_CDC2_DESC_OFFSET (9 + (8 + 58) + 8)
 #define CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET (9)
 #define CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET (9 + 23 + 8)
 #define CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET (9 + 23 + (8 + 58) + 8)
@@ -69,13 +71,9 @@
 #define HID_IFACE_NUM_WITH_CDC (0)
 #define HID_IFACE_NUM_WITH_MSC (1)
 
-#define CDC_IN_EP (0x83)
-#define CDC_OUT_EP (0x03)
-#define CDC_CMD_EP (0x82)
-
-#define CDC2_IN_EP (0x85)
-#define CDC2_OUT_EP (0x05)
-#define CDC2_CMD_EP (0x84)
+#define CDC_IN_EP(i) (0x83 + 2 * (i))
+#define CDC_OUT_EP(i) (0x03 + 2 * (i))
+#define CDC_CMD_EP(i) (0x82 + 2 * (i))
 
 #define HID_IN_EP_WITH_CDC (0x81)
 #define HID_OUT_EP_WITH_CDC (0x01)
@@ -232,7 +230,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = {
     // Endpoint CMD Descriptor
     0x07,                           // bLength: Endpoint Descriptor size
     USB_DESC_TYPE_ENDPOINT,         // bDescriptorType: Endpoint
-    CDC_CMD_EP,                     // bEndpointAddress
+    CDC_CMD_EP(0),                  // bEndpointAddress
     0x03,                           // bmAttributes: Interrupt
     LOBYTE(CDC_CMD_PACKET_SIZE),    // wMaxPacketSize:
     HIBYTE(CDC_CMD_PACKET_SIZE),
@@ -253,7 +251,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = {
     // Endpoint OUT Descriptor
     0x07,                               // bLength: Endpoint Descriptor size
     USB_DESC_TYPE_ENDPOINT,             // bDescriptorType: Endpoint
-    CDC_OUT_EP,                         // bEndpointAddress
+    CDC_OUT_EP(0),                      // bEndpointAddress
     0x02,                               // bmAttributes: Bulk
     LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize:
     HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
@@ -262,7 +260,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = {
     // Endpoint IN Descriptor
     0x07,                               // bLength: Endpoint Descriptor size
     USB_DESC_TYPE_ENDPOINT,             // bDescriptorType: Endpoint
-    CDC_IN_EP,                          // bEndpointAddress
+    CDC_IN_EP(0),                       // bEndpointAddress
     0x02,                               // bmAttributes: Bulk
     LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize:
     HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
@@ -421,7 +419,7 @@ static size_t make_cdc_desc(uint8_t *dest, int need_iad, uint8_t iface_num) {
     return need_iad ? 8 + 58 : 58;
 }
 
-#if MICROPY_HW_USB_ENABLE_CDC2
+#if MICROPY_HW_USB_CDC_NUM >= 2
 static size_t make_cdc_desc_ep(uint8_t *dest, int need_iad, uint8_t iface_num, uint8_t cmd_ep, uint8_t out_ep, uint8_t in_ep) {
     size_t n = make_cdc_desc(dest, need_iad, iface_num);
     if (need_iad) {
@@ -461,7 +459,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
     size_t n = HEAD_DESC_SIZE;
     uint8_t *d = usbd->usbd_config_desc;
     uint8_t num_itf = 0;
-    switch (usbd->usbd_mode) {
+    switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) {
         case USBD_MODE_MSC:
             n += make_msc_desc(d + n);
             num_itf = 1;
@@ -470,19 +468,16 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
         case USBD_MODE_CDC_MSC:
             n += make_msc_desc(d + n);
             n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC);
-            usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC;
+            usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC;
             num_itf = 3;
             break;
 
-        #if MICROPY_HW_USB_ENABLE_CDC2
+        #if MICROPY_HW_USB_CDC_NUM >= 2
         case USBD_MODE_CDC2: {
-            // Ensure the first interface is also enabled
-            usbd->usbd_mode |= USBD_MODE_CDC;
-
             n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_ALONE);
-            n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC2_CMD_EP, CDC2_OUT_EP, CDC2_IN_EP);
-            usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE;
-            usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_CDC;
+            n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1));
+            usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE;
+            usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_CDC;
             num_itf = 4;
             break;
         }
@@ -490,9 +485,9 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
         case USBD_MODE_CDC2_MSC: {
             n += make_msc_desc(d + n);
             n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC);
-            n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC2_CMD_EP, CDC2_OUT_EP, CDC2_IN_EP);
-            usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC;
-            usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_MSC;
+            n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1));
+            usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC;
+            usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC;
             num_itf = 5;
             break;
         }
@@ -502,7 +497,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
             usbd->hid->desc = d + n;
             n += make_hid_desc(d + n, hid_info);
             n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_HID);
-            usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_HID;
+            usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_HID;
             usbd->hid->in_ep = HID_IN_EP_WITH_CDC;
             usbd->hid->out_ep = HID_OUT_EP_WITH_CDC;
             usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC;
@@ -512,7 +507,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
 
         case USBD_MODE_CDC:
             n += make_cdc_desc(d + n, 0, CDC_IFACE_NUM_ALONE);
-            usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE;
+            usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE;
             num_itf = 2;
             break;
 
@@ -533,17 +528,12 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
     make_head_desc(d, n, num_itf);
     usbd->usbd_config_desc_size = n;
 
-    if (usbd->usbd_mode & USBD_MODE_CDC) {
-        usbd->cdc->in_ep = CDC_IN_EP;
-        usbd->cdc->out_ep = CDC_OUT_EP;
-    }
-
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    if (usbd->usbd_mode & USBD_MODE_CDC2) {
-        usbd->cdc2->in_ep = CDC2_IN_EP;
-        usbd->cdc2->out_ep = CDC2_OUT_EP;
+    for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+        if (usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) {
+            usbd->cdc[i]->in_ep = CDC_IN_EP(i);
+            usbd->cdc[i]->out_ep = CDC_OUT_EP(i);
+        }
     }
-    #endif
 
     return 0;
 }
@@ -578,19 +568,14 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
 
     usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
 
-    if (usbd->usbd_mode & USBD_MODE_CDC) {
-        // CDC VCP component
-        usbd_cdc_state_init(pdev, usbd, usbd->cdc, CDC_CMD_EP);
-    }
-
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    if (usbd->usbd_mode & USBD_MODE_CDC2) {
-        // CDC VCP #2 component
-        usbd_cdc_state_init(pdev, usbd, usbd->cdc2, CDC2_CMD_EP);
+    // CDC VCP component(s)
+    for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+        if (usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) {
+            usbd_cdc_state_init(pdev, usbd, usbd->cdc[i], CDC_CMD_EP(i));
+        }
     }
-    #endif
 
-    if (usbd->usbd_mode & USBD_MODE_MSC) {
+    if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) {
         // MSC component
 
         int mp = usbd_msc_max_packet(pdev);
@@ -611,7 +596,7 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
         MSC_BOT_Init(pdev);
     }
 
-    if (usbd->usbd_mode & USBD_MODE_HID) {
+    if (usbd->usbd_mode & USBD_MODE_IFACE_HID) {
         // HID component
 
         // get max packet lengths from descriptor
@@ -644,31 +629,20 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
 static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
     usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
 
-    if ((usbd->usbd_mode & USBD_MODE_CDC) && usbd->cdc) {
-        // CDC VCP component
-
-        usbd_cdc_deinit(usbd->cdc);
-
-        // close endpoints
-        USBD_LL_CloseEP(pdev, CDC_IN_EP);
-        USBD_LL_CloseEP(pdev, CDC_OUT_EP);
-        USBD_LL_CloseEP(pdev, CDC_CMD_EP);
-    }
-
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    if ((usbd->usbd_mode & USBD_MODE_CDC2) && usbd->cdc2) {
-        // CDC VCP #2 component
+    for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+        if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && usbd->cdc[i]) {
+            // CDC VCP component
 
-        usbd_cdc_deinit(usbd->cdc2);
+            usbd_cdc_deinit(usbd->cdc[i]);
 
-        // close endpoints
-        USBD_LL_CloseEP(pdev, CDC2_IN_EP);
-        USBD_LL_CloseEP(pdev, CDC2_OUT_EP);
-        USBD_LL_CloseEP(pdev, CDC2_CMD_EP);
+            // close endpoints
+            USBD_LL_CloseEP(pdev, CDC_IN_EP(i));
+            USBD_LL_CloseEP(pdev, CDC_OUT_EP(i));
+            USBD_LL_CloseEP(pdev, CDC_CMD_EP(i));
+        }
     }
-    #endif
 
-    if (usbd->usbd_mode & USBD_MODE_MSC) {
+    if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) {
         // MSC component
 
         // close endpoints
@@ -679,7 +653,7 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
         MSC_BOT_DeInit(pdev);
     }
 
-    if (usbd->usbd_mode & USBD_MODE_HID) {
+    if (usbd->usbd_mode & USBD_MODE_IFACE_HID) {
         // HID component
 
         // close endpoints
@@ -717,35 +691,35 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
     switch (req->bmRequest & USB_REQ_RECIPIENT_MASK) {
         case USB_REQ_RECIPIENT_INTERFACE: {
             uint16_t iface = req->wIndex;
-            if ((mode & USBD_MODE_CDC) && iface == usbd->cdc->iface_num) {
-                recipient = USBD_MODE_CDC;
-                cdc = usbd->cdc;
-            #if MICROPY_HW_USB_ENABLE_CDC2
-            } else if ((mode & USBD_MODE_CDC2) && iface == usbd->cdc2->iface_num) {
-                recipient = USBD_MODE_CDC;
-                cdc = usbd->cdc2;
-            #endif
-            } else if ((mode & USBD_MODE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) {
+            if ((mode & USBD_MODE_IFACE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) {
                 recipient = USBD_MODE_MSC;
-            } else if ((mode & USBD_MODE_HID) && iface == usbd->hid->iface_num) {
+            } else if ((mode & USBD_MODE_IFACE_HID) && iface == usbd->hid->iface_num) {
                 recipient = USBD_MODE_HID;
+            } else {
+                for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+                    if ((mode & USBD_MODE_IFACE_CDC(i)) && iface == usbd->cdc[i]->iface_num) {
+                        recipient = USBD_MODE_CDC;
+                        cdc = usbd->cdc[i];
+                        break;
+                    }
+                }
             }
             break;
         }
         case USB_REQ_RECIPIENT_ENDPOINT: {
             uint8_t ep = req->wIndex & 0x7f;
-            if ((mode & USBD_MODE_CDC) && (ep == CDC_OUT_EP || ep == (CDC_CMD_EP & 0x7f))) {
-                recipient = USBD_MODE_CDC;
-                cdc = usbd->cdc;
-            #if MICROPY_HW_USB_ENABLE_CDC2
-            } else if ((mode & USBD_MODE_CDC2) && (ep == CDC2_OUT_EP || ep == (CDC2_CMD_EP & 0x7f))) {
-                recipient = USBD_MODE_CDC;
-                cdc = usbd->cdc2;
-            #endif
-            } else if ((mode & USBD_MODE_MSC) && ep == MSC_OUT_EP) {
+            if ((mode & USBD_MODE_IFACE_MSC) && ep == MSC_OUT_EP) {
                 recipient = USBD_MODE_MSC;
-            } else if ((mode & USBD_MODE_HID) && ep == usbd->hid->out_ep) {
+            } else if ((mode & USBD_MODE_IFACE_HID) && ep == usbd->hid->out_ep) {
                 recipient = USBD_MODE_HID;
+            } else {
+                for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+                    if ((mode & USBD_MODE_IFACE_CDC(i)) && (ep == CDC_OUT_EP(i) || ep == (CDC_CMD_EP(i) & 0x7f))) {
+                        recipient = USBD_MODE_CDC;
+                        cdc = usbd->cdc[i];
+                        break;
+                    }
+                }
             }
             break;
         }
@@ -894,36 +868,32 @@ static uint8_t EP0_TxSent(USBD_HandleTypeDef *pdev) {
 
 static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) {
     usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
-    if (usbd->cdc != NULL && usbd->cdc->cur_request != 0xff) {
-        usbd_cdc_control(usbd->cdc, usbd->cdc->cur_request, (uint8_t*)usbd->cdc->ctl_packet_buf, usbd->cdc->cur_length);
-        usbd->cdc->cur_request = 0xff;
-    }
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    if (usbd->cdc2 != NULL && usbd->cdc2->cur_request != 0xff) {
-        usbd_cdc_control(usbd->cdc2, usbd->cdc2->cur_request, (uint8_t*)usbd->cdc2->ctl_packet_buf, usbd->cdc2->cur_length);
-        usbd->cdc2->cur_request = 0xff;
+    for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+        if (usbd->cdc[i] != NULL && usbd->cdc[i]->cur_request != 0xff) {
+            usbd_cdc_control(usbd->cdc[i], usbd->cdc[i]->cur_request, (uint8_t*)usbd->cdc[i]->ctl_packet_buf, usbd->cdc[i]->cur_length);
+            usbd->cdc[i]->cur_request = 0xff;
+        }
     }
-    #endif
-
     return USBD_OK;
 }
 
 static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) {
     usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
-    if ((usbd->usbd_mode & USBD_MODE_CDC) && (epnum == (CDC_IN_EP & 0x7f) || epnum == (CDC_CMD_EP & 0x7f))) {
-        usbd->cdc->tx_in_progress = 0;
-        usbd_cdc_tx_ready(usbd->cdc);
-        return USBD_OK;
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    } else if ((usbd->usbd_mode & USBD_MODE_CDC2) && (epnum == (CDC2_IN_EP & 0x7f) || epnum == (CDC2_CMD_EP & 0x7f))) {
-        usbd->cdc2->tx_in_progress = 0;
-        usbd_cdc_tx_ready(usbd->cdc2);
-        return USBD_OK;
-    #endif
-    } else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_IN_EP & 0x7f)) {
+
+    for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+        if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && (epnum == (CDC_IN_EP(i) & 0x7f) || epnum == (CDC_CMD_EP(i) & 0x7f))) {
+            usbd->cdc[i]->tx_in_progress = 0;
+            usbd_cdc_tx_ready(usbd->cdc[i]);
+            return USBD_OK;
+        }
+    }
+
+    if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_IN_EP & 0x7f)) {
         MSC_BOT_DataIn(pdev, epnum);
         return USBD_OK;
-    } else if ((usbd->usbd_mode & USBD_MODE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) {
+    }
+
+    if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) {
         /* Ensure that the FIFO is empty before a new transfer, this condition could
         be caused by  a new transfer before the end of the previous transfer */
         usbd->hid->state = HID_IDLE;
@@ -935,26 +905,23 @@ static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
 
 static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) {
     usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
-    if ((usbd->usbd_mode & USBD_MODE_CDC) && epnum == (CDC_OUT_EP & 0x7f)) {
-        /* Get the received data length */
-        size_t len = USBD_LL_GetRxDataSize (pdev, epnum);
 
-        /* USB data will be immediately processed, this allow next USB traffic being
-        NAKed till the end of the application Xfer */
-        return usbd_cdc_receive(usbd->cdc, len);
+    for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+        if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && epnum == (CDC_OUT_EP(i) & 0x7f)) {
+            size_t len = USBD_LL_GetRxDataSize(pdev, epnum);
+            // USB data will be immediately processed, and next USB traffic is NAKed until it's done
+            return usbd_cdc_receive(usbd->cdc[i], len);
+        }
+    }
 
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    } else if ((usbd->usbd_mode & USBD_MODE_CDC2) && epnum == (CDC2_OUT_EP & 0x7f)) {
-        size_t len = USBD_LL_GetRxDataSize(pdev, epnum);
-        return usbd_cdc_receive(usbd->cdc2, len);
-        
-    #endif
-    } else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) {
+    if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) {
         MSC_BOT_DataOut(pdev, epnum);
         return USBD_OK;
-    } else if ((usbd->usbd_mode & USBD_MODE_HID) && epnum == (usbd->hid->out_ep & 0x7f)) {
+    }
+
+    if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->out_ep & 0x7f)) {
         size_t len = USBD_LL_GetRxDataSize(pdev, epnum);
-        usbd_hid_receive(usbd->hid, len);
+        return usbd_hid_receive(usbd->hid, len);
     }
 
     return USBD_OK;
@@ -981,48 +948,46 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t *
     usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
 
     #if USBD_SUPPORT_HS_MODE
-    uint8_t *cdc_desc = NULL;
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    uint8_t *cdc2_desc = NULL;
-    #endif
+    uint8_t *cdc_desc[MICROPY_HW_USB_CDC_NUM] = {0};
     uint8_t *msc_desc = NULL;
-    switch (usbd->usbd_mode) {
+    switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) {
         case USBD_MODE_MSC:
             msc_desc = usbd->usbd_config_desc + MSC_TEMPLATE_MSC_DESC_OFFSET;
             break;
 
         case USBD_MODE_CDC_MSC:
-            cdc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_CDC_DESC_OFFSET;
+            cdc_desc[0] = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_CDC_DESC_OFFSET;
             msc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_MSC_DESC_OFFSET;
             break;
 
-        #if MICROPY_HW_USB_ENABLE_CDC2
+        #if MICROPY_HW_USB_CDC_NUM >= 2
+        case USBD_MODE_CDC2:
+            cdc_desc[0] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC_DESC_OFFSET;
+            cdc_desc[1] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC2_DESC_OFFSET;
+            break;
+
         case USBD_MODE_CDC2_MSC:
-            cdc_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET;
-            cdc2_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET;
+            cdc_desc[0] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET;
+            cdc_desc[1] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET;
             msc_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET;
             break;
         #endif
 
         case USBD_MODE_CDC_HID:
-            cdc_desc = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET;
+            cdc_desc[0] = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET;
             break;
 
         case USBD_MODE_CDC:
-            cdc_desc = usbd->usbd_config_desc + CDC_TEMPLATE_CDC_DESC_OFFSET;
+            cdc_desc[0] = usbd->usbd_config_desc + CDC_TEMPLATE_CDC_DESC_OFFSET;
             break;
     }
 
     // configure CDC descriptors, if needed
-    if (cdc_desc != NULL) {
-        usbd_cdc_desc_config_max_packet(pdev, cdc_desc);
-    }
-
-    #if MICROPY_HW_USB_ENABLE_CDC2
-    if (cdc2_desc != NULL) {
-        usbd_cdc_desc_config_max_packet(pdev, cdc2_desc);
+    for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
+        if (cdc_desc[i] != NULL) {
+            usbd_cdc_desc_config_max_packet(pdev, cdc_desc[i]);
+        }
     }
-    #endif
 
     if (msc_desc != NULL) {
         uint32_t mp = usbd_msc_max_packet(pdev);