summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOnlyou_tzZ <[email protected]>2026-06-26 14:35:26 +0800
committerGitHub <[email protected]>2026-06-26 14:35:26 +0800
commitb3e822b049429f2b7f2e26bbd5cc491a6d65ea63 (patch)
tree4a455985ec494332b21c8299a040da52fa0f2c59
parent0ae587a64c533530dc6a06a3c6863eba98fd88c1 (diff)
usb_hc.h中bug修改和usb_glue_nation.c中添加N32H49X和N32H7XX系列MCU的USBHS支持 (#422)
* 1、usb_hc.h中struct usbh_urb结构体添加defined(__CC_ARM)判断,MDK AC5编译器不支持struct usbh_iso_frame_packet iso_packet[0]只支持struct usbh_iso_frame_packet *iso_packet 2、usb_glue_nation.c中添加N32H49X和N32H7XX系列MCU的USBHS支持 * 回退对usb_hc.h的修改
-rw-r--r--port/dwc2/usb_glue_nation.c920
1 files changed, 862 insertions, 58 deletions
diff --git a/port/dwc2/usb_glue_nation.c b/port/dwc2/usb_glue_nation.c
index 3e96b22f..ecb5969a 100644
--- a/port/dwc2/usb_glue_nation.c
+++ b/port/dwc2/usb_glue_nation.c
@@ -17,8 +17,8 @@ __WEAK void USBH_IRQHandler(uint8_t busid)
#if defined(N32H473) || defined(N32H474) || defined(N32H475) || defined(N32H482) || defined(N32H487)
#include "n32h47x_48x_rcc.h"
#include "n32h47x_48x_gpio.h"
-#include "n32h47x_48x_exti.h"
#include "misc.h"
+#include "usb_dwc2_param.h"
typedef void (*usb_dwc2_irq)(uint8_t busid);
@@ -29,95 +29,343 @@ static void usbhs_common_init(void)
{
RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
- /* PLL= 240MHz */
#if (HSE_VALUE == 8000000)
- /* Select PLL clock as USBHS clock source , clock 15 divisions = 16M */
+ /* System PLL = 240 MHz; divide by 15 to produce 16 MHz USB PHY reference. */
RCC_ConfigUSBPLLPresClk(RCC_USBPLLCLK_SRC_PLL, RCC_USBPLLCLK_DIV15);
-
- /* Select the corresponding bandwidth and frequency*/
RCC_ConfigUSBHSBandwidth(RCC_USBHS_BW_16M);
-
- /* Select USBHS clock source frequency */
RCC_ConfigUSBHSFrequency(RCC_USBHS_FREQ_16_OR_32M);
-
- /* Select PLL as USBHS clock */
RCC_ConfigUSBHSClk(RCC_USBHS_CLKSRC_PLLPRES);
-#else //HSE 16M
+#else /* HSE 16 MHz — feed directly to USBHS */
RCC_ConfigUSBHSBandwidth(RCC_USBHS_BW_16M);
RCC_ConfigUSBHSFrequency(RCC_USBHS_FREQ_16_OR_32M);
RCC_ConfigUSBHSClk(RCC_USBHS_CLKSRC_HSE);
#endif
- /* Reset the USBHS phy clock*/
RCC_EnableAHBPeriphReset(RCC_AHBPRST_USBHSPHYRST);
- /* Enables the USBHS peripheral clock*/
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_USBHS, ENABLE);
- NVIC_InitType NVIC_InitStructure;
- // EXTI_InitType EXTI_InitStructure;
+ /* TX analog tuning for 8-bit UTMI PHY (N32H47x_48x USBHSCTRL2 layout). */
+ RCC->USBHSCTRL2 = (RCC->USBHSCTRL2 & (~(0xF << 4))) | (0x5 << 4); /* TX vref TUNE [7:4] */
+ RCC->USBHSCTRL2 = (RCC->USBHSCTRL2 & (~(0x3 << 12))) | (0x3 << 12); /* TX Rise TUNE [13:12] */
+ RCC->USBHSCTRL2 = (RCC->USBHSCTRL2 & (~(0x3 << 14))) | (0x3 << 14); /* TX Res TUNE [15:14] */
+ RCC->USBHSCTRL2 = (RCC->USBHSCTRL2 & (~(0x3 << 16))) | (0x3 << 16); /* TX preempamp TUNE [17:16] */
- // NVIC_InitStructure.NVIC_IRQChannel = USB_HS_WKUP_IRQn;
- // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- // NVIC_Init(&NVIC_InitStructure);
+ NVIC_InitType NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USB_HS_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
+}
+
+/* Override in the board layer to configure USB DM/DP alternate-function pins.
+ * In host mode, also drive any VBUS power-switch GPIO here (e.g. board/ports/usb_gpio.c). */
+__weak void n32h47x_48x_usbhs_gpio_init(void) { }
+
+void usb_dc_low_level_init(uint8_t busid)
+{
+ g_usb_dwc2_irq = USBD_IRQHandler;
+ g_usb_dwc2_busid = busid;
- /* Configure the EXTI line 23 connected internally to the USBHS IP */
- // EXTI_ClrITPendBit(EXTI_LINE23);
- // EXTI_InitStructure.EXTI_Line = EXTI_LINE23;
- // EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
- // EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
- // EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- // EXTI_InitPeripheral(&EXTI_InitStructure);
+ n32h47x_48x_usbhs_gpio_init();
+ usbhs_common_init();
+
+ RCC->USBHSCTRL2 |= (uint32_t)0x01 << 19;
+ RCC->USBHSCTRL1 |= (uint32_t)0x01 << 31;
}
-static void usbhs_gpio_init(void)
+void usb_dc_low_level_deinit(uint8_t busid)
{
- GPIO_InitType GPIO_InitStructure;
+ NVIC_InitType NVIC_InitStructure;
- RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB | RCC_AHB_PERIPHEN_GPIOE, ENABLE);
- RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
- GPIO_ConfigPinRemap(0, 0, GPIO_RMP_SWJ_SWD);
+ NVIC_InitStructure.NVIC_IRQChannel = USB_HS_IRQn;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
+ NVIC_Init(&NVIC_InitStructure);
+
+ RCC_EnableAHBPeriphReset(RCC_AHBPRST_USBHSPHYRST);
+ /* Disable the USBHS peripheral clock. */
+ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_USBHS, DISABLE);
+}
+
+void usb_hc_low_level_init(struct usbh_bus *bus)
+{
+ g_usb_dwc2_irq = USBH_IRQHandler;
+ g_usb_dwc2_busid = 0;
+
+ n32h47x_48x_usbhs_gpio_init();
+ usbhs_common_init();
+
+ RCC->USBHSCTRL2 &= ~(uint32_t)0x01 << 19;
+ RCC->USBHSCTRL1 |= (uint32_t)0x01 << 31;
+}
+
+void usb_hc_low_level_deinit(struct usbh_bus *bus)
+{
+ NVIC_InitType NVIC_InitStructure;
+
+ NVIC_InitStructure.NVIC_IRQChannel = USB_HS_IRQn;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
+ NVIC_Init(&NVIC_InitStructure);
+
+ RCC_EnableAHBPeriphReset(RCC_AHBPRST_USBHSPHYRST);
+ /* Disable the USBHS peripheral clock. */
+ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_USBHS, DISABLE);
+}
+
+uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
+{
+ return 0;
+}
+
+uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
+{
+ return 0;
+}
+
+void USB_HS_IRQHandler(void)
+{
+ g_usb_dwc2_irq(g_usb_dwc2_busid);
+}
+
+void usbd_dwc2_delay_ms(uint8_t ms)
+{
+ RCC_ClocksType RCC_clocks = { 0 };
+
+ RCC_GetClocksFreqValue(&RCC_clocks);
+
+ uint32_t count = RCC_clocks.SysclkFreq / 1000 * ms;
+ while (count--) {
+ __asm volatile("nop");
+ }
+}
+
+uint32_t usbd_dwc2_get_system_clock(void)
+{
+ RCC_ClocksType RCC_clocks = { 0 };
+
+ RCC_GetClocksFreqValue(&RCC_clocks);
+ return RCC_clocks.SysclkFreq;
+}
+
+/*
+ * N32H47x_48x USBHS has 4 KB (1024 x 32-bit words) of dedicated FIFO RAM;
+ * GRXFSIZ.RXFDEP max = 1024.
+ *
+ * Internal HS UTMI+ PHY, 8-bit data bus (GCFG.PHYIF = 0).
+ * PHY is configured via RCC USBHSCTRL registers, not DWC2 GCCFG,
+ * so device_gccfg / host_gccfg are both zero.
+ *
+ * Device FIFO layout (1024 words, 4096 bytes):
+ * RX shared 512 words (2048 bytes)
+ * EP0 IN TX 64 words ( 256 bytes) — control
+ * EP1 IN TX 256 words (1024 bytes) — bulk / isochronous HS
+ * EP2 IN TX 64 words ( 256 bytes)
+ * EP3 IN TX 64 words ( 256 bytes)
+ * EP4 IN TX 64 words ( 256 bytes)
+ * Total 1024 words (4096 bytes)
+ *
+ * Host FIFO layout (1024 words, 4096 bytes):
+ * RX 512 words (2048 bytes)
+ * Non-periodic TX 256 words (1024 bytes)
+ * Periodic TX 256 words (1024 bytes)
+ * Total 1024 words (4096 bytes)
+ *
+ */
+static const struct dwc2_user_params param_n32h47x_48x = {
+ /* Built-in HS UTMI+ PHY; sets GUSBCFG.ULPI_UTMI_SEL = 0. */
+ .phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
+
+ /* 8-bit UTMI data bus (USBHS_GCFG.PHYIF = 0).
+ * USB_CoreInit() in usbhs_core.c explicitly clears PHYIF.
+ * CherryUSB only sets GUSBCFG.PHYIF16 when this field == 16. */
+ .phy_utmi_width = 8,
+
+ /* Slave mode vs DMA mode; controlled by CONFIG_USB_DWC2_DMA_ENABLE.
+ * DMA mode frees the CPU from FIFO polling but requires aligned buffers. */
+#ifdef CONFIG_USB_DWC2_DMA_ENABLE
+ .device_dma_enable = true,
+#else
+ .device_dma_enable = false,
+#endif
+
+ /* Scatter-Gather descriptor DMA: not supported by this hardware
+ * (GHWCFG4.DESC_DMA_ENABLED = 0). */
+ .device_dma_desc_enable = false,
+
+ /* Shared RX FIFO depth for device mode, in 32-bit words.
+ * All OUT endpoints and SETUP packets share this single FIFO.
+ * Minimum formula:
+ * RX >= (5*ctrl_eps + 8) + (max_pkt/4 + 1) + (2*OUT_eps) + 1
+ * With HS MPS=512 and 7 OUT eps: (5+8) + (129) + (14) + 1 = 157 words min.
+ * 512 words (2048 bytes) matches Nations CDC demo (RX_FIFO_HS_SIZE=512).
+ * Hardware limit: GRXFSIZ.RXFDEP max = 1024.
+ * To redistribute, define CONFIG_USB_DWC2_CUSTOM_FIFO; keep total <= 1024. */
+ .device_rx_fifo_size = 512,
+
+ /* Per-IN-endpoint dedicated TX FIFO depths, in 32-bit words.
+ * Index matches endpoint number: [0]=EP0, [1]=EP1, ..., [8]=EP8.
+ * N32H47x_48x has EP0 (control) + EP1..EP8 (IN); [9]..[15] unused.
+ *
+ * Current allocation (512 words TX + 512 words RX = 1024 words total):
+ * [0] EP0: 64 words (256 bytes) -- control, buffers 4x 64-byte HS packets.
+ * Matches Nations TX0_FIFO_HS_SIZE = 64.
+ * [1] EP1: 256 words (1024 bytes) -- primary HS bulk/isochronous endpoint.
+ * Double-buffers one HS bulk packet (512 bytes max).
+ * Matches Nations TX1_FIFO_HS_SIZE = 256.
+ * [2] EP2: 64 words (256 bytes) -- interrupt or secondary bulk.
+ * [3] EP3: 64 words (256 bytes) -- same.
+ * [4] EP4: 64 words (256 bytes) -- same.
+ * [5]..[8]: 0 -- EP5..EP8 unallocated by default.
+ * Use CONFIG_USB_DWC2_CUSTOM_FIFO to add more IN endpoints;
+ * sum of all TX entries must stay <= (1024 - device_rx_fifo_size).
+ * Per-FIFO hardware limit: INEPTXFDEP max = 768 words. */
+ .device_tx_fifo_size = {
+ [0] = 64, /* EP0: 256 bytes, control */
+ [1] = 256, /* EP1: 1024 bytes, HS bulk/iso primary */
+ [2] = 64, /* EP2: 256 bytes */
+ [3] = 64, /* EP3: 256 bytes */
+ [4] = 64, /* EP4: 256 bytes */
+ [5] = 0, /* EP5..EP8: unallocated, use CUSTOM_FIFO to enable */
+ [6] = 0,
+ [7] = 0,
+ [8] = 0,
+ [9] = 0, /* [9]..[15]: invalid for N32H47x_48x (only EP0..EP8 exist) */
+ [10] = 0,
+ [11] = 0,
+ [12] = 0,
+ [13] = 0,
+ [14] = 0,
+ [15] = 0,
+ },
+
+ /* Host descriptor DMA: not supported, same reason as device_dma_desc_enable. */
+ .host_dma_desc_enable = false,
+
+ /* Host mode shared RX FIFO depth, in 32-bit words.
+ * All host channel IN data shares this single FIFO.
+ * Minimum formula:
+ * Host RX >= (max_pkt/4 + 1) + 1
+ * With HS MPS=1024: (256 + 1) + 1 = 258 words min.
+ * 512 words matches Nations Host demo (RX_FIFO_HS_SIZE=512). */
+ .host_rx_fifo_size = 512,
+
+ /* Host non-periodic TX FIFO depth (control + bulk OUT), in 32-bit words.
+ * Recommended >= max_nonperiodic_pkt/4; double for pipelining.
+ * HS MPS=512: 512/4 = 128 words min; 256 words provides double-buffering.
+ * Matches Nations Host demo (TXH_NP_HS_FIFOSIZE=256).
+ * Hardware limit: NPTXFDEP max = 1024. */
+ .host_nperio_tx_fifo_size = 256,
+
+ /* Host periodic TX FIFO depth (interrupt + isochronous OUT), in 32-bit words.
+ * Recommended >= max_periodic_pkt/4; double for isochronous.
+ * HS iso MPS=1024: 1024/4 = 256 words min.
+ * Matches Nations Host demo (TXH_P_HS_FIFOSIZE=256).
+ * Host FIFO total: 512 + 256 + 256 = 1024 words, fills the 4 KB RAM exactly. */
+ .host_perio_tx_fifo_size = 256,
+
+ /* Extra bits OR'd into GCCFG for device mode.
+ * Some DWC2 platforms use GCCFG to enable VBUS sensing via an external PHY.
+ * N32H47x_48x PHY is controlled through RCC USBHSCTRL1/2, not GCCFG,
+ * so no additional bits are needed. */
+ .device_gccfg = 0,
+
+ /* Same as device_gccfg but applied in host mode. */
+ .host_gccfg = 0,
+
+ /* Set to true to bypass VBUS hardware sensing on boards that do not route
+ * USB VBUS to a GPIO sense pin. false = rely on hardware VBUS detection. */
+ .b_session_valid_override = false,
+
+ /* Total FIFO RAM depth, in 32-bit words.
+ * CherryUSB asserts at init: device_rx + sum(device_tx) <= total_fifo_size.
+ * N32H47x_48x has 4 KB dedicated FIFO RAM = 1024 x 32-bit words;
+ * GRXFSIZ.RXFDEP max = 1024. */
+ .total_fifo_size = 1024,
+};
+
+#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
+void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
+{
+ memcpy(params, &param_n32h47x_48x, sizeof(struct dwc2_user_params));
+#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
+ struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
+
+ dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
+
+ params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
+ for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++) {
+ params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
+ }
+#endif /* CONFIG_USB_DWC2_CUSTOM_FIFO */
+}
+#endif /* CONFIG_USB_DWC2_CUSTOM_PARAM */
+
+#elif defined(N32H49X)
+
+/*
+ * N32H49x series: single USBHS controller, internal HS UTMI+ PHY (8-bit bus).
+ *
+ * FIFO RAM: 4 KB (1024 x 32-bit words).
+ * USBHS base address: 0x40040000 (AHBPERIPH_BASE + 0x20000).
+ * IRQ: USB_HS_IRQn (62), USB_HS_WKUP_IRQn (84).
+ */
+
+#include "n32h49x_rcc.h"
+#include "n32h49x_gpio.h"
+#include "misc.h"
+#include "usb_dwc2_param.h"
+
+typedef void (*usb_dwc2_irq)(uint8_t busid);
- GPIO_InitStruct(&GPIO_InitStructure);
-#ifdef USBHS_HOST
- GPIO_InitStructure.Pin = GPIO_PIN_1;
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitPeripheral(GPIOE, &GPIO_InitStructure);
- GPIO_ResetBits(GPIOE, GPIO_PIN_1);
+static usb_dwc2_irq g_usb_dwc2_irq;
+static volatile uint8_t g_usb_dwc2_busid = 0;
- GPIO_InitStructure.Pin = GPIO_PIN_3;
- GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
- GPIO_ResetBits(GPIOB, GPIO_PIN_3);
+static void usbhs_common_init(void)
+{
+ RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB, ENABLE);
+#if (HSE_VALUE == 8000000)
+ /* System PLL = 240 MHz; divide by 15 to produce 16 MHz USB PHY reference. */
+ RCC_ConfigUSBPLLPresClk(RCC_USBPLLCLK_SRC_PLL, RCC_USBPLLCLK_DIV15);
+ RCC_ConfigUSBHSBandwidth(RCC_USBHS_BW_16M);
+ RCC_ConfigUSBHSFrequency(RCC_USBHS_FREQ_16_OR_32M);
+ RCC_ConfigUSBHSClk(RCC_USBHS_CLKSRC_PLLPRES);
+#else /* HSE 16 MHz — feed directly to USBHS */
+ RCC_ConfigUSBHSBandwidth(RCC_USBHS_BW_16M);
+ RCC_ConfigUSBHSFrequency(RCC_USBHS_FREQ_16_OR_32M);
+ RCC_ConfigUSBHSClk(RCC_USBHS_CLKSRC_HSE);
#endif
- // VBUS
- // GPIO_InitStructure.Pin = GPIO_PIN_13;
- // GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
- // GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
+ RCC_EnableAHBPeriphReset(RCC_AHBPRST_USBHSPHYRST);
+ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_USBHS, ENABLE);
- // // SOF
- // GPIO_InitStructure.Pin = GPIO_PIN_4;
- // GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
- // GPIO_InitStructure.GPIO_Alternate = 8; // SOF
- // GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
+ /* TX analog tuning for 8-bit UTMI PHY (N32H49x USBHSCTRL layout). */
+ RCC->USBHSCTRL2 = (RCC->USBHSCTRL2 & (~(0xF << 4))) | (0xB << 4); /* HDCVTRIM[7:4] */
+ RCC->USBHSCTRL1 = (RCC->USBHSCTRL1 & (~(0x7 << 12))) | (0x5 << 12); /* USBHSCTRL1[14:12] */
+ RCC->USBHSCTRL2 = (RCC->USBHSCTRL2 & (~(0x3 << 12))) | (0x0 << 14); /* RFTRIM[13:12] = 0 (clear) */
+ RCC->USBHSCTRL2 = (RCC->USBHSCTRL2 & (~(0x3 << 16))) | (0x1 << 16); /* USBHSCTRL2[17:16] */
- // // ID
- // GPIO_InitStructure.Pin = GPIO_PIN_12;
- // GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
- // GPIO_InitStructure.GPIO_Alternate = 14; // ID
- // GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
+ NVIC_InitType NVIC_InitStructure;
+
+ NVIC_InitStructure.NVIC_IRQChannel = USB_HS_IRQn;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init(&NVIC_InitStructure);
}
+/* Override in the board layer to configure USB DM/DP alternate-function pins.
+ * In host mode, also drive any VBUS power-switch GPIO here (e.g. board/ports/usb_gpio.c). */
+__weak void n32h49x_usbhs_gpio_init(void) { }
+
void usb_dc_low_level_init(uint8_t busid)
{
g_usb_dwc2_irq = USBD_IRQHandler;
g_usb_dwc2_busid = busid;
+ n32h49x_usbhs_gpio_init();
usbhs_common_init();
RCC->USBHSCTRL2 |= (uint32_t)0x01 << 19;
@@ -135,7 +383,7 @@ void usb_dc_low_level_deinit(uint8_t busid)
NVIC_Init(&NVIC_InitStructure);
RCC_EnableAHBPeriphReset(RCC_AHBPRST_USBHSPHYRST);
- /* Enables the USBHS peripheral clock*/
+ /* Disable the USBHS peripheral clock. */
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_USBHS, DISABLE);
}
@@ -144,6 +392,7 @@ void usb_hc_low_level_init(struct usbh_bus *bus)
g_usb_dwc2_irq = USBH_IRQHandler;
g_usb_dwc2_busid = 0;
+ n32h49x_usbhs_gpio_init();
usbhs_common_init();
RCC->USBHSCTRL2 &= ~(uint32_t)0x01 << 19;
@@ -161,7 +410,7 @@ void usb_hc_low_level_deinit(struct usbh_bus *bus)
NVIC_Init(&NVIC_InitStructure);
RCC_EnableAHBPeriphReset(RCC_AHBPRST_USBHSPHYRST);
- /* Enables the USBHS peripheral clock*/
+ /* Disable the USBHS peripheral clock. */
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_USBHS, DISABLE);
}
@@ -180,14 +429,569 @@ void USB_HS_IRQHandler(void)
g_usb_dwc2_irq(g_usb_dwc2_busid);
}
-extern uint32_t SystemCoreClock;
+void usbd_dwc2_delay_ms(uint8_t ms)
+{
+ RCC_ClocksType RCC_clocks = { 0 };
+
+ RCC_GetClocksFreqValue(&RCC_clocks);
+ uint32_t count = RCC_clocks.SysclkFreq / 1000U * ms;
+ while (count--) {
+ __asm volatile("nop");
+ }
+}
+
+uint32_t usbd_dwc2_get_system_clock(void)
+{
+ RCC_ClocksType RCC_clocks = { 0 };
+
+ RCC_GetClocksFreqValue(&RCC_clocks);
+ return RCC_clocks.SysclkFreq;
+}
+
+/*
+ * N32H49x USBHS has 4 KB (1024 x 32-bit words) of dedicated FIFO RAM.
+ *
+ * Internal HS UTMI+ PHY, 8-bit data bus (GCFG.PHYIF = 0).
+ * PHY is configured via RCC USBHSCTRL1/2, not DWC2 GCCFG,
+ * so device_gccfg / host_gccfg are both zero.
+ *
+ * FIFO layout matches N32H47x_48x CDC demo (same FIFO sizes confirmed):
+ * RX shared 512 words (2048 bytes)
+ * EP0 IN TX 64 words ( 256 bytes)
+ * EP1 IN TX 256 words (1024 bytes)
+ * EP2 IN TX 64 words ( 256 bytes)
+ * EP3 IN TX 64 words ( 256 bytes)
+ * EP4 IN TX 64 words ( 256 bytes)
+ * Total 1024 words (4096 bytes)
+ *
+ * Host FIFO layout:
+ * RX 512 words (2048 bytes)
+ * Non-periodic TX 256 words (1024 bytes)
+ * Periodic TX 256 words (1024 bytes)
+ * Total 1024 words (4096 bytes)
+ */
+static const struct dwc2_user_params param_n32h49x = {
+ .phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
+
+ /* 8-bit UTMI data bus (GCFG.PHYIF = 0).
+ * USB_CoreInit() in usbhs_core.c explicitly clears PHYIF. */
+ .phy_utmi_width = 8,
+
+#ifdef CONFIG_USB_DWC2_DMA_ENABLE
+ .device_dma_enable = true,
+#else
+ .device_dma_enable = false,
+#endif
+
+ /* Scatter-Gather descriptor DMA: not supported (GHWCFG4.DESC_DMA_ENABLED = 0). */
+ .device_dma_desc_enable = false,
+
+ /* Shared RX FIFO: 512 words (2048 bytes). */
+ .device_rx_fifo_size = 512,
+
+ .device_tx_fifo_size = {
+ [0] = 64, /* EP0: 256 bytes, control */
+ [1] = 256, /* EP1: 1024 bytes, HS bulk/iso primary */
+ [2] = 64, /* EP2: 256 bytes */
+ [3] = 64, /* EP3: 256 bytes */
+ [4] = 64, /* EP4: 256 bytes */
+ [5] = 0, /* EP5..EP8: unallocated, use CUSTOM_FIFO to enable */
+ [6] = 0,
+ [7] = 0,
+ [8] = 0,
+ [9] = 0, /* [9]..[15]: invalid for N32H49x (only EP0..EP8 exist) */
+ [10] = 0,
+ [11] = 0,
+ [12] = 0,
+ [13] = 0,
+ [14] = 0,
+ [15] = 0,
+ },
+
+ /* Host descriptor DMA: not supported, same reason as device_dma_desc_enable. */
+ .host_dma_desc_enable = false,
+
+ /* Host RX: 512 words (2048 bytes). */
+ .host_rx_fifo_size = 512,
+
+ /* Host non-periodic TX (control + bulk OUT): 256 words (1024 bytes). */
+ .host_nperio_tx_fifo_size = 256,
+
+ /* Host periodic TX (interrupt + iso OUT): 256 words.
+ * Host FIFO total: 512 + 256 + 256 = 1024 words, fills 4 KB RAM exactly. */
+ .host_perio_tx_fifo_size = 256,
+
+ /* N32H49x PHY is controlled through RCC USBHSCTRL1/2, not DWC2 GCCFG. */
+ .device_gccfg = 0,
+ .host_gccfg = 0,
+
+ /* Set to true to bypass VBUS hardware sensing on boards that do not route
+ * USB VBUS to a GPIO sense pin. false = rely on hardware VBUS detection. */
+ .b_session_valid_override = false,
+
+ /* 4 KB dedicated FIFO RAM = 1024 x 32-bit words. */
+ .total_fifo_size = 1024,
+};
+
+#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
+void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
+{
+ memcpy(params, &param_n32h49x, sizeof(struct dwc2_user_params));
+#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
+ struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
+
+ dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
+
+ params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
+ for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++) {
+ params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
+ }
+#endif /* CONFIG_USB_DWC2_CUSTOM_FIFO */
+}
+#endif /* CONFIG_USB_DWC2_CUSTOM_PARAM */
+
+#elif defined(N32H73x) || defined(N32H76x) || defined(N32H73x_76x) || defined(N32H78x)
+
+/*
+ * N32H7xx series: dual USBHS controllers (USBHS1 + USBHS2).
+ *
+ * Each controller is a DWC2 IP core with an internal HS UTMI+ PHY
+ * accessed through a Wrapper register block (WRPCFG / WRPCTRL).
+ * The PHY uses a 16-bit UTMI data bus (GCFG.PHYIF = 1).
+ *
+ * Controller base addresses:
+ * USBHS1 core: 0x40100000 wrapper: 0x40140000
+ * USBHS2 core: 0x40060000 wrapper: 0x400A0000
+ *
+ * busid convention used by this glue layer:
+ * busid 0 -> USBHS1 (PA11=DM, PA12=DP, USB1_HS_IRQn, EXTI_LINE62)
+ * busid 1 -> USBHS2 (PB14=DM, PB15=DP, USB2_HS_IRQn, EXTI_LINE63)
+ *
+ * For usb_hc_low_level_init the controller is identified by bus->hcd.reg_base
+ * rather than busid to avoid aliasing with the device busid namespace in
+ * dual-USB (one host + one device) configurations.
+ *
+ * Both controllers share identical DWC2 hardware parameters and
+ * 4 KB (1024-word) dedicated FIFO RAM.
+ */
+
+#include "n32h7xx_rcc.h"
+#include "n32h7xx_gpio.h"
+#include "n32h7xx_pwr.h"
+#include "misc.h"
+#include "n32h7xx.h"
+#include "usb_dwc2_param.h"
+
+#define N32H7XX_USBHS1_BASE 0x40100000U
+#define N32H7XX_USBHS2_BASE 0x40060000U
+#define N32H7XX_USBHS1_WRAP 0x40140000U
+#define N32H7XX_USBHS2_WRAP 0x400A0000U
+
+typedef void (*usb_dwc2_irq_fn)(uint8_t busid);
+
+/* Per-controller IRQ dispatch: index 0 = USBHS1, index 1 = USBHS2. */
+static struct {
+ usb_dwc2_irq_fn fn;
+ uint8_t busid;
+} g_n32h7xx_irq[2];
void usbd_dwc2_delay_ms(uint8_t ms)
{
- uint32_t count = SystemCoreClock / 1000 * ms;
+ RCC_ClocksTypeDef RCC_Clocks = { 0 };
+
+ RCC_GetClocksFreqValue(&RCC_Clocks);
+ uint32_t count = RCC_Clocks.SysClkFreq / 1000U * ms;
while (count--) {
__asm volatile("nop");
}
}
+uint32_t usbd_dwc2_get_system_clock(void)
+{
+ RCC_ClocksTypeDef RCC_Clocks = { 0 };
+
+ RCC_GetClocksFreqValue(&RCC_Clocks);
+ return RCC_Clocks.SysClkFreq;
+}
+
+/*
+ * Wrapper register init: configure PHY PLL clock source, enable PLL,
+ * set IDSIG (device/host role), enable ID-pin detection, then pulse
+ * the PHY power-on reset.
+ *
+ * IDSIG MUST be set here, before USB_CoreInit() runs.
+ * USB_CoreInitHost() does NOT clear IDSIG, so if left at 1 the host
+ * controller cannot operate. When two controllers run simultaneously
+ * (one host + one device) failing to clear IDSIG on the host is the
+ * root cause of host malfunction.
+ *
+ * is_device: true -> IDSIG = 1 (device role)
+ * false -> IDSIG = 0 (host role)
+ * is_usbhs1: selects the RCC PHY reset register (AHB2 vs AHB1).
+ */
+static void n32h7xx_wrapper_init(uint32_t wrap_base, bool is_device, bool is_usbhs1)
+{
+ USB_Wrapper_Registers *wrap = (USB_Wrapper_Registers *)wrap_base;
+ uint32_t wrpcfg;
+ uint32_t wrpctrl;
+
+ wrpcfg = wrap->WRPCFG;
+ wrpcfg &= ~USBHS_WRPCFG_PHYCLKSEL;
+
+#if (HSE_VALUE == 10000000U)
+ wrpcfg |= USBHS_WRPCFG_PHYCLKSEL_10M;
+#elif (HSE_VALUE == 12000000U)
+ wrpcfg |= USBHS_WRPCFG_PHYCLKSEL_12M;
+#elif (HSE_VALUE == 19200000U)
+ wrpcfg |= USBHS_WRPCFG_PHYCLKSEL_19_2M;
+#elif (HSE_VALUE == 24000000U)
+ wrpcfg |= USBHS_WRPCFG_PHYCLKSEL_24M;
+#elif (HSE_VALUE == 25000000U)
+ wrpcfg |= USBHS_WRPCFG_PHYCLKSEL_25M;
+#elif (HSE_VALUE == 27000000U)
+ wrpcfg |= USBHS_WRPCFG_PHYCLKSEL_27M;
+#elif (HSE_VALUE == 30000000U)
+ wrpcfg |= USBHS_WRPCFG_PHYCLKSEL_30M;
+#elif (HSE_VALUE == 40000000U)
+ wrpcfg |= USBHS_WRPCFG_PHYCLKSEL_40M;
+#else
+#error "Unsupported HSE_VALUE for N32H7xx USBHS PHY. Supported: 10/12/19.2/24/25/27/30/40 MHz."
+#endif
+
+ wrpcfg |= USBHS_WRPCFG_PLLEN;
+
+ if (is_device) {
+ wrpcfg |= USBHS_WRPCFG_IDSIG;
+ } else {
+ wrpcfg &= ~USBHS_WRPCFG_IDSIG;
+ }
+
+ wrap->WRPCFG = wrpcfg;
+
+ wrpctrl = wrap->WRPCTRL;
+ wrpctrl |= USBHS_WRPCTRL_PINDETEN;
+ wrap->WRPCTRL = wrpctrl;
+
+ if (is_usbhs1) {
+ RCC_EnableAHB2PeriphReset1(RCC_AHB2_PERIPHRST_USB1POR);
+ } else {
+ RCC_EnableAHB1PeriphReset1(RCC_AHB1_PERIPHRST_USB2POR);
+ }
+
+ usbd_dwc2_delay_ms(1);
+}
+
+/* -----------------------------------------------------------------------
+ * GPIO init: weak stubs — override in your board layer.
+ * Implement n32h7xx_usbhs1_gpio_init / n32h7xx_usbhs2_gpio_init to configure
+ * the DM/DP pins (and optionally SOF/ID) for your specific board.
+ * In host mode, also drive any VBUS power-switch GPIO here.
+ * ----------------------------------------------------------------------- */
+__weak void n32h7xx_usbhs1_gpio_init(void) { }
+__weak void n32h7xx_usbhs2_gpio_init(void) { }
+
+/* -----------------------------------------------------------------------
+ * NVIC + init
+ * ----------------------------------------------------------------------- */
+static void n32h7xx_usbhs1_irq_enable(void)
+{
+ NVIC_InitType nvic;
+
+ nvic.NVIC_IRQChannel = USB1_HS_IRQn;
+ nvic.NVIC_IRQChannelPreemptionPriority = 1;
+ nvic.NVIC_IRQChannelSubPriority = 3;
+ nvic.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init(&nvic);
+}
+
+static void n32h7xx_usbhs2_irq_enable(void)
+{
+ NVIC_InitType nvic;
+
+ nvic.NVIC_IRQChannel = USB2_HS_IRQn;
+ nvic.NVIC_IRQChannelPreemptionPriority = 1;
+ nvic.NVIC_IRQChannelSubPriority = 3;
+ nvic.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init(&nvic);
+}
+
+/* -----------------------------------------------------------------------
+ * Per-controller hardware bringup
+ * ----------------------------------------------------------------------- */
+static void n32h7xx_usbhs1_hw_init(uint8_t busid, usb_dwc2_irq_fn irq_fn)
+{
+ /* AFIO alternate-function remapping clock */
+ RCC_EnableAHB5PeriphClk2(RCC_AHB5_PERIPHEN_M7_AFIO, ENABLE);
+
+ n32h7xx_usbhs1_gpio_init();
+
+ /* Route HSE directly to the USB PHY reference clock input.
+ * HSE must already be running (done by system clock init).
+ * PHYCLKSEL in WRPCFG must match the resulting frequency. */
+ RCC_ConfigUSBRefClk(RCC_USBREFCLK_HSE_DIV1);
+
+ /* PWR peripheral clock is required before calling PWR_MoudlePowerEnable. */
+ RCC_EnableAHB5PeriphClk2(RCC_AHB5_PERIPHEN_PWR, ENABLE);
+
+ /* Enable USBHS1 peripheral clock (AHB2). */
+ RCC_EnableAHB2PeriphClk1(RCC_AHB2_PERIPHEN_M7_USB1, ENABLE);
+
+ /* Power up the USBHS1 hardware module. Without this the USB core
+ * registers are inaccessible and the PHY will not start. */
+ PWR_MoudlePowerEnable(HSC1_USB1_PWRCTRL, ENABLE);
+
+ g_n32h7xx_irq[0].fn = irq_fn;
+ g_n32h7xx_irq[0].busid = busid;
+ n32h7xx_usbhs1_irq_enable();
+}
+
+static void n32h7xx_usbhs2_hw_init(uint8_t busid, usb_dwc2_irq_fn irq_fn)
+{
+ RCC_EnableAHB5PeriphClk2(RCC_AHB5_PERIPHEN_M7_AFIO, ENABLE);
+
+ n32h7xx_usbhs2_gpio_init();
+
+ RCC_ConfigUSBRefClk(RCC_USBREFCLK_HSE_DIV1);
+
+ RCC_EnableAHB5PeriphClk2(RCC_AHB5_PERIPHEN_PWR, ENABLE);
+
+ /* Enable USBHS2 peripheral clock (AHB1). */
+ RCC_EnableAHB1PeriphClk1(RCC_AHB1_PERIPHEN_M7_USB2, ENABLE);
+
+ /* Power up the USBHS2 hardware module. */
+ PWR_MoudlePowerEnable(HSC2_USB2_PWRCTRL, ENABLE);
+
+ g_n32h7xx_irq[1].fn = irq_fn;
+ g_n32h7xx_irq[1].busid = busid;
+ n32h7xx_usbhs2_irq_enable();
+}
+
+/* -----------------------------------------------------------------------
+ * Device mode
+ * ----------------------------------------------------------------------- */
+void usb_dc_low_level_init(uint8_t busid)
+{
+ /* Identify the controller by reg_base, not busid.
+ * busid is a user-assigned index and does not imply a fixed controller mapping. */
+ if (g_usbdev_bus[busid].reg_base == N32H7XX_USBHS1_BASE) {
+ n32h7xx_usbhs1_hw_init(busid, USBD_IRQHandler);
+ n32h7xx_wrapper_init(N32H7XX_USBHS1_WRAP, true, true);
+ } else {
+ n32h7xx_usbhs2_hw_init(busid, USBD_IRQHandler);
+ n32h7xx_wrapper_init(N32H7XX_USBHS2_WRAP, true, false);
+ }
+}
+
+void usb_dc_low_level_deinit(uint8_t busid)
+{
+ NVIC_InitType nvic;
+
+ if (g_usbdev_bus[busid].reg_base == N32H7XX_USBHS1_BASE) {
+ nvic.NVIC_IRQChannel = USB1_HS_IRQn;
+ nvic.NVIC_IRQChannelCmd = DISABLE;
+ NVIC_Init(&nvic);
+ RCC_EnableAHB2PeriphReset1(RCC_AHB2_PERIPHRST_USB1POR);
+ RCC_EnableAHB2PeriphClk1(RCC_AHB2_PERIPHEN_M7_USB1, DISABLE);
+ } else {
+ nvic.NVIC_IRQChannel = USB2_HS_IRQn;
+ nvic.NVIC_IRQChannelCmd = DISABLE;
+ NVIC_Init(&nvic);
+ RCC_EnableAHB1PeriphReset1(RCC_AHB1_PERIPHRST_USB2POR);
+ RCC_EnableAHB1PeriphClk1(RCC_AHB1_PERIPHEN_M7_USB2, DISABLE);
+ }
+}
+
+/* -----------------------------------------------------------------------
+ * Host mode
+ * ----------------------------------------------------------------------- */
+void usb_hc_low_level_init(struct usbh_bus *bus)
+{
+ if (bus->hcd.reg_base == N32H7XX_USBHS1_BASE) {
+ n32h7xx_usbhs1_hw_init(bus->busid, USBH_IRQHandler);
+ n32h7xx_wrapper_init(N32H7XX_USBHS1_WRAP, false, true);
+ } else {
+ n32h7xx_usbhs2_hw_init(bus->busid, USBH_IRQHandler);
+ n32h7xx_wrapper_init(N32H7XX_USBHS2_WRAP, false, false);
+ }
+}
+
+void usb_hc_low_level_deinit(struct usbh_bus *bus)
+{
+ NVIC_InitType nvic;
+
+ if (bus->hcd.reg_base == N32H7XX_USBHS1_BASE) {
+ nvic.NVIC_IRQChannel = USB1_HS_IRQn;
+ nvic.NVIC_IRQChannelCmd = DISABLE;
+ NVIC_Init(&nvic);
+ RCC_EnableAHB2PeriphReset1(RCC_AHB2_PERIPHRST_USB1POR);
+ RCC_EnableAHB2PeriphClk1(RCC_AHB2_PERIPHEN_M7_USB1, DISABLE);
+ } else {
+ nvic.NVIC_IRQChannel = USB2_HS_IRQn;
+ nvic.NVIC_IRQChannelCmd = DISABLE;
+ NVIC_Init(&nvic);
+ RCC_EnableAHB1PeriphReset1(RCC_AHB1_PERIPHRST_USB2POR);
+ RCC_EnableAHB1PeriphClk1(RCC_AHB1_PERIPHEN_M7_USB2, DISABLE);
+ }
+}
+
+/* PHY is controlled via Wrapper registers, not GCCFG. */
+uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
+{
+ return 0;
+}
+
+uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
+{
+ return 0;
+}
+
+/* -----------------------------------------------------------------------
+ * IRQ handlers -- one per controller, fixed at link time.
+ * ----------------------------------------------------------------------- */
+void USB1_HS_IRQHandler(void)
+{
+ g_n32h7xx_irq[0].fn(g_n32h7xx_irq[0].busid);
+}
+
+void USB2_HS_IRQHandler(void)
+{
+ g_n32h7xx_irq[1].fn(g_n32h7xx_irq[1].busid);
+}
+
+/*
+ * N32H7xx USBHS DWC2 parameters (applies to both USBHS1 and USBHS2).
+ *
+ * Both controllers have identical hardware: 4 KB FIFO RAM (1024 words),
+ * 16-bit UTMI PHY, no descriptor DMA. Differs from N32H47x_48x only in
+ * phy_utmi_width = 16 (GCFG.PHYIF = 1).
+ *
+ * Device FIFO layout (1024 words, 4096 bytes):
+ * RX shared 512 words (2048 bytes)
+ * EP0 IN TX 64 words ( 256 bytes) -- control
+ * EP1 IN TX 256 words (1024 bytes) -- primary HS bulk/iso
+ * EP2 IN TX 64 words ( 256 bytes)
+ * EP3 IN TX 64 words ( 256 bytes)
+ * EP4 IN TX 64 words ( 256 bytes)
+ * Total 1024 words (4096 bytes)
+ *
+ * Host FIFO layout (1024 words, 4096 bytes):
+ * RX 512 words (2048 bytes)
+ * Non-periodic TX 256 words (1024 bytes)
+ * Periodic TX 256 words (1024 bytes)
+ * Total 1024 words (4096 bytes)
+ *
+ * Adjust via CONFIG_USB_DWC2_CUSTOM_FIFO or CONFIG_USB_DWC2_CUSTOM_PARAM;
+ * keep RX + sum(TX) <= 1024 words.
+ */
+static const struct dwc2_user_params param_n32h7xx = {
+ /* Built-in HS UTMI+ PHY; GUSBCFG.ULPI_UTMI_SEL = 0. */
+ .phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
+
+ /* 16-bit UTMI data bus (GCFG.PHYIF = 1).
+ * USB_CoreInit() sets PHYIF via USBHS_GCFG_PHYIF.
+ * CherryUSB sets GUSBCFG.PHYIF16 only when phy_utmi_width == 16.
+ * GCFG.PHYIF: 0 = 8-bit bus, 1 = 16-bit bus. */
+ .phy_utmi_width = 16,
+
+#ifdef CONFIG_USB_DWC2_DMA_ENABLE
+ .device_dma_enable = true,
+#else
+ .device_dma_enable = false,
+#endif
+
+ /* Scatter-Gather descriptor DMA: not supported (GHWCFG4.DESC_DMA_ENABLED = 0). */
+ .device_dma_desc_enable = false,
+
+ /* Shared RX FIFO depth for device mode, in 32-bit words.
+ * Minimum formula: (5+8) + (512/4+1) + (2*7) + 1 = 157 words.
+ * 512 words matches Nations CDC demo (RX_FIFO_HS_SIZE = 512).
+ * Hardware limit: RXFDEP max = 1024 words. */
+ .device_rx_fifo_size = 512,
+
+ /* Per-IN-endpoint TX FIFO depths, in 32-bit words.
+ * 512 TX + 512 RX = 1024 words total.
+ * Per-FIFO hardware limit: INEPTXFDEP max = 768 words. */
+ .device_tx_fifo_size = {
+ [0] = 64, /* EP0: 256 bytes, control; matches TX0_FIFO_HS_SIZE = 64 */
+ [1] = 256, /* EP1: 1024 bytes, HS bulk/iso; matches TX1_FIFO_HS_SIZE = 256 */
+ [2] = 64, /* EP2: 256 bytes */
+ [3] = 64, /* EP3: 256 bytes */
+ [4] = 64, /* EP4: 256 bytes */
+ [5] = 0, /* EP5..EP8: unallocated; use CONFIG_USB_DWC2_CUSTOM_FIFO to enable */
+ [6] = 0,
+ [7] = 0,
+ [8] = 0,
+ [9] = 0,
+ [10] = 0,
+ [11] = 0,
+ [12] = 0,
+ [13] = 0,
+ [14] = 0,
+ [15] = 0,
+ },
+
+ .host_dma_desc_enable = false,
+
+ /* Host RX FIFO: 512 words (min formula: (1024/4+1)+1 = 258 words). */
+ .host_rx_fifo_size = 512,
+
+ /* Host NP TX FIFO: 256 words (double-buffer, HS MPS = 512 bytes).
+ * Matches Nations Host demo (TXH_NP_HS_FIFOSIZE = 256). */
+ .host_nperio_tx_fifo_size = 256,
+
+ /* Host periodic TX FIFO: 256 words (HS iso MPS = 1024: 1024/4 = 256 min).
+ * Matches Nations Host demo (TXH_P_HS_FIFOSIZE = 256).
+ * Host total: 512 + 256 + 256 = 1024 words. */
+ .host_perio_tx_fifo_size = 256,
+
+ /* PHY controlled via Wrapper registers (WRPCFG/WRPCTRL), not GCCFG. */
+ .device_gccfg = 0,
+ .host_gccfg = 0,
+
+ /* Set to true to bypass VBUS hardware sensing on boards that do not route
+ * USB VBUS to a GPIO sense pin. false = rely on hardware VBUS detection. */
+ .b_session_valid_override = false,
+
+ /* 4 KB dedicated FIFO RAM = 1024 x 32-bit words; GRXFSIZ.RXFDEP max = 1024. */
+ .total_fifo_size = 1024,
+};
+
+#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
+void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
+{
+ memcpy(params, &param_n32h7xx, sizeof(struct dwc2_user_params));
+#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
+ struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
+
+ dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
+ params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
+ for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++) {
+ params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
+ }
+#endif /* CONFIG_USB_DWC2_CUSTOM_FIFO */
+}
+#endif /* CONFIG_USB_DWC2_CUSTOM_PARAM */
+
+#endif /* N32H73x || N32H76x || N32H78x */
+
+/* USB DMA buffers reside in AXI SRAM (D-Cache enabled on N32H7xx Cortex-M7).
+ * Cache coherency is maintained via CMSIS SCB helpers:
+ * clean -- flush CPU write-buffer to SRAM before DMA TX
+ * invalidate -- discard stale cache lines after DMA RX
+ * flush -- clean + invalidate (bi-directional transfers) */
+#ifdef CONFIG_USB_DCACHE_ENABLE
+void usb_dcache_clean(uintptr_t addr, size_t size)
+{
+ SCB_CleanDCache_by_Addr((void *)addr, size);
+}
+
+void usb_dcache_invalidate(uintptr_t addr, size_t size)
+{
+ SCB_InvalidateDCache_by_Addr((void *)addr, size);
+}
+
+void usb_dcache_flush(uintptr_t addr, size_t size)
+{
+ SCB_CleanInvalidateDCache_by_Addr((void *)addr, size);
+}
#endif