refactor dwc2 port

This commit is contained in:
sakumisu
2022-06-14 22:05:48 +08:00
parent f761392ed1
commit 8d7ef730a2
16 changed files with 2506 additions and 2005 deletions

View File

@@ -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']):

View File

@@ -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

View File

@@ -41,7 +41,7 @@ __initial_sp
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x200
Heap_Size EQU 0x1000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base

View File

@@ -103,7 +103,7 @@
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>6</nTsel>
<nTsel>3</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>
@@ -114,7 +114,7 @@
<tDlgDll></tDlgDll>
<tDlgPa></tDlgPa>
<tIfile></tIfile>
<pMon>STLink\ST-LINKIII-KEIL_SWO.dll</pMon>
<pMon>BIN\CMSIS_AGDI.dll</pMon>
</DebugOpt>
<TargetDriverDllRegistry>
<SetRegEntry>
@@ -135,12 +135,12 @@
<SetRegEntry>
<Number>0</Number>
<Key>DLGUARM</Key>
<Name>(105=-1,-1,-1,-1,0)</Name>
<Name></Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>CMSIS_AGDI</Key>
<Name>-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)</Name>
<Name>-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)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
@@ -157,7 +157,7 @@
<Bp>
<Number>0</Number>
<Type>0</Type>
<LineNumber>525</LineNumber>
<LineNumber>537</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>0</Address>
<ByteObject>0</ByteObject>
@@ -166,7 +166,23 @@
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>0</BreakIfRCount>
<Filename>C:\Users\lvjiazhen\Desktop\usb_stack\demo\port\synopsys\usb_dc_synopsys.c</Filename>
<Filename>..\..\..\..\..\core\usbd_core.c</Filename>
<ExecCommand></ExecCommand>
<Expression></Expression>
</Bp>
<Bp>
<Number>1</Number>
<Type>0</Type>
<LineNumber>383</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>0</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>0</BreakIfRCount>
<Filename>..\..\..\..\..\core\usbd_core.c</Filename>
<ExecCommand></ExecCommand>
<Expression></Expression>
</Bp>
@@ -245,7 +261,7 @@
<Group>
<GroupName>Application/User/Core</GroupName>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
@@ -497,53 +513,17 @@
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>22</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c</PathWithFileName>
<FilenameWithoutPath>stm32f4xx_hal_pcd.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>23</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c</PathWithFileName>
<FilenameWithoutPath>stm32f4xx_hal_pcd_ex.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>24</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c</PathWithFileName>
<FilenameWithoutPath>stm32f4xx_ll_usb.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>Drivers/CMSIS</GroupName>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>25</FileNumber>
<FileNumber>22</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -563,7 +543,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>26</FileNumber>
<FileNumber>23</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -575,7 +555,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>27</FileNumber>
<FileNumber>24</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -587,13 +567,13 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>28</FileNumber>
<FileNumber>25</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\..\port\synopsys\usb_dc_synopsys.c</PathWithFileName>
<FilenameWithoutPath>usb_dc_synopsys.c</FilenameWithoutPath>
<PathWithFileName>..\..\..\..\..\port\dwc2\usb_dc_dwc2.c</PathWithFileName>
<FilenameWithoutPath>usb_dc_dwc2.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>

View File

@@ -338,9 +338,9 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>USE_HAL_DRIVER,STM32F429xx,CONFIG_USB_HS_IN_FULL</Define>
<Define>USE_HAL_DRIVER,STM32F429xx,CONFIG_USB_DWC2_PORT=HS_PORT</Define>
<Undefine></Undefine>
<IncludePath>../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</IncludePath>
<IncludePath>../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</IncludePath>
</VariousControls>
</Cads>
<Aads>
@@ -550,21 +550,6 @@
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c</FilePath>
</File>
<File>
<FileName>stm32f4xx_hal_pcd.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c</FilePath>
</File>
<File>
<FileName>stm32f4xx_hal_pcd_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c</FilePath>
</File>
<File>
<FileName>stm32f4xx_ll_usb.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c</FilePath>
</File>
</Files>
</Group>
<Group>
@@ -591,9 +576,9 @@
<FilePath>..\..\..\..\..\core\usbd_core.c</FilePath>
</File>
<File>
<FileName>usb_dc_synopsys.c</FileName>
<FileName>usb_dc_dwc2.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\..\port\synopsys\usb_dc_synopsys.c</FilePath>
<FilePath>..\..\..\..\..\port\dwc2\usb_dc_dwc2.c</FilePath>
</File>
</Files>
</Group>

View File

@@ -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
#endif

View File

@@ -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 */

View File

@@ -30,7 +30,7 @@
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Stack_Size EQU 0x400
Stack_Size EQU 0x1000
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size

View File

@@ -153,39 +153,17 @@
<Name>-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)</Name>
</SetRegEntry>
</TargetDriverDllRegistry>
<Breakpoint>
<Bp>
<Number>0</Number>
<Type>0</Type>
<LineNumber>493</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>0</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>0</BreakIfRCount>
<Filename>..\..\..\..\..\core\usbh_core.c</Filename>
<ExecCommand></ExecCommand>
<Expression></Expression>
</Bp>
</Breakpoint>
<Breakpoint/>
<WatchWindow1>
<Ww>
<count>0</count>
<WinNumber>1</WinNumber>
<ItemText>intf</ItemText>
<ItemText>gint_status</ItemText>
</Ww>
<Ww>
<count>1</count>
<WinNumber>1</WinNumber>
<ItemText>setup</ItemText>
</Ww>
<Ww>
<count>2</count>
<WinNumber>1</WinNumber>
<ItemText>hport</ItemText>
<ItemText>chan_int</ItemText>
</Ww>
</WatchWindow1>
<Tracepoint>
@@ -242,7 +220,7 @@
<Group>
<GroupName>Application/MDK-ARM</GroupName>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
@@ -262,7 +240,7 @@
<Group>
<GroupName>Application/User/Core</GroupName>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
@@ -330,7 +308,7 @@
<Group>
<GroupName>Drivers/STM32F4xx_HAL_Driver</GroupName>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
@@ -574,7 +552,7 @@
<Group>
<GroupName>FreeRTOS</GroupName>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
@@ -678,7 +656,7 @@
<Group>
<GroupName>CherryUSB</GroupName>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
@@ -734,11 +712,11 @@
<GroupNumber>6</GroupNumber>
<FileNumber>38</FileNumber>
<FileType>1</FileType>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\..\class\hub\usbh_hub.c</PathWithFileName>
<FilenameWithoutPath>usbh_hub.c</FilenameWithoutPath>
<PathWithFileName>..\..\..\..\..\osal\usb_osal_freertos.c</PathWithFileName>
<FilenameWithoutPath>usb_osal_freertos.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
@@ -749,8 +727,8 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\..\osal\usb_osal_freertos.c</PathWithFileName>
<FilenameWithoutPath>usb_osal_freertos.c</FilenameWithoutPath>
<PathWithFileName>..\..\..\..\..\port\dwc2\usb_hc_dwc2.c</PathWithFileName>
<FilenameWithoutPath>usb_hc_dwc2.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
@@ -766,18 +744,6 @@
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>41</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\..\port\synopsys\usb_hc_synopsys.c</PathWithFileName>
<FilenameWithoutPath>usb_hc_synopsys.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
@@ -788,7 +754,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>42</FileNumber>
<FileNumber>41</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -800,7 +766,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>43</FileNumber>
<FileNumber>42</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -812,7 +778,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>44</FileNumber>
<FileNumber>43</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -824,7 +790,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>45</FileNumber>
<FileNumber>44</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -836,7 +802,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>46</FileNumber>
<FileNumber>45</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>

View File

@@ -314,7 +314,7 @@
</ArmAdsMisc>
<Cads>
<interw>1</interw>
<Optim>3</Optim>
<Optim>1</Optim>
<oTime>0</oTime>
<SplitLS>0</SplitLS>
<OneElfS>1</OneElfS>
@@ -338,7 +338,7 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>USE_HAL_DRIVER,STM32F429xx,CONFIG_USB_HS_IN_FULL,CONFIG_USBHOST_HUB</Define>
<Define>USE_HAL_DRIVER,STM32F429xx,CONFIG_USBHOST_HIGH_WORKQ</Define>
<Undefine></Undefine>
<IncludePath>../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</IncludePath>
</VariousControls>
@@ -594,26 +594,21 @@
<FileType>1</FileType>
<FilePath>..\..\..\..\..\class\hid\usbh_hid.c</FilePath>
</File>
<File>
<FileName>usbh_hub.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\..\class\hub\usbh_hub.c</FilePath>
</File>
<File>
<FileName>usb_osal_freertos.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\..\osal\usb_osal_freertos.c</FilePath>
</File>
<File>
<FileName>usb_hc_dwc2.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\..\port\dwc2\usb_hc_dwc2.c</FilePath>
</File>
<File>
<FileName>usb_workq.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\..\osal\usb_workq.c</FilePath>
</File>
<File>
<FileName>usb_hc_synopsys.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\..\port\synopsys\usb_hc_synopsys.c</FilePath>
</File>
</Files>
</Group>
<Group>

917
port/dwc2/usb_dc_dwc2.c Normal file
View File

@@ -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;
}
}
}

View File

@@ -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
#define CLEAR_HC_INT(chnum, __INTERRUPT__) (USBx_HC(chnum)->HCINT = (__INTERRUPT__))
#endif

1389
port/dwc2/usb_hc_dwc2.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}
}

View File

@@ -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);
}