diff --git a/ports/stm32/mboot/main.c b/ports/stm32/mboot/main.c
index f6b89004d41624c4f6780c73d3ad5fd86f557d91..fcd43edc7f3eaaf3397853671a10140258e98c40 100644
--- a/ports/stm32/mboot/main.c
+++ b/ports/stm32/mboot/main.c
@@ -1088,6 +1088,13 @@ typedef struct _pyb_usbdd_obj_t {
 #define MBOOT_USB_PID 0xDF11
 #endif
 
+static const uint8_t usbd_fifo_size[] = {
+    32, 8, 16, 8, 16, 0, 0, // FS: RX, EP0(in), 5x IN endpoints
+    #if MICROPY_HW_USB_HS
+    116, 8, 64, 4, 64, 0, 0, 0, 0, 0, // HS: RX, EP0(in), 8x IN endpoints
+    #endif
+};
+
 __ALIGN_BEGIN static const uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
     USB_LEN_LANGID_STR_DESC,
     USB_DESC_TYPE_STRING,
@@ -1315,7 +1322,7 @@ static void pyb_usbdd_start(pyb_usbdd_obj_t *self) {
         while (!(PWR->CR3 & PWR_CR3_USB33RDY)) {
         }
         #endif
-        USBD_LL_Init(&self->hUSBDDevice, 0);
+        USBD_LL_Init(&self->hUSBDDevice, 0, usbd_fifo_size);
         USBD_LL_Start(&self->hUSBDDevice);
         self->started = true;
     }
diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c
index 3308f074498333e077b09058adad2951c9d45f5f..791a6472a5a40efc2464a334af24565e5393ef45 100644
--- a/ports/stm32/usb.c
+++ b/ports/stm32/usb.c
@@ -75,6 +75,50 @@ typedef struct _usb_device_t {
 usb_device_t usb_device = {0};
 pyb_usb_storage_medium_t pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_NONE;
 
+#if !MICROPY_HW_USB_IS_MULTI_OTG
+
+// Units of FIFO size arrays below are 4x 16-bit words = 8 bytes
+// There are 512x 16-bit words it total to use here (when using PCD_SNG_BUF)
+
+// EP0(out), EP0(in), MSC/HID(out), MSC/HID(in), unused, CDC_CMD(in), CDC_DATA(out), CDC_DATA(in)
+STATIC const uint8_t usbd_fifo_size_cdc1[] = {16, 16, 16, 16, 0, 16, 16, 16};
+
+#else
+
+// Units of FIFO size arrays below are 4x 32-bit words = 16 bytes
+// FS: there are 320x 32-bit words in total to use here
+// HS: there are 1024x 32-bit words in total to use here
+
+// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA
+STATIC const uint8_t usbd_fifo_size_cdc1[] = {
+    32, 8, 16, 8, 16, 0, 0, // FS: RX, EP0(in), 5x IN endpoints
+    #if MICROPY_HW_USB_HS
+    116, 8, 64, 4, 64, 0, 0, 0, 0, 0, // HS: RX, EP0(in), 8x IN endpoints
+    #endif
+};
+
+#if MICROPY_HW_USB_CDC_NUM >= 2
+// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD, CDC2_DATA
+STATIC const uint8_t usbd_fifo_size_cdc2[] = {
+    32, 8, 16, 4, 8, 4, 8,
+    #if MICROPY_HW_USB_HS
+    116, 8, 64, 2, 32, 2, 32, 0, 0, 0,
+    #endif
+};
+#endif
+
+#if MICROPY_HW_USB_CDC_NUM >= 3
+// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD, CDC2_DATA, CDC3_CMD, CDC3_DATA
+STATIC const uint8_t usbd_fifo_size_cdc3[] = {
+    0, 0, 0, 0, 0, 0, 0, // FS: can't support 3x VCP mode
+    #if MICROPY_HW_USB_HS
+    82, 8, 64, 2, 32, 2, 32, 2, 32, 0,
+    #endif
+};
+#endif
+
+#endif
+
 #if MICROPY_HW_USB_HID
 // predefined hid mouse data
 STATIC const mp_obj_str_t pyb_usb_hid_mouse_desc_obj = {
@@ -197,8 +241,20 @@ bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size
         USBD_MSC_RegisterStorage(&usb_dev->usbd_cdc_msc_hid_state, (USBD_StorageTypeDef*)&usbd_msc_fops);
         #endif
 
+        const uint8_t *fifo_size = usbd_fifo_size_cdc1;
+        #if MICROPY_HW_USB_CDC_NUM >= 3
+        if (mode & USBD_MODE_IFACE_CDC(2)) {
+            fifo_size = usbd_fifo_size_cdc3;
+        } else
+        #endif
+        #if MICROPY_HW_USB_CDC_NUM >= 2
+        if (mode & USBD_MODE_IFACE_CDC(1)) {
+            fifo_size = usbd_fifo_size_cdc2;
+        }
+        #endif
+
         // start the USB device
-        USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0);
+        USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0, fifo_size);
         USBD_LL_Start(usbd);
         usb_dev->enabled = true;
     }
diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c
index 275ec15aa61ca2ce7bc1c06234660b1d45b057aa..d30f28b2fc60c6c41825d01f01d7a32bc0cdb18f 100644
--- a/ports/stm32/usbd_conf.c
+++ b/ports/stm32/usbd_conf.c
@@ -361,7 +361,7 @@ void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) {
   * @param  pdev: Device handle
   * @retval USBD Status
   */
-USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
+USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed, const uint8_t *fifo_size) {
     #if MICROPY_HW_USB_FS
     if (pdev->id ==  USB_PHY_FS_ID) {
         #if defined(STM32WB)
@@ -401,35 +401,19 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
         // Initialize LL Driver
         HAL_PCD_Init(&pcd_fs_handle);
 
+        // Set FIFO buffer sizes
         #if !MICROPY_HW_USB_IS_MULTI_OTG
-        // We have 512 16-bit words it total to use here (when using PCD_SNG_BUF)
-        HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x00, PCD_SNG_BUF, 64); // EP0
-        HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x80, PCD_SNG_BUF, 128); // EP0
-        HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x01, PCD_SNG_BUF, 192); // MSC / HID
-        HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x81, PCD_SNG_BUF, 256); // MSC / HID
-        HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x02, PCD_SNG_BUF, 320); // unused
-        HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x82, PCD_SNG_BUF, 320); // CDC CMD
-        HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x03, PCD_SNG_BUF, 384); // CDC DATA
-        HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x83, PCD_SNG_BUF, 448); // CDC DATA
-        #else
-
-        // We have 320 32-bit words in total to use here
-        #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
-        HAL_PCD_SetTxFiFo(&pcd_fs_handle, 2, 16); // CDC CMD
-        HAL_PCD_SetTxFiFo(&pcd_fs_handle, 3, 32); // CDC DATA
-        HAL_PCD_SetTxFiFo(&pcd_fs_handle, 4, 16); // CDC2 CMD
-        HAL_PCD_SetTxFiFo(&pcd_fs_handle, 5, 32); // CDC2 DATA
+        uint32_t fifo_offset = USBD_PMA_RESERVE; // need to reserve some data at start of FIFO
+        for (size_t i = 0; i < USBD_PMA_NUM_FIFO; ++i) {
+            uint16_t ep_addr = ((i & 1) * 0x80) | (i >> 1);
+            HAL_PCDEx_PMAConfig(&pcd_fs_handle, ep_addr, PCD_SNG_BUF, fifo_offset);
+            fifo_offset += fifo_size[i] * 4;
+        }
         #else
-        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
-        HAL_PCD_SetTxFiFo(&pcd_fs_handle, 2, 32); // CDC CMD
-        HAL_PCD_SetTxFiFo(&pcd_fs_handle, 3, 64); // CDC DATA
-        #endif
-
+        HAL_PCD_SetRxFiFo(&pcd_fs_handle, fifo_size[0] * 4);
+        for (size_t i = 0; i < USBD_FS_NUM_TX_FIFO; ++i) {
+            HAL_PCD_SetTxFiFo(&pcd_fs_handle, i, fifo_size[1 + i] * 4);
+        }
         #endif
     }
     #endif
@@ -486,22 +470,12 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
         // Initialize LL Driver
         HAL_PCD_Init(&pcd_hs_handle);
 
-        // We have 1024 32-bit words in total to use here
-        #if MICROPY_HW_USB_CDC_NUM == 3
-        HAL_PCD_SetRxFiFo(&pcd_hs_handle, 328);
-        #else
-        HAL_PCD_SetRxFiFo(&pcd_hs_handle, 464);
-        #endif
-        HAL_PCD_SetTxFiFo(&pcd_hs_handle, 0, 32); // EP0
-        HAL_PCD_SetTxFiFo(&pcd_hs_handle, 1, 256); // MSC / HID
-        HAL_PCD_SetTxFiFo(&pcd_hs_handle, 2, 8); // CDC CMD
-        HAL_PCD_SetTxFiFo(&pcd_hs_handle, 3, 128); // CDC DATA
-        HAL_PCD_SetTxFiFo(&pcd_hs_handle, 4, 8); // CDC2 CMD
-        HAL_PCD_SetTxFiFo(&pcd_hs_handle, 5, 128); // CDC2 DATA
-        #if MICROPY_HW_USB_CDC_NUM == 3
-        HAL_PCD_SetTxFiFo(&pcd_hs_handle, 6, 8); // CDC3 CMD
-        HAL_PCD_SetTxFiFo(&pcd_hs_handle, 7, 128); // CDC3 DATA
-        #endif
+        // Set FIFO buffer sizes
+        fifo_size += USBD_FS_NUM_FIFO; // skip over FS FIFO size values
+        HAL_PCD_SetRxFiFo(&pcd_hs_handle, fifo_size[0] * 4);
+        for (size_t i = 0; i < USBD_HS_NUM_TX_FIFO; ++i) {
+            HAL_PCD_SetTxFiFo(&pcd_hs_handle, i, fifo_size[1 + i] * 4);
+        }
     }
     #endif  // MICROPY_HW_USB_HS
 
diff --git a/ports/stm32/usbd_conf.h b/ports/stm32/usbd_conf.h
index 639b54d9f39c0d568b0366dc5664754a811c7267..83629bfc4f76695de1c716869fdac3f2893422b4 100644
--- a/ports/stm32/usbd_conf.h
+++ b/ports/stm32/usbd_conf.h
@@ -49,6 +49,16 @@
 #endif
 #define USBD_DEBUG_LEVEL                      0
 
+// For MCUs with a device-only USB peripheral
+#define USBD_PMA_RESERVE                      (64)
+#define USBD_PMA_NUM_FIFO                     (8)
+
+// For MCUs with multiple OTG USB peripherals
+#define USBD_FS_NUM_TX_FIFO                   (6)
+#define USBD_FS_NUM_FIFO                      (1 + USBD_FS_NUM_TX_FIFO)
+#define USBD_HS_NUM_TX_FIFO                   (9)
+#define USBD_HS_NUM_FIFO                      (1 + USBD_HS_NUM_TX_FIFO)
+
 #endif // MICROPY_INCLUDED_STM32_USBD_CONF_H
 
 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm32/usbdev/core/inc/usbd_core.h b/ports/stm32/usbdev/core/inc/usbd_core.h
index 5494be3a22ec25b25f49b45558f49a9b9da4a9b6..d3925fc6b714829803d59fc94b41fb1ec4606a20 100644
--- a/ports/stm32/usbdev/core/inc/usbd_core.h
+++ b/ports/stm32/usbdev/core/inc/usbd_core.h
@@ -111,7 +111,7 @@ USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef  *pdev);
 USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef  *pdev);
 
 /* USBD Low Level Driver */
-USBD_StatusTypeDef  USBD_LL_Init (USBD_HandleTypeDef *pdev, int high_speed);
+USBD_StatusTypeDef  USBD_LL_Init (USBD_HandleTypeDef *pdev, int high_speed, const uint8_t *fifo_size);
 USBD_StatusTypeDef  USBD_LL_DeInit (USBD_HandleTypeDef *pdev);
 USBD_StatusTypeDef  USBD_LL_Start(USBD_HandleTypeDef *pdev);
 USBD_StatusTypeDef  USBD_LL_Stop (USBD_HandleTypeDef *pdev);
diff --git a/ports/stm32/usbdev/core/src/usbd_core.c b/ports/stm32/usbdev/core/src/usbd_core.c
index f235b24ee6c3ec91d82972f95959f4779961d29f..4c69a77eb60c64479bbec22dcbecb2bb4ee2a7c1 100644
--- a/ports/stm32/usbdev/core/src/usbd_core.c
+++ b/ports/stm32/usbdev/core/src/usbd_core.c
@@ -85,6 +85,7 @@
 * @{
 */
 
+#if 0
 /**
 * @brief  USBD_Init
 *         Initailizes the device stack and load the class driver
@@ -122,6 +123,7 @@ USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *
 
   return USBD_OK;
 }
+#endif
 
 /**
 * @brief  USBD_DeInit