diff --git a/SConscript b/SConscript index d74326d4..2ce805bf 100644 --- a/SConscript +++ b/SConscript @@ -5,15 +5,12 @@ path = [cwd + '/common'] path += [cwd + '/core'] src = [] -CPPDEFINES = ['-Dprintf=rt_kprintf'] - # USB DEVICE if GetDepend(['PKG_CHERRYUSB_DEVICE']): src += Glob('core/usbd_core.c') + if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']): CPPDEFINES+=['CONFIG_USB_HS'] - elif GetDepend(['PKG_CHERRYUSB_DEVICE_HS_IN_FULL']): - CPPDEFINES += ['CONFIG_USB_HS_IN_FULL'] if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC']): path += [cwd + '/class/cdc'] @@ -49,16 +46,20 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']): if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_TEMPLATE']): src += Glob('demo/msc_ram_template.c') if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V1_TEMPLATE']): - src += Glob('demo/audio_v1_mic_speaker_dualchan_template.c') + src += Glob('demo/audio_v1_mic_speaker_multichan_template.c') if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V2_TEMPLATE']): src += Glob('demo/audio_v2_mic_speaker_multichan_template.c') if GetDepend(['PKG_CHERRYUSB_DEVICE_VIDEO_TEMPLATE']): src += Glob('demo/video_static_mjpeg_template.c') - if GetDepend(['PKG_CHERRYUSB_DEVICE_FSDEV_STM32']): + if GetDepend(['PKG_CHERRYUSB_DEVICE_FSDEV']): src += Glob('port/fsdev/usb_dc_fsdev.c') - if GetDepend(['PKG_CHERRYUSB_DEVICE_SYNOPSYS_STM32']): - src += Glob('port/synopsys/usb_dc_synopsys.c') + if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2']): + src += Glob('port/synopsys/usb_dc_dwc2.c') + if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_PORT_FS']): + CPPDEFINES += ['CONFIG_USB_DWC2_PORT=FS_PORT'] + elif GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_PORT_HS']): + CPPDEFINES += ['CONFIG_USB_DWC2_PORT=HS_PORT'] if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB']): src += Glob('port/musb/usb_dc_musb.c') if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_SUNXI']): @@ -88,8 +89,9 @@ if GetDepend(['PKG_CHERRYUSB_HOST']): src += Glob('class/hub/usbh_hub.c') CPPDEFINES += ['CONFIG_USBHOST_HUB'] - if GetDepend(['PKG_CHERRYUSB_HOST_SYNOPSYS_STM32']): - src += Glob('port/synopsys/usb_hc_synopsys.c') + if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']): + src += Glob('port/synopsys/usb_hc_dwc2.c') + CPPDEFINES += ['CONFIG_USBHOST_HIGH_WORKQ'] if GetDepend(['PKG_CHERRYUSB_HOST_MUSB']): src += Glob('port/musb/usb_hc_musb.c') if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_SUNXI']): diff --git a/demo/stm32/usb_device/stm32f429igt6/Core/Inc/usb_config.h b/demo/stm32/usb_device/stm32f429igt6/Core/Inc/usb_config.h index 59dd164b..39c77df6 100644 --- a/demo/stm32/usb_device/stm32f429igt6/Core/Inc/usb_config.h +++ b/demo/stm32/usb_device/stm32f429igt6/Core/Inc/usb_config.h @@ -1,6 +1,17 @@ #ifndef _USB_CONFIG_H #define _USB_CONFIG_H +/* USB common Configuration */ +#ifndef CONFIG_USB_DBG_LEVEL +#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO +#endif + +#ifndef CONFIG_USB_PRINTF +#define CONFIG_USB_PRINTF printf +#endif + +#define CONFIG_USB_PRINTF_COLOR_ENABLE + /* USB DEVICE Configuration */ /* core */ #ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN @@ -15,6 +26,9 @@ #define CONFIG_USBDEV_TEST_MODE 0 #endif +/* cdc class */ +// #define CONFIG_USBDEV_CDC_ACM_UART + /* msc class */ #ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING #define CONFIG_USBDEV_MSC_MANUFACTURER_STRING "" @@ -28,6 +42,18 @@ #define CONFIG_USBDEV_MSC_VERSION_STRING "0.01" #endif +// #define CONFIG_USBDEV_MSC_THREAD + +#ifdef CONFIG_USBDEV_MSC_THREAD +#ifndef CONFIG_USBDEV_MSC_STACKSIZE +#define CONFIG_USBDEV_MSC_STACKSIZE 2048 +#endif + +#ifndef CONFIG_USBDEV_MSC_PRIO +#define CONFIG_USBDEV_MSC_PRIO 4 +#endif +#endif + /* audio class */ #ifndef CONFIG_USBDEV_AUDIO_VERSION #define CONFIG_USBDEV_AUDIO_VERSION 0x0100 diff --git a/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/startup_stm32f429xx.s b/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/startup_stm32f429xx.s index 6d04068b..5943e2be 100644 --- a/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/startup_stm32f429xx.s +++ b/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/startup_stm32f429xx.s @@ -41,7 +41,7 @@ __initial_sp ; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ; -Heap_Size EQU 0x200 +Heap_Size EQU 0x1000 AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base diff --git a/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx b/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx index 646cbe21..767de2d5 100644 --- a/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx +++ b/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx @@ -103,7 +103,7 @@ 1 0 0 - 6 + 3 @@ -114,7 +114,7 @@ - STLink\ST-LINKIII-KEIL_SWO.dll + BIN\CMSIS_AGDI.dll @@ -135,12 +135,12 @@ 0 DLGUARM - (105=-1,-1,-1,-1,0) + 0 CMSIS_AGDI - -X"Fire CMSIS-DAP" -UFS-00001418 -O239 -S8 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F429IGTx$CMSIS\Flash\STM32F4xx_1024.FLM) + -X"Fire CMSIS-DAP" -UFS-00001418 -O239 -S10 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F429IGTx$CMSIS\Flash\STM32F4xx_1024.FLM) 0 @@ -157,7 +157,7 @@ 0 0 - 525 + 537 1
0
0 @@ -166,7 +166,23 @@ 0 0 0 - C:\Users\lvjiazhen\Desktop\usb_stack\demo\port\synopsys\usb_dc_synopsys.c + ..\..\..\..\..\core\usbd_core.c + + +
+ + 1 + 0 + 383 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\..\..\..\..\core\usbd_core.c
@@ -245,7 +261,7 @@ Application/User/Core - 1 + 0 0 0 0 @@ -497,53 +513,17 @@ 0 0 - - 3 - 22 - 1 - 0 - 0 - 0 - ../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c - stm32f4xx_hal_pcd.c - 0 - 0 - - - 3 - 23 - 1 - 0 - 0 - 0 - ../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c - stm32f4xx_hal_pcd_ex.c - 0 - 0 - - - 3 - 24 - 1 - 0 - 0 - 0 - ../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c - stm32f4xx_ll_usb.c - 0 - 0 - Drivers/CMSIS - 1 + 0 0 0 0 4 - 25 + 22 1 0 0 @@ -563,7 +543,7 @@ 0 5 - 26 + 23 1 0 0 @@ -575,7 +555,7 @@ 5 - 27 + 24 1 0 0 @@ -587,13 +567,13 @@ 5 - 28 + 25 1 - 0 + 1 0 0 - ..\..\..\..\..\port\synopsys\usb_dc_synopsys.c - usb_dc_synopsys.c + ..\..\..\..\..\port\dwc2\usb_dc_dwc2.c + usb_dc_dwc2.c 0 0 diff --git a/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx b/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx index 36eafaf4..7c6e4b84 100644 --- a/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx +++ b/demo/stm32/usb_device/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx @@ -338,9 +338,9 @@ 0 - USE_HAL_DRIVER,STM32F429xx,CONFIG_USB_HS_IN_FULL + USE_HAL_DRIVER,STM32F429xx,CONFIG_USB_DWC2_PORT=HS_PORT - ../Core/Inc; ../Drivers/STM32F4xx_HAL_Driver/Inc; ../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy; ../Drivers/CMSIS/Device/ST/STM32F4xx/Include; ../Drivers/CMSIS/Include; ..\..\..\..\..\class\cdc; ..\..\..\..\..\core; ..\..\..\..\..\common + ../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;..\..\..\..\..\class\cdc;..\..\..\..\..\core;..\..\..\..\..\common;..\..\..\..\..\class\video;..\..\..\..\..\class\msc;..\..\..\..\..\class\audio @@ -550,21 +550,6 @@ 1 ../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c - - stm32f4xx_hal_pcd.c - 1 - ../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c - - - stm32f4xx_hal_pcd_ex.c - 1 - ../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c - - - stm32f4xx_ll_usb.c - 1 - ../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c - @@ -591,9 +576,9 @@ ..\..\..\..\..\core\usbd_core.c - usb_dc_synopsys.c + usb_dc_dwc2.c 1 - ..\..\..\..\..\port\synopsys\usb_dc_synopsys.c + ..\..\..\..\..\port\dwc2\usb_dc_dwc2.c diff --git a/demo/stm32/usb_host/stm32f429igt6/Core/Inc/usb_config.h b/demo/stm32/usb_host/stm32f429igt6/Core/Inc/usb_config.h index 86c786cc..39c77df6 100644 --- a/demo/stm32/usb_host/stm32f429igt6/Core/Inc/usb_config.h +++ b/demo/stm32/usb_host/stm32f429igt6/Core/Inc/usb_config.h @@ -1,7 +1,67 @@ #ifndef _USB_CONFIG_H #define _USB_CONFIG_H +/* USB common Configuration */ +#ifndef CONFIG_USB_DBG_LEVEL +#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO +#endif + +#ifndef CONFIG_USB_PRINTF +#define CONFIG_USB_PRINTF printf +#endif + +#define CONFIG_USB_PRINTF_COLOR_ENABLE + /* USB DEVICE Configuration */ +/* core */ +#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN +#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256 +#endif + +#ifndef CONFIG_USBDEV_DESC_CHECK +#define CONFIG_USBDEV_DESC_CHECK 0 +#endif + +#ifndef CONFIG_USBDEV_TEST_MODE +#define CONFIG_USBDEV_TEST_MODE 0 +#endif + +/* cdc class */ +// #define CONFIG_USBDEV_CDC_ACM_UART + +/* msc class */ +#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING +#define CONFIG_USBDEV_MSC_MANUFACTURER_STRING "" +#endif + +#ifndef CONFIG_USBDEV_MSC_PRODUCT_STRING +#define CONFIG_USBDEV_MSC_PRODUCT_STRING "" +#endif + +#ifndef CONFIG_USBDEV_MSC_VERSION_STRING +#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01" +#endif + +// #define CONFIG_USBDEV_MSC_THREAD + +#ifdef CONFIG_USBDEV_MSC_THREAD +#ifndef CONFIG_USBDEV_MSC_STACKSIZE +#define CONFIG_USBDEV_MSC_STACKSIZE 2048 +#endif + +#ifndef CONFIG_USBDEV_MSC_PRIO +#define CONFIG_USBDEV_MSC_PRIO 4 +#endif +#endif + +/* audio class */ +#ifndef CONFIG_USBDEV_AUDIO_VERSION +#define CONFIG_USBDEV_AUDIO_VERSION 0x0100 +#endif + +#ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL +#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 2 +#endif /* USB HOST Configuration */ #ifndef CONFIG_USBHOST_RHPORTS @@ -69,4 +129,4 @@ #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE // #define CONFIG_USB_EHCI_CONFIGFLAG -#endif \ No newline at end of file +#endif diff --git a/demo/stm32/usb_host/stm32f429igt6/Core/Src/main.c b/demo/stm32/usb_host/stm32f429igt6/Core/Src/main.c index e9fe153f..9edcc26d 100644 --- a/demo/stm32/usb_host/stm32f429igt6/Core/Src/main.c +++ b/demo/stm32/usb_host/stm32f429igt6/Core/Src/main.c @@ -45,7 +45,7 @@ /* Private variables ---------------------------------------------------------*/ UART_HandleTypeDef huart1; -//HCD_HandleTypeDef hhcd_USB_OTG_HS; +HCD_HandleTypeDef hhcd_USB_OTG_HS; /* USER CODE BEGIN PV */ @@ -68,6 +68,27 @@ int fputc(int ch, FILE *f) return ch; } +void usb_hc_low_level_init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**USB_OTG_HS GPIO Configuration + PB14 ------> USB_OTG_HS_DM + PB15 ------> USB_OTG_HS_DP + */ + GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_OTG_HS_FS; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + /* USB_OTG_HS interrupt Init */ + HAL_NVIC_SetPriority(OTG_HS_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(OTG_HS_IRQn); +} /* USER CODE END 0 */ /** @@ -209,19 +230,19 @@ static void MX_USB_OTG_HS_HCD_Init(void) /* USER CODE BEGIN USB_OTG_HS_Init 1 */ /* USER CODE END USB_OTG_HS_Init 1 */ -// hhcd_USB_OTG_HS.Instance = USB_OTG_HS; -// hhcd_USB_OTG_HS.Init.Host_channels = 12; -// hhcd_USB_OTG_HS.Init.speed = HCD_SPEED_FULL; -// hhcd_USB_OTG_HS.Init.dma_enable = DISABLE; -// hhcd_USB_OTG_HS.Init.phy_itface = USB_OTG_EMBEDDED_PHY; -// hhcd_USB_OTG_HS.Init.Sof_enable = DISABLE; -// hhcd_USB_OTG_HS.Init.low_power_enable = DISABLE; -// hhcd_USB_OTG_HS.Init.vbus_sensing_enable = DISABLE; -// hhcd_USB_OTG_HS.Init.use_external_vbus = DISABLE; -// if (HAL_HCD_Init(&hhcd_USB_OTG_HS) != HAL_OK) -// { -// Error_Handler(); -// } + hhcd_USB_OTG_HS.Instance = USB_OTG_HS; + hhcd_USB_OTG_HS.Init.Host_channels = 12; + hhcd_USB_OTG_HS.Init.speed = HCD_SPEED_FULL; + hhcd_USB_OTG_HS.Init.dma_enable = DISABLE; + hhcd_USB_OTG_HS.Init.phy_itface = USB_OTG_EMBEDDED_PHY; + hhcd_USB_OTG_HS.Init.Sof_enable = DISABLE; + hhcd_USB_OTG_HS.Init.low_power_enable = DISABLE; + hhcd_USB_OTG_HS.Init.vbus_sensing_enable = DISABLE; + hhcd_USB_OTG_HS.Init.use_external_vbus = DISABLE; + if (HAL_HCD_Init(&hhcd_USB_OTG_HS) != HAL_OK) + { + Error_Handler(); + } /* USER CODE BEGIN USB_OTG_HS_Init 2 */ /* USER CODE END USB_OTG_HS_Init 2 */ diff --git a/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/startup_stm32f429xx.s b/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/startup_stm32f429xx.s index ffaf8b3b..75b5b4d5 100644 --- a/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/startup_stm32f429xx.s +++ b/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/startup_stm32f429xx.s @@ -30,7 +30,7 @@ ; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> ; -Stack_Size EQU 0x400 +Stack_Size EQU 0x1000 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size diff --git a/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx b/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx index c7398ea8..6ce3cf8d 100644 --- a/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx +++ b/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvoptx @@ -153,39 +153,17 @@ -U066EFF555453774987091527 -O2287 -SF4000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(2BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F429IGTx$CMSIS\Flash\STM32F4xx_1024.FLM)
- - - 0 - 0 - 493 - 1 -
0
- 0 - 0 - 0 - 0 - 0 - 0 - ..\..\..\..\..\core\usbh_core.c - - -
-
+ 0 1 - intf + gint_status 1 1 - setup - - - 2 - 1 - hport + chan_int @@ -242,7 +220,7 @@ Application/MDK-ARM - 1 + 0 0 0 0 @@ -262,7 +240,7 @@ Application/User/Core - 1 + 0 0 0 0 @@ -330,7 +308,7 @@ Drivers/STM32F4xx_HAL_Driver - 1 + 0 0 0 0 @@ -574,7 +552,7 @@ FreeRTOS - 1 + 0 0 0 0 @@ -678,7 +656,7 @@ CherryUSB - 1 + 0 0 0 0 @@ -734,11 +712,11 @@ 6 38 1 - 1 + 0 0 0 - ..\..\..\..\..\class\hub\usbh_hub.c - usbh_hub.c + ..\..\..\..\..\osal\usb_osal_freertos.c + usb_osal_freertos.c 0 0 @@ -749,8 +727,8 @@ 0 0 0 - ..\..\..\..\..\osal\usb_osal_freertos.c - usb_osal_freertos.c + ..\..\..\..\..\port\dwc2\usb_hc_dwc2.c + usb_hc_dwc2.c 0 0 @@ -766,18 +744,6 @@ 0 0 - - 6 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\..\port\synopsys\usb_hc_synopsys.c - usb_hc_synopsys.c - 0 - 0 - @@ -788,7 +754,7 @@ 0 7 - 42 + 41 1 0 0 @@ -800,7 +766,7 @@ 7 - 43 + 42 1 0 0 @@ -812,7 +778,7 @@ 7 - 44 + 43 1 0 0 @@ -824,7 +790,7 @@ 7 - 45 + 44 1 0 0 @@ -836,7 +802,7 @@ 7 - 46 + 45 1 0 0 diff --git a/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx b/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx index b3a47206..872fcc6f 100644 --- a/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx +++ b/demo/stm32/usb_host/stm32f429igt6/MDK-ARM/stm32f429igt6.uvprojx @@ -314,7 +314,7 @@ 1 - 3 + 1 0 0 1 @@ -338,7 +338,7 @@ 0 - USE_HAL_DRIVER,STM32F429xx,CONFIG_USB_HS_IN_FULL,CONFIG_USBHOST_HUB + USE_HAL_DRIVER,STM32F429xx,CONFIG_USBHOST_HIGH_WORKQ ../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;..\..\..\..\..\common;..\..\..\..\..\core;..\..\..\..\..\class\cdc;..\..\..\..\..\class\hub;..\..\..\..\..\class\hid;..\..\..\..\..\class\msc;..\..\..\..\..\osal;..\..\..\..\..\third_party\FreeRTOS-10.4\include;..\..\..\..\..\third_party\FreeRTOS-10.4\portable\GCC\ARM_CM4F;..\..\..\..\..\third_party\fatfs-0.14\source @@ -594,26 +594,21 @@ 1 ..\..\..\..\..\class\hid\usbh_hid.c - - usbh_hub.c - 1 - ..\..\..\..\..\class\hub\usbh_hub.c - usb_osal_freertos.c 1 ..\..\..\..\..\osal\usb_osal_freertos.c + + usb_hc_dwc2.c + 1 + ..\..\..\..\..\port\dwc2\usb_hc_dwc2.c + usb_workq.c 1 ..\..\..\..\..\osal\usb_workq.c - - usb_hc_synopsys.c - 1 - ..\..\..\..\..\port\synopsys\usb_hc_synopsys.c - diff --git a/port/synopsys/README.md b/port/dwc2/README.md similarity index 100% rename from port/synopsys/README.md rename to port/dwc2/README.md diff --git a/port/dwc2/usb_dc_dwc2.c b/port/dwc2/usb_dc_dwc2.c new file mode 100644 index 00000000..733b5391 --- /dev/null +++ b/port/dwc2/usb_dc_dwc2.c @@ -0,0 +1,917 @@ +#include "usbd_core.h" +#include "usb_dwc2_reg.h" + +#define FS_PORT 0 +#define HS_PORT 1 + +#ifndef CONFIG_USB_DWC2_PORT +#error "please select CONFIG_USB_DWC2_PORT with FS_PORT or HS_PORT" +#endif + +#if CONFIG_USB_DWC2_PORT == FS_PORT +#ifndef USBD_IRQHandler +#define USBD_IRQHandler OTG_FS_IRQHandler +#endif + +#ifndef USB_BASE +#ifdef STM32H7 +#define USB_BASE (0x40080000UL) +#else +#define USB_BASE (0x50000000UL) +#endif +#endif + +#define USB_RAM_SIZE 1280 /* define with minimum value*/ + +/*FIFO sizes in bytes (total available memory for FIFOs is 1.25KB )*/ +#ifndef CONFIG_USB_DWC2_RX_FIFO_SIZE +#define CONFIG_USB_DWC2_RX_FIFO_SIZE (512) +#endif + +#ifndef CONFIG_USB_DWC2_TX0_FIFO_SIZE +#define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64) +#endif + +#ifndef CONFIG_USB_DWC2_TX1_FIFO_SIZE +#define CONFIG_USB_DWC2_TX1_FIFO_SIZE (128) +#endif + +#ifndef CONFIG_USB_DWC2_TX2_FIFO_SIZE +#define CONFIG_USB_DWC2_TX2_FIFO_SIZE (128) +#endif + +#ifndef CONFIG_USB_DWC2_TX3_FIFO_SIZE +#define CONFIG_USB_DWC2_TX3_FIFO_SIZE (128) +#endif + +#ifndef CONFIG_USB_DWC2_TX4_FIFO_SIZE +#define CONFIG_USB_DWC2_TX4_FIFO_SIZE (128) +#endif + +#ifndef CONFIG_USB_DWC2_TX5_FIFO_SIZE +#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (128) +#endif + +#else + +#ifndef USBD_IRQHandler +#define USBD_IRQHandler OTG_HS_IRQHandler +#endif + +#ifndef USB_BASE +#define USB_BASE (0x40040000UL) +#endif + +#define USB_RAM_SIZE 4096 /* define with minimum value*/ + +/*FIFO sizes in bytes (total available memory for FIFOs is 4KB )*/ +#ifndef CONFIG_USB_DWC2_RX_FIFO_SIZE +#define CONFIG_USB_DWC2_RX_FIFO_SIZE (1024) +#endif + +#ifndef CONFIG_USB_DWC2_TX0_FIFO_SIZE +#define CONFIG_USB_DWC2_TX0_FIFO_SIZE (512) +#endif + +#ifndef CONFIG_USB_DWC2_TX1_FIFO_SIZE +#define CONFIG_USB_DWC2_TX1_FIFO_SIZE (1024) +#endif + +#ifndef CONFIG_USB_DWC2_TX2_FIFO_SIZE +#define CONFIG_USB_DWC2_TX2_FIFO_SIZE (512) +#endif + +#ifndef CONFIG_USB_DWC2_TX3_FIFO_SIZE +#define CONFIG_USB_DWC2_TX3_FIFO_SIZE (512) +#endif + +#ifndef CONFIG_USB_DWC2_TX4_FIFO_SIZE +#define CONFIG_USB_DWC2_TX4_FIFO_SIZE (256) +#endif + +#ifndef CONFIG_USB_DWC2_TX5_FIFO_SIZE +#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (256) +#endif + +#endif + +#ifndef USB_NUM_BIDIR_ENDPOINTS +#define USB_NUM_BIDIR_ENDPOINTS 6 /* define with minimum value*/ +#endif + +#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USB_BASE)) +#define USB_OTG_DEV ((USB_OTG_DeviceTypeDef *)(USB_BASE + USB_OTG_DEVICE_BASE)) +#define USB_OTG_PCGCCTL *(__IO uint32_t *)((uint32_t)USB_BASE + USB_OTG_PCGCCTL_BASE) +#define USB_OTG_INEP(i) ((USB_OTG_INEndpointTypeDef *)(USB_BASE + USB_OTG_IN_ENDPOINT_BASE + ((i)*USB_OTG_EP_REG_SIZE))) +#define USB_OTG_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)(USB_BASE + USB_OTG_OUT_ENDPOINT_BASE + ((i)*USB_OTG_EP_REG_SIZE))) +#define USB_OTG_FIFO(i) *(__IO uint32_t *)(USB_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE)) + +extern uint32_t SystemCoreClock; + +/* Endpoint state */ +struct dwc2_ep_state { + /** Endpoint max packet size */ + uint16_t ep_mps; + /** Endpoint Transfer Type. + * May be Bulk, Interrupt, Control or Isochronous + */ + uint8_t ep_type; + uint8_t ep_stalled; /** Endpoint stall flag */ +}; + +/* Driver state */ +struct dwc2_udc { + volatile uint32_t read_len; + struct dwc2_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/ + struct dwc2_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */ +} g_dwc2_udc; + +static int usb_dwc2_reset(void) +{ + uint32_t count = 0U; + + /* Wait for AHB master IDLE state. */ + do { + if (++count > 200000U) { + return -1; + } + } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U); + + /* Core Soft Reset */ + count = 0U; + USB_OTG_GLB->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + + do { + if (++count > 200000U) { + return -1; + } + } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); + + return 0; +} + +static inline int usb_dwc2_core_init(void) +{ + int ret; +#if defined(CONFIG_USB_HS) + +#else + /* Select FS Embedded PHY */ + USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; +#endif + /* Reset after a PHY select */ + ret = usb_dwc2_reset(); + + /* Activate the USB Transceiver */ + USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_PWRDWN; + + return ret; +} + +static void usb_dwc2_set_mode(uint8_t mode) +{ + USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD); + + if (mode == USB_OTG_MODE_HOST) { + USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD; + } else if (mode == USB_OTG_MODE_DEVICE) { + USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + } +} + +static void usb_dwc2_set_turnaroundtime(uint32_t hclk, uint8_t speed) +{ + uint32_t UsbTrd; + + /* The USBTRD is configured according to the tables below, depending on AHB frequency + used by application. In the low AHB frequency range it is used to stretch enough the USB response + time to IN tokens, the USB turnaround time, so to compensate for the longer AHB read access + latency to the Data FIFO */ + if (speed == USB_OTG_SPEED_FULL) { + if ((hclk >= 14200000U) && (hclk < 15000000U)) { + /* hclk Clock Range between 14.2-15 MHz */ + UsbTrd = 0xFU; + } else if ((hclk >= 15000000U) && (hclk < 16000000U)) { + /* hclk Clock Range between 15-16 MHz */ + UsbTrd = 0xEU; + } else if ((hclk >= 16000000U) && (hclk < 17200000U)) { + /* hclk Clock Range between 16-17.2 MHz */ + UsbTrd = 0xDU; + } else if ((hclk >= 17200000U) && (hclk < 18500000U)) { + /* hclk Clock Range between 17.2-18.5 MHz */ + UsbTrd = 0xCU; + } else if ((hclk >= 18500000U) && (hclk < 20000000U)) { + /* hclk Clock Range between 18.5-20 MHz */ + UsbTrd = 0xBU; + } else if ((hclk >= 20000000U) && (hclk < 21800000U)) { + /* hclk Clock Range between 20-21.8 MHz */ + UsbTrd = 0xAU; + } else if ((hclk >= 21800000U) && (hclk < 24000000U)) { + /* hclk Clock Range between 21.8-24 MHz */ + UsbTrd = 0x9U; + } else if ((hclk >= 24000000U) && (hclk < 27700000U)) { + /* hclk Clock Range between 24-27.7 MHz */ + UsbTrd = 0x8U; + } else if ((hclk >= 27700000U) && (hclk < 32000000U)) { + /* hclk Clock Range between 27.7-32 MHz */ + UsbTrd = 0x7U; + } else /* if(hclk >= 32000000) */ + { + /* hclk Clock Range between 32-200 MHz */ + UsbTrd = 0x6U; + } + } else if (speed == USB_OTG_SPEED_HIGH) { + UsbTrd = USBD_HS_TRDT_VALUE; + } else { + UsbTrd = USBD_DEFAULT_TRDT_VALUE; + } + + USB_OTG_GLB->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; + USB_OTG_GLB->GUSBCFG |= (uint32_t)((UsbTrd << 10) & USB_OTG_GUSBCFG_TRDT); +} + +static int usb_dwc2_flush_rxfifo(void) +{ + uint32_t count = 0; + + USB_OTG_GLB->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; + + do { + if (++count > 200000U) { + return -1; + } + } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH); + + return 0; +} + +static int usb_dwc2_flush_txfifo(uint32_t num) +{ + uint32_t count = 0U; + + USB_OTG_GLB->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (num << 6)); + + do { + if (++count > 200000U) { + return -1; + } + } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH); + + return 0; +} + +static void usb_set_txfifo(uint8_t fifo, uint16_t size) +{ + uint8_t i; + uint32_t Tx_Offset; + + /* TXn min size = 16 words. (n : Transmit FIFO index) + When a TxFIFO is not used, the Configuration should be as follows: + case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes) + --> Txm can use the space allocated for Txn. + case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes) + --> Txn should be configured with the minimum space of 16 words + The FIFO is used optimally when used TxFIFOs are allocated in the top + of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones. + When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */ + + Tx_Offset = USB_OTG_GLB->GRXFSIZ; + + if (fifo == 0U) { + USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset; + } else { + Tx_Offset += (USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ) >> 16; + for (i = 0U; i < (fifo - 1U); i++) { + Tx_Offset += (USB_OTG_GLB->DIEPTXF[i] >> 16); + } + + /* Multiply Tx_Size by 2 to get higher performance */ + USB_OTG_GLB->DIEPTXF[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset; + } +} + +static uint8_t usb_dwc2_get_devspeed(void) +{ + uint8_t speed; + uint32_t DevEnumSpeed = USB_OTG_DEV->DSTS & USB_OTG_DSTS_ENUMSPD; + + if (DevEnumSpeed == DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ) { + speed = USB_OTG_SPEED_HIGH; + } else if ((DevEnumSpeed == DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ) || + (DevEnumSpeed == DSTS_ENUMSPD_FS_PHY_48MHZ)) { + speed = USB_OTG_SPEED_FULL; + } else { + speed = 0xFU; + } + + return speed; +} + +/** + * @brief USB_ReadInterrupts: return the global USB interrupt status + * @retval status + */ +static inline uint32_t usb_dwc2_get_glb_intstatus(void) +{ + uint32_t tmpreg; + + tmpreg = USB_OTG_GLB->GINTSTS; + tmpreg &= USB_OTG_GLB->GINTMSK; + + return tmpreg; +} + +/** + * @brief usb_dwc2_get_outeps_intstatus: return the USB device OUT endpoints interrupt status + * @retval status + */ +static inline uint32_t usb_dwc2_get_outeps_intstatus(void) +{ + uint32_t tmpreg; + + tmpreg = USB_OTG_DEV->DAINT; + tmpreg &= USB_OTG_DEV->DAINTMSK; + + return ((tmpreg & 0xffff0000U) >> 16); +} + +/** + * @brief usb_dwc2_get_ineps_intstatus: return the USB device IN endpoints interrupt status + * @retval status + */ +static inline uint32_t usb_dwc2_get_ineps_intstatus(void) +{ + uint32_t tmpreg; + + tmpreg = USB_OTG_DEV->DAINT; + tmpreg &= USB_OTG_DEV->DAINTMSK; + + return ((tmpreg & 0xFFFFU)); +} + +/** + * @brief Returns Device OUT EP Interrupt register + * @param epnum endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device OUT EP Interrupt register + */ +static inline uint32_t usb_dwc2_get_outep_intstatus(uint8_t epnum) +{ + uint32_t tmpreg; + + tmpreg = USB_OTG_OUTEP((uint32_t)epnum)->DOEPINT; + tmpreg &= USB_OTG_DEV->DOEPMSK; + + return tmpreg; +} + +/** + * @brief Returns Device IN EP Interrupt register + * @param epnum endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device IN EP Interrupt register + */ +static inline uint32_t usb_dwc2_get_inep_intstatus(uint8_t epnum) +{ + uint32_t tmpreg, msk, emp; + + msk = USB_OTG_DEV->DIEPMSK; + emp = USB_OTG_DEV->DIEPEMPMSK; + msk |= ((emp >> (epnum & 0x07)) & 0x1U) << 7; + tmpreg = USB_OTG_INEP((uint32_t)epnum)->DIEPINT & msk; + + return tmpreg; +} + +__WEAK void usb_dc_low_level_init(void) +{ +} + +__WEAK void usb_dc_low_level_deinit(void) +{ +} + +int usb_dc_init(void) +{ + int ret; + + memset(&g_dwc2_udc, 0, sizeof(struct dwc2_udc)); + + usb_dc_low_level_init(); + + USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS; + + USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT; + + /* Disable DMA mode for FS instance */ + if ((USB_OTG_GLB->CID & (0x1U << 8)) != 0U) { + // USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_HBSTLEN_2; + // USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_DMAEN; + } + + ret = usb_dwc2_core_init(); + + /* Force Device Mode*/ + usb_dwc2_set_mode(USB_OTG_MODE_DEVICE); + + for (uint8_t i = 0U; i < 15U; i++) { + USB_OTG_GLB->DIEPTXF[i] = 0U; + } + +#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) || \ + defined(STM32F7) || defined(STM32H7) +#ifdef CONFIG_DWC2_VBUS_SENSING_ENABLE + /* Enable HW VBUS sensing */ + USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_VBDEN; +#else + /* Deactivate VBUS Sensing B */ + USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBDEN; + + /* B-peripheral session valid override enable */ + USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; + USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; +#endif + +#else +#ifdef CONFIG_DWC2_VBUS_SENSING_ENABLE + /* Enable HW VBUS sensing */ + USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_NOVBUSSENS; + USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_VBUSBSEN; +#else + /* + * Disable HW VBUS sensing. VBUS is internally considered to be always + * at VBUS-Valid level (5V). + */ + USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS; + USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN; + USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN; +#endif + +#endif + /* Restart the Phy Clock */ + USB_OTG_PCGCCTL = 0U; + + /* Device mode configuration */ + USB_OTG_DEV->DCFG |= DCFG_FRAME_INTERVAL_80; + +#if defined(CONFIG_USB_HS) + /* Set Core speed to High speed mode */ + USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH; +#else + USB_OTG_DEV->DCFG |= USB_OTG_SPEED_FULL; +#endif + + ret = usb_dwc2_flush_txfifo(0x10U); + ret = usb_dwc2_flush_rxfifo(); + + for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + if ((USB_OTG_INEP(i)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA) { + if (i == 0U) { + USB_OTG_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_SNAK; + } else { + USB_OTG_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK; + } + } else { + USB_OTG_INEP(i)->DIEPCTL = 0U; + } + + USB_OTG_INEP(i)->DIEPTSIZ = 0U; + USB_OTG_INEP(i)->DIEPINT = 0xFB7FU; + } + for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + if ((USB_OTG_OUTEP(i)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) { + if (i == 0U) { + USB_OTG_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_SNAK; + } else { + USB_OTG_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_EPDIS | USB_OTG_DOEPCTL_SNAK; + } + } else { + USB_OTG_OUTEP(i)->DOEPCTL = 0U; + } + + USB_OTG_OUTEP(i)->DOEPTSIZ = 0U; + USB_OTG_OUTEP(i)->DOEPINT = 0xFB7FU; + } + + /* Clear all pending Device Interrupts */ + USB_OTG_DEV->DIEPMSK = 0U; + USB_OTG_DEV->DOEPMSK = 0U; + USB_OTG_DEV->DAINTMSK = 0U; + + /* Disable all interrupts. */ + USB_OTG_GLB->GINTMSK = 0U; + /* Clear any pending interrupts */ + USB_OTG_GLB->GINTSTS = 0xBFFFFFFFU; + + /* Enable interrupts matching to the Device mode ONLY */ + USB_OTG_GLB->GINTMSK = USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | + USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_RXFLVLM | + USB_OTG_GINTMSK_WUIM; + +#if CONFIG_DWC2_VBUS_SENSING + USB_OTG_GLB->GINTMSK |= (USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_SRQIM); +#endif +#if 0 + USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_SOFM; +#endif + USB_OTG_DEV->DOEPMSK = USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; + USB_OTG_DEV->DIEPMSK = USB_OTG_DIEPMSK_XFRCM; + + USB_OTG_GLB->GRXFSIZ = (CONFIG_USB_DWC2_RX_FIFO_SIZE / 4); + + usb_set_txfifo(0, CONFIG_USB_DWC2_TX0_FIFO_SIZE / 4); + usb_set_txfifo(1, CONFIG_USB_DWC2_TX1_FIFO_SIZE / 4); + usb_set_txfifo(2, CONFIG_USB_DWC2_TX2_FIFO_SIZE / 4); + usb_set_txfifo(3, CONFIG_USB_DWC2_TX3_FIFO_SIZE / 4); +#if USB_NUM_BIDIR_ENDPOINTS > 4 + usb_set_txfifo(4, CONFIG_USB_DWC2_TX4_FIFO_SIZE / 4); +#endif +#if USB_NUM_BIDIR_ENDPOINTS > 5 + usb_set_txfifo(5, CONFIG_USB_DWC2_TX5_FIFO_SIZE / 4); +#endif + USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + USB_OTG_DEV->DCTL &= ~USB_OTG_DCTL_SDIS; + + return ret; +} + +int usb_dc_deinit(void) +{ + usb_dc_low_level_deinit(); + /* Clear Pending interrupt */ + for (uint8_t i = 0U; i < 15U; i++) { + USB_OTG_INEP(i)->DIEPINT = 0xFB7FU; + USB_OTG_OUTEP(i)->DOEPINT = 0xFB7FU; + } + + /* Clear interrupt masks */ + USB_OTG_DEV->DIEPMSK = 0U; + USB_OTG_DEV->DOEPMSK = 0U; + USB_OTG_DEV->DAINTMSK = 0U; + + /* Flush the FIFO */ + usb_dwc2_flush_txfifo(0x10U); + usb_dwc2_flush_rxfifo(); + + USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS; + + return 0; +} + +int usbd_set_address(const uint8_t addr) +{ + USB_OTG_DEV->DCFG &= ~(USB_OTG_DCFG_DAD); + USB_OTG_DEV->DCFG |= ((uint32_t)addr << 4) & USB_OTG_DCFG_DAD; + return 0; +} + +int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr); + uint8_t ep_mps; + + if (!ep_cfg) { + return -1; + } + + if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) { + g_dwc2_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps; + g_dwc2_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type; + + USB_OTG_DEV->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & (uint32_t)(1UL << (16 + ep_idx)); + + ep_mps = ep_cfg->ep_mps; + if (ep_idx == 0) { + switch (ep_cfg->ep_mps) { + case 8: + ep_mps = EP_MPS_8; + break; + case 16: + ep_mps = EP_MPS_16; + break; + case 32: + ep_mps = EP_MPS_32; + break; + case 64: + ep_mps = EP_MPS_64; + break; + } + } + USB_OTG_OUTEP(ep_idx)->DOEPCTL |= (ep_mps & USB_OTG_DOEPCTL_MPSIZ) | + ((uint32_t)ep_cfg->ep_type << 18) | + USB_OTG_DIEPCTL_SD0PID_SEVNFRM | + USB_OTG_DOEPCTL_USBAEP; + /* EP enable */ + USB_OTG_OUTEP(ep_idx)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA); + } else { + g_dwc2_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps; + g_dwc2_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type; + + USB_OTG_DEV->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << ep_idx); + + USB_OTG_INEP(ep_idx)->DIEPCTL |= (ep_cfg->ep_mps & USB_OTG_DIEPCTL_MPSIZ) | + ((uint32_t)ep_cfg->ep_type << 18) | (ep_idx << 22) | + USB_OTG_DIEPCTL_SD0PID_SEVNFRM | + USB_OTG_DIEPCTL_USBAEP; + } + return 0; +} + +int usbd_ep_close(const uint8_t ep) +{ + return 0; +} + +int usbd_ep_set_stall(const uint8_t ep) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (USB_EP_DIR_IS_OUT(ep)) { + if (((USB_OTG_OUTEP(ep_idx)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == 0U) && (ep_idx != 0U)) { + USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~(USB_OTG_DOEPCTL_EPDIS); + } + USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_STALL; + } else { + if (((USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == 0U) && (ep_idx != 0U)) { + USB_OTG_INEP(ep_idx)->DIEPCTL &= ~(USB_OTG_DIEPCTL_EPDIS); + } + USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_STALL; + } + + return 0; +} + +int usbd_ep_clear_stall(const uint8_t ep) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (USB_EP_DIR_IS_OUT(ep)) { + USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL; + if ((g_dwc2_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) || + (g_dwc2_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) { + USB_OTG_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; /* DATA0 */ + } + } else { + USB_OTG_INEP(ep_idx)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; + if ((g_dwc2_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) || + (g_dwc2_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) { + USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; /* DATA0 */ + } + } + return 0; +} + +int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled) +{ + if (USB_EP_DIR_IS_OUT(ep)) { + } else { + } + return 0; +} + +int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint32_t len32b; + uint32_t pktcnt; + + if (!data && data_len) { + return -1; + } + + if (data_len > g_dwc2_udc.in_ep[ep_idx].ep_mps) { + data_len = g_dwc2_udc.in_ep[ep_idx].ep_mps; + } + + len32b = (data_len + 3U) / 4U; + + while (((USB_OTG_INEP(ep_idx)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA) || + (USB_OTG_INEP(ep_idx)->DTXFSTS < len32b)) { + } + + if (!data_len) { + USB_OTG_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); + USB_OTG_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); + USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19)); + /* EP enable, IN data in FIFO */ + USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); + + return 0; + } + + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet + * exist ? 1 : 0) + */ + pktcnt = (uint16_t)((data_len + g_dwc2_udc.in_ep[ep_idx].ep_mps - 1U) / g_dwc2_udc.in_ep[ep_idx].ep_mps); + USB_OTG_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); + USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (pktcnt << 19)); + USB_OTG_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); + USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & data_len); + /* EP enable, IN data in FIFO */ + USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); + + if (g_dwc2_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) { + USB_OTG_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT); + USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1U << 29)); + + if ((USB_OTG_DEV->DSTS & (1U << 8)) == 0U) { + USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM; + } else { + USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; + } + } + + for (uint8_t i = 0U; i < len32b; i++) { + USB_OTG_FIFO(ep_idx) = ((uint32_t *)data)[i]; + } + + if (ret_bytes) { + *ret_bytes = data_len; + } + + return 0; +} + +int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint32_t *pdest = (uint32_t *)data; + uint32_t len32b; + uint32_t read_count; + uint32_t pktcnt; + + if (!data && max_data_len) { + return -1; + } + + if (((uint32_t)data) & 0x03) { + return -2; + } + + if (max_data_len > g_dwc2_udc.out_ep[ep_idx].ep_mps) { + max_data_len = g_dwc2_udc.out_ep[ep_idx].ep_mps; + } + + if (!max_data_len) { + if (ep_idx != 0) { + /* Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + pktcnt = (uint16_t)((max_data_len + g_dwc2_udc.out_ep[ep_idx].ep_mps - 1U) / g_dwc2_udc.out_ep[ep_idx].ep_mps); + USB_OTG_OUTEP(ep_idx)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT); + USB_OTG_OUTEP(ep_idx)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ); + USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)); + USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & g_dwc2_udc.out_ep[ep_idx].ep_mps * pktcnt); + /* EP enable */ + USB_OTG_OUTEP(ep_idx)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA); + } + + return 0; + } + + read_count = g_dwc2_udc.read_len; + + read_count = MIN(read_count, max_data_len); + + len32b = ((uint32_t)read_count + 3U) / 4U; + + for (uint8_t i = 0U; i < len32b; i++) { + *pdest = USB_OTG_FIFO(0U); + pdest++; + } + + if (read_bytes) { + *read_bytes = read_count; + } + + g_dwc2_udc.read_len = 0; + return 0; +} + +void USBD_IRQHandler(void) +{ + uint32_t gint_status, temp, epnum, ep_intr, epint; + gint_status = usb_dwc2_get_glb_intstatus(); + + if ((USB_OTG_GLB->GINTSTS & 0x1U) == USB_OTG_MODE_DEVICE) { + /* Avoid spurious interrupt */ + if (gint_status == 0) { + return; + } + + /* Handle RxQLevel Interrupt */ + if (gint_status & USB_OTG_GINTSTS_RXFLVL) { + USB_MASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL); + + temp = USB_OTG_GLB->GRXSTSP; + epnum = temp & USB_OTG_GRXSTSP_EPNUM; + g_dwc2_udc.read_len = (temp & USB_OTG_GRXSTSP_BCNT) >> 4; + + if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_DATA_UPDT) { + if (g_dwc2_udc.read_len != 0U) { + if (epnum == 0) { + usbd_event_notify_handler(USBD_EVENT_EP0_OUT_NOTIFY, NULL); + } else { + usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(epnum | USB_EP_DIR_OUT)); + } + } + } else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_SETUP_UPDT) { + usbd_event_notify_handler(USBD_EVENT_SETUP_NOTIFY, NULL); + } else { + /* ... */ + } + USB_UNMASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL); + } + + if (gint_status & USB_OTG_GINTSTS_OEPINT) { + epnum = 0; + ep_intr = usb_dwc2_get_outeps_intstatus(); + while (ep_intr != 0U) { + if ((ep_intr & 0x1U) != 0U) { + epint = usb_dwc2_get_outep_intstatus(epnum); + USB_OTG_OUTEP(epnum)->DOEPINT = epint; + + if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) { + USB_OTG_OUTEP(0)->DOEPTSIZ = 1U << USB_OTG_DOEPTSIZ_PKTCNT_Pos | + (USB_OTG_OUTEP(0)->DOEPCTL & USB_OTG_DOEPCTL_MPSIZ) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos; + USB_OTG_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + } + if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC) { + if (epnum == 0) { + USB_OTG_OUTEP(0)->DOEPTSIZ = 1U << USB_OTG_DOEPTSIZ_PKTCNT_Pos | + (USB_OTG_OUTEP(0)->DOEPCTL & USB_OTG_DOEPCTL_MPSIZ) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos; + USB_OTG_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + } + } + } + ep_intr >>= 1U; + epnum++; + } + } + if (gint_status & USB_OTG_GINTSTS_IEPINT) { + epnum = 0U; + ep_intr = usb_dwc2_get_ineps_intstatus(); + while (ep_intr != 0U) { + if ((ep_intr & 0x1U) != 0U) { + epint = usb_dwc2_get_inep_intstatus(epnum); + USB_OTG_INEP(epnum)->DIEPINT = epint; + + if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC) { + if (epnum == 0) { + usbd_event_notify_handler(USBD_EVENT_EP0_IN_NOTIFY, NULL); + } else { + usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(epnum | USB_EP_DIR_IN)); + } + } + } + ep_intr >>= 1U; + epnum++; + } + } + if (gint_status & USB_OTG_GINTSTS_USBRST) { + USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_USBRST; + USB_OTG_DEV->DCTL &= ~USB_OTG_DCTL_RWUSIG; + + usb_dwc2_flush_txfifo(0x10U); + usb_dwc2_flush_rxfifo(); + for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + USB_OTG_INEP(i)->DIEPINT = 0xFB7FU; + USB_OTG_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; + USB_OTG_INEP(i)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK; + USB_OTG_OUTEP(i)->DOEPINT = 0xFB7FU; + USB_OTG_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL; + USB_OTG_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK; + } + USB_OTG_DEV->DAINTMSK |= 0x10001U; + + USB_OTG_OUTEP(0U)->DOEPTSIZ = 0U; + USB_OTG_OUTEP(0U)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19)); + USB_OTG_OUTEP(0U)->DOEPTSIZ |= (3U * 8U); + USB_OTG_OUTEP(0U)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT; + USB_OTG_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + + usbd_event_notify_handler(USBD_EVENT_RESET, NULL); + } + if (gint_status & USB_OTG_GINTSTS_ENUMDNE) { + USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_ENUMDNE; + usb_dwc2_set_turnaroundtime(SystemCoreClock, usb_dwc2_get_devspeed()); + USB_OTG_DEV->DCTL |= USB_OTG_DCTL_CGINAK; + } + if (gint_status & USB_OTG_GINTSTS_SOF) { + USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_SOF; + } + if (gint_status & USB_OTG_GINTSTS_USBSUSP) { + USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_USBSUSP; + } + if (gint_status & USB_OTG_GINTSTS_OTGINT) { + temp = USB_OTG_GLB->GOTGINT; + if ((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET) { + } else { + } + USB_OTG_GLB->GOTGINT |= temp; + } + } +} diff --git a/port/synopsys/usb_synopsys_reg.h b/port/dwc2/usb_dwc2_reg.h similarity index 93% rename from port/synopsys/usb_synopsys_reg.h rename to port/dwc2/usb_dwc2_reg.h index d3acceb9..ec137b20 100644 --- a/port/synopsys/usb_synopsys_reg.h +++ b/port/dwc2/usb_dwc2_reg.h @@ -1578,18 +1578,6 @@ typedef struct * @} */ -/** @defgroup USB_LL Device Speed - * @{ - */ -#define USBD_HS_SPEED 0U -#define USBD_HSINFS_SPEED 1U -#define USBH_HS_SPEED 0U -#define USBD_FS_SPEED 2U -#define USBH_FSLS_SPEED 1U -/** - * @} - */ - /** @defgroup USB_LL_Core_Speed USB Low Layer Core Speed * @{ */ @@ -1623,16 +1611,6 @@ typedef struct * @} */ -/** @defgroup USB_LL_Core_MPS USB Low Layer Core MPS - * @{ - */ -#define USB_OTG_HS_MAX_PACKET_SIZE 512U -#define USB_OTG_FS_MAX_PACKET_SIZE 64U -#define USB_OTG_MAX_EP0_SIZE 64U -/** - * @} - */ - /** @defgroup USB_LL_Core_PHY_Frequency USB Low Layer Core PHY Frequency * @{ */ @@ -1665,24 +1643,6 @@ typedef struct * @} */ -/** @defgroup USB_LL_EP_Speed USB Low Layer EP Speed - * @{ - */ -#define EP_SPEED_LOW 0U -#define EP_SPEED_FULL 1U -#define EP_SPEED_HIGH 2U -/** - * @} - */ - -/** @defgroup USB_LL_EP_Type USB Low Layer EP Type - * @{ - */ -#define EP_TYPE_CTRL 0U -#define EP_TYPE_ISOC 1U -#define EP_TYPE_BULK 2U -#define EP_TYPE_INTR 3U -#define EP_TYPE_MSK 3U /** * @} */ @@ -1734,187 +1694,11 @@ typedef struct #define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U #define GRXSTS_PKTSTS_CH_HALTED 7U -#define USBx_PCGCCTL *(__IO uint32_t *)((uint32_t)USBx_BASE + USB_OTG_PCGCCTL_BASE) -#define USBx_HPRT0 *(__IO uint32_t *)((uint32_t)USBx_BASE + USB_OTG_HOST_PORT_BASE) - -#define USBx_DEVICE ((USB_OTG_DeviceTypeDef *)(USBx_BASE + USB_OTG_DEVICE_BASE)) -#define USBx_INEP(i) ((USB_OTG_INEndpointTypeDef *)(USBx_BASE + USB_OTG_IN_ENDPOINT_BASE + ((i) * USB_OTG_EP_REG_SIZE))) -#define USBx_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)(USBx_BASE + USB_OTG_OUT_ENDPOINT_BASE + ((i) * USB_OTG_EP_REG_SIZE))) -#define USBx_DFIFO(i) *(__IO uint32_t *)(USBx_BASE + USB_OTG_FIFO_BASE + ((i) * USB_OTG_FIFO_SIZE)) - -#define USBx_HOST ((USB_OTG_HostTypeDef *)(USBx_BASE + USB_OTG_HOST_BASE)) -#define USBx_HC(i) ((USB_OTG_HostChannelTypeDef *)(USBx_BASE + USB_OTG_HOST_CHANNEL_BASE + ((i) * USB_OTG_HOST_CHANNEL_SIZE))) - -#define EP_ADDR_MSK 0xFU - #define USB_MASK_INTERRUPT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->GINTMSK &= ~(__INTERRUPT__)) #define USB_UNMASK_INTERRUPT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->GINTMSK |= (__INTERRUPT__)) - +#define USB_MASK_HALT_HC_INT(chnum) (USBx_HC(chnum)->HCINTMSK &= ~USB_OTG_HCINTMSK_CHHM) +#define USB_UNMASK_HALT_HC_INT(chnum) (USBx_HC(chnum)->HCINTMSK |= USB_OTG_HCINTMSK_CHHM) #define CLEAR_IN_EP_INTR(__EPNUM__, __INTERRUPT__) (USBx_INEP(__EPNUM__)->DIEPINT = (__INTERRUPT__)) #define CLEAR_OUT_EP_INTR(__EPNUM__, __INTERRUPT__) (USBx_OUTEP(__EPNUM__)->DOEPINT = (__INTERRUPT__)) - - -typedef enum -{ - USB_DEVICE_MODE = 0, - USB_HOST_MODE = 1, - USB_DRD_MODE = 2 -} USB_OTG_ModeTypeDef; - -/** - * @brief URB States definition - */ -typedef enum -{ - URB_IDLE = 0, - URB_DONE, - URB_NOTREADY, - URB_NYET, - URB_ERROR, - URB_STALL -} USB_OTG_URBStateTypeDef; - -/** - * @brief Host channel States definition - */ -typedef enum -{ - HC_IDLE = 0, - HC_XFRC, - HC_HALTED, - HC_NAK, - HC_NYET, - HC_STALL, - HC_XACTERR, - HC_BBLERR, - HC_DATATGLERR -} USB_OTG_HCStateTypeDef; - -/** - * @brief USB Instance Initialization Structure definition - */ -typedef struct -{ - uint32_t dev_endpoints; /*!< Device Endpoints number. - This parameter depends on the used USB core. - This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ - - uint32_t Host_channels; /*!< Host Channels number. - This parameter Depends on the used USB core. - This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ - - uint32_t speed; /*!< USB Core speed. - This parameter can be any value of @ref USB_Core_Speed */ - - uint32_t dma_enable; /*!< Enable or disable of the USB embedded DMA used only for OTG HS. */ - - uint32_t ep0_mps; /*!< Set the Endpoint 0 Max Packet size. */ - - uint32_t phy_itface; /*!< Select the used PHY interface. - This parameter can be any value of @ref USB_Core_PHY */ - - uint32_t Sof_enable; /*!< Enable or disable the output of the SOF signal. */ - - uint32_t low_power_enable; /*!< Enable or disable the low power mode. */ - - uint32_t lpm_enable; /*!< Enable or disable Link Power Management. */ - - uint32_t battery_charging_enable; /*!< Enable or disable Battery charging. */ - - uint32_t vbus_sensing_enable; /*!< Enable or disable the VBUS Sensing feature. */ - - uint32_t use_dedicated_ep1; /*!< Enable or disable the use of the dedicated EP1 interrupt. */ - - uint32_t use_external_vbus; /*!< Enable or disable the use of the external VBUS. */ - -} USB_OTG_CfgTypeDef; - -typedef struct -{ - uint8_t num; /*!< Endpoint number - This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ - - uint8_t is_in; /*!< Endpoint direction - This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ - - uint8_t is_stall; /*!< Endpoint stall condition - This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ - - uint8_t type; /*!< Endpoint type - This parameter can be any value of @ref USB_EP_Type_ */ - - uint8_t data_pid_start; /*!< Initial data PID - This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ - - uint8_t even_odd_frame; /*!< IFrame parity - This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ - - uint16_t tx_fifo_num; /*!< Transmission FIFO number - This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ - - uint32_t maxpacket; /*!< Endpoint Max packet size - This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */ - - uint8_t *xfer_buff; /*!< Pointer to transfer buffer */ - - uint32_t dma_addr; /*!< 32 bits aligned transfer buffer address */ - - uint32_t xfer_len; /*!< Current transfer length */ - - uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer */ -} USB_OTG_EPTypeDef; - -typedef struct -{ - uint8_t dev_addr; /*!< USB device address. - This parameter must be a number between Min_Data = 1 and Max_Data = 255 */ - - uint8_t ch_num; /*!< Host channel number. - This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ - - uint8_t ep_num; /*!< Endpoint number. - This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ - - uint8_t ep_is_in; /*!< Endpoint direction - This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ - - uint8_t speed; /*!< USB Host speed. - This parameter can be any value of @ref USB_Core_Speed_ */ - - uint8_t do_ping; /*!< Enable or disable the use of the PING protocol for HS mode. */ - - uint8_t process_ping; /*!< Execute the PING protocol for HS mode. */ - - uint8_t ep_type; /*!< Endpoint Type. - This parameter can be any value of @ref USB_EP_Type_ */ - - uint16_t max_packet; /*!< Endpoint Max packet size. - This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */ - - uint8_t data_pid; /*!< Initial data PID. - This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ - - uint8_t *xfer_buff; /*!< Pointer to transfer buffer. */ - - uint32_t xfer_len; /*!< Current transfer length. */ - - uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer. */ - - uint8_t toggle_in; /*!< IN transfer current toggle flag. - This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ - - uint8_t toggle_out; /*!< OUT transfer current toggle flag - This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ - - uint32_t dma_addr; /*!< 32 bits aligned transfer buffer address. */ - - uint32_t ErrCnt; /*!< Host channel error count. */ - - USB_OTG_URBStateTypeDef urb_state; /*!< URB state. - This parameter can be any value of @ref USB_OTG_URBStateTypeDef */ - - USB_OTG_HCStateTypeDef state; /*!< Host Channel state. - This parameter can be any value of @ref USB_OTG_HCStateTypeDef */ -} USB_OTG_HCTypeDef; - -#endif \ No newline at end of file +#define CLEAR_HC_INT(chnum, __INTERRUPT__) (USBx_HC(chnum)->HCINT = (__INTERRUPT__)) +#endif diff --git a/port/dwc2/usb_hc_dwc2.c b/port/dwc2/usb_hc_dwc2.c new file mode 100644 index 00000000..d8bf8a7d --- /dev/null +++ b/port/dwc2/usb_hc_dwc2.c @@ -0,0 +1,1389 @@ +#include "usbh_core.h" +#include "usb_dwc2_reg.h" + +#ifndef USBH_IRQHandler +#define USBH_IRQHandler OTG_HS_IRQHandler +#endif + +#ifndef USB_BASE +#define USB_BASE (0x40040000UL) +#endif + +#ifndef CONFIG_USB_DWC2_CHANNELS +#define CONFIG_USB_DWC2_CHANNELS 12 /* Number of host channels */ +#endif + +#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(USB_BASE)) +#define USB_OTG_PCGCCTL *(__IO uint32_t *)((uint32_t)USB_BASE + USB_OTG_PCGCCTL_BASE) +#define USBx_HPRT0 *(__IO uint32_t *)((uint32_t)USB_BASE + USB_OTG_HOST_PORT_BASE) +#define USBx_HOST ((USB_OTG_HostTypeDef *)(USB_BASE + USB_OTG_HOST_BASE)) +#define USBx_HC(i) ((USB_OTG_HostChannelTypeDef *)(USB_BASE + USB_OTG_HOST_CHANNEL_BASE + ((i)*USB_OTG_HOST_CHANNEL_SIZE))) +#define USB_OTG_FIFO(i) *(__IO uint32_t *)(USB_BASE + USB_OTG_FIFO_BASE + ((i)*USB_OTG_FIFO_SIZE)) + +/* This structure retains the state of one host channel. NOTE: Since there + * is only one channel operation active at a time, some of the fields in + * in the structure could be moved in struct stm32_ubhost_s to achieve + * some memory savings. + */ + +struct dwc2_pipe { + uint8_t ep_addr; + uint8_t ep_type; + uint16_t ep_mps; + uint8_t speed; + uint8_t dev_addr; + uint8_t data_pid; + bool inuse; /* True: This channel is "in use" */ + uint8_t interval; /* Interrupt/isochronous EP polling interval */ + uint32_t xferlen; /* for HCTSIZx*/ + uint8_t num_packets; /* for HCTSIZx*/ + volatile int result; /* The result of the transfer */ + volatile uint32_t xfrd; /* Bytes transferred (at end of transfer) */ + volatile bool waiter; /* True: Thread is waiting for a channel event */ + usb_osal_sem_t waitsem; /* Channel wait semaphore */ + usb_osal_mutex_t exclsem; /* Support mutually exclusive access */ +#ifdef CONFIG_USBHOST_ASYNCH + usbh_asynch_callback_t callback; /* Transfer complete callback */ + void *arg; /* Argument that accompanies the callback */ +#endif +}; + +/* A channel represents on uni-directional endpoint. So, in the case of the + * bi-directional, control endpoint, there must be two channels to represent + * the endpoint. + */ + +struct usb_dwc2_ctrlinfo { + uint8_t inndx; /* EP0 IN control channel index */ + uint8_t outndx; /* EP0 OUT control channel index */ +}; + +struct dwc2_hcd { + volatile bool connected; + struct usb_work work; + struct dwc2_pipe chan[CONFIG_USB_DWC2_CHANNELS]; +} g_dwc2_hcd; + +static int usb_dwc2_reset(void) +{ + uint32_t count = 0U; + + /* Wait for AHB master IDLE state. */ + do { + if (++count > 200000U) { + return -1; + } + } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U); + + /* Core Soft Reset */ + count = 0U; + USB_OTG_GLB->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + + do { + if (++count > 200000U) { + return -1; + } + } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); + + return 0; +} + +static inline int usb_dwc2_core_init(void) +{ + int ret; +#if defined(CONFIG_USB_DWC2_ULPI_PHY) + +#else + /* Select FS Embedded PHY */ + USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; +#endif + /* Reset after a PHY select */ + ret = usb_dwc2_reset(); + + /* Activate the USB Transceiver */ + USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_PWRDWN; + + return ret; +} + +static void usb_dwc2_set_mode(uint8_t mode) +{ + USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD); + + if (mode == USB_OTG_MODE_HOST) { + USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD; + } else if (mode == USB_OTG_MODE_DEVICE) { + USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + } +} + +static int usb_dwc2_flush_rxfifo(void) +{ + uint32_t count = 0; + + USB_OTG_GLB->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; + + do { + if (++count > 200000U) { + return -1; + } + } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH); + + return 0; +} + +static int usb_dwc2_flush_txfifo(uint32_t num) +{ + uint32_t count = 0U; + + USB_OTG_GLB->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (num << 6)); + + do { + if (++count > 200000U) { + return -1; + } + } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH); + + return 0; +} + +static void usb_dwc2_drivebus(uint8_t state) +{ + __IO uint32_t hprt0 = 0U; + + hprt0 = USBx_HPRT0; + + hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG); + + if (((hprt0 & USB_OTG_HPRT_PPWR) == 0U) && (state == 1U)) { + USBx_HPRT0 = (USB_OTG_HPRT_PPWR | hprt0); + } + if (((hprt0 & USB_OTG_HPRT_PPWR) == USB_OTG_HPRT_PPWR) && (state == 0U)) { + USBx_HPRT0 = ((~USB_OTG_HPRT_PPWR) & hprt0); + } +} + +/** + * @brief USB_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the + * HCFG register on the PHY type and set the right frame interval + * @param USBx Selected device + * @param freq clock frequency + * This parameter can be one of these values: + * HCFG_48_MHZ : Full Speed 48 MHz Clock + * HCFG_6_MHZ : Low Speed 6 MHz Clock + * @retval HAL status + */ +static void usb_dwc2_init_fsls_pclksel(uint8_t freq) +{ + USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSPCS); + USBx_HOST->HCFG |= (uint32_t)freq & USB_OTG_HCFG_FSLSPCS; + + if (freq == HCFG_48_MHZ) { + USBx_HOST->HFIR = 48000U; + } else if (freq == HCFG_6_MHZ) { + USBx_HOST->HFIR = 6000U; + } else { + /* ... */ + } +} + +static void dwc2_pipe_init(uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uint8_t ep_type, uint8_t ep_mps, uint8_t speed) +{ + uint32_t regval; + + /* Clear old interrupt conditions for this host channel. */ + USBx_HC((uint32_t)ch_num)->HCINT = 0xFFFFFFFFU; + + /* Enable channel interrupts required for this transfer. */ + regval = USB_OTG_HCINTMSK_XFRCM | + USB_OTG_HCINTMSK_STALLM | + USB_OTG_HCINTMSK_TXERRM | + USB_OTG_HCINTMSK_DTERRM | + USB_OTG_HCINTMSK_AHBERR; + + if ((ep_addr & 0x80U) == 0x80U) { + regval |= USB_OTG_HCINTMSK_BBERRM; + } + + switch (ep_type) { + case USB_ENDPOINT_TYPE_CONTROL: + case USB_ENDPOINT_TYPE_BULK: + if ((ep_addr & 0x80U) == 0x00U) { + regval |= USB_OTG_HCINTMSK_NYET; + } + break; + case USB_ENDPOINT_TYPE_INTERRUPT: + regval |= USB_OTG_HCINTMSK_FRMORM | USB_OTG_HCINTMSK_NAKM; + break; + case USB_ENDPOINT_TYPE_ISOCHRONOUS: + regval |= USB_OTG_HCINTMSK_FRMORM; + break; + } + + USBx_HC((uint32_t)ch_num)->HCINTMSK = regval; + + /* Enable the top level host channel interrupt. */ + USBx_HOST->HAINTMSK |= 1UL << (ch_num & 0xFU); + + /* Make sure host channel interrupts are enabled. */ + USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_HCIM; + + /* Program the HCCHAR register */ + + regval = (((uint32_t)ep_mps << USB_OTG_HCCHAR_MPSIZ_Pos) & USB_OTG_HCCHAR_MPSIZ) | + ((((uint32_t)ep_addr & 0x7FU) << USB_OTG_HCCHAR_EPNUM_Pos) & USB_OTG_HCCHAR_EPNUM) | + (((uint32_t)ep_type << USB_OTG_HCCHAR_EPTYP_Pos) & USB_OTG_HCCHAR_EPTYP) | + (((uint32_t)devaddr << USB_OTG_HCCHAR_DAD_Pos) & USB_OTG_HCCHAR_DAD); + + if ((ep_addr & 0x80U) == 0x80U) { + regval |= USB_OTG_HCCHAR_EPDIR; + } + + /* LS device plugged to HUB */ + if (speed == USB_SPEED_LOW) { + regval |= USB_OTG_HCCHAR_LSDEV; + } + + if (ep_type == USB_ENDPOINT_TYPE_INTERRUPT) { + regval |= USB_OTG_HCCHAR_ODDFRM; + } + + USBx_HC((uint32_t)ch_num)->HCCHAR = regval; +} + +static uint8_t usb_dwc2_calculate_packet_num(uint32_t input_size, uint8_t ep_addr, uint16_t ep_mps, uint32_t *output_size) +{ + uint16_t num_packets; + + num_packets = (uint16_t)((input_size + ep_mps - 1U) / ep_mps); + + if (num_packets > 256) { + num_packets = 256; + } + + if (input_size == 0) { + num_packets = 1; + } + + if (ep_addr & 0x80) { + input_size = num_packets * ep_mps; + } else { + } + + *output_size = input_size; + return num_packets; +} +/* +* For IN channel HCTSIZ.XferSize is expected to be an integer multiple of +* max_packet size. +*/ +static inline void usb_dwc2_pipe_transfer(uint8_t ch_num, uint8_t ep_addr, uint32_t *buf, uint32_t size, uint8_t num_packets, uint8_t pid) +{ + __IO uint32_t tmpreg; + uint8_t is_oddframe; + + /* Initialize the HCTSIZn register */ + USBx_HC(ch_num)->HCTSIZ = (size & USB_OTG_HCTSIZ_XFRSIZ) | + (((uint32_t)num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) | + (((uint32_t)pid << 29) & USB_OTG_HCTSIZ_DPID); + + /* xfer_buff MUST be 32-bits aligned */ + USBx_HC(ch_num)->HCDMA = (uint32_t)buf; + + is_oddframe = (((uint32_t)USBx_HOST->HFNUM & 0x01U) != 0U) ? 0U : 1U; + USBx_HC(ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_ODDFRM; + USBx_HC(ch_num)->HCCHAR |= (uint32_t)is_oddframe << 29; + + /* make sure to set the correct ep direction */ + if (ep_addr & 0x80) { + tmpreg |= USB_OTG_HCCHAR_EPDIR; + } else { + tmpreg &= ~USB_OTG_HCCHAR_EPDIR; + } + + /* Set host channel enable */ + tmpreg = USBx_HC(ch_num)->HCCHAR; + tmpreg &= ~USB_OTG_HCCHAR_CHDIS; + tmpreg |= USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR = tmpreg; +} + +static void usb_dwc2_halt(uint8_t ch_num) +{ + uint32_t count = 0U; + uint32_t HcEpType = (USBx_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_EPTYP) >> 18; + uint32_t ChannelEna = (USBx_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) >> 31; + + if (((USB_OTG_GLB->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == USB_OTG_GAHBCFG_DMAEN) && + (ChannelEna == 0U)) { + return; + } + + /* Check for space in the request queue to issue the halt. */ + if ((HcEpType == HCCHAR_CTRL) || (HcEpType == HCCHAR_BULK)) { + USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_CHDIS; + + if ((USB_OTG_GLB->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == 0U) { + if ((USB_OTG_GLB->HNPTXSTS & (0xFFU << 16)) == 0U) { + USBx_HC(ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR; + do { + if (++count > 1000U) { + break; + } + } while ((USBx_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA); + } else { + USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + } + } + } else { + USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_CHDIS; + + if ((USBx_HOST->HPTXSTS & (0xFFU << 16)) == 0U) { + USBx_HC(ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR; + do { + if (++count > 1000U) { + break; + } + } while ((USBx_HC(ch_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA); + } else { + USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + } + } +} +/** + * @brief USB_ReadInterrupts: return the global USB interrupt status + * @retval status + */ +static inline uint32_t usb_dwc2_get_glb_intstatus(void) +{ + uint32_t tmpreg; + + tmpreg = USB_OTG_GLB->GINTSTS; + tmpreg &= USB_OTG_GLB->GINTMSK; + + return tmpreg; +} + +/**************************************************************************** + * Name: dwc2_pipe_alloc + * + * Description: + * Allocate a channel. + * + ****************************************************************************/ + +static int dwc2_pipe_alloc(void) +{ + int chidx; + + /* Search the table of channels */ + + for (chidx = 0; chidx < CONFIG_USB_DWC2_CHANNELS; chidx++) { + /* Is this channel available? */ + if (!g_dwc2_hcd.chan[chidx].inuse) { + /* Yes... make it "in use" and return the index */ + + g_dwc2_hcd.chan[chidx].inuse = true; + return chidx; + } + } + + /* All of the channels are "in-use" */ + + return -EBUSY; +} + +/**************************************************************************** + * Name: dwc2_pipe_free + * + * Description: + * Free a previoiusly allocated channel. + * + ****************************************************************************/ + +static void dwc2_pipe_free(int chidx) +{ + /* Mark the channel available */ + + g_dwc2_hcd.chan[chidx].inuse = false; +} + +/**************************************************************************** + * Name: dwc2_pipe_freeall + * + * Description: + * Free all channels. + * + ****************************************************************************/ + +static inline void dwc2_pipe_freeall(void) +{ + uint8_t chidx; + + /* Free all host channels */ + + for (chidx = 1; chidx < CONFIG_USB_DWC2_CHANNELS; chidx++) { + dwc2_pipe_free(chidx); + } +} + +/**************************************************************************** + * Name: dwc2_pipe_waitsetup + * + * Description: + * Set the request for the transfer complete event well BEFORE enabling + * the transfer (as soon as we are absolutely committed to the transfer). + * We do this to minimize race conditions. This logic would have to be + * expanded if we want to have more than one packet in flight at a time! + * + * Assumptions: + * Called from a normal thread context BEFORE the transfer has been + * started. + * + ****************************************************************************/ + +static int dwc2_pipe_waitsetup(struct dwc2_pipe *chan) +{ + size_t flags; + int ret = -ENODEV; + + flags = usb_osal_enter_critical_section(); + + /* Is the device still connected? */ + + if (usbh_get_port_connect_status(1)) { + /* Yes.. then set waiter to indicate that we expect to be informed + * when either (1) the device is disconnected, or (2) the transfer + * completed. + */ + chan->waiter = true; + chan->result = -EBUSY; + chan->xfrd = 0; +#ifdef CONFIG_USBHOST_ASYNCH + chan->callback = NULL; + chan->arg = NULL; +#endif + ret = 0; + } + usb_osal_leave_critical_section(flags); + return ret; +} + +/**************************************************************************** + * Name: dwc2_pipe_asynchsetup + * + * Description: + * Set the request for the transfer complete event well BEFORE enabling + * the transfer (as soon as we are absolutely committed to the to avoid + * transfer). We do this to minimize race conditions. This logic would + * have to be expanded if we want to have more than one packet in flight + * at a time! + * + * Assumptions: + * Might be called from the level of an interrupt handler + * + ****************************************************************************/ + +#ifdef CONFIG_USBHOST_ASYNCH +static int dwc2_pipe_asynchsetup(struct dwc2_pipe *chan, usbh_asynch_callback_t callback, void *arg) +{ + size_t flags; + int ret = -ENODEV; + + flags = usb_osal_enter_critical_section(); + /* Is the device still connected? */ + + if (usbh_get_port_connect_status(1)) { + /* Yes.. then set waiter to indicate that we expect to be informed + * when either (1) the device is disconnected, or (2) the transfer + * completed. + */ + + chan->waiter = false; + chan->result = -EBUSY; + chan->xfrd = 0; + chan->callback = callback; + chan->arg = arg; + + ret = 0; + } + + usb_osal_leave_critical_section(flags); + return ret; +} +#endif + +/**************************************************************************** + * Name: dwc2_pipe_wait + * + * Description: + * Wait for a transfer on a channel to complete. + * + * Assumptions: + * Called from a normal thread context + * + ****************************************************************************/ + +static int dwc2_pipe_wait(struct dwc2_pipe *chan, uint32_t timeout) +{ + int ret; + + /* Loop, testing for an end of transfer condition. The channel 'result' + * was set to EBUSY and 'waiter' was set to true before the transfer; + * 'waiter' will be set to false and 'result' will be set appropriately + * when the transfer is completed. + */ + + if (chan->waiter) { + ret = usb_osal_sem_take(chan->waitsem, timeout); + if (ret < 0) { + return ret; + } + } + + /* The transfer is complete re-enable interrupts and return the result */ + ret = chan->result; + + if (ret < 0) { + return ret; + } + return chan->xfrd; +} + +/**************************************************************************** + * Name: dwc2_pipe_wakeup + * + * Description: + * A channel transfer has completed... wakeup any threads waiting for the + * transfer to complete. + * + * Assumptions: + * This function is called from the transfer complete interrupt handler for + * the channel. Interrupts are disabled. + * + ****************************************************************************/ + +static void dwc2_pipe_wakeup(struct dwc2_pipe *chan) +{ + usbh_asynch_callback_t callback; + void *arg; + int nbytes; + + /* Is the transfer complete? */ + + if (chan->result != -EBUSY) { + /* Is there a thread waiting for this transfer to complete? */ + + if (chan->waiter) { + /* Wake'em up! */ + chan->waiter = false; + usb_osal_sem_give(chan->waitsem); + } +#ifdef CONFIG_USBHOST_ASYNCH + /* No.. is an asynchronous callback expected when the transfer + * completes? + */ + else if (chan->callback) { + callback = chan->callback; + arg = chan->arg; + nbytes = chan->xfrd; + chan->callback = NULL; + chan->arg = NULL; + if (chan->result < 0) { + nbytes = chan->result; + } + + callback(arg, nbytes); + } +#endif + } +} + +__WEAK void usb_hc_low_level_init(void) +{ +} + +int usb_hc_sw_init(void) +{ + memset(&g_dwc2_hcd, 0, sizeof(struct dwc2_hcd)); + + for (uint8_t chidx = 0; chidx < CONFIG_USB_DWC2_CHANNELS; chidx++) { + g_dwc2_hcd.chan[chidx].exclsem = usb_osal_mutex_create(); + g_dwc2_hcd.chan[chidx].waitsem = usb_osal_sem_create(0); + } + + return 0; +} + +int usb_hc_hw_init(void) +{ + int ret; + + usb_hc_low_level_init(); + + USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT; + + ret = usb_dwc2_core_init(); + /* Force Host Mode*/ + usb_dwc2_set_mode(USB_OTG_MODE_HOST); + usb_osal_msleep(50); + + /* Restart the Phy Clock */ + USB_OTG_PCGCCTL = 0U; + +#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) || \ + defined(STM32F7) || defined(STM32H7) + /* Disable HW VBUS sensing */ + USB_OTG_GLB->GCCFG &= ~(USB_OTG_GCCFG_VBDEN); +#else + /* + * Disable HW VBUS sensing. VBUS is internally considered to be always + * at VBUS-Valid level (5V). + */ + USB_OTG_GLB->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS; + USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN; + USB_OTG_GLB->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN; +#endif + USBx_HOST->HCFG |= USB_OTG_HCFG_FSLSPCS_0; + usbh_reset_port(1); + + /* Set default Max speed support */ + USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS); + + ret = usb_dwc2_flush_txfifo(0x10U); + ret = usb_dwc2_flush_rxfifo(); + + /* Clear all pending HC Interrupts */ + for (uint8_t i = 0U; i < CONFIG_USB_DWC2_CHANNELS; i++) { + USBx_HC(i)->HCINT = 0xFFFFFFFFU; + USBx_HC(i)->HCINTMSK = 0U; + } + + usb_dwc2_drivebus(1); + usb_osal_msleep(200); + + /* Disable all interrupts. */ + USB_OTG_GLB->GINTMSK = 0U; + + /* Clear any pending interrupts */ + USB_OTG_GLB->GINTSTS = 0xFFFFFFFFU; + + /* set Rx FIFO size */ + USB_OTG_GLB->GRXFSIZ = 0x200U; + USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((0x100U << 16) & USB_OTG_NPTXFD) | 0x200U); + USB_OTG_GLB->HPTXFSIZ = (uint32_t)(((0xE0U << 16) & USB_OTG_HPTXFSIZ_PTXFD) | 0x300U); + + USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_HBSTLEN_2; + USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_DMAEN; + + /* Enable interrupts matching to the Host mode ONLY */ + USB_OTG_GLB->GINTMSK |= (USB_OTG_GINTMSK_PRTIM | USB_OTG_GINTMSK_HCIM | + USB_OTG_GINTSTS_DISCINT | + USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM); + + // USB_OTG_GLB->GINTMSK |=USB_OTG_GINTMSK_SOFM; + + USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + + return 0; +} + +bool usbh_get_port_connect_status(const uint8_t port) +{ + __IO uint32_t hprt0; + + hprt0 = USBx_HPRT0; + + if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) { + return true; + } else { + return false; + } +} + +int usbh_reset_port(const uint8_t port) +{ + __IO uint32_t hprt0 = 0U; + + hprt0 = USBx_HPRT0; + + hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG); + + USBx_HPRT0 = (USB_OTG_HPRT_PRST | hprt0); + usb_osal_msleep(100U); /* See Note #1 */ + USBx_HPRT0 = ((~USB_OTG_HPRT_PRST) & hprt0); + usb_osal_msleep(10U); + return 0; +} + +uint8_t usbh_get_port_speed(const uint8_t port) +{ + __IO uint32_t hprt0 = 0U; + uint8_t speed; + + hprt0 = USBx_HPRT0; + + speed = (hprt0 & USB_OTG_HPRT_PSPD) >> 17; + + if (speed == HPRT0_PRTSPD_HIGH_SPEED) { + return USB_SPEED_HIGH; + } else if (speed == HPRT0_PRTSPD_FULL_SPEED) { + return USB_SPEED_FULL; + } else if (speed == HPRT0_PRTSPD_LOW_SPEED) { + return USB_SPEED_LOW; + } else { + return USB_SPEED_UNKNOWN; + } +} + +int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed) +{ + struct dwc2_pipe *chan; + int chidx; + int ret; + + chidx = (int)ep; + + chan = &g_dwc2_hcd.chan[chidx]; + ret = usb_osal_mutex_take(chan->exclsem); + if (ret < 0) { + return ret; + } + chan->dev_addr = dev_addr; + chan->ep_mps = ep_mps; + chan->speed = speed; + usb_osal_mutex_give(chan->exclsem); + return 0; +} + +int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg) +{ + struct dwc2_pipe *chan; + struct usbh_hubport *hport; + int chidx; + uint8_t speed; + + hport = ep_cfg->hport; + + chidx = dwc2_pipe_alloc(); + + chan = &g_dwc2_hcd.chan[chidx]; + chan->ep_addr = ep_cfg->ep_addr; + chan->ep_mps = ep_cfg->ep_mps; + chan->ep_type = ep_cfg->ep_type; + chan->dev_addr = hport->dev_addr; + chan->speed = hport->speed; + *ep = (usbh_epinfo_t)chidx; + + if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) { + chan->data_pid = HC_PID_DATA1; + } else { + dwc2_pipe_init(chidx, chan->dev_addr, ep_cfg->ep_addr, ep_cfg->ep_type, chan->ep_mps, chan->speed); + chan->data_pid = HC_PID_DATA0; + } + + return 0; +} + +int usbh_ep_free(usbh_epinfo_t ep) +{ + int chidx; + + chidx = (int)ep; + dwc2_pipe_free(chidx); + return 0; +} + +int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint8_t *buffer) +{ + struct dwc2_pipe *chan; + int chidx; + int ret; + + chidx = (int)ep; + + chan = &g_dwc2_hcd.chan[chidx]; + ret = usb_osal_mutex_take(chan->exclsem); + if (ret < 0) { + return ret; + } + + ret = dwc2_pipe_waitsetup(chan); + if (ret < 0) { + goto error_out; + } + + chan->waiter = true; + chan->result = -EBUSY; + chan->num_packets = usb_dwc2_calculate_packet_num(8, chan->ep_addr, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chidx, chan->dev_addr, 0x00, 0x00, chan->ep_mps, chan->speed); + usb_dwc2_pipe_transfer(chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP); + ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); + if (ret < 0) { + goto error_out; + } + + if (setup->wLength && buffer) { + if (setup->bmRequestType & 0x80) { + chan->waiter = true; + chan->result = -EBUSY; + chan->num_packets = usb_dwc2_calculate_packet_num(setup->wLength, 0x80, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chidx, chan->dev_addr, 0x80, 0x00, chan->ep_mps, chan->speed); + usb_dwc2_pipe_transfer(chidx, 0x80, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1); + ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); + if (ret < 0) { + goto error_out; + } + chan->waiter = true; + chan->result = -EBUSY; + chan->num_packets = usb_dwc2_calculate_packet_num(0, 0x00, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chidx, chan->dev_addr, 0x00, 0x00, chan->ep_mps, chan->speed); + usb_dwc2_pipe_transfer(chidx, 0x00, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); + ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); + if (ret < 0) { + goto error_out; + } + } else { + chan->waiter = true; + chan->result = -EBUSY; + chan->num_packets = usb_dwc2_calculate_packet_num(setup->wLength, 0x00, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chidx, chan->dev_addr, 0x00, 0x00, chan->ep_mps, chan->speed); + usb_dwc2_pipe_transfer(chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1); + ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); + if (ret < 0) { + goto error_out; + } + chan->waiter = true; + chan->result = -EBUSY; + chan->num_packets = usb_dwc2_calculate_packet_num(0, 0x80, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chidx, chan->dev_addr, 0x80, 0x00, chan->ep_mps, chan->speed); + usb_dwc2_pipe_transfer(chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); + ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); + if (ret < 0) { + goto error_out; + } + } + } else { + chan->waiter = true; + chan->result = -EBUSY; + chan->num_packets = usb_dwc2_calculate_packet_num(0, 0x80, chan->ep_mps, &chan->xferlen); + dwc2_pipe_init(chidx, chan->dev_addr, 0x80, 0x00, chan->ep_mps, chan->speed); + usb_dwc2_pipe_transfer(chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1); + ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); + if (ret < 0) { + goto error_out; + } + } + usb_osal_mutex_give(chan->exclsem); + return ret; +error_out: + chan->waiter = false; + usb_osal_mutex_give(chan->exclsem); + return ret; +} + +int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + struct dwc2_pipe *chan; + int chidx; + int ret; + + chidx = (int)ep; + + chan = &g_dwc2_hcd.chan[chidx]; + ret = usb_osal_mutex_take(chan->exclsem); + if (ret < 0) { + return ret; + } + + ret = dwc2_pipe_waitsetup(chan); + if (ret < 0) { + goto error_out; + } + + chan->num_packets = usb_dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen); + usb_dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid); + ret = dwc2_pipe_wait(chan, timeout); + if (ret < 0) { + goto error_out; + } + + usb_osal_mutex_give(chan->exclsem); + return ret; +error_out: + chan->waiter = false; + usb_osal_mutex_give(chan->exclsem); + return ret; +} + +int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) +{ + struct dwc2_pipe *chan; + int chidx; + int ret; + + chidx = (int)ep; + + chan = &g_dwc2_hcd.chan[chidx]; + ret = usb_osal_mutex_take(chan->exclsem); + if (ret < 0) { + return ret; + } + + ret = dwc2_pipe_waitsetup(chan); + if (ret < 0) { + goto error_out; + } + + chan->num_packets = usb_dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen); + usb_dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid); + ret = dwc2_pipe_wait(chan, timeout); + if (ret < 0) { + goto error_out; + } + usb_osal_mutex_give(chan->exclsem); + return ret; +error_out: + chan->waiter = false; + usb_osal_mutex_give(chan->exclsem); + return ret; +} + +int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) +{ + struct dwc2_pipe *chan; + int chidx; + int ret; + + chidx = (int)ep; + + chan = &g_dwc2_hcd.chan[chidx]; + ret = usb_osal_mutex_take(chan->exclsem); + if (ret < 0) { + return ret; + } + + ret = dwc2_pipe_asynchsetup(chan, callback, arg); + if (ret < 0) { + goto error_out; + } + + chan->num_packets = usb_dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen); + usb_dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid); + + return 0; +error_out: + usb_osal_mutex_give(chan->exclsem); + return ret; +} + +int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) +{ + struct dwc2_pipe *chan; + int chidx; + int ret; + + chidx = (int)ep; + + chan = &g_dwc2_hcd.chan[chidx]; + ret = usb_osal_mutex_take(chan->exclsem); + if (ret < 0) { + return ret; + } + + ret = dwc2_pipe_asynchsetup(chan, callback, arg); + if (ret < 0) { + goto error_out; + } + + chan->num_packets = usb_dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen); + usb_dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid); + + return 0; +error_out: + usb_osal_mutex_give(chan->exclsem); + return ret; +} + +int usb_ep_cancel(usbh_epinfo_t ep) +{ + struct dwc2_pipe *chan; + int chidx; + int ret; + size_t flags; +#ifdef CONFIG_USBHOST_ASYNCH + usbh_asynch_callback_t callback; + void *arg; +#endif + + chidx = (int)ep; + chan = &g_dwc2_hcd.chan[chidx]; + + flags = usb_osal_enter_critical_section(); + + chan->result = -ESHUTDOWN; +#ifdef CONFIG_USBHOST_ASYNCH + /* Extract the callback information */ + callback = chan->callback; + arg = chan->arg; + chan->callback = NULL; + chan->arg = NULL; + chan->xfrd = 0; +#endif + usb_osal_leave_critical_section(flags); + + /* Is there a thread waiting for this transfer to complete? */ + + if (chan->waiter) { + /* Wake'em up! */ + chan->waiter = false; + usb_osal_sem_give(chan->waitsem); + } +#ifdef CONFIG_USBHOST_ASYNCH + /* No.. is an asynchronous callback expected when the transfer completes? */ + else if (callback) { + /* Then perform the callback */ + callback(arg, -ESHUTDOWN); + } +#endif + return 0; +} + +void usb_dwc2_reset_handler(void *arg) +{ + usbh_reset_port(1); +} + +//static void usb_dwc2_rxqlvl_irq_handler(void) +//{ +// uint32_t pktsts; +// uint32_t pktcnt; +// uint32_t GrxstspReg; +// uint32_t xferSizePktCnt; +// uint32_t tmpreg; +// uint32_t ch_num; +// uint32_t len32b; +// uint32_t *pdest; +// struct dwc2_pipe *chan; + +// GrxstspReg = USB_OTG_GLB->GRXSTSP; +// ch_num = GrxstspReg & USB_OTG_GRXSTSP_EPNUM; +// pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17; +// pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4; + +// chan = &g_dwc2_hcd.chan[ch_num]; +// switch (pktsts) { +// case GRXSTS_PKTSTS_IN: +// /* Read the data into the host buffer. */ +// if ((pktcnt > 0U) && (chan->buffer != NULL)) { +// len32b = ((uint32_t)pktcnt + 3U) / 4U; + +// pdest = (uint32_t *)chan->buffer; + +// for (uint8_t i = 0U; i < len32b; i++) { +// *pdest = USB_OTG_FIFO(0U); +// pdest++; +// } + +// chan->buffer += pktcnt; +// chan->xfrd += pktcnt; +// chan->buflen -= pktcnt; + +// if (chan->buflen == 0) { +// } +// } +// break; + +// case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: +// break; + +// case GRXSTS_PKTSTS_IN_XFER_COMP: +// case GRXSTS_PKTSTS_CH_HALTED: +// default: +// break; +// } +//} + +static void usb_dwc2_inchan_irq_handler(uint8_t ch_num) +{ + uint32_t chan_intstatus; + struct dwc2_pipe *chan; + + chan_intstatus = (USBx_HC(ch_num)->HCINT) & (USBx_HC((uint32_t)ch_num)->HCINTMSK); + + chan = &g_dwc2_hcd.chan[ch_num]; + + if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) { + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC); + usb_dwc2_halt(ch_num); + chan->result = 0; + USB_UNMASK_HALT_HC_INT(ch_num); + } else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) { + USB_UNMASK_HALT_HC_INT(ch_num); + chan->result = -EIO; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR); + } else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EPERM; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL); + } else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EAGAIN; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); + } else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) { + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK); + } else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EAGAIN; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET); + } else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EIO; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR); + } else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EIO; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR); + } else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EPIPE; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR); + } else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EIO; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR); + } else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) { + USB_MASK_HALT_HC_INT(ch_num); + + if (chan->result == 0) { + uint32_t count = chan->xferlen - (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* size that has received */ + uint32_t has_sent_packets = chan->num_packets - ((USBx_HC(ch_num)->HCTSIZ & USB_OTG_DIEPTSIZ_PKTCNT) >> 19); /*how many packets has sent*/ + + chan->xfrd += count; + + if ((has_sent_packets % 2) == 1) /* Flip in odd numbers */ + { + if (chan->data_pid == HC_PID_DATA0) { + chan->data_pid = HC_PID_DATA1; + } else { + chan->data_pid = HC_PID_DATA0; + } + } + chan->result = 0; + } + dwc2_pipe_wakeup(chan); + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH); + } +} + +static void usb_dwc2_outchan_irq_handler(uint8_t ch_num) +{ + uint32_t chan_intstatus; + struct dwc2_pipe *chan; + uint16_t buflen; + + chan_intstatus = (USBx_HC(ch_num)->HCINT) & (USBx_HC((uint32_t)ch_num)->HCINTMSK); + + chan = &g_dwc2_hcd.chan[ch_num]; + + if ((chan_intstatus & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) { + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC); + usb_dwc2_halt(ch_num); + chan->result = 0; + USB_UNMASK_HALT_HC_INT(ch_num); + } else if ((chan_intstatus & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) { + USB_UNMASK_HALT_HC_INT(ch_num); + chan->result = -EIO; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR); + } else if ((chan_intstatus & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EPERM; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL); + } else if ((chan_intstatus & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EAGAIN; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); + } else if ((chan_intstatus & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) { + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK); + } else if ((chan_intstatus & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EAGAIN; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET); + } else if ((chan_intstatus & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EIO; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR); + } else if ((chan_intstatus & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EIO; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR); + } else if ((chan_intstatus & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EPIPE; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR); + } else if ((chan_intstatus & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) { + USB_UNMASK_HALT_HC_INT(ch_num); + usb_dwc2_halt(ch_num); + chan->result = -EIO; + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR); + } else if ((chan_intstatus & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) { + USB_MASK_HALT_HC_INT(ch_num); + + if (chan->result == 0) { + uint32_t count = (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); /* last send size */ + + if (count == chan->ep_mps) { + chan->xfrd += chan->num_packets * chan->ep_mps; + } else { + chan->xfrd += (chan->num_packets - 1) * chan->ep_mps + count; + } + + if ((chan->num_packets % 2) == 1) /* Flip in odd numbers */ + { + if (chan->data_pid == HC_PID_DATA0) { + chan->data_pid = HC_PID_DATA1; + } else { + chan->data_pid = HC_PID_DATA0; + } + } + chan->result = 0; + } + dwc2_pipe_wakeup(chan); + CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH); + } +} + +static void usb_dwc2_port_irq_handler(void) +{ + __IO uint32_t hprt0, hprt0_dup, regval; + + /* Handle Host Port Interrupts */ + hprt0 = USBx_HPRT0; + hprt0_dup = USBx_HPRT0; + + hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG); + + /* Check whether Port Connect detected */ + if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET) { + if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) { + usb_workqueue_submit(&g_hpworkq, &g_dwc2_hcd.work, usb_dwc2_reset_handler, NULL, 0); + } + hprt0_dup |= USB_OTG_HPRT_PCDET; + } + + /* Check whether Port Enable Changed */ + if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG) { + hprt0_dup |= USB_OTG_HPRT_PENCHNG; + + if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) { +#if defined(CONFIG_USB_DWC2_ULPI_PHY) +#else + if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17)) { + USBx_HOST->HFIR = 6000U; + if ((USBx_HOST->HCFG & USB_OTG_HCFG_FSLSPCS) != USB_OTG_HCFG_FSLSPCS_1) { + regval = USBx_HOST->HCFG; + regval &= ~USB_OTG_HCFG_FSLSPCS; + regval |= USB_OTG_HCFG_FSLSPCS_1; + USBx_HOST->HCFG = regval; + usb_workqueue_submit(&g_hpworkq, &g_dwc2_hcd.work, usb_dwc2_reset_handler, NULL, 0); + } + } else { + USBx_HOST->HFIR = 48000U; + if ((USBx_HOST->HCFG & USB_OTG_HCFG_FSLSPCS) != USB_OTG_HCFG_FSLSPCS_0) { + regval = USBx_HOST->HCFG; + regval &= ~USB_OTG_HCFG_FSLSPCS; + regval |= USB_OTG_HCFG_FSLSPCS_0; + USBx_HOST->HCFG = regval; + usb_workqueue_submit(&g_hpworkq, &g_dwc2_hcd.work, usb_dwc2_reset_handler, NULL, 0); + } + } +#endif + + if (!g_dwc2_hcd.connected) { + g_dwc2_hcd.connected = true; + usbh_event_notify_handler(USBH_EVENT_CONNECTED, 1); + } + } else { + if (g_dwc2_hcd.connected) { + g_dwc2_hcd.connected = false; + + for (int chidx = 0; chidx < CONFIG_USB_DWC2_CHANNELS; chidx++) { + struct dwc2_pipe *chan; + chan = &g_dwc2_hcd.chan[chidx]; + if ((chan->ep_type == 0x00) && chan->waiter) { + chan->waiter = false; + usb_osal_sem_give(chan->waitsem); + } + } + usbh_event_notify_handler(USBH_EVENT_DISCONNECTED, 1); + } + } + } + + /* Check for an overcurrent */ + if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG) { + hprt0_dup |= USB_OTG_HPRT_POCCHNG; + } + /* Clear Port Interrupts */ + USBx_HPRT0 = hprt0_dup; +} + +void USBH_IRQHandler(void) +{ + uint32_t gint_status, chan_int; + gint_status = usb_dwc2_get_glb_intstatus(); + if ((USB_OTG_GLB->GINTSTS & 0x1U) == USB_OTG_MODE_HOST) { + /* Avoid spurious interrupt */ + if (gint_status == 0) { + return; + } + + if (gint_status & USB_OTG_GINTSTS_HPRTINT) { + usb_dwc2_port_irq_handler(); + } + if (gint_status & USB_OTG_GINTSTS_DISCINT) { + USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_DISCINT; + } + // if (gint_status & USB_OTG_GINTSTS_RXFLVL) { + // USB_MASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL); + // usb_dwc2_rxqlvl_irq_handler(); + // USB_UNMASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL); + // } + if (gint_status & USB_OTG_GINTSTS_HCINT) { + chan_int = (USBx_HOST->HAINT & USBx_HOST->HAINTMSK) & 0xFFFFU; + for (uint8_t i = 0U; i < CONFIG_USB_DWC2_CHANNELS; i++) { + if ((chan_int & (1UL << (i & 0xFU))) != 0U) { + if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR) { + usb_dwc2_inchan_irq_handler(i); + } else { + usb_dwc2_outchan_irq_handler(i); + } + } + } + USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_HCINT; + } + if (gint_status & USB_OTG_GINTSTS_SOF) { + USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_SOF; + } + } +} \ No newline at end of file diff --git a/port/synopsys/usb_dc_synopsys.c b/port/synopsys/usb_dc_synopsys.c deleted file mode 100644 index 25f08e6b..00000000 --- a/port/synopsys/usb_dc_synopsys.c +++ /dev/null @@ -1,696 +0,0 @@ -#include "usbd_core.h" -#include "usb_synopsys_reg.h" - -#if defined(CONFIG_USB_HS) || defined(CONFIG_USB_HS_IN_FULL) -#ifndef USBD_IRQHandler -#define USBD_IRQHandler OTG_HS_IRQHandler -#endif - -#ifndef USB_BASE -#define USB_BASE (0x40040000UL) -#endif - -#ifndef USB_NUM_BIDIR_ENDPOINTS -#define USB_NUM_BIDIR_ENDPOINTS 6 /* define with minimum value*/ -#endif - -#ifndef USB_RAM_SIZE -#define USB_RAM_SIZE 4096 /* define with minimum value*/ -#endif - -#else -#ifndef USBD_IRQHandler -#define USBD_IRQHandler OTG_FS_IRQHandler -#endif - -#ifndef USB_BASE -#define USB_BASE (0x50000000UL) -#endif - -#ifndef USB_NUM_BIDIR_ENDPOINTS -#define USB_NUM_BIDIR_ENDPOINTS 4 /* define with minimum value*/ -#endif - -#ifndef USB_RAM_SIZE -#define USB_RAM_SIZE 1280 /* define with minimum value*/ -#endif - -#endif - -#if defined(CONFIG_USB_HS) || defined(CONFIG_USB_HS_IN_FULL) -/*FIFO sizes in bytes (total available memory for FIFOs is 4 kB)*/ -#ifndef CONFIG_USB_RX_FIFO_SIZE -#define CONFIG_USB_RX_FIFO_SIZE (1024U) -#endif -#ifndef CONFIG_USB_TX0_FIFO_SIZE -#define CONFIG_USB_TX0_FIFO_SIZE (64U) -#endif -#ifndef CONFIG_USB_TX1_FIFO_SIZE -#define CONFIG_USB_TX1_FIFO_SIZE (1024U) -#endif -#ifndef CONFIG_USB_TX2_FIFO_SIZE -#define CONFIG_USB_TX2_FIFO_SIZE (512U) -#endif -#ifndef CONFIG_USB_TX3_FIFO_SIZE -#define CONFIG_USB_TX3_FIFO_SIZE (256U) -#endif -#ifndef CONFIG_USB_TX4_FIFO_SIZE -#define CONFIG_USB_TX4_FIFO_SIZE (256U) -#endif -#ifndef CONFIG_USB_TX5_FIFO_SIZE -#define CONFIG_USB_TX5_FIFO_SIZE (256U) -#endif -#else -/*FIFO sizes in bytes (total available memory for FIFOs is 1.25kB)*/ -#ifndef CONFIG_USB_RX_FIFO_SIZE -#define CONFIG_USB_RX_FIFO_SIZE (640U) -#endif -#ifndef CONFIG_USB_TX0_FIFO_SIZE -#define CONFIG_USB_TX0_FIFO_SIZE (64U) -#endif -#ifndef CONFIG_USB_TX1_FIFO_SIZE -#define CONFIG_USB_TX1_FIFO_SIZE (256U) -#endif -#ifndef CONFIG_USB_TX2_FIFO_SIZE -#define CONFIG_USB_TX2_FIFO_SIZE (160U) -#endif -#ifndef CONFIG_USB_TX3_FIFO_SIZE -#define CONFIG_USB_TX3_FIFO_SIZE (160U) -#endif -#endif - -#ifndef CONFIG_USB_TURNAROUND_TIME -#define CONFIG_USB_TURNAROUND_TIME 6 -#endif - -/* Endpoint state */ -struct usb_dc_ep_state { - /** Endpoint max packet size */ - uint16_t ep_mps; - /** Endpoint Transfer Type. - * May be Bulk, Interrupt, Control or Isochronous - */ - uint8_t ep_type; - uint8_t ep_stalled; /** Endpoint stall flag */ -}; - -/* Driver state */ -struct usb_dc_config_priv { - USB_OTG_GlobalTypeDef *Instance; /*!< Register base address */ - volatile uint32_t grxstsp; - struct usb_dc_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/ - struct usb_dc_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */ -} usb_dc_cfg; - -static int usb_flush_rxfifo(USB_OTG_GlobalTypeDef *USBx); -static int usb_flush_txfifo(USB_OTG_GlobalTypeDef *USBx, uint32_t num); -static void usb_set_txfifo(USB_OTG_GlobalTypeDef *USBx, uint8_t fifo, uint16_t size); - -__WEAK void usb_dc_low_level_init(void) -{ -} - -__WEAK void usb_dc_low_level_deinit(void) -{ -} - -int usb_dc_init(void) -{ - uint32_t USBx_BASE; - uint32_t count = 0U; - - memset(&usb_dc_cfg, 0, sizeof(struct usb_dc_config_priv)); - - usb_dc_cfg.Instance = (USB_OTG_GlobalTypeDef *)USB_BASE; - - USB_OTG_GlobalTypeDef *USBx = usb_dc_cfg.Instance; - - usb_dc_low_level_init(); - - USBx_BASE = (uint32_t)USBx; - - USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS; - - USBx->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT; -#if defined(CONFIG_USB_HS) - USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN); - - /* Init The ULPI Interface */ - USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL); - - /* Select vbus source */ - USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); - - //USBx->GUSBCFG |= USB_OTG_GUSBCFG_ULPIEVBUSD; - -#else - /* Select FS Embedded PHY */ - USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; - /* Activate the USB Transceiver */ - USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN; - -#endif - - /* Reset after a PHY select and set Host mode */ - /* Wait for AHB master IDLE state. */ - do { - if (++count > 200000U) { - return -1; - } - } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U); - - /* Core Soft Reset */ - count = 0U; - USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; - - do { - if (++count > 200000U) { - return -1; - } - } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); - - /* Force Device Mode*/ - USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; - - USBx->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - USBx->GUSBCFG |= (uint32_t)((CONFIG_USB_TURNAROUND_TIME << 10) & USB_OTG_GUSBCFG_TRDT); - - for (uint8_t i = 0U; i < 15U; i++) { - USBx->DIEPTXF[i] = 0U; - } - -#ifdef CONFIG_USB_SYNOPSYS_NOVBUSSEN - /* Deactivate VBUS Sensing B */ - USBx->GCCFG &= ~USB_OTG_GCCFG_VBDEN; - - /* B-peripheral session valid override enable */ - USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; - USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; -#else - USBx->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS; - USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN; - USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN; -#endif - /* Restart the Phy Clock */ - USBx_PCGCCTL = 0U; - - /* Device mode configuration */ - USBx_DEVICE->DCFG |= DCFG_FRAME_INTERVAL_80; -#if defined(CONFIG_USB_HS) - /* Set Core speed to High speed mode */ - USBx_DEVICE->DCFG |= USB_OTG_SPEED_HIGH; -#elif defined(CONFIG_USB_HS_IN_FULL) - USBx_DEVICE->DCFG |= USB_OTG_SPEED_HIGH_IN_FULL; -#else - USBx_DEVICE->DCFG |= USB_OTG_SPEED_FULL; -#endif - - usb_flush_txfifo(USBx, 0x10U); - usb_flush_rxfifo(USBx); - - /* Clear all pending Device Interrupts */ - USBx_DEVICE->DIEPMSK = 0U; - USBx_DEVICE->DOEPMSK = 0U; - USBx_DEVICE->DAINTMSK = 0U; - - for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { - if ((USBx_INEP(i)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA) { - if (i == 0U) { - USBx_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_SNAK; - } else { - USBx_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK; - } - } else { - USBx_INEP(i)->DIEPCTL = 0U; - } - - USBx_INEP(i)->DIEPTSIZ = 0U; - USBx_INEP(i)->DIEPINT = 0xFB7FU; - } - for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { - if ((USBx_OUTEP(i)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) { - if (i == 0U) { - USBx_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_SNAK; - } else { - USBx_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_EPDIS | USB_OTG_DOEPCTL_SNAK; - } - } else { - USBx_OUTEP(i)->DOEPCTL = 0U; - } - - USBx_OUTEP(i)->DOEPTSIZ = 0U; - USBx_OUTEP(i)->DOEPINT = 0xFB7FU; - } - - /* Disable all interrupts. */ - USBx->GINTMSK = 0U; - - /* Clear any pending interrupts */ - USBx->GINTSTS = 0xBFFFFFFFU; - - /* Enable interrupts matching to the Device mode ONLY */ - USBx->GINTMSK |= USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | - USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_RXFLVLM | - USB_OTG_GINTMSK_WUIM; -#if 0 - USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM; -#endif - USBx_DEVICE->DOEPMSK = USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; - - USBx_DEVICE->DIEPMSK = USB_OTG_DIEPMSK_XFRCM; - - USBx->GRXFSIZ = (CONFIG_USB_RX_FIFO_SIZE / 4); -#if defined(CONFIG_USB_HS) || defined(CONFIG_USB_HS_IN_FULL) - usb_set_txfifo(USBx, 0, CONFIG_USB_TX0_FIFO_SIZE / 4); - usb_set_txfifo(USBx, 1, CONFIG_USB_TX1_FIFO_SIZE / 4); - usb_set_txfifo(USBx, 2, CONFIG_USB_TX2_FIFO_SIZE / 4); - usb_set_txfifo(USBx, 3, CONFIG_USB_TX3_FIFO_SIZE / 4); - usb_set_txfifo(USBx, 4, CONFIG_USB_TX4_FIFO_SIZE / 4); - usb_set_txfifo(USBx, 5, CONFIG_USB_TX5_FIFO_SIZE / 4); -#else - usb_set_txfifo(USBx, 0, CONFIG_USB_TX0_FIFO_SIZE / 4); - usb_set_txfifo(USBx, 1, CONFIG_USB_TX1_FIFO_SIZE / 4); - usb_set_txfifo(USBx, 2, CONFIG_USB_TX2_FIFO_SIZE / 4); - usb_set_txfifo(USBx, 3, CONFIG_USB_TX3_FIFO_SIZE / 4); -#endif - USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT; - USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS; - - return 0; -} - -int usb_dc_deinit(void) -{ - USB_OTG_GlobalTypeDef *USBx = usb_dc_cfg.Instance; - uint32_t USBx_BASE = (uint32_t)USBx; - - usb_dc_low_level_deinit(); - /* Clear Pending interrupt */ - for (uint8_t i = 0U; i < 15U; i++) { - USBx_INEP(i)->DIEPINT = 0xFB7FU; - USBx_OUTEP(i)->DOEPINT = 0xFB7FU; - } - - /* Clear interrupt masks */ - USBx_DEVICE->DIEPMSK = 0U; - USBx_DEVICE->DOEPMSK = 0U; - USBx_DEVICE->DAINTMSK = 0U; - - /* Flush the FIFO */ - usb_flush_txfifo(USBx, 0x10U); - usb_flush_rxfifo(USBx); - - USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS; - - return 0; -} - -int usbd_set_address(const uint8_t addr) -{ - USB_OTG_GlobalTypeDef *USBx = usb_dc_cfg.Instance; - uint32_t USBx_BASE = (uint32_t)USBx; - USBx_DEVICE->DCFG &= ~(USB_OTG_DCFG_DAD); - USBx_DEVICE->DCFG |= ((uint32_t)addr << 4) & USB_OTG_DCFG_DAD; - return 0; -} - -int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg) -{ - USB_OTG_GlobalTypeDef *USBx = usb_dc_cfg.Instance; - uint32_t USBx_BASE = (uint32_t)USBx; - uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr); - - if (!ep_cfg) { - return -1; - } - - if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) { - usb_dc_cfg.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps; - usb_dc_cfg.out_ep[ep_idx].ep_type = ep_cfg->ep_type; - - USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & (uint32_t)(1UL << (16 + ep_idx)); - - USBx_OUTEP(ep_idx)->DOEPCTL |= (ep_cfg->ep_mps & USB_OTG_DOEPCTL_MPSIZ) | - ((uint32_t)ep_cfg->ep_type << 18) | - USB_OTG_DIEPCTL_SD0PID_SEVNFRM | - USB_OTG_DOEPCTL_USBAEP; - /* EP enable */ - USBx_OUTEP(ep_idx)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA); - } else { - usb_dc_cfg.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps; - usb_dc_cfg.in_ep[ep_idx].ep_type = ep_cfg->ep_type; - - USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << ep_idx); - - USBx_INEP(ep_idx)->DIEPCTL |= (ep_cfg->ep_mps & USB_OTG_DIEPCTL_MPSIZ) | - ((uint32_t)ep_cfg->ep_type << 18) | (ep_idx << 22) | - USB_OTG_DIEPCTL_SD0PID_SEVNFRM | - USB_OTG_DIEPCTL_USBAEP; - } - return 0; -} -int usbd_ep_close(const uint8_t ep) -{ - return 0; -} -int usbd_ep_set_stall(const uint8_t ep) -{ - USB_OTG_GlobalTypeDef *USBx = usb_dc_cfg.Instance; - uint32_t USBx_BASE = (uint32_t)USBx; - uint8_t ep_idx = USB_EP_GET_IDX(ep); - - if (USB_EP_DIR_IS_OUT(ep)) { - USBx_OUTEP(ep_idx)->DOEPCTL |= USB_OTG_DOEPCTL_STALL; - } else { - USBx_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_STALL; - } - - return 0; -} -int usbd_ep_clear_stall(const uint8_t ep) -{ - USB_OTG_GlobalTypeDef *USBx = usb_dc_cfg.Instance; - uint32_t USBx_BASE = (uint32_t)USBx; - uint8_t ep_idx = USB_EP_GET_IDX(ep); - - if (USB_EP_DIR_IS_OUT(ep)) { - USBx_OUTEP(ep_idx)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL; - } else { - USBx_INEP(ep_idx)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; - } - return 0; -} -int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled) -{ - if (USB_EP_DIR_IS_OUT(ep)) { - } else { - } - return 0; -} - -int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes) -{ - USB_OTG_GlobalTypeDef *USBx = usb_dc_cfg.Instance; - uint32_t USBx_BASE = (uint32_t)USBx; - uint8_t ep_idx = USB_EP_GET_IDX(ep); - uint32_t len32b; - - if (!data && data_len) { - return -1; - } - - if (!data_len) { - USBx_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); - USBx_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); - USBx_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19)); - /* EP enable, IN data in FIFO */ - USBx_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); - - return 0; - } - - if (data_len > usb_dc_cfg.in_ep[ep_idx].ep_mps) { - data_len = usb_dc_cfg.in_ep[ep_idx].ep_mps; - } - - /* Program the transfer size and packet count - * as follows: xfersize = N * maxpacket + - * short_packet pktcnt = N + (short_packet - * exist ? 1 : 0) - */ - USBx_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); - USBx_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); - USBx_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19)); - //USBx_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (((data_len + usb_dc_cfg.in_ep[ep_idx].ep_mps - 1U) / usb_dc_cfg.in_ep[ep_idx].ep_mps) << 19)); - USBx_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & data_len); - /* EP enable, IN data in FIFO */ - USBx_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); - - if (usb_dc_cfg.in_ep[ep_idx].ep_type == EP_TYPE_ISOC) { - USBx_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT); - USBx_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1U << 29)); - - if ((USBx_DEVICE->DSTS & (1U << 8)) == 0U) { - USBx_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM; - } else { - USBx_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; - } - } - - len32b = (data_len + 3U) / 4U; - - while (USBx_INEP(ep_idx)->DTXFSTS < len32b) { - } - for (uint8_t i = 0U; i < len32b; i++) { - USBx_DFIFO(ep_idx) = ((uint32_t *)data)[i]; - } - - if (ret_bytes) { - *ret_bytes = data_len; - } - - return 0; -} - -int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes) -{ - USB_OTG_GlobalTypeDef *USBx = usb_dc_cfg.Instance; - uint32_t USBx_BASE = (uint32_t)USBx; - uint8_t ep_idx = USB_EP_GET_IDX(ep); - uint32_t *pdest = (uint32_t *)data; - uint32_t len32b; - uint32_t read_count; - uint32_t pktcnt; - if (!data && max_data_len) { - return -1; - } - - if (!max_data_len) { - if (ep_idx != 0) { - /* Program the transfer size and packet count as follows: - * pktcnt = N - * xfersize = N * maxpacket - */ - pktcnt = (uint16_t)((max_data_len + usb_dc_cfg.out_ep[ep_idx].ep_mps - 1U) / usb_dc_cfg.out_ep[ep_idx].ep_mps); - USBx_OUTEP(ep_idx)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT); - USBx_OUTEP(ep_idx)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ); - USBx_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (pktcnt << 19)); - USBx_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & usb_dc_cfg.out_ep[ep_idx].ep_mps * pktcnt); - /* EP enable */ - USBx_OUTEP(ep_idx)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA); - } - - return 0; - } - - if (max_data_len > usb_dc_cfg.out_ep[ep_idx].ep_mps) { - max_data_len = usb_dc_cfg.out_ep[ep_idx].ep_mps; - } - - read_count = (usb_dc_cfg.grxstsp & USB_OTG_GRXSTSP_BCNT) >> 4; - read_count = MIN(read_count, max_data_len); - - len32b = ((uint32_t)read_count + 3U) / 4U; - - for (uint8_t i = 0U; i < len32b; i++) { - *pdest = USBx_DFIFO(0U); - pdest++; - } - - if (read_bytes) { - *read_bytes = read_count; - } - - usb_dc_cfg.grxstsp = 0; - return 0; -} - -void USBD_IRQHandler(void) -{ - USB_OTG_GlobalTypeDef *USBx = usb_dc_cfg.Instance; - uint32_t gint_status, temp, epnum, ep_intr, epint; - uint32_t USBx_BASE = (uint32_t)USBx; - gint_status = USBx->GINTSTS; - - if ((gint_status & 0x1U) == USB_OTG_MODE_DEVICE) { - if (gint_status == 0) { - return; - } - /* Handle RxQLevel Interrupt */ - if (gint_status & USB_OTG_GINTSTS_RXFLVL) { - USB_MASK_INTERRUPT(USBx, USB_OTG_GINTSTS_RXFLVL); - temp = USBx->GRXSTSP; - usb_dc_cfg.grxstsp = temp; - epnum = temp & USB_OTG_GRXSTSP_EPNUM; - if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_DATA_UPDT) { - if ((temp & USB_OTG_GRXSTSP_BCNT) != 0U) { - if (epnum == 0) { - usbd_event_notify_handler(USBD_EVENT_EP0_OUT_NOTIFY, NULL); - } else { - usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(epnum | USB_EP_DIR_OUT)); - } - } - } else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_SETUP_UPDT) { - uint8_t len = (temp & USB_OTG_GRXSTSP_BCNT) >> 4; - usbd_event_notify_handler(USBD_EVENT_SETUP_NOTIFY, NULL); - } else { - /* ... */ - } - USB_UNMASK_INTERRUPT(USBx, USB_OTG_GINTSTS_RXFLVL); - } - - if (gint_status & USB_OTG_GINTSTS_OEPINT) { - epnum = 0; - /* Read in the device interrupt bits */ - ep_intr = USBx_DEVICE->DAINT; - ep_intr &= USBx_DEVICE->DAINTMSK; - ep_intr >>= 16; - - while (ep_intr != 0U) { - if ((ep_intr & 0x1U) != 0U) { - epint = USBx_OUTEP((uint32_t)epnum)->DOEPINT; - - epint &= USBx_DEVICE->DOEPMSK; - if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) { - USBx_OUTEP(epnum)->DOEPINT = (USB_OTG_DOEPINT_STUP); - - USBx_OUTEP(epnum)->DOEPTSIZ = 1U << USB_OTG_DOEPTSIZ_PKTCNT_Pos | - (USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_MPSIZ) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos; - USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; - } - if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC) { - USBx_OUTEP(epnum)->DOEPINT = (USB_OTG_DOEPINT_XFRC); - - if (epnum == 0) { - USBx_OUTEP(epnum)->DOEPTSIZ = 1U << USB_OTG_DOEPTSIZ_PKTCNT_Pos | - (USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_MPSIZ) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos; - USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; - } - } - } - ep_intr >>= 1U; - epnum++; - } - } - if (gint_status & USB_OTG_GINTSTS_IEPINT) { - epnum = 0U; - ep_intr = USBx_DEVICE->DAINT & 0xFFFF; - ep_intr &= USBx_DEVICE->DAINTMSK; - while (ep_intr != 0U) { - if ((ep_intr & 0x1U) != 0U) { - epint = USBx_INEP((uint32_t)epnum)->DIEPINT; - epint &= USBx_DEVICE->DIEPMSK; - - if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC) { - USBx_INEP(epnum)->DIEPINT = USB_OTG_DIEPINT_XFRC; - if (epnum == 0) { - usbd_event_notify_handler(USBD_EVENT_EP0_IN_NOTIFY, NULL); - } else { - usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(epnum | USB_EP_DIR_IN)); - } - } - } - ep_intr >>= 1U; - epnum++; - } - } - if (gint_status & USB_OTG_GINTSTS_USBRST) { - USBx->GINTSTS |= USB_OTG_GINTSTS_USBRST; - USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG; - - usb_flush_txfifo(USBx, 0x10U); - usb_flush_rxfifo(USBx); - for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { - USBx_INEP(i)->DIEPINT = 0xFB7FU; - USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; - USBx_INEP(i)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK; - USBx_OUTEP(i)->DOEPINT = 0xFB7FU; - USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL; - USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK; - } - USBx_DEVICE->DAINTMSK |= 0x10001U; - - USBx_OUTEP(0U)->DOEPTSIZ = 0U; - USBx_OUTEP(0U)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19)); - USBx_OUTEP(0U)->DOEPTSIZ |= (3U * 8U); - USBx_OUTEP(0U)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT; - USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; - - usbd_event_notify_handler(USBD_EVENT_RESET, NULL); - } - if (gint_status & USB_OTG_GINTSTS_ENUMDNE) { - USBx->GINTSTS |= USB_OTG_GINTSTS_ENUMDNE; - //uint8_t speed = USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD; - /* Set the MPS of the IN EP0 to 64 bytes */ - USBx_INEP(0U)->DIEPCTL &= ~USB_OTG_DIEPCTL_MPSIZ; - - USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK; - } - if (gint_status & USB_OTG_GINTSTS_SOF) { - USBx->GINTSTS |= USB_OTG_GINTSTS_SOF; - } - if (gint_status & USB_OTG_GINTSTS_USBSUSP) { - USBx->GINTSTS |= USB_OTG_GINTSTS_USBSUSP; - } - } -} - -static int usb_flush_rxfifo(USB_OTG_GlobalTypeDef *USBx) -{ - uint32_t count = 0; - - USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; - - do { - if (++count > 200000U) { - return -1; - } - } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH); - - return 0; -} - -static int usb_flush_txfifo(USB_OTG_GlobalTypeDef *USBx, uint32_t num) -{ - uint32_t count = 0U; - - USBx->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (num << 6)); - - do { - if (++count > 200000U) { - return -1; - } - } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH); - - return 0; -} - -static void usb_set_txfifo(USB_OTG_GlobalTypeDef *USBx, uint8_t fifo, uint16_t size) -{ - uint8_t i; - uint32_t Tx_Offset; - - /* TXn min size = 16 words. (n : Transmit FIFO index) - When a TxFIFO is not used, the Configuration should be as follows: - case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes) - --> Txm can use the space allocated for Txn. - case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes) - --> Txn should be configured with the minimum space of 16 words - The FIFO is used optimally when used TxFIFOs are allocated in the top - of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones. - When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */ - - Tx_Offset = USBx->GRXFSIZ; - - if (fifo == 0U) { - USBx->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset; - } else { - Tx_Offset += (USBx->DIEPTXF0_HNPTXFSIZ) >> 16; - for (i = 0U; i < (fifo - 1U); i++) { - Tx_Offset += (USBx->DIEPTXF[i] >> 16); - } - - /* Multiply Tx_Size by 2 to get higher performance */ - USBx->DIEPTXF[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset; - } -} diff --git a/port/synopsys/usb_hc_synopsys.c b/port/synopsys/usb_hc_synopsys.c deleted file mode 100644 index edd69c88..00000000 --- a/port/synopsys/usb_hc_synopsys.c +++ /dev/null @@ -1,928 +0,0 @@ -#include "usbh_core.h" -#include "stm32f4xx_hal.h" - -#if defined(CONFIG_USB_HS) || defined(CONFIG_USB_HS_IN_FULL) -HCD_HandleTypeDef hhcd_USB_OTG_HS; -#ifndef USBH_IRQHandler -#define USBH_IRQHandler OTG_HS_IRQHandler -#endif -#else -HCD_HandleTypeDef hhcd_USB_OTG_FS; -#ifndef USBH_IRQHandler -#define USBH_IRQHandler OTG_FS_IRQHandler -#endif -#endif - -#ifndef CONFIG_USBHOST_CHANNELS -#define CONFIG_USBHOST_CHANNELS 12 /* Number of host channels */ -#endif - -#define CONFIG_CONTROL_RETRY_COUNT 10 - -#define USBH_PID_SETUP 0U -#define USBH_PID_DATA 1U - -enum usb_synopsys_transfer_state { - TRANSFER_IDLE = 0, - TRANSFER_BUSY, -}; -/* This structure retains the state of one host channel. NOTE: Since there - * is only one channel operation active at a time, some of the fields in - * in the structure could be moved in struct stm32_ubhost_s to achieve - * some memory savings. - */ - -struct usb_synopsys_chan { - bool inuse; /* True: This channel is "in use" */ - bool in; /* True: IN endpoint */ - uint8_t interval; /* Interrupt/isochronous EP polling interval */ - uint8_t transfer_state; /* Interrupt/isochronous EP transfer state */ - volatile int result; /* The result of the transfer */ - volatile uint16_t xfrd; /* Bytes transferred (at end of transfer) */ - volatile bool waiter; /* True: Thread is waiting for a channel event */ - usb_osal_sem_t waitsem; /* Channel wait semaphore */ - usb_osal_mutex_t exclsem; /* Support mutually exclusive access */ -#ifdef CONFIG_USBHOST_ASYNCH - usbh_asynch_callback_t callback; /* Transfer complete callback */ - void *arg; /* Argument that accompanies the callback */ -#endif -}; - -/* A channel represents on uni-directional endpoint. So, in the case of the - * bi-directional, control endpoint, there must be two channels to represent - * the endpoint. - */ - -struct usb_synopsys_ctrlinfo { - uint8_t inndx; /* EP0 IN control channel index */ - uint8_t outndx; /* EP0 OUT control channel index */ -}; - -struct usb_synopsys_priv { - HCD_HandleTypeDef *handle; - volatile uint64_t sof_timer; - volatile bool connected; /* Connected to device */ - struct usb_synopsys_chan chan[CONFIG_USBHOST_CHANNELS]; -} g_usbhost; - -/**************************************************************************** - * Name: usb_synopsys_chan_alloc - * - * Description: - * Allocate a channel. - * - ****************************************************************************/ - -static int usb_synopsys_chan_alloc(void) -{ - int chidx; - - /* Search the table of channels */ - - for (chidx = 0; chidx < CONFIG_USBHOST_CHANNELS; chidx++) { - /* Is this channel available? */ - if (!g_usbhost.chan[chidx].inuse) { - /* Yes... make it "in use" and return the index */ - - g_usbhost.chan[chidx].inuse = true; - return chidx; - } - } - - /* All of the channels are "in-use" */ - - return -EBUSY; -} - -/**************************************************************************** - * Name: usb_synopsys_chan_free - * - * Description: - * Free a previoiusly allocated channel. - * - ****************************************************************************/ - -static void usb_synopsys_chan_free(int chidx) -{ - /* Halt the channel */ - HAL_HCD_HC_Halt(g_usbhost.handle, chidx); - /* Mark the channel available */ - - g_usbhost.chan[chidx].inuse = false; -} - -/**************************************************************************** - * Name: usb_synopsys_chan_freeall - * - * Description: - * Free all channels. - * - ****************************************************************************/ - -static inline void usb_synopsys_chan_freeall(void) -{ - uint8_t chidx; - - /* Free all host channels */ - - for (chidx = 2; chidx < CONFIG_USBHOST_CHANNELS; chidx++) { - usb_synopsys_chan_free(chidx); - } -} - -/**************************************************************************** - * Name: usb_synopsys_chan_waitsetup - * - * Description: - * Set the request for the transfer complete event well BEFORE enabling - * the transfer (as soon as we are absolutely committed to the transfer). - * We do this to minimize race conditions. This logic would have to be - * expanded if we want to have more than one packet in flight at a time! - * - * Assumptions: - * Called from a normal thread context BEFORE the transfer has been - * started. - * - ****************************************************************************/ - -static int usb_synopsys_chan_waitsetup(struct usb_synopsys_chan *chan) -{ - size_t flags; - int ret = -ENODEV; - - flags = usb_osal_enter_critical_section(); - - /* Is the device still connected? */ - - if (g_usbhost.connected) { - /* Yes.. then set waiter to indicate that we expect to be informed - * when either (1) the device is disconnected, or (2) the transfer - * completed. - */ - - chan->waiter = true; - chan->result = -EBUSY; - chan->xfrd = 0; -#ifdef CONFIG_USBHOST_ASYNCH - chan->callback = NULL; - chan->arg = NULL; -#endif - ret = 0; - } - usb_osal_leave_critical_section(flags); - return ret; -} - -/**************************************************************************** - * Name: usb_synopsys_chan_asynchsetup - * - * Description: - * Set the request for the transfer complete event well BEFORE enabling - * the transfer (as soon as we are absolutely committed to the to avoid - * transfer). We do this to minimize race conditions. This logic would - * have to be expanded if we want to have more than one packet in flight - * at a time! - * - * Assumptions: - * Might be called from the level of an interrupt handler - * - ****************************************************************************/ - -#ifdef CONFIG_USBHOST_ASYNCH -static int usb_synopsys_chan_asynchsetup(struct usb_synopsys_chan *chan, usbh_asynch_callback_t callback, void *arg) -{ - size_t flags; - int ret = -ENODEV; - - flags = usb_osal_enter_critical_section(); - /* Is the device still connected? */ - - if (g_usbhost.connected) { - /* Yes.. then set waiter to indicate that we expect to be informed - * when either (1) the device is disconnected, or (2) the transfer - * completed. - */ - - chan->waiter = false; - chan->result = -EBUSY; - chan->xfrd = 0; - chan->callback = callback; - chan->arg = arg; - ret = 0; - } - - usb_osal_leave_critical_section(flags); - return ret; -} -#endif - -/**************************************************************************** - * Name: usb_synopsys_chan_wait - * - * Description: - * Wait for a transfer on a channel to complete. - * - * Assumptions: - * Called from a normal thread context - * - ****************************************************************************/ - -static int usb_synopsys_chan_wait(struct usb_synopsys_chan *chan, uint32_t timeout) -{ - int ret; - - /* Loop, testing for an end of transfer condition. The channel 'result' - * was set to EBUSY and 'waiter' was set to true before the transfer; - * 'waiter' will be set to false and 'result' will be set appropriately - * when the transfer is completed. - */ - - if (chan->waiter) { - ret = usb_osal_sem_take(chan->waitsem, timeout); - if (ret < 0) { - return ret; - } - } - - /* The transfer is complete re-enable interrupts and return the result */ - ret = chan->result; - - if (ret < 0) { - return ret; - } - return chan->xfrd; -} - -/**************************************************************************** - * Name: usb_synopsys_chan_wakeup - * - * Description: - * A channel transfer has completed... wakeup any threads waiting for the - * transfer to complete. - * - * Assumptions: - * This function is called from the transfer complete interrupt handler for - * the channel. Interrupts are disabled. - * - ****************************************************************************/ - -static void usb_synopsys_chan_wakeup(struct usb_synopsys_chan *chan) -{ - usbh_asynch_callback_t callback; - void *arg; - int nbytes; - - /* Is the transfer complete? */ - - if (chan->result != -EBUSY) { - /* Is there a thread waiting for this transfer to complete? */ - - if (chan->waiter) { - /* Wake'em up! */ - chan->waiter = false; - usb_osal_sem_give(chan->waitsem); - } -#ifdef CONFIG_USBHOST_ASYNCH - /* No.. is an asynchronous callback expected when the transfer - * completes? - */ - else if (chan->callback) { - /* Handle continuation of IN/OUT pipes */ - if (chan->in) { - callback = chan->callback; - arg = chan->arg; - nbytes = chan->xfrd; - chan->callback = NULL; - chan->arg = NULL; - if (chan->result < 0) { - nbytes = chan->result; - } - - callback(arg, nbytes); - - } else { - callback = chan->callback; - arg = chan->arg; - nbytes = chan->xfrd; - chan->callback = NULL; - chan->arg = NULL; - if (chan->result < 0) { - nbytes = chan->result; - } - - callback(arg, nbytes); - } - } -#endif - } -} - -__WEAK void usb_hc_low_level_init(void) -{ -} - -int usb_hc_init(void) -{ - g_usbhost.connected = 0; - g_usbhost.sof_timer = 0; -#if defined(CONFIG_USB_HS) || defined(CONFIG_USB_HS_IN_FULL) - g_usbhost.handle = &hhcd_USB_OTG_HS; - g_usbhost.handle->Instance = USB_OTG_HS; -#else - g_usbhost.handle = &hhcd_USB_OTG_FS; - g_usbhost.handle->Instance = USB_OTG_FS; -#endif - - g_usbhost.handle->Init.Host_channels = CONFIG_USBHOST_CHANNELS; - g_usbhost.handle->Init.speed = HCD_SPEED_FULL; - g_usbhost.handle->Init.dma_enable = DISABLE; - g_usbhost.handle->Init.phy_itface = USB_OTG_EMBEDDED_PHY; - g_usbhost.handle->Init.Sof_enable = DISABLE; - g_usbhost.handle->Init.low_power_enable = DISABLE; - g_usbhost.handle->Init.vbus_sensing_enable = DISABLE; - g_usbhost.handle->Init.use_external_vbus = DISABLE; - if (HAL_HCD_Init(g_usbhost.handle) != HAL_OK) { - return -1; - } - HAL_HCD_Start(g_usbhost.handle); - return 0; -} - -bool usbh_get_port_connect_status(const uint8_t port) -{ - USB_OTG_GlobalTypeDef *USBx = g_usbhost.handle->Instance; - uint32_t USBx_BASE = (uint32_t)USBx; - __IO uint32_t hprt0; - - hprt0 = USBx_HPRT0; - - if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) { - return true; - } else { - return false; - } -} - -int usbh_reset_port(const uint8_t port) -{ - HAL_HCD_ResetPort(g_usbhost.handle); - return 0; -} - -uint8_t usbh_get_port_speed(const uint8_t port) -{ - if (HAL_HCD_GetCurrentSpeed(g_usbhost.handle) == 1) { - return USB_SPEED_FULL; - } else if (HAL_HCD_GetCurrentSpeed(g_usbhost.handle) == 2) - return USB_SPEED_LOW; - else - return USB_SPEED_HIGH; -} - -int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed) -{ - struct usb_synopsys_chan *chan; - struct usb_synopsys_ctrlinfo *ep0info; - int ret; - - ep0info = (struct usb_synopsys_ctrlinfo *)ep; - - chan = &g_usbhost.chan[ep0info->outndx]; - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - if (speed == USB_SPEED_FULL) { - speed = 1; - } else if (speed == USB_SPEED_LOW) { - speed = 2; - } else if (speed == USB_SPEED_HIGH) { - speed = 0; - } - - ret = HAL_HCD_HC_Init(g_usbhost.handle, ep0info->outndx, 0x00, dev_addr, speed, USB_ENDPOINT_TYPE_CONTROL, ep_mps); - ret = HAL_HCD_HC_Init(g_usbhost.handle, ep0info->inndx, 0x80, dev_addr, speed, USB_ENDPOINT_TYPE_CONTROL, ep_mps); - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg) -{ - struct usb_synopsys_chan *chan; - struct usb_synopsys_priv *priv = &g_usbhost; - struct usb_synopsys_ctrlinfo *ep0; - struct usbh_hubport *hport; - int chidx; - uint8_t speed; - - hport = ep_cfg->hport; - - if (hport->speed == USB_SPEED_FULL) { - speed = 1; - } else if (hport->speed == USB_SPEED_LOW) { - speed = 2; - } else if (hport->speed == USB_SPEED_HIGH) { - speed = 0; - } - - if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) { - ep0 = usb_malloc(sizeof(struct usb_synopsys_ctrlinfo)); - memset(ep0, 0, sizeof(struct usb_synopsys_ctrlinfo)); - - ep0->outndx = usb_synopsys_chan_alloc(); - ep0->inndx = usb_synopsys_chan_alloc(); - - chan = &priv->chan[ep0->outndx]; - memset(chan, 0, sizeof(struct usb_synopsys_chan)); - chan->inuse = true; - chan->waitsem = usb_osal_sem_create(0); - chan->exclsem = usb_osal_mutex_create(); - - chan = &priv->chan[ep0->inndx]; - memset(chan, 0, sizeof(struct usb_synopsys_chan)); - chan->inuse = true; - chan->waitsem = usb_osal_sem_create(0); - - HAL_HCD_HC_Init(g_usbhost.handle, ep0->outndx, 0x00, hport->dev_addr, speed, USB_ENDPOINT_TYPE_CONTROL, ep_cfg->ep_mps); - HAL_HCD_HC_Init(g_usbhost.handle, ep0->inndx, 0x80, hport->dev_addr, speed, USB_ENDPOINT_TYPE_CONTROL, ep_cfg->ep_mps); - - *ep = (usbh_epinfo_t)ep0; - - } else { - chidx = usb_synopsys_chan_alloc(); - - chan = &priv->chan[chidx]; - memset(chan, 0, sizeof(struct usb_synopsys_chan)); - chan->inuse = true; - chan->interval = ep_cfg->ep_interval; - chan->in = ep_cfg->ep_addr & 0x80 ? 1 : 0; - - chan->waitsem = usb_osal_sem_create(0); - chan->exclsem = usb_osal_mutex_create(); - - HAL_HCD_HC_Init(g_usbhost.handle, chidx, ep_cfg->ep_addr, hport->dev_addr, speed, ep_cfg->ep_type, ep_cfg->ep_mps); - - g_usbhost.handle->hc[chidx].toggle_in = 0; - g_usbhost.handle->hc[chidx].toggle_out = 0; - - *ep = (usbh_epinfo_t)chidx; - } - - return 0; -} - -int usbh_ep_free(usbh_epinfo_t ep) -{ - if ((uintptr_t)ep < CONFIG_USBHOST_CHANNELS) { - usb_synopsys_chan_free((int)ep); - usb_osal_sem_delete(g_usbhost.chan[(int)ep].waitsem); - usb_osal_mutex_delete(g_usbhost.chan[(int)ep].exclsem); - } else { - struct usb_synopsys_ctrlinfo *ep0 = (struct usb_synopsys_ctrlinfo *)ep; - usb_synopsys_chan_free(ep0->inndx); - usb_synopsys_chan_free(ep0->outndx); - usb_osal_sem_delete(g_usbhost.chan[ep0->inndx].waitsem); - usb_osal_sem_delete(g_usbhost.chan[ep0->outndx].waitsem); - usb_osal_mutex_delete(g_usbhost.chan[ep0->outndx].exclsem); - } - - return 0; -} - -int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint8_t *buffer) -{ - int ret; - uint32_t retries; - struct usb_synopsys_chan *chan; - struct usb_synopsys_ctrlinfo *ep0info = (struct usb_synopsys_ctrlinfo *)ep; - - chan = &g_usbhost.chan[ep0info->outndx]; - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - usb_synopsys_chan_waitsetup(chan); - - ret = HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - ep0info->outndx, /* Pipe index */ - 0, /* Direction : OUT */ - 0, /* EP type */ - USBH_PID_SETUP, /* Type Data */ - (uint8_t *)setup, /* data buffer */ - 8, /* data length */ - 0); /* do ping (HS Only)*/ - - ret = usb_synopsys_chan_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto errout_with_mutex; - } - - if (setup->wLength && buffer) { - if (setup->bmRequestType & 0x80) { - chan = &g_usbhost.chan[ep0info->inndx]; - usb_synopsys_chan_waitsetup(chan); - - ret = HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - ep0info->inndx, /* Pipe index */ - 1, /* Direction : IN */ - 0, /* EP type */ - USBH_PID_DATA, /* Type Data */ - buffer, /* data buffer */ - setup->wLength, /* data length */ - 0); /* do ping (HS Only)*/ - - ret = usb_synopsys_chan_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto errout_with_mutex; - } - - chan = &g_usbhost.chan[ep0info->outndx]; - - /* For ep0 out,we must retry more */ - for (retries = 0; retries < 10; retries++) { - usb_synopsys_chan_waitsetup(chan); - - ret = HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - ep0info->outndx, /* Pipe index */ - 0, /* Direction : OUT */ - 0, /* EP type */ - USBH_PID_DATA, /* Type Data */ - NULL, /* data buffer */ - 0, /* data length */ - 0); /* do ping (HS Only)*/ - - ret = usb_synopsys_chan_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret == -EAGAIN) { - continue; - } else if (ret < 0) { - goto errout_with_mutex; - } else { - break; - } - } - if (retries >= CONFIG_CONTROL_RETRY_COUNT) { - ret = -ETIMEDOUT; - goto errout_with_mutex; - } - - } else { - chan = &g_usbhost.chan[ep0info->outndx]; - - /* For ep0 out,we must retry more */ - for (retries = 0; retries < CONFIG_CONTROL_RETRY_COUNT; retries++) { - usb_synopsys_chan_waitsetup(chan); - - ret = HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - ep0info->outndx, /* Pipe index */ - 0, /* Direction : OUT */ - 0, /* EP type */ - USBH_PID_DATA, /* Type Data */ - buffer, /* data buffer */ - setup->wLength, /* data length */ - 0); /* do ping (HS Only)*/ - - ret = usb_synopsys_chan_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret == -EAGAIN) { - continue; - } else if (ret < 0) { - goto errout_with_mutex; - } else { - break; - } - } - if (retries >= CONFIG_CONTROL_RETRY_COUNT) { - ret = -ETIMEDOUT; - goto errout_with_mutex; - } - - chan = &g_usbhost.chan[ep0info->inndx]; - usb_synopsys_chan_waitsetup(chan); - - ret = HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - ep0info->inndx, /* Pipe index */ - 1, /* Direction : IN */ - 0, /* EP type */ - USBH_PID_DATA, /* Type Data */ - NULL, /* data buffer */ - 0, /* data length */ - 0); /* do ping (HS Only)*/ - - ret = usb_synopsys_chan_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto errout_with_mutex; - } - } - } else { - chan = &g_usbhost.chan[ep0info->inndx]; - usb_synopsys_chan_waitsetup(chan); - - ret = HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - ep0info->inndx, /* Pipe index */ - 1, /* Direction : IN */ - 0, /* EP type */ - USBH_PID_DATA, /* Type Data */ - NULL, /* data buffer */ - 0, /* data length */ - 0); /* do ping (HS Only)*/ - - ret = usb_synopsys_chan_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); - if (ret < 0) { - goto errout_with_mutex; - } - } - chan = &g_usbhost.chan[ep0info->outndx]; - usb_osal_mutex_give(chan->exclsem); - return 0; -errout_with_mutex: - chan->waiter = false; - chan = &g_usbhost.chan[ep0info->outndx]; - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - int ret; - struct usb_synopsys_chan *chan; - struct usb_synopsys_priv *priv = &g_usbhost; - uint8_t chidx = (uint8_t)ep; - - chan = &priv->chan[chidx]; - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - usb_synopsys_chan_waitsetup(chan); - - ret = HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - chidx, /* Pipe index */ - g_usbhost.handle->hc[chidx].ep_is_in ? 1 : 0, /* Direction : IN */ - 2, /* EP type */ - USBH_PID_DATA, /* Type Data */ - buffer, /* data buffer */ - buflen, /* data length */ - 0); /* do ping (HS Only)*/ - - ret = usb_synopsys_chan_wait(chan, timeout); - if (ret < 0) { - goto errout_with_mutex; - } - - usb_osal_mutex_give(chan->exclsem); - return g_usbhost.handle->hc[chidx].ep_is_in ? HAL_HCD_HC_GetXferCount(g_usbhost.handle, chidx) : buflen; -errout_with_mutex: - chan->waiter = false; - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) -{ - size_t flags; - uint32_t retries; - int ret; - struct usb_synopsys_chan *chan; - uint8_t chidx = (uint8_t)ep; - - chan = &g_usbhost.chan[chidx]; - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - usb_synopsys_chan_waitsetup(chan); - flags = usb_osal_enter_critical_section(); - chan->transfer_state = TRANSFER_BUSY; - - ret = HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - chidx, /* Pipe index */ - g_usbhost.handle->hc[chidx].ep_is_in ? 1 : 0, /* Direction : IN */ - 3, /* EP type */ - USBH_PID_DATA, /* Type Data */ - buffer, /* data buffer */ - buflen, /* data length */ - 0); /* do ping (HS Only)*/ - - usb_osal_leave_critical_section(flags); - ret = usb_synopsys_chan_wait(chan, timeout); - if (ret < 0) { - goto errout_with_mutex; - } - - usb_osal_mutex_give(chan->exclsem); - return g_usbhost.handle->hc[chidx].ep_is_in ? HAL_HCD_HC_GetXferCount(g_usbhost.handle, chidx) : buflen; -errout_with_mutex: - chan->waiter = false; - usb_osal_mutex_give(chan->exclsem); - return ret; -} - -int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) -{ - int ret; - struct usb_synopsys_chan *chan; - struct usb_synopsys_priv *priv = &g_usbhost; - uint8_t chidx = (uint8_t)ep; - - chan = &g_usbhost.chan[chidx]; - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - usb_synopsys_chan_asynchsetup(chan, callback, arg); - - ret = HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - chidx, /* Pipe index */ - g_usbhost.handle->hc[chidx].ep_is_in ? 1 : 0, /* Direction : IN */ - 2, /* EP type */ - USBH_PID_DATA, /* Type Data */ - buffer, /* data buffer */ - buflen, /* data length */ - 0); /* do ping (HS Only)*/ - - usb_osal_mutex_give(chan->exclsem); - - return ret; -} - -int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) -{ - int ret; - size_t flags; - struct usb_synopsys_chan *chan; - struct usb_synopsys_priv *priv = &g_usbhost; - uint8_t chidx = (uint8_t)ep; - - chan = &priv->chan[chidx]; - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - usb_synopsys_chan_asynchsetup(chan, callback, arg); - flags = usb_osal_enter_critical_section(); - chan->transfer_state = TRANSFER_BUSY; - - ret = HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - chidx, /* Pipe index */ - g_usbhost.handle->hc[chidx].ep_is_in ? 1 : 0, /* Direction : IN */ - 3, /* EP type */ - USBH_PID_DATA, /* Type Data */ - buffer, /* data buffer */ - buflen, /* data length */ - 0); /* do ping (HS Only)*/ - - usb_osal_leave_critical_section(flags); - usb_osal_mutex_give(chan->exclsem); - - return ret; -} - -int usb_ep_cancel(usbh_epinfo_t ep) -{ - int ret; - size_t flags; - struct usb_synopsys_chan *chan; - struct usb_synopsys_priv *priv = &g_usbhost; -#ifdef CONFIG_USBHOST_ASYNCH - usbh_asynch_callback_t callback; - void *arg; -#endif - - uint8_t chidx = (uint8_t)ep; - - chan = &priv->chan[chidx]; - - flags = usb_osal_enter_critical_section(); - - chan->result = -ESHUTDOWN; -#ifdef CONFIG_USBHOST_ASYNCH - /* Extract the callback information */ - callback = chan->callback; - arg = chan->arg; - chan->callback = NULL; - chan->arg = NULL; - chan->xfrd = 0; -#endif - usb_osal_leave_critical_section(flags); - - /* Is there a thread waiting for this transfer to complete? */ - - if (chan->waiter) { - /* Wake'em up! */ - chan->waiter = false; - usb_osal_sem_give(chan->waitsem); - } -#ifdef CONFIG_USBHOST_ASYNCH - /* No.. is an asynchronous callback expected when the transfer completes? */ - else if (callback) { - /* Then perform the callback */ - callback(arg, -ESHUTDOWN); - } -#endif - return 0; -} - -void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) -{ - if (!g_usbhost.connected) { - g_usbhost.connected = true; - extern void usbh_event_notify_handler(uint8_t event, uint8_t rhport); - usbh_event_notify_handler(USBH_EVENT_CONNECTED, 1); - } -} - -/** - * @brief SOF callback. - * @param hhcd: HCD handle - * @retval None - */ -void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) -{ - if (g_usbhost.connected) { - g_usbhost.connected = false; - usb_synopsys_chan_freeall(); - - for (uint8_t chnum = 0; chnum < CONFIG_USBHOST_CHANNELS; chnum++) { - { - if (g_usbhost.chan[chnum].waiter) { - /* Wake'em up! */ - g_usbhost.chan[chnum].waiter = false; - usb_osal_sem_give(g_usbhost.chan[chnum].waitsem); - } - } - - usbh_event_notify_handler(USBH_EVENT_DISCONNECTED, 1); - } - } -} - -void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) -{ - struct usb_synopsys_chan *chan; - struct usb_synopsys_priv *priv = &g_usbhost; - - chan = &priv->chan[chnum]; - - if (urb_state == URB_NOTREADY) { - chan->result = -EAGAIN; - } else if (urb_state == URB_STALL) { - chan->result = -EPERM; - } else if (urb_state == URB_ERROR) { - chan->result = -EIO; - } else if (urb_state == URB_DONE) { - chan->transfer_state = TRANSFER_IDLE; - chan->result = 0; - } - chan->in = g_usbhost.handle->hc[chnum].ep_is_in; - chan->xfrd += g_usbhost.handle->hc[chnum].ep_is_in ? HAL_HCD_HC_GetXferCount(g_usbhost.handle, chnum) : g_usbhost.handle->hc[chnum].xfer_len; - - if (g_usbhost.handle->hc[chnum].ep_type == 0x00 && (urb_state == URB_NOTREADY) && g_usbhost.handle->hc[chnum].ep_is_in) { - return; - } - if ((g_usbhost.handle->hc[chnum].ep_type == 0x02) && (urb_state == URB_NOTREADY)) { - return; - } - - usb_synopsys_chan_wakeup(chan); -} - -void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd) -{ - g_usbhost.sof_timer++; - for (uint8_t chnum = 2; chnum < CONFIG_USBHOST_CHANNELS; chnum++) { - if (g_usbhost.handle->hc[chnum].ep_type == 0x01 || g_usbhost.handle->hc[chnum].ep_type == 0x03) { - if ((g_usbhost.chan[chnum].transfer_state == TRANSFER_BUSY) && - ((g_usbhost.sof_timer % g_usbhost.chan[chnum].interval) == 0)) { - HAL_HCD_HC_SubmitRequest(g_usbhost.handle, - chnum, /* Pipe index */ - g_usbhost.handle->hc[chnum].ep_is_in ? 1 : 0, /* Direction : IN */ - g_usbhost.handle->hc[chnum].ep_type, /* EP type */ - USBH_PID_DATA, /* Type Data */ - g_usbhost.handle->hc[chnum].xfer_buff, /* data buffer */ - g_usbhost.handle->hc[chnum].xfer_len, /* data length */ - 0); /* do ping (HS Only)*/ - } - } - } -} - -void USBH_IRQHandler(void) -{ - /* USER CODE BEGIN OTG_HS_IRQn 0 */ - - /* USER CODE END OTG_HS_IRQn 0 */ - HAL_HCD_IRQHandler(g_usbhost.handle); - /* USER CODE BEGIN OTG_HS_IRQn 1 */ - - /* USER CODE END OTG_HS_IRQn 1 */ -} - -void HAL_Delay(uint32_t Delay) -{ - usb_osal_msleep(Delay); -}