Murad Jabir 2 lat temu
rodzic
commit
14214e1b7a
38 zmienionych plików z 25804 dodań i 37 usunięć
  1. 15 3
      .cproject
  2. 1 0
      .gitignore
  3. 0 17
      .mxproject
  4. 2 1
      .settings/stm32cubeide.project.prefs
  5. 1 1
      Core/Inc/stm32f4xx_hal_conf.h
  6. 1 0
      Core/Inc/stm32f4xx_it.h
  7. 34 3
      Core/Src/main.c
  8. 15 1
      Core/Src/stm32f4xx_it.c
  9. 461 0
      Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h
  10. 94 0
      Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h
  11. 2155 0
      Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h
  12. 355 0
      Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h
  13. 578 0
      Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h
  14. 2395 0
      Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c
  15. 347 0
      Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c
  16. 7632 0
      Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c
  17. 2410 0
      Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c
  18. 2316 0
      Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c
  19. 332 0
      Middlewares/ST/STM32_USB_Device_Library/Class/AUDIO/Inc/usbd_audio.h
  20. 980 0
      Middlewares/ST/STM32_USB_Device_Library/Class/AUDIO/Src/usbd_audio.c
  21. 175 0
      Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h
  22. 101 0
      Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h
  23. 523 0
      Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h
  24. 113 0
      Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h
  25. 1214 0
      Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c
  26. 1056 0
      Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c
  27. 224 0
      Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c
  28. 86 0
      Middlewares/ST/STM32_USB_Device_Library/LICENSE.txt
  29. 100 0
      USB_DEVICE/App/usb_device.c
  30. 102 0
      USB_DEVICE/App/usb_device.h
  31. 285 0
      USB_DEVICE/App/usbd_audio_if.c
  32. 137 0
      USB_DEVICE/App/usbd_audio_if.h
  33. 445 0
      USB_DEVICE/App/usbd_desc.c
  34. 143 0
      USB_DEVICE/App/usbd_desc.h
  35. 671 0
      USB_DEVICE/Target/usbd_conf.c
  36. 175 0
      USB_DEVICE/Target/usbd_conf.h
  37. 48 11
      usb_mic.ioc
  38. 82 0
      usb_mic.launch

+ 15 - 3
.cproject

@@ -23,7 +23,7 @@
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.1092052415" name="Floating-point unit" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.value.fpv4-sp-d16" valueType="enumerated"/>
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.1503607401" name="Floating-point ABI" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.value.hard" valueType="enumerated"/>
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.694059824" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
-							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.1249493161" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Debug || true || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32F411CEUx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32F4xx_HAL_Driver/Inc | ../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32F4xx/Include | ../Drivers/CMSIS/Include ||  ||  || USE_HAL_DRIVER | STM32F411xE ||  || Drivers | Core/Startup | Core ||  ||  || ${workspace_loc:/${ProjName}/STM32F411CEUX_FLASH.ld} || true || NonSecure ||  || secure_nsclib.o ||  || None ||  ||  || " valueType="string"/>
+							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.1249493161" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Debug || true || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32F411CEUx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32F4xx_HAL_Driver/Inc | ../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32F4xx/Include | ../Drivers/CMSIS/Include | ../USB_DEVICE/App | ../USB_DEVICE/Target | ../Middlewares/ST/STM32_USB_Device_Library/Core/Inc | ../Middlewares/ST/STM32_USB_Device_Library/Class/AUDIO/Inc ||  ||  || USE_HAL_DRIVER | STM32F411xE ||  || Drivers | Core/Startup | Middlewares | Core | USB_DEVICE ||  ||  || ${workspace_loc:/${ProjName}/STM32F411CEUX_FLASH.ld} || true || NonSecure ||  || secure_nsclib.o ||  || None ||  ||  || " valueType="string"/>
 							<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.27236052" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="16" valueType="string"/>
 							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.411701672" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
 							<builder buildPath="${workspace_loc:/usb_mic}/Debug" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.1228698083" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
@@ -48,6 +48,10 @@
 									<listOptionValue builtIn="false" value="../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy"/>
 									<listOptionValue builtIn="false" value="../Drivers/CMSIS/Device/ST/STM32F4xx/Include"/>
 									<listOptionValue builtIn="false" value="../Drivers/CMSIS/Include"/>
+									<listOptionValue builtIn="false" value="../USB_DEVICE/App"/>
+									<listOptionValue builtIn="false" value="../USB_DEVICE/Target"/>
+									<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Core/Inc"/>
+									<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Class/AUDIO/Inc"/>
 								</option>
 								<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.1455972285" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c"/>
 							</tool>
@@ -75,7 +79,9 @@
 					</folderInfo>
 					<sourceEntries>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Middlewares"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Drivers"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="USB_DEVICE"/>
 					</sourceEntries>
 				</configuration>
 			</storageModule>
@@ -103,8 +109,8 @@
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.240310785" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.value.fpv4-sp-d16" valueType="enumerated"/>
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.1810988892" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.value.hard" valueType="enumerated"/>
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.746597665" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
-							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.1197905197" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32F411CEUx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32F4xx_HAL_Driver/Inc | ../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32F4xx/Include | ../Drivers/CMSIS/Include ||  ||  || USE_HAL_DRIVER | STM32F411xE ||  || Drivers | Core/Startup | Core ||  ||  || ${workspace_loc:/${ProjName}/STM32F411CEUX_FLASH.ld} || true || NonSecure ||  || secure_nsclib.o ||  || None ||  ||  || " valueType="string"/>
-							<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.337631777" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" value="16" valueType="string"/>
+							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.1197905197" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32F411CEUx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32F4xx_HAL_Driver/Inc | ../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32F4xx/Include | ../Drivers/CMSIS/Include | ../USB_DEVICE/App | ../USB_DEVICE/Target | ../Middlewares/ST/STM32_USB_Device_Library/Core/Inc | ../Middlewares/ST/STM32_USB_Device_Library/Class/AUDIO/Inc ||  ||  || USE_HAL_DRIVER | STM32F411xE ||  || Drivers | Core/Startup | Middlewares | Core | USB_DEVICE ||  ||  || ${workspace_loc:/${ProjName}/STM32F411CEUX_FLASH.ld} || true || NonSecure ||  || secure_nsclib.o ||  || None ||  ||  || " valueType="string"/>
+							<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.337631777" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="16" valueType="string"/>
 							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.704800227" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
 							<builder buildPath="${workspace_loc:/usb_mic}/Release" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.767866749" managedBuildOn="true" name="Gnu Make Builder.Release" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
 							<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.454773099" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">
@@ -124,6 +130,10 @@
 									<listOptionValue builtIn="false" value="../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy"/>
 									<listOptionValue builtIn="false" value="../Drivers/CMSIS/Device/ST/STM32F4xx/Include"/>
 									<listOptionValue builtIn="false" value="../Drivers/CMSIS/Include"/>
+									<listOptionValue builtIn="false" value="../USB_DEVICE/App"/>
+									<listOptionValue builtIn="false" value="../USB_DEVICE/Target"/>
+									<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Core/Inc"/>
+									<listOptionValue builtIn="false" value="../Middlewares/ST/STM32_USB_Device_Library/Class/AUDIO/Inc"/>
 								</option>
 								<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.1896920108" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c"/>
 							</tool>
@@ -151,7 +161,9 @@
 					</folderInfo>
 					<sourceEntries>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Middlewares"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Drivers"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="USB_DEVICE"/>
 					</sourceEntries>
 				</configuration>
 			</storageModule>

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+Debug

Plik diff jest za duży
+ 0 - 17
.mxproject


+ 2 - 1
.settings/stm32cubeide.project.prefs

@@ -1,4 +1,5 @@
 635E684B79701B039C64EA45C3F84D30=943910FD82241AB913596F30776C7D8E
-66BE74F758C12D739921AEA421D593D3=0
+66BE74F758C12D739921AEA421D593D3=1
+8DF89ED150041C4CBC7CB9A9CAA90856=DAC8EEE01985C0FB0DA41DBE9E20E1A4
 DC22A860405A8BF2F2C095E5B6529F12=DAC8EEE01985C0FB0DA41DBE9E20E1A4
 eclipse.preferences.version=1

+ 1 - 1
Core/Inc/stm32f4xx_hal_conf.h

@@ -70,7 +70,7 @@
 /* #define HAL_SMARTCARD_MODULE_ENABLED */
 /* #define HAL_SMBUS_MODULE_ENABLED */
 /* #define HAL_WWDG_MODULE_ENABLED */
-/* #define HAL_PCD_MODULE_ENABLED */
+#define HAL_PCD_MODULE_ENABLED
 /* #define HAL_HCD_MODULE_ENABLED */
 /* #define HAL_DSI_MODULE_ENABLED */
 /* #define HAL_QSPI_MODULE_ENABLED */

+ 1 - 0
Core/Inc/stm32f4xx_it.h

@@ -55,6 +55,7 @@ void SVC_Handler(void);
 void DebugMon_Handler(void);
 void PendSV_Handler(void);
 void SysTick_Handler(void);
+void OTG_FS_IRQHandler(void);
 /* USER CODE BEGIN EFP */
 
 /* USER CODE END EFP */

+ 34 - 3
Core/Src/main.c

@@ -17,7 +17,10 @@
   */
 /* USER CODE END Header */
 /* Includes ------------------------------------------------------------------*/
-#include "main/* Private includes ----------------------------------------------------------*/
+#include "main.h"
+#include "usb_device.h"
+
+/* Private includes ----------------------------------------------------------*/
 /* USER CODE BEGIN Includes */
 
 /* USER CODE END Includes */
@@ -45,6 +48,7 @@
 
 /* Private function prototypes -----------------------------------------------*/
 void SystemClock_Config(void);
+static void MX_GPIO_Init(void);
 /* USER CODE BEGIN PFP */
 
 /* USER CODE END PFP */
@@ -81,6 +85,8 @@ int main(void)
   /* USER CODE END SysInit */
 
   /* Initialize all configured peripherals */
+  MX_GPIO_Init();
+  MX_USB_DEVICE_Init();
   /* USER CODE BEGIN 2 */
 
   /* USER CODE END 2 */
@@ -113,10 +119,16 @@ void SystemClock_Config(void)
   /** Initializes the RCC Oscillators according to the specified parameters
   * in the RCC_OscInitTypeDef structure.
   */
-  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
+  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
+  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
-  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
+  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+  RCC_OscInitStruct.PLL.PLLM = 15;
+  RCC_OscInitStruct.PLL.PLLN = 144;
+  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
+  RCC_OscInitStruct.PLL.PLLQ = 5;
   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
   {
     Error_Handler();
@@ -137,6 +149,25 @@ void SystemClock_Config(void)
   }
 }
 
+/**
+  * @brief GPIO Initialization Function
+  * @param None
+  * @retval None
+  */
+static void MX_GPIO_Init(void)
+{
+/* USER CODE BEGIN MX_GPIO_Init_1 */
+/* USER CODE END MX_GPIO_Init_1 */
+
+  /* GPIO Ports Clock Enable */
+  __HAL_RCC_GPIOC_CLK_ENABLE();
+  __HAL_RCC_GPIOH_CLK_ENABLE();
+  __HAL_RCC_GPIOA_CLK_ENABLE();
+
+/* USER CODE BEGIN MX_GPIO_Init_2 */
+/* USER CODE END MX_GPIO_Init_2 */
+}
+
 /* USER CODE BEGIN 4 */
 
 /* USER CODE END 4 */

+ 15 - 1
Core/Src/stm32f4xx_it.c

@@ -55,7 +55,7 @@
 /* USER CODE END 0 */
 
 /* External variables --------------------------------------------------------*/
-
+extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
 /* USER CODE BEGIN EV */
 
 /* USER CODE END EV */
@@ -198,6 +198,20 @@ void SysTick_Handler(void)
 /* please refer to the startup file (startup_stm32f4xx.s).                    */
 /******************************************************************************/
 
+/**
+  * @brief This function handles USB On The Go FS global interrupt.
+  */
+void OTG_FS_IRQHandler(void)
+{
+  /* USER CODE BEGIN OTG_FS_IRQn 0 */
+
+  /* USER CODE END OTG_FS_IRQn 0 */
+  HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
+  /* USER CODE BEGIN OTG_FS_IRQn 1 */
+
+  /* USER CODE END OTG_FS_IRQn 1 */
+}
+
 /* USER CODE BEGIN 1 */
 
 /* USER CODE END 1 */

+ 461 - 0
Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h

@@ -0,0 +1,461 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_hal_pcd.h
+  * @author  MCD Application Team
+  * @brief   Header file of PCD HAL module.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef STM32F4xx_HAL_PCD_H
+#define STM32F4xx_HAL_PCD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_ll_usb.h"
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @addtogroup PCD
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup PCD_Exported_Types PCD Exported Types
+  * @{
+  */
+
+/**
+  * @brief  PCD State structure definition
+  */
+typedef enum
+{
+  HAL_PCD_STATE_RESET   = 0x00,
+  HAL_PCD_STATE_READY   = 0x01,
+  HAL_PCD_STATE_ERROR   = 0x02,
+  HAL_PCD_STATE_BUSY    = 0x03,
+  HAL_PCD_STATE_TIMEOUT = 0x04
+} PCD_StateTypeDef;
+
+/* Device LPM suspend state */
+typedef enum
+{
+  LPM_L0 = 0x00, /* on */
+  LPM_L1 = 0x01, /* LPM L1 sleep */
+  LPM_L2 = 0x02, /* suspend */
+  LPM_L3 = 0x03, /* off */
+} PCD_LPM_StateTypeDef;
+
+typedef enum
+{
+  PCD_LPM_L0_ACTIVE = 0x00, /* on */
+  PCD_LPM_L1_ACTIVE = 0x01, /* LPM L1 sleep */
+} PCD_LPM_MsgTypeDef;
+
+typedef enum
+{
+  PCD_BCD_ERROR                     = 0xFF,
+  PCD_BCD_CONTACT_DETECTION         = 0xFE,
+  PCD_BCD_STD_DOWNSTREAM_PORT       = 0xFD,
+  PCD_BCD_CHARGING_DOWNSTREAM_PORT  = 0xFC,
+  PCD_BCD_DEDICATED_CHARGING_PORT   = 0xFB,
+  PCD_BCD_DISCOVERY_COMPLETED       = 0x00,
+
+} PCD_BCD_MsgTypeDef;
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+typedef USB_OTG_GlobalTypeDef  PCD_TypeDef;
+typedef USB_OTG_CfgTypeDef     PCD_InitTypeDef;
+typedef USB_OTG_EPTypeDef      PCD_EPTypeDef;
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+/**
+  * @brief  PCD Handle Structure definition
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+typedef struct __PCD_HandleTypeDef
+#else
+typedef struct
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  PCD_TypeDef             *Instance;   /*!< Register base address             */
+  PCD_InitTypeDef         Init;        /*!< PCD required parameters           */
+  __IO uint8_t            USB_Address; /*!< USB Address                       */
+  PCD_EPTypeDef           IN_ep[16];   /*!< IN endpoint parameters            */
+  PCD_EPTypeDef           OUT_ep[16];  /*!< OUT endpoint parameters           */
+  HAL_LockTypeDef         Lock;        /*!< PCD peripheral status             */
+  __IO PCD_StateTypeDef   State;       /*!< PCD communication state           */
+  __IO  uint32_t          ErrorCode;   /*!< PCD Error code                    */
+  uint32_t                Setup[12];   /*!< Setup packet buffer               */
+  PCD_LPM_StateTypeDef    LPM_State;   /*!< LPM State                         */
+  uint32_t                BESL;
+  uint32_t                FrameNumber; /*!< Store Current Frame number        */
+
+
+  uint32_t lpm_active;                 /*!< Enable or disable the Link Power Management .
+                                       This parameter can be set to ENABLE or DISABLE        */
+
+  uint32_t battery_charging_active;    /*!< Enable or disable Battery charging.
+                                       This parameter can be set to ENABLE or DISABLE        */
+  void                    *pData;      /*!< Pointer to upper stack Handler */
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+  void (* SOFCallback)(struct __PCD_HandleTypeDef *hpcd);                              /*!< USB OTG PCD SOF callback                */
+  void (* SetupStageCallback)(struct __PCD_HandleTypeDef *hpcd);                       /*!< USB OTG PCD Setup Stage callback        */
+  void (* ResetCallback)(struct __PCD_HandleTypeDef *hpcd);                            /*!< USB OTG PCD Reset callback              */
+  void (* SuspendCallback)(struct __PCD_HandleTypeDef *hpcd);                          /*!< USB OTG PCD Suspend callback            */
+  void (* ResumeCallback)(struct __PCD_HandleTypeDef *hpcd);                           /*!< USB OTG PCD Resume callback             */
+  void (* ConnectCallback)(struct __PCD_HandleTypeDef *hpcd);                          /*!< USB OTG PCD Connect callback            */
+  void (* DisconnectCallback)(struct __PCD_HandleTypeDef *hpcd);                       /*!< USB OTG PCD Disconnect callback         */
+
+  void (* DataOutStageCallback)(struct __PCD_HandleTypeDef *hpcd, uint8_t epnum);      /*!< USB OTG PCD Data OUT Stage callback     */
+  void (* DataInStageCallback)(struct __PCD_HandleTypeDef *hpcd, uint8_t epnum);       /*!< USB OTG PCD Data IN Stage callback      */
+  void (* ISOOUTIncompleteCallback)(struct __PCD_HandleTypeDef *hpcd, uint8_t epnum);  /*!< USB OTG PCD ISO OUT Incomplete callback */
+  void (* ISOINIncompleteCallback)(struct __PCD_HandleTypeDef *hpcd, uint8_t epnum);   /*!< USB OTG PCD ISO IN Incomplete callback  */
+  void (* BCDCallback)(struct __PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg);      /*!< USB OTG PCD BCD callback                */
+  void (* LPMCallback)(struct __PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg);      /*!< USB OTG PCD LPM callback                */
+
+  void (* MspInitCallback)(struct __PCD_HandleTypeDef *hpcd);                          /*!< USB OTG PCD Msp Init callback           */
+  void (* MspDeInitCallback)(struct __PCD_HandleTypeDef *hpcd);                        /*!< USB OTG PCD Msp DeInit callback         */
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+} PCD_HandleTypeDef;
+
+/**
+  * @}
+  */
+
+/* Include PCD HAL Extended module */
+#include "stm32f4xx_hal_pcd_ex.h"
+
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup PCD_Exported_Constants PCD Exported Constants
+  * @{
+  */
+
+/** @defgroup PCD_Speed PCD Speed
+  * @{
+  */
+#define PCD_SPEED_HIGH               USBD_HS_SPEED
+#define PCD_SPEED_HIGH_IN_FULL       USBD_HSINFS_SPEED
+#define PCD_SPEED_FULL               USBD_FS_SPEED
+/**
+  * @}
+  */
+
+/** @defgroup PCD_PHY_Module PCD PHY Module
+  * @{
+  */
+#define PCD_PHY_ULPI                 1U
+#define PCD_PHY_EMBEDDED             2U
+#define PCD_PHY_UTMI                 3U
+/**
+  * @}
+  */
+
+/** @defgroup PCD_Error_Code_definition PCD Error Code definition
+  * @brief  PCD Error Code definition
+  * @{
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+#define  HAL_PCD_ERROR_INVALID_CALLBACK                        (0x00000010U)    /*!< Invalid Callback error  */
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macros -----------------------------------------------------------*/
+/** @defgroup PCD_Exported_Macros PCD Exported Macros
+  *  @brief macros to handle interrupts and specific clock configurations
+  * @{
+  */
+#define __HAL_PCD_ENABLE(__HANDLE__)                       (void)USB_EnableGlobalInt ((__HANDLE__)->Instance)
+#define __HAL_PCD_DISABLE(__HANDLE__)                      (void)USB_DisableGlobalInt ((__HANDLE__)->Instance)
+
+#define __HAL_PCD_GET_FLAG(__HANDLE__, __INTERRUPT__) \
+  ((USB_ReadInterrupts((__HANDLE__)->Instance) & (__INTERRUPT__)) == (__INTERRUPT__))
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+#define __HAL_PCD_CLEAR_FLAG(__HANDLE__, __INTERRUPT__)    (((__HANDLE__)->Instance->GINTSTS) &= (__INTERRUPT__))
+#define __HAL_PCD_IS_INVALID_INTERRUPT(__HANDLE__)         (USB_ReadInterrupts((__HANDLE__)->Instance) == 0U)
+
+#define __HAL_PCD_UNGATE_PHYCLOCK(__HANDLE__) \
+  *(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE) &= ~(USB_OTG_PCGCCTL_STOPCLK)
+
+#define __HAL_PCD_GATE_PHYCLOCK(__HANDLE__) \
+  *(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE) |= USB_OTG_PCGCCTL_STOPCLK
+
+#define __HAL_PCD_IS_PHY_SUSPENDED(__HANDLE__) \
+  ((*(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE)) & 0x10U)
+
+#define __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_IT()    EXTI->IMR |= (USB_OTG_HS_WAKEUP_EXTI_LINE)
+#define __HAL_USB_OTG_HS_WAKEUP_EXTI_DISABLE_IT()   EXTI->IMR &= ~(USB_OTG_HS_WAKEUP_EXTI_LINE)
+#define __HAL_USB_OTG_HS_WAKEUP_EXTI_GET_FLAG()     EXTI->PR & (USB_OTG_HS_WAKEUP_EXTI_LINE)
+#define __HAL_USB_OTG_HS_WAKEUP_EXTI_CLEAR_FLAG()   EXTI->PR = (USB_OTG_HS_WAKEUP_EXTI_LINE)
+
+#define __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_RISING_EDGE() \
+  do { \
+    EXTI->FTSR &= ~(USB_OTG_HS_WAKEUP_EXTI_LINE); \
+    EXTI->RTSR |= USB_OTG_HS_WAKEUP_EXTI_LINE; \
+  } while(0U)
+#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_IT()    EXTI->IMR |= USB_OTG_FS_WAKEUP_EXTI_LINE
+#define __HAL_USB_OTG_FS_WAKEUP_EXTI_DISABLE_IT()   EXTI->IMR &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE)
+#define __HAL_USB_OTG_FS_WAKEUP_EXTI_GET_FLAG()     EXTI->PR & (USB_OTG_FS_WAKEUP_EXTI_LINE)
+#define __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG()   EXTI->PR = USB_OTG_FS_WAKEUP_EXTI_LINE
+
+#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_EDGE() \
+  do { \
+    EXTI->FTSR &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE); \
+    EXTI->RTSR |= USB_OTG_FS_WAKEUP_EXTI_LINE; \
+  } while(0U)
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+
+/**
+  * @}
+  */
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup PCD_Exported_Functions PCD Exported Functions
+  * @{
+  */
+
+/* Initialization/de-initialization functions  ********************************/
+/** @addtogroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
+  * @{
+  */
+HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd);
+HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd);
+void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd);
+void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd);
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+/** @defgroup HAL_PCD_Callback_ID_enumeration_definition HAL USB OTG PCD Callback ID enumeration definition
+  * @brief  HAL USB OTG PCD Callback ID enumeration definition
+  * @{
+  */
+typedef enum
+{
+  HAL_PCD_SOF_CB_ID          = 0x01,      /*!< USB PCD SOF callback ID          */
+  HAL_PCD_SETUPSTAGE_CB_ID   = 0x02,      /*!< USB PCD Setup Stage callback ID  */
+  HAL_PCD_RESET_CB_ID        = 0x03,      /*!< USB PCD Reset callback ID        */
+  HAL_PCD_SUSPEND_CB_ID      = 0x04,      /*!< USB PCD Suspend callback ID      */
+  HAL_PCD_RESUME_CB_ID       = 0x05,      /*!< USB PCD Resume callback ID       */
+  HAL_PCD_CONNECT_CB_ID      = 0x06,      /*!< USB PCD Connect callback ID      */
+  HAL_PCD_DISCONNECT_CB_ID   = 0x07,      /*!< USB PCD Disconnect callback ID   */
+
+  HAL_PCD_MSPINIT_CB_ID      = 0x08,      /*!< USB PCD MspInit callback ID      */
+  HAL_PCD_MSPDEINIT_CB_ID    = 0x09       /*!< USB PCD MspDeInit callback ID    */
+
+} HAL_PCD_CallbackIDTypeDef;
+/**
+  * @}
+  */
+
+/** @defgroup HAL_PCD_Callback_pointer_definition HAL USB OTG PCD Callback pointer definition
+  * @brief  HAL USB OTG PCD Callback pointer definition
+  * @{
+  */
+
+typedef void (*pPCD_CallbackTypeDef)(PCD_HandleTypeDef *hpcd);                                   /*!< pointer to a common USB OTG PCD callback function  */
+typedef void (*pPCD_DataOutStageCallbackTypeDef)(PCD_HandleTypeDef *hpcd, uint8_t epnum);        /*!< pointer to USB OTG PCD Data OUT Stage callback     */
+typedef void (*pPCD_DataInStageCallbackTypeDef)(PCD_HandleTypeDef *hpcd, uint8_t epnum);         /*!< pointer to USB OTG PCD Data IN Stage callback      */
+typedef void (*pPCD_IsoOutIncpltCallbackTypeDef)(PCD_HandleTypeDef *hpcd, uint8_t epnum);        /*!< pointer to USB OTG PCD ISO OUT Incomplete callback */
+typedef void (*pPCD_IsoInIncpltCallbackTypeDef)(PCD_HandleTypeDef *hpcd, uint8_t epnum);         /*!< pointer to USB OTG PCD ISO IN Incomplete callback  */
+typedef void (*pPCD_LpmCallbackTypeDef)(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg);        /*!< pointer to USB OTG PCD LPM callback                */
+typedef void (*pPCD_BcdCallbackTypeDef)(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg);        /*!< pointer to USB OTG PCD BCD callback                */
+
+/**
+  * @}
+  */
+
+HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID,
+                                           pPCD_CallbackTypeDef pCallback);
+
+HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID);
+
+HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
+                                                       pPCD_DataOutStageCallbackTypeDef pCallback);
+
+HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd);
+
+HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
+                                                      pPCD_DataInStageCallbackTypeDef pCallback);
+
+HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd);
+
+HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
+                                                       pPCD_IsoOutIncpltCallbackTypeDef pCallback);
+
+HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd);
+
+HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
+                                                      pPCD_IsoInIncpltCallbackTypeDef pCallback);
+
+HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd);
+
+HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd, pPCD_BcdCallbackTypeDef pCallback);
+HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd);
+
+HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd, pPCD_LpmCallbackTypeDef pCallback);
+HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+/**
+  * @}
+  */
+
+/* I/O operation functions  ***************************************************/
+/* Non-Blocking mode: Interrupt */
+/** @addtogroup PCD_Exported_Functions_Group2 Input and Output operation functions
+  * @{
+  */
+HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd);
+HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd);
+void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd);
+void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd);
+
+void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd);
+void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd);
+void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd);
+void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd);
+void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd);
+void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd);
+void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd);
+
+void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
+void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
+void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
+void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum);
+/**
+  * @}
+  */
+
+/* Peripheral Control functions  **********************************************/
+/** @addtogroup PCD_Exported_Functions_Group3 Peripheral Control functions
+  * @{
+  */
+HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd);
+HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd);
+HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address);
+HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type);
+HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
+HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len);
+HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len);
+HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
+HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
+HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
+HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
+HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd);
+HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd);
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+HAL_StatusTypeDef HAL_PCD_SetTestMode(const PCD_HandleTypeDef *hpcd, uint8_t testmode);
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+uint32_t          HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef const *hpcd, uint8_t ep_addr);
+/**
+  * @}
+  */
+
+/* Peripheral State functions  ************************************************/
+/** @addtogroup PCD_Exported_Functions_Group4 Peripheral State functions
+  * @{
+  */
+PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef const *hpcd);
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Private constants ---------------------------------------------------------*/
+/** @defgroup PCD_Private_Constants PCD Private Constants
+  * @{
+  */
+/** @defgroup USB_EXTI_Line_Interrupt USB EXTI line interrupt
+  * @{
+  */
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+#define USB_OTG_FS_WAKEUP_EXTI_LINE                                   (0x1U << 18)  /*!< USB FS EXTI Line WakeUp Interrupt */
+#define USB_OTG_HS_WAKEUP_EXTI_LINE                                   (0x1U << 20)  /*!< USB HS EXTI Line WakeUp Interrupt */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+
+/**
+  * @}
+  */
+/**
+  * @}
+  */
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+#ifndef USB_OTG_DOEPINT_OTEPSPR
+#define USB_OTG_DOEPINT_OTEPSPR                (0x1UL << 5)      /*!< Status Phase Received interrupt */
+#endif /* defined USB_OTG_DOEPINT_OTEPSPR */
+
+#ifndef USB_OTG_DOEPMSK_OTEPSPRM
+#define USB_OTG_DOEPMSK_OTEPSPRM               (0x1UL << 5)      /*!< Setup Packet Received interrupt mask */
+#endif /* defined USB_OTG_DOEPMSK_OTEPSPRM */
+
+#ifndef USB_OTG_DOEPINT_NAK
+#define USB_OTG_DOEPINT_NAK                    (0x1UL << 13)      /*!< NAK interrupt */
+#endif /* defined USB_OTG_DOEPINT_NAK */
+
+#ifndef USB_OTG_DOEPMSK_NAKM
+#define USB_OTG_DOEPMSK_NAKM                   (0x1UL << 13)      /*!< OUT Packet NAK interrupt mask */
+#endif /* defined USB_OTG_DOEPMSK_NAKM */
+
+#ifndef USB_OTG_DOEPINT_STPKTRX
+#define USB_OTG_DOEPINT_STPKTRX                (0x1UL << 15)      /*!< Setup Packet Received interrupt */
+#endif /* defined USB_OTG_DOEPINT_STPKTRX */
+
+#ifndef USB_OTG_DOEPMSK_NYETM
+#define USB_OTG_DOEPMSK_NYETM                  (0x1UL << 14)      /*!< Setup Packet Received interrupt mask */
+#endif /* defined USB_OTG_DOEPMSK_NYETM */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup PCD_Private_Macros PCD Private Macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32F4xx_HAL_PCD_H */

+ 94 - 0
Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h

@@ -0,0 +1,94 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_hal_pcd_ex.h
+  * @author  MCD Application Team
+  * @brief   Header file of PCD HAL Extension module.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef STM32F4xx_HAL_PCD_EX_H
+#define STM32F4xx_HAL_PCD_EX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal_def.h"
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @addtogroup PCDEx
+  * @{
+  */
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup PCDEx_Exported_Functions PCDEx Exported Functions
+  * @{
+  */
+/** @addtogroup PCDEx_Exported_Functions_Group1 Peripheral Control functions
+  * @{
+  */
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size);
+HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size);
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) \
+ || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) \
+ || defined(STM32F423xx)
+HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd);
+HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd);
+#endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||
+          defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) ||
+          defined(STM32F423xx) */
+#if defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) \
+ || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
+HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd);
+HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd);
+void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd);
+#endif /* defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) ||
+          defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) */
+void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg);
+void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg);
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* STM32F4xx_HAL_PCD_EX_H */

+ 2155 - 0
Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h

@@ -0,0 +1,2155 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_hal_tim.h
+  * @author  MCD Application Team
+  * @brief   Header file of TIM HAL module.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef STM32F4xx_HAL_TIM_H
+#define STM32F4xx_HAL_TIM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal_def.h"
+
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @addtogroup TIM
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup TIM_Exported_Types TIM Exported Types
+  * @{
+  */
+
+/**
+  * @brief  TIM Time base Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
+                                   This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
+
+  uint32_t CounterMode;       /*!< Specifies the counter mode.
+                                   This parameter can be a value of @ref TIM_Counter_Mode */
+
+  uint32_t Period;            /*!< Specifies the period value to be loaded into the active
+                                   Auto-Reload Register at the next update event.
+                                   This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF.  */
+
+  uint32_t ClockDivision;     /*!< Specifies the clock division.
+                                   This parameter can be a value of @ref TIM_ClockDivision */
+
+  uint32_t RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
+                                    reaches zero, an update event is generated and counting restarts
+                                    from the RCR value (N).
+                                    This means in PWM mode that (N+1) corresponds to:
+                                        - the number of PWM periods in edge-aligned mode
+                                        - the number of half PWM period in center-aligned mode
+                                     GP timers: this parameter must be a number between Min_Data = 0x00 and
+                                     Max_Data = 0xFF.
+                                     Advanced timers: this parameter must be a number between Min_Data = 0x0000 and
+                                     Max_Data = 0xFFFF. */
+
+  uint32_t AutoReloadPreload;  /*!< Specifies the auto-reload preload.
+                                   This parameter can be a value of @ref TIM_AutoReloadPreload */
+} TIM_Base_InitTypeDef;
+
+/**
+  * @brief  TIM Output Compare Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t OCMode;        /*!< Specifies the TIM mode.
+                               This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
+
+  uint32_t Pulse;         /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
+                               This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
+
+  uint32_t OCPolarity;    /*!< Specifies the output polarity.
+                               This parameter can be a value of @ref TIM_Output_Compare_Polarity */
+
+  uint32_t OCNPolarity;   /*!< Specifies the complementary output polarity.
+                               This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
+                               @note This parameter is valid only for timer instances supporting break feature. */
+
+  uint32_t OCFastMode;    /*!< Specifies the Fast mode state.
+                               This parameter can be a value of @ref TIM_Output_Fast_State
+                               @note This parameter is valid only in PWM1 and PWM2 mode. */
+
+
+  uint32_t OCIdleState;   /*!< Specifies the TIM Output Compare pin state during Idle state.
+                               This parameter can be a value of @ref TIM_Output_Compare_Idle_State
+                               @note This parameter is valid only for timer instances supporting break feature. */
+
+  uint32_t OCNIdleState;  /*!< Specifies the TIM Output Compare pin state during Idle state.
+                               This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
+                               @note This parameter is valid only for timer instances supporting break feature. */
+} TIM_OC_InitTypeDef;
+
+/**
+  * @brief  TIM One Pulse Mode Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t OCMode;        /*!< Specifies the TIM mode.
+                               This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
+
+  uint32_t Pulse;         /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
+                               This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
+
+  uint32_t OCPolarity;    /*!< Specifies the output polarity.
+                               This parameter can be a value of @ref TIM_Output_Compare_Polarity */
+
+  uint32_t OCNPolarity;   /*!< Specifies the complementary output polarity.
+                               This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
+                               @note This parameter is valid only for timer instances supporting break feature. */
+
+  uint32_t OCIdleState;   /*!< Specifies the TIM Output Compare pin state during Idle state.
+                               This parameter can be a value of @ref TIM_Output_Compare_Idle_State
+                               @note This parameter is valid only for timer instances supporting break feature. */
+
+  uint32_t OCNIdleState;  /*!< Specifies the TIM Output Compare pin state during Idle state.
+                               This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
+                               @note This parameter is valid only for timer instances supporting break feature. */
+
+  uint32_t ICPolarity;    /*!< Specifies the active edge of the input signal.
+                               This parameter can be a value of @ref TIM_Input_Capture_Polarity */
+
+  uint32_t ICSelection;   /*!< Specifies the input.
+                              This parameter can be a value of @ref TIM_Input_Capture_Selection */
+
+  uint32_t ICFilter;      /*!< Specifies the input capture filter.
+                              This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+} TIM_OnePulse_InitTypeDef;
+
+/**
+  * @brief  TIM Input Capture Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t  ICPolarity;  /*!< Specifies the active edge of the input signal.
+                              This parameter can be a value of @ref TIM_Input_Capture_Polarity */
+
+  uint32_t ICSelection;  /*!< Specifies the input.
+                              This parameter can be a value of @ref TIM_Input_Capture_Selection */
+
+  uint32_t ICPrescaler;  /*!< Specifies the Input Capture Prescaler.
+                              This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
+
+  uint32_t ICFilter;     /*!< Specifies the input capture filter.
+                              This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+} TIM_IC_InitTypeDef;
+
+/**
+  * @brief  TIM Encoder Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t EncoderMode;   /*!< Specifies the active edge of the input signal.
+                               This parameter can be a value of @ref TIM_Encoder_Mode */
+
+  uint32_t IC1Polarity;   /*!< Specifies the active edge of the input signal.
+                               This parameter can be a value of @ref TIM_Encoder_Input_Polarity */
+
+  uint32_t IC1Selection;  /*!< Specifies the input.
+                               This parameter can be a value of @ref TIM_Input_Capture_Selection */
+
+  uint32_t IC1Prescaler;  /*!< Specifies the Input Capture Prescaler.
+                               This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
+
+  uint32_t IC1Filter;     /*!< Specifies the input capture filter.
+                               This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+
+  uint32_t IC2Polarity;   /*!< Specifies the active edge of the input signal.
+                               This parameter can be a value of @ref TIM_Encoder_Input_Polarity */
+
+  uint32_t IC2Selection;  /*!< Specifies the input.
+                              This parameter can be a value of @ref TIM_Input_Capture_Selection */
+
+  uint32_t IC2Prescaler;  /*!< Specifies the Input Capture Prescaler.
+                               This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
+
+  uint32_t IC2Filter;     /*!< Specifies the input capture filter.
+                               This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+} TIM_Encoder_InitTypeDef;
+
+/**
+  * @brief  Clock Configuration Handle Structure definition
+  */
+typedef struct
+{
+  uint32_t ClockSource;     /*!< TIM clock sources
+                                 This parameter can be a value of @ref TIM_Clock_Source */
+  uint32_t ClockPolarity;   /*!< TIM clock polarity
+                                 This parameter can be a value of @ref TIM_Clock_Polarity */
+  uint32_t ClockPrescaler;  /*!< TIM clock prescaler
+                                 This parameter can be a value of @ref TIM_Clock_Prescaler */
+  uint32_t ClockFilter;     /*!< TIM clock filter
+                                 This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+} TIM_ClockConfigTypeDef;
+
+/**
+  * @brief  TIM Clear Input Configuration Handle Structure definition
+  */
+typedef struct
+{
+  uint32_t ClearInputState;      /*!< TIM clear Input state
+                                      This parameter can be ENABLE or DISABLE */
+  uint32_t ClearInputSource;     /*!< TIM clear Input sources
+                                      This parameter can be a value of @ref TIM_ClearInput_Source */
+  uint32_t ClearInputPolarity;   /*!< TIM Clear Input polarity
+                                      This parameter can be a value of @ref TIM_ClearInput_Polarity */
+  uint32_t ClearInputPrescaler;  /*!< TIM Clear Input prescaler
+                                      This parameter must be 0: When OCRef clear feature is used with ETR source,
+                                      ETR prescaler must be off */
+  uint32_t ClearInputFilter;     /*!< TIM Clear Input filter
+                                      This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+} TIM_ClearInputConfigTypeDef;
+
+/**
+  * @brief  TIM Master configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t  MasterOutputTrigger;   /*!< Trigger output (TRGO) selection
+                                        This parameter can be a value of @ref TIM_Master_Mode_Selection */
+  uint32_t  MasterSlaveMode;       /*!< Master/slave mode selection
+                                        This parameter can be a value of @ref TIM_Master_Slave_Mode
+                                        @note When the Master/slave mode is enabled, the effect of
+                                        an event on the trigger input (TRGI) is delayed to allow a
+                                        perfect synchronization between the current timer and its
+                                        slaves (through TRGO). It is not mandatory in case of timer
+                                        synchronization mode. */
+} TIM_MasterConfigTypeDef;
+
+/**
+  * @brief  TIM Slave configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t  SlaveMode;         /*!< Slave mode selection
+                                    This parameter can be a value of @ref TIM_Slave_Mode */
+  uint32_t  InputTrigger;      /*!< Input Trigger source
+                                    This parameter can be a value of @ref TIM_Trigger_Selection */
+  uint32_t  TriggerPolarity;   /*!< Input Trigger polarity
+                                    This parameter can be a value of @ref TIM_Trigger_Polarity */
+  uint32_t  TriggerPrescaler;  /*!< Input trigger prescaler
+                                    This parameter can be a value of @ref TIM_Trigger_Prescaler */
+  uint32_t  TriggerFilter;     /*!< Input trigger filter
+                                    This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF  */
+
+} TIM_SlaveConfigTypeDef;
+
+/**
+  * @brief  TIM Break input(s) and Dead time configuration Structure definition
+  * @note   2 break inputs can be configured (BKIN and BKIN2) with configurable
+  *        filter and polarity.
+  */
+typedef struct
+{
+  uint32_t OffStateRunMode;      /*!< TIM off state in run mode, This parameter can be a value of @ref TIM_OSSR_Off_State_Selection_for_Run_mode_state */
+
+  uint32_t OffStateIDLEMode;     /*!< TIM off state in IDLE mode, This parameter can be a value of @ref TIM_OSSI_Off_State_Selection_for_Idle_mode_state */
+
+  uint32_t LockLevel;            /*!< TIM Lock level, This parameter can be a value of @ref TIM_Lock_level */
+
+  uint32_t DeadTime;             /*!< TIM dead Time, This parameter can be a number between Min_Data = 0x00 and Max_Data = 0xFF */
+
+  uint32_t BreakState;           /*!< TIM Break State, This parameter can be a value of @ref TIM_Break_Input_enable_disable */
+
+  uint32_t BreakPolarity;        /*!< TIM Break input polarity, This parameter can be a value of @ref TIM_Break_Polarity */
+
+  uint32_t BreakFilter;          /*!< Specifies the break input filter.This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+
+  uint32_t AutomaticOutput;      /*!< TIM Automatic Output Enable state, This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset */
+
+} TIM_BreakDeadTimeConfigTypeDef;
+
+/**
+  * @brief  HAL State structures definition
+  */
+typedef enum
+{
+  HAL_TIM_STATE_RESET             = 0x00U,    /*!< Peripheral not yet initialized or disabled  */
+  HAL_TIM_STATE_READY             = 0x01U,    /*!< Peripheral Initialized and ready for use    */
+  HAL_TIM_STATE_BUSY              = 0x02U,    /*!< An internal process is ongoing              */
+  HAL_TIM_STATE_TIMEOUT           = 0x03U,    /*!< Timeout state                               */
+  HAL_TIM_STATE_ERROR             = 0x04U     /*!< Reception process is ongoing                */
+} HAL_TIM_StateTypeDef;
+
+/**
+  * @brief  TIM Channel States definition
+  */
+typedef enum
+{
+  HAL_TIM_CHANNEL_STATE_RESET             = 0x00U,    /*!< TIM Channel initial state                         */
+  HAL_TIM_CHANNEL_STATE_READY             = 0x01U,    /*!< TIM Channel ready for use                         */
+  HAL_TIM_CHANNEL_STATE_BUSY              = 0x02U,    /*!< An internal process is ongoing on the TIM channel */
+} HAL_TIM_ChannelStateTypeDef;
+
+/**
+  * @brief  DMA Burst States definition
+  */
+typedef enum
+{
+  HAL_DMA_BURST_STATE_RESET             = 0x00U,    /*!< DMA Burst initial state */
+  HAL_DMA_BURST_STATE_READY             = 0x01U,    /*!< DMA Burst ready for use */
+  HAL_DMA_BURST_STATE_BUSY              = 0x02U,    /*!< Ongoing DMA Burst       */
+} HAL_TIM_DMABurstStateTypeDef;
+
+/**
+  * @brief  HAL Active channel structures definition
+  */
+typedef enum
+{
+  HAL_TIM_ACTIVE_CHANNEL_1        = 0x01U,    /*!< The active channel is 1     */
+  HAL_TIM_ACTIVE_CHANNEL_2        = 0x02U,    /*!< The active channel is 2     */
+  HAL_TIM_ACTIVE_CHANNEL_3        = 0x04U,    /*!< The active channel is 3     */
+  HAL_TIM_ACTIVE_CHANNEL_4        = 0x08U,    /*!< The active channel is 4     */
+  HAL_TIM_ACTIVE_CHANNEL_CLEARED  = 0x00U     /*!< All active channels cleared */
+} HAL_TIM_ActiveChannel;
+
+/**
+  * @brief  TIM Time Base Handle Structure definition
+  */
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+typedef struct __TIM_HandleTypeDef
+#else
+typedef struct
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+{
+  TIM_TypeDef                        *Instance;         /*!< Register base address                             */
+  TIM_Base_InitTypeDef               Init;              /*!< TIM Time Base required parameters                 */
+  HAL_TIM_ActiveChannel              Channel;           /*!< Active channel                                    */
+  DMA_HandleTypeDef                  *hdma[7];          /*!< DMA Handlers array
+                                                             This array is accessed by a @ref DMA_Handle_index */
+  HAL_LockTypeDef                    Lock;              /*!< Locking object                                    */
+  __IO HAL_TIM_StateTypeDef          State;             /*!< TIM operation state                               */
+  __IO HAL_TIM_ChannelStateTypeDef   ChannelState[4];   /*!< TIM channel operation state                       */
+  __IO HAL_TIM_ChannelStateTypeDef   ChannelNState[4];  /*!< TIM complementary channel operation state         */
+  __IO HAL_TIM_DMABurstStateTypeDef  DMABurstState;     /*!< DMA burst operation state                         */
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  void (* Base_MspInitCallback)(struct __TIM_HandleTypeDef *htim);              /*!< TIM Base Msp Init Callback                              */
+  void (* Base_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);            /*!< TIM Base Msp DeInit Callback                            */
+  void (* IC_MspInitCallback)(struct __TIM_HandleTypeDef *htim);                /*!< TIM IC Msp Init Callback                                */
+  void (* IC_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);              /*!< TIM IC Msp DeInit Callback                              */
+  void (* OC_MspInitCallback)(struct __TIM_HandleTypeDef *htim);                /*!< TIM OC Msp Init Callback                                */
+  void (* OC_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);              /*!< TIM OC Msp DeInit Callback                              */
+  void (* PWM_MspInitCallback)(struct __TIM_HandleTypeDef *htim);               /*!< TIM PWM Msp Init Callback                               */
+  void (* PWM_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);             /*!< TIM PWM Msp DeInit Callback                             */
+  void (* OnePulse_MspInitCallback)(struct __TIM_HandleTypeDef *htim);          /*!< TIM One Pulse Msp Init Callback                         */
+  void (* OnePulse_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);        /*!< TIM One Pulse Msp DeInit Callback                       */
+  void (* Encoder_MspInitCallback)(struct __TIM_HandleTypeDef *htim);           /*!< TIM Encoder Msp Init Callback                           */
+  void (* Encoder_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);         /*!< TIM Encoder Msp DeInit Callback                         */
+  void (* HallSensor_MspInitCallback)(struct __TIM_HandleTypeDef *htim);        /*!< TIM Hall Sensor Msp Init Callback                       */
+  void (* HallSensor_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);      /*!< TIM Hall Sensor Msp DeInit Callback                     */
+  void (* PeriodElapsedCallback)(struct __TIM_HandleTypeDef *htim);             /*!< TIM Period Elapsed Callback                             */
+  void (* PeriodElapsedHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);     /*!< TIM Period Elapsed half complete Callback               */
+  void (* TriggerCallback)(struct __TIM_HandleTypeDef *htim);                   /*!< TIM Trigger Callback                                    */
+  void (* TriggerHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);           /*!< TIM Trigger half complete Callback                      */
+  void (* IC_CaptureCallback)(struct __TIM_HandleTypeDef *htim);                /*!< TIM Input Capture Callback                              */
+  void (* IC_CaptureHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);        /*!< TIM Input Capture half complete Callback                */
+  void (* OC_DelayElapsedCallback)(struct __TIM_HandleTypeDef *htim);           /*!< TIM Output Compare Delay Elapsed Callback               */
+  void (* PWM_PulseFinishedCallback)(struct __TIM_HandleTypeDef *htim);         /*!< TIM PWM Pulse Finished Callback                         */
+  void (* PWM_PulseFinishedHalfCpltCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM PWM Pulse Finished half complete Callback           */
+  void (* ErrorCallback)(struct __TIM_HandleTypeDef *htim);                     /*!< TIM Error Callback                                      */
+  void (* CommutationCallback)(struct __TIM_HandleTypeDef *htim);               /*!< TIM Commutation Callback                                */
+  void (* CommutationHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);       /*!< TIM Commutation half complete Callback                  */
+  void (* BreakCallback)(struct __TIM_HandleTypeDef *htim);                     /*!< TIM Break Callback                                      */
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+} TIM_HandleTypeDef;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+/**
+  * @brief  HAL TIM Callback ID enumeration definition
+  */
+typedef enum
+{
+  HAL_TIM_BASE_MSPINIT_CB_ID              = 0x00U   /*!< TIM Base MspInit Callback ID                               */
+  , HAL_TIM_BASE_MSPDEINIT_CB_ID          = 0x01U   /*!< TIM Base MspDeInit Callback ID                             */
+  , HAL_TIM_IC_MSPINIT_CB_ID              = 0x02U   /*!< TIM IC MspInit Callback ID                                 */
+  , HAL_TIM_IC_MSPDEINIT_CB_ID            = 0x03U   /*!< TIM IC MspDeInit Callback ID                               */
+  , HAL_TIM_OC_MSPINIT_CB_ID              = 0x04U   /*!< TIM OC MspInit Callback ID                                 */
+  , HAL_TIM_OC_MSPDEINIT_CB_ID            = 0x05U   /*!< TIM OC MspDeInit Callback ID                               */
+  , HAL_TIM_PWM_MSPINIT_CB_ID             = 0x06U   /*!< TIM PWM MspInit Callback ID                                */
+  , HAL_TIM_PWM_MSPDEINIT_CB_ID           = 0x07U   /*!< TIM PWM MspDeInit Callback ID                              */
+  , HAL_TIM_ONE_PULSE_MSPINIT_CB_ID       = 0x08U   /*!< TIM One Pulse MspInit Callback ID                          */
+  , HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID     = 0x09U   /*!< TIM One Pulse MspDeInit Callback ID                        */
+  , HAL_TIM_ENCODER_MSPINIT_CB_ID         = 0x0AU   /*!< TIM Encoder MspInit Callback ID                            */
+  , HAL_TIM_ENCODER_MSPDEINIT_CB_ID       = 0x0BU   /*!< TIM Encoder MspDeInit Callback ID                          */
+  , HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID     = 0x0CU   /*!< TIM Hall Sensor MspDeInit Callback ID                      */
+  , HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID   = 0x0DU   /*!< TIM Hall Sensor MspDeInit Callback ID                      */
+  , HAL_TIM_PERIOD_ELAPSED_CB_ID          = 0x0EU   /*!< TIM Period Elapsed Callback ID                             */
+  , HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID     = 0x0FU   /*!< TIM Period Elapsed half complete Callback ID               */
+  , HAL_TIM_TRIGGER_CB_ID                 = 0x10U   /*!< TIM Trigger Callback ID                                    */
+  , HAL_TIM_TRIGGER_HALF_CB_ID            = 0x11U   /*!< TIM Trigger half complete Callback ID                      */
+  , HAL_TIM_IC_CAPTURE_CB_ID              = 0x12U   /*!< TIM Input Capture Callback ID                              */
+  , HAL_TIM_IC_CAPTURE_HALF_CB_ID         = 0x13U   /*!< TIM Input Capture half complete Callback ID                */
+  , HAL_TIM_OC_DELAY_ELAPSED_CB_ID        = 0x14U   /*!< TIM Output Compare Delay Elapsed Callback ID               */
+  , HAL_TIM_PWM_PULSE_FINISHED_CB_ID      = 0x15U   /*!< TIM PWM Pulse Finished Callback ID                         */
+  , HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID = 0x16U   /*!< TIM PWM Pulse Finished half complete Callback ID           */
+  , HAL_TIM_ERROR_CB_ID                   = 0x17U   /*!< TIM Error Callback ID                                      */
+  , HAL_TIM_COMMUTATION_CB_ID             = 0x18U   /*!< TIM Commutation Callback ID                                */
+  , HAL_TIM_COMMUTATION_HALF_CB_ID        = 0x19U   /*!< TIM Commutation half complete Callback ID                  */
+  , HAL_TIM_BREAK_CB_ID                   = 0x1AU   /*!< TIM Break Callback ID                                      */
+} HAL_TIM_CallbackIDTypeDef;
+
+/**
+  * @brief  HAL TIM Callback pointer definition
+  */
+typedef  void (*pTIM_CallbackTypeDef)(TIM_HandleTypeDef *htim);  /*!< pointer to the TIM callback function */
+
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+/* End of exported types -----------------------------------------------------*/
+
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup TIM_Exported_Constants TIM Exported Constants
+  * @{
+  */
+
+/** @defgroup TIM_ClearInput_Source TIM Clear Input Source
+  * @{
+  */
+#define TIM_CLEARINPUTSOURCE_NONE           0x00000000U   /*!< OCREF_CLR is disabled */
+#define TIM_CLEARINPUTSOURCE_ETR            0x00000001U   /*!< OCREF_CLR is connected to ETRF input */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_DMA_Base_address TIM DMA Base Address
+  * @{
+  */
+#define TIM_DMABASE_CR1                    0x00000000U
+#define TIM_DMABASE_CR2                    0x00000001U
+#define TIM_DMABASE_SMCR                   0x00000002U
+#define TIM_DMABASE_DIER                   0x00000003U
+#define TIM_DMABASE_SR                     0x00000004U
+#define TIM_DMABASE_EGR                    0x00000005U
+#define TIM_DMABASE_CCMR1                  0x00000006U
+#define TIM_DMABASE_CCMR2                  0x00000007U
+#define TIM_DMABASE_CCER                   0x00000008U
+#define TIM_DMABASE_CNT                    0x00000009U
+#define TIM_DMABASE_PSC                    0x0000000AU
+#define TIM_DMABASE_ARR                    0x0000000BU
+#define TIM_DMABASE_RCR                    0x0000000CU
+#define TIM_DMABASE_CCR1                   0x0000000DU
+#define TIM_DMABASE_CCR2                   0x0000000EU
+#define TIM_DMABASE_CCR3                   0x0000000FU
+#define TIM_DMABASE_CCR4                   0x00000010U
+#define TIM_DMABASE_BDTR                   0x00000011U
+#define TIM_DMABASE_DCR                    0x00000012U
+#define TIM_DMABASE_DMAR                   0x00000013U
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Event_Source TIM Event Source
+  * @{
+  */
+#define TIM_EVENTSOURCE_UPDATE              TIM_EGR_UG     /*!< Reinitialize the counter and generates an update of the registers */
+#define TIM_EVENTSOURCE_CC1                 TIM_EGR_CC1G   /*!< A capture/compare event is generated on channel 1 */
+#define TIM_EVENTSOURCE_CC2                 TIM_EGR_CC2G   /*!< A capture/compare event is generated on channel 2 */
+#define TIM_EVENTSOURCE_CC3                 TIM_EGR_CC3G   /*!< A capture/compare event is generated on channel 3 */
+#define TIM_EVENTSOURCE_CC4                 TIM_EGR_CC4G   /*!< A capture/compare event is generated on channel 4 */
+#define TIM_EVENTSOURCE_COM                 TIM_EGR_COMG   /*!< A commutation event is generated */
+#define TIM_EVENTSOURCE_TRIGGER             TIM_EGR_TG     /*!< A trigger event is generated */
+#define TIM_EVENTSOURCE_BREAK               TIM_EGR_BG     /*!< A break event is generated */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Input_Channel_Polarity TIM Input Channel polarity
+  * @{
+  */
+#define  TIM_INPUTCHANNELPOLARITY_RISING      0x00000000U                       /*!< Polarity for TIx source */
+#define  TIM_INPUTCHANNELPOLARITY_FALLING     TIM_CCER_CC1P                     /*!< Polarity for TIx source */
+#define  TIM_INPUTCHANNELPOLARITY_BOTHEDGE    (TIM_CCER_CC1P | TIM_CCER_CC1NP)  /*!< Polarity for TIx source */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_ETR_Polarity TIM ETR Polarity
+  * @{
+  */
+#define TIM_ETRPOLARITY_INVERTED              TIM_SMCR_ETP                      /*!< Polarity for ETR source */
+#define TIM_ETRPOLARITY_NONINVERTED           0x00000000U                       /*!< Polarity for ETR source */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_ETR_Prescaler TIM ETR Prescaler
+  * @{
+  */
+#define TIM_ETRPRESCALER_DIV1                 0x00000000U                       /*!< No prescaler is used */
+#define TIM_ETRPRESCALER_DIV2                 TIM_SMCR_ETPS_0                   /*!< ETR input source is divided by 2 */
+#define TIM_ETRPRESCALER_DIV4                 TIM_SMCR_ETPS_1                   /*!< ETR input source is divided by 4 */
+#define TIM_ETRPRESCALER_DIV8                 TIM_SMCR_ETPS                     /*!< ETR input source is divided by 8 */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Counter_Mode TIM Counter Mode
+  * @{
+  */
+#define TIM_COUNTERMODE_UP                 0x00000000U                          /*!< Counter used as up-counter   */
+#define TIM_COUNTERMODE_DOWN               TIM_CR1_DIR                          /*!< Counter used as down-counter */
+#define TIM_COUNTERMODE_CENTERALIGNED1     TIM_CR1_CMS_0                        /*!< Center-aligned mode 1        */
+#define TIM_COUNTERMODE_CENTERALIGNED2     TIM_CR1_CMS_1                        /*!< Center-aligned mode 2        */
+#define TIM_COUNTERMODE_CENTERALIGNED3     TIM_CR1_CMS                          /*!< Center-aligned mode 3        */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_ClockDivision TIM Clock Division
+  * @{
+  */
+#define TIM_CLOCKDIVISION_DIV1             0x00000000U                          /*!< Clock division: tDTS=tCK_INT   */
+#define TIM_CLOCKDIVISION_DIV2             TIM_CR1_CKD_0                        /*!< Clock division: tDTS=2*tCK_INT */
+#define TIM_CLOCKDIVISION_DIV4             TIM_CR1_CKD_1                        /*!< Clock division: tDTS=4*tCK_INT */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_State TIM Output Compare State
+  * @{
+  */
+#define TIM_OUTPUTSTATE_DISABLE            0x00000000U                          /*!< Capture/Compare 1 output disabled */
+#define TIM_OUTPUTSTATE_ENABLE             TIM_CCER_CC1E                        /*!< Capture/Compare 1 output enabled */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_AutoReloadPreload TIM Auto-Reload Preload
+  * @{
+  */
+#define TIM_AUTORELOAD_PRELOAD_DISABLE                0x00000000U               /*!< TIMx_ARR register is not buffered */
+#define TIM_AUTORELOAD_PRELOAD_ENABLE                 TIM_CR1_ARPE              /*!< TIMx_ARR register is buffered */
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Fast_State TIM Output Fast State
+  * @{
+  */
+#define TIM_OCFAST_DISABLE                 0x00000000U                          /*!< Output Compare fast disable */
+#define TIM_OCFAST_ENABLE                  TIM_CCMR1_OC1FE                      /*!< Output Compare fast enable  */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_N_State TIM Complementary Output Compare State
+  * @{
+  */
+#define TIM_OUTPUTNSTATE_DISABLE           0x00000000U                          /*!< OCxN is disabled  */
+#define TIM_OUTPUTNSTATE_ENABLE            TIM_CCER_CC1NE                       /*!< OCxN is enabled   */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_Polarity TIM Output Compare Polarity
+  * @{
+  */
+#define TIM_OCPOLARITY_HIGH                0x00000000U                          /*!< Capture/Compare output polarity  */
+#define TIM_OCPOLARITY_LOW                 TIM_CCER_CC1P                        /*!< Capture/Compare output polarity  */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_N_Polarity TIM Complementary Output Compare Polarity
+  * @{
+  */
+#define TIM_OCNPOLARITY_HIGH               0x00000000U                          /*!< Capture/Compare complementary output polarity */
+#define TIM_OCNPOLARITY_LOW                TIM_CCER_CC1NP                       /*!< Capture/Compare complementary output polarity */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_Idle_State TIM Output Compare Idle State
+  * @{
+  */
+#define TIM_OCIDLESTATE_SET                TIM_CR2_OIS1                         /*!< Output Idle state: OCx=1 when MOE=0 */
+#define TIM_OCIDLESTATE_RESET              0x00000000U                          /*!< Output Idle state: OCx=0 when MOE=0 */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_N_Idle_State TIM Complementary Output Compare Idle State
+  * @{
+  */
+#define TIM_OCNIDLESTATE_SET               TIM_CR2_OIS1N                        /*!< Complementary output Idle state: OCxN=1 when MOE=0 */
+#define TIM_OCNIDLESTATE_RESET             0x00000000U                          /*!< Complementary output Idle state: OCxN=0 when MOE=0 */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Input_Capture_Polarity TIM Input Capture Polarity
+  * @{
+  */
+#define  TIM_ICPOLARITY_RISING             TIM_INPUTCHANNELPOLARITY_RISING      /*!< Capture triggered by rising edge on timer input                  */
+#define  TIM_ICPOLARITY_FALLING            TIM_INPUTCHANNELPOLARITY_FALLING     /*!< Capture triggered by falling edge on timer input                 */
+#define  TIM_ICPOLARITY_BOTHEDGE           TIM_INPUTCHANNELPOLARITY_BOTHEDGE    /*!< Capture triggered by both rising and falling edges on timer input*/
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Encoder_Input_Polarity TIM Encoder Input Polarity
+  * @{
+  */
+#define  TIM_ENCODERINPUTPOLARITY_RISING   TIM_INPUTCHANNELPOLARITY_RISING      /*!< Encoder input with rising edge polarity  */
+#define  TIM_ENCODERINPUTPOLARITY_FALLING  TIM_INPUTCHANNELPOLARITY_FALLING     /*!< Encoder input with falling edge polarity */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Input_Capture_Selection TIM Input Capture Selection
+  * @{
+  */
+#define TIM_ICSELECTION_DIRECTTI           TIM_CCMR1_CC1S_0                     /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to IC1, IC2, IC3 or IC4, respectively */
+#define TIM_ICSELECTION_INDIRECTTI         TIM_CCMR1_CC1S_1                     /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to IC2, IC1, IC4 or IC3, respectively */
+#define TIM_ICSELECTION_TRC                TIM_CCMR1_CC1S                       /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Input_Capture_Prescaler TIM Input Capture Prescaler
+  * @{
+  */
+#define TIM_ICPSC_DIV1                     0x00000000U                          /*!< Capture performed each time an edge is detected on the capture input */
+#define TIM_ICPSC_DIV2                     TIM_CCMR1_IC1PSC_0                   /*!< Capture performed once every 2 events                                */
+#define TIM_ICPSC_DIV4                     TIM_CCMR1_IC1PSC_1                   /*!< Capture performed once every 4 events                                */
+#define TIM_ICPSC_DIV8                     TIM_CCMR1_IC1PSC                     /*!< Capture performed once every 8 events                                */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_One_Pulse_Mode TIM One Pulse Mode
+  * @{
+  */
+#define TIM_OPMODE_SINGLE                  TIM_CR1_OPM                          /*!< Counter stops counting at the next update event */
+#define TIM_OPMODE_REPETITIVE              0x00000000U                          /*!< Counter is not stopped at update event          */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Encoder_Mode TIM Encoder Mode
+  * @{
+  */
+#define TIM_ENCODERMODE_TI1                      TIM_SMCR_SMS_0                                                      /*!< Quadrature encoder mode 1, x2 mode, counts up/down on TI1FP1 edge depending on TI2FP2 level  */
+#define TIM_ENCODERMODE_TI2                      TIM_SMCR_SMS_1                                                      /*!< Quadrature encoder mode 2, x2 mode, counts up/down on TI2FP2 edge depending on TI1FP1 level. */
+#define TIM_ENCODERMODE_TI12                     (TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0)                                   /*!< Quadrature encoder mode 3, x4 mode, counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Interrupt_definition TIM interrupt Definition
+  * @{
+  */
+#define TIM_IT_UPDATE                      TIM_DIER_UIE                         /*!< Update interrupt            */
+#define TIM_IT_CC1                         TIM_DIER_CC1IE                       /*!< Capture/Compare 1 interrupt */
+#define TIM_IT_CC2                         TIM_DIER_CC2IE                       /*!< Capture/Compare 2 interrupt */
+#define TIM_IT_CC3                         TIM_DIER_CC3IE                       /*!< Capture/Compare 3 interrupt */
+#define TIM_IT_CC4                         TIM_DIER_CC4IE                       /*!< Capture/Compare 4 interrupt */
+#define TIM_IT_COM                         TIM_DIER_COMIE                       /*!< Commutation interrupt       */
+#define TIM_IT_TRIGGER                     TIM_DIER_TIE                         /*!< Trigger interrupt           */
+#define TIM_IT_BREAK                       TIM_DIER_BIE                         /*!< Break interrupt             */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Commutation_Source  TIM Commutation Source
+  * @{
+  */
+#define TIM_COMMUTATION_TRGI              TIM_CR2_CCUS                          /*!< When Capture/compare control bits are preloaded, they are updated by setting the COMG bit or when an rising edge occurs on trigger input */
+#define TIM_COMMUTATION_SOFTWARE          0x00000000U                           /*!< When Capture/compare control bits are preloaded, they are updated by setting the COMG bit */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_DMA_sources TIM DMA Sources
+  * @{
+  */
+#define TIM_DMA_UPDATE                     TIM_DIER_UDE                         /*!< DMA request is triggered by the update event */
+#define TIM_DMA_CC1                        TIM_DIER_CC1DE                       /*!< DMA request is triggered by the capture/compare macth 1 event */
+#define TIM_DMA_CC2                        TIM_DIER_CC2DE                       /*!< DMA request is triggered by the capture/compare macth 2 event event */
+#define TIM_DMA_CC3                        TIM_DIER_CC3DE                       /*!< DMA request is triggered by the capture/compare macth 3 event event */
+#define TIM_DMA_CC4                        TIM_DIER_CC4DE                       /*!< DMA request is triggered by the capture/compare macth 4 event event */
+#define TIM_DMA_COM                        TIM_DIER_COMDE                       /*!< DMA request is triggered by the commutation event */
+#define TIM_DMA_TRIGGER                    TIM_DIER_TDE                         /*!< DMA request is triggered by the trigger event */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_CC_DMA_Request CCx DMA request selection
+  * @{
+  */
+#define TIM_CCDMAREQUEST_CC                 0x00000000U                         /*!< CCx DMA request sent when capture or compare match event occurs */
+#define TIM_CCDMAREQUEST_UPDATE             TIM_CR2_CCDS                        /*!< CCx DMA requests sent when update event occurs */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Flag_definition TIM Flag Definition
+  * @{
+  */
+#define TIM_FLAG_UPDATE                    TIM_SR_UIF                           /*!< Update interrupt flag         */
+#define TIM_FLAG_CC1                       TIM_SR_CC1IF                         /*!< Capture/Compare 1 interrupt flag */
+#define TIM_FLAG_CC2                       TIM_SR_CC2IF                         /*!< Capture/Compare 2 interrupt flag */
+#define TIM_FLAG_CC3                       TIM_SR_CC3IF                         /*!< Capture/Compare 3 interrupt flag */
+#define TIM_FLAG_CC4                       TIM_SR_CC4IF                         /*!< Capture/Compare 4 interrupt flag */
+#define TIM_FLAG_COM                       TIM_SR_COMIF                         /*!< Commutation interrupt flag    */
+#define TIM_FLAG_TRIGGER                   TIM_SR_TIF                           /*!< Trigger interrupt flag        */
+#define TIM_FLAG_BREAK                     TIM_SR_BIF                           /*!< Break interrupt flag          */
+#define TIM_FLAG_CC1OF                     TIM_SR_CC1OF                         /*!< Capture 1 overcapture flag    */
+#define TIM_FLAG_CC2OF                     TIM_SR_CC2OF                         /*!< Capture 2 overcapture flag    */
+#define TIM_FLAG_CC3OF                     TIM_SR_CC3OF                         /*!< Capture 3 overcapture flag    */
+#define TIM_FLAG_CC4OF                     TIM_SR_CC4OF                         /*!< Capture 4 overcapture flag    */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Channel TIM Channel
+  * @{
+  */
+#define TIM_CHANNEL_1                      0x00000000U                          /*!< Capture/compare channel 1 identifier      */
+#define TIM_CHANNEL_2                      0x00000004U                          /*!< Capture/compare channel 2 identifier      */
+#define TIM_CHANNEL_3                      0x00000008U                          /*!< Capture/compare channel 3 identifier      */
+#define TIM_CHANNEL_4                      0x0000000CU                          /*!< Capture/compare channel 4 identifier      */
+#define TIM_CHANNEL_ALL                    0x0000003CU                          /*!< Global Capture/compare channel identifier  */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Clock_Source TIM Clock Source
+  * @{
+  */
+#define TIM_CLOCKSOURCE_INTERNAL    TIM_SMCR_ETPS_0      /*!< Internal clock source                                 */
+#define TIM_CLOCKSOURCE_ETRMODE1    TIM_TS_ETRF          /*!< External clock source mode 1 (ETRF)                   */
+#define TIM_CLOCKSOURCE_ETRMODE2    TIM_SMCR_ETPS_1      /*!< External clock source mode 2                          */
+#define TIM_CLOCKSOURCE_TI1ED       TIM_TS_TI1F_ED       /*!< External clock source mode 1 (TTI1FP1 + edge detect.) */
+#define TIM_CLOCKSOURCE_TI1         TIM_TS_TI1FP1        /*!< External clock source mode 1 (TTI1FP1)                */
+#define TIM_CLOCKSOURCE_TI2         TIM_TS_TI2FP2        /*!< External clock source mode 1 (TTI2FP2)                */
+#define TIM_CLOCKSOURCE_ITR0        TIM_TS_ITR0          /*!< External clock source mode 1 (ITR0)                   */
+#define TIM_CLOCKSOURCE_ITR1        TIM_TS_ITR1          /*!< External clock source mode 1 (ITR1)                   */
+#define TIM_CLOCKSOURCE_ITR2        TIM_TS_ITR2          /*!< External clock source mode 1 (ITR2)                   */
+#define TIM_CLOCKSOURCE_ITR3        TIM_TS_ITR3          /*!< External clock source mode 1 (ITR3)                   */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Clock_Polarity TIM Clock Polarity
+  * @{
+  */
+#define TIM_CLOCKPOLARITY_INVERTED           TIM_ETRPOLARITY_INVERTED           /*!< Polarity for ETRx clock sources */
+#define TIM_CLOCKPOLARITY_NONINVERTED        TIM_ETRPOLARITY_NONINVERTED        /*!< Polarity for ETRx clock sources */
+#define TIM_CLOCKPOLARITY_RISING             TIM_INPUTCHANNELPOLARITY_RISING    /*!< Polarity for TIx clock sources */
+#define TIM_CLOCKPOLARITY_FALLING            TIM_INPUTCHANNELPOLARITY_FALLING   /*!< Polarity for TIx clock sources */
+#define TIM_CLOCKPOLARITY_BOTHEDGE           TIM_INPUTCHANNELPOLARITY_BOTHEDGE  /*!< Polarity for TIx clock sources */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Clock_Prescaler TIM Clock Prescaler
+  * @{
+  */
+#define TIM_CLOCKPRESCALER_DIV1                 TIM_ETRPRESCALER_DIV1           /*!< No prescaler is used                                                     */
+#define TIM_CLOCKPRESCALER_DIV2                 TIM_ETRPRESCALER_DIV2           /*!< Prescaler for External ETR Clock: Capture performed once every 2 events. */
+#define TIM_CLOCKPRESCALER_DIV4                 TIM_ETRPRESCALER_DIV4           /*!< Prescaler for External ETR Clock: Capture performed once every 4 events. */
+#define TIM_CLOCKPRESCALER_DIV8                 TIM_ETRPRESCALER_DIV8           /*!< Prescaler for External ETR Clock: Capture performed once every 8 events. */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_ClearInput_Polarity TIM Clear Input Polarity
+  * @{
+  */
+#define TIM_CLEARINPUTPOLARITY_INVERTED           TIM_ETRPOLARITY_INVERTED      /*!< Polarity for ETRx pin */
+#define TIM_CLEARINPUTPOLARITY_NONINVERTED        TIM_ETRPOLARITY_NONINVERTED   /*!< Polarity for ETRx pin */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_ClearInput_Prescaler TIM Clear Input Prescaler
+  * @{
+  */
+#define TIM_CLEARINPUTPRESCALER_DIV1              TIM_ETRPRESCALER_DIV1         /*!< No prescaler is used                                                   */
+#define TIM_CLEARINPUTPRESCALER_DIV2              TIM_ETRPRESCALER_DIV2         /*!< Prescaler for External ETR pin: Capture performed once every 2 events. */
+#define TIM_CLEARINPUTPRESCALER_DIV4              TIM_ETRPRESCALER_DIV4         /*!< Prescaler for External ETR pin: Capture performed once every 4 events. */
+#define TIM_CLEARINPUTPRESCALER_DIV8              TIM_ETRPRESCALER_DIV8         /*!< Prescaler for External ETR pin: Capture performed once every 8 events. */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_OSSR_Off_State_Selection_for_Run_mode_state TIM OSSR OffState Selection for Run mode state
+  * @{
+  */
+#define TIM_OSSR_ENABLE                          TIM_BDTR_OSSR                  /*!< When inactive, OC/OCN outputs are enabled (still controlled by the timer)           */
+#define TIM_OSSR_DISABLE                         0x00000000U                    /*!< When inactive, OC/OCN outputs are disabled (not controlled any longer by the timer) */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_OSSI_Off_State_Selection_for_Idle_mode_state TIM OSSI OffState Selection for Idle mode state
+  * @{
+  */
+#define TIM_OSSI_ENABLE                          TIM_BDTR_OSSI                  /*!< When inactive, OC/OCN outputs are enabled (still controlled by the timer)           */
+#define TIM_OSSI_DISABLE                         0x00000000U                    /*!< When inactive, OC/OCN outputs are disabled (not controlled any longer by the timer) */
+/**
+  * @}
+  */
+/** @defgroup TIM_Lock_level  TIM Lock level
+  * @{
+  */
+#define TIM_LOCKLEVEL_OFF                  0x00000000U                          /*!< LOCK OFF     */
+#define TIM_LOCKLEVEL_1                    TIM_BDTR_LOCK_0                      /*!< LOCK Level 1 */
+#define TIM_LOCKLEVEL_2                    TIM_BDTR_LOCK_1                      /*!< LOCK Level 2 */
+#define TIM_LOCKLEVEL_3                    TIM_BDTR_LOCK                        /*!< LOCK Level 3 */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Break_Input_enable_disable TIM Break Input Enable
+  * @{
+  */
+#define TIM_BREAK_ENABLE                   TIM_BDTR_BKE                         /*!< Break input BRK is enabled  */
+#define TIM_BREAK_DISABLE                  0x00000000U                          /*!< Break input BRK is disabled */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Break_Polarity TIM Break Input Polarity
+  * @{
+  */
+#define TIM_BREAKPOLARITY_LOW              0x00000000U                          /*!< Break input BRK is active low  */
+#define TIM_BREAKPOLARITY_HIGH             TIM_BDTR_BKP                         /*!< Break input BRK is active high */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_AOE_Bit_Set_Reset TIM Automatic Output Enable
+  * @{
+  */
+#define TIM_AUTOMATICOUTPUT_DISABLE        0x00000000U                          /*!< MOE can be set only by software */
+#define TIM_AUTOMATICOUTPUT_ENABLE         TIM_BDTR_AOE                         /*!< MOE can be set by software or automatically at the next update event (if none of the break inputs BRK and BRK2 is active) */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Master_Mode_Selection TIM Master Mode Selection
+  * @{
+  */
+#define TIM_TRGO_RESET            0x00000000U                                      /*!< TIMx_EGR.UG bit is used as trigger output (TRGO)              */
+#define TIM_TRGO_ENABLE           TIM_CR2_MMS_0                                    /*!< TIMx_CR1.CEN bit is used as trigger output (TRGO)             */
+#define TIM_TRGO_UPDATE           TIM_CR2_MMS_1                                    /*!< Update event is used as trigger output (TRGO)                 */
+#define TIM_TRGO_OC1              (TIM_CR2_MMS_1 | TIM_CR2_MMS_0)                  /*!< Capture or a compare match 1 is used as trigger output (TRGO) */
+#define TIM_TRGO_OC1REF           TIM_CR2_MMS_2                                    /*!< OC1REF signal is used as trigger output (TRGO)                */
+#define TIM_TRGO_OC2REF           (TIM_CR2_MMS_2 | TIM_CR2_MMS_0)                  /*!< OC2REF signal is used as trigger output(TRGO)                 */
+#define TIM_TRGO_OC3REF           (TIM_CR2_MMS_2 | TIM_CR2_MMS_1)                  /*!< OC3REF signal is used as trigger output(TRGO)                 */
+#define TIM_TRGO_OC4REF           (TIM_CR2_MMS_2 | TIM_CR2_MMS_1 | TIM_CR2_MMS_0)  /*!< OC4REF signal is used as trigger output(TRGO)                 */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Master_Slave_Mode TIM Master/Slave Mode
+  * @{
+  */
+#define TIM_MASTERSLAVEMODE_ENABLE         TIM_SMCR_MSM                         /*!< No action */
+#define TIM_MASTERSLAVEMODE_DISABLE        0x00000000U                          /*!< Master/slave mode is selected */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Slave_Mode TIM Slave mode
+  * @{
+  */
+#define TIM_SLAVEMODE_DISABLE                0x00000000U                                        /*!< Slave mode disabled           */
+#define TIM_SLAVEMODE_RESET                  TIM_SMCR_SMS_2                                     /*!< Reset Mode                    */
+#define TIM_SLAVEMODE_GATED                  (TIM_SMCR_SMS_2 | TIM_SMCR_SMS_0)                  /*!< Gated Mode                    */
+#define TIM_SLAVEMODE_TRIGGER                (TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1)                  /*!< Trigger Mode                  */
+#define TIM_SLAVEMODE_EXTERNAL1              (TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0) /*!< External Clock Mode 1         */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_and_PWM_modes TIM Output Compare and PWM Modes
+  * @{
+  */
+#define TIM_OCMODE_TIMING                   0x00000000U                                              /*!< Frozen                                 */
+#define TIM_OCMODE_ACTIVE                   TIM_CCMR1_OC1M_0                                         /*!< Set channel to active level on match   */
+#define TIM_OCMODE_INACTIVE                 TIM_CCMR1_OC1M_1                                         /*!< Set channel to inactive level on match */
+#define TIM_OCMODE_TOGGLE                   (TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0)                    /*!< Toggle                                 */
+#define TIM_OCMODE_PWM1                     (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1)                    /*!< PWM mode 1                             */
+#define TIM_OCMODE_PWM2                     (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0) /*!< PWM mode 2                             */
+#define TIM_OCMODE_FORCED_ACTIVE            (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0)                    /*!< Force active level                     */
+#define TIM_OCMODE_FORCED_INACTIVE          TIM_CCMR1_OC1M_2                                         /*!< Force inactive level                   */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Trigger_Selection TIM Trigger Selection
+  * @{
+  */
+#define TIM_TS_ITR0          0x00000000U                                                       /*!< Internal Trigger 0 (ITR0)              */
+#define TIM_TS_ITR1          TIM_SMCR_TS_0                                                     /*!< Internal Trigger 1 (ITR1)              */
+#define TIM_TS_ITR2          TIM_SMCR_TS_1                                                     /*!< Internal Trigger 2 (ITR2)              */
+#define TIM_TS_ITR3          (TIM_SMCR_TS_0 | TIM_SMCR_TS_1)                                   /*!< Internal Trigger 3 (ITR3)              */
+#define TIM_TS_TI1F_ED       TIM_SMCR_TS_2                                                     /*!< TI1 Edge Detector (TI1F_ED)            */
+#define TIM_TS_TI1FP1        (TIM_SMCR_TS_0 | TIM_SMCR_TS_2)                                   /*!< Filtered Timer Input 1 (TI1FP1)        */
+#define TIM_TS_TI2FP2        (TIM_SMCR_TS_1 | TIM_SMCR_TS_2)                                   /*!< Filtered Timer Input 2 (TI2FP2)        */
+#define TIM_TS_ETRF          (TIM_SMCR_TS_0 | TIM_SMCR_TS_1 | TIM_SMCR_TS_2)                   /*!< Filtered External Trigger input (ETRF) */
+#define TIM_TS_NONE          0x0000FFFFU                                                       /*!< No trigger selected                    */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Trigger_Polarity TIM Trigger Polarity
+  * @{
+  */
+#define TIM_TRIGGERPOLARITY_INVERTED           TIM_ETRPOLARITY_INVERTED               /*!< Polarity for ETRx trigger sources             */
+#define TIM_TRIGGERPOLARITY_NONINVERTED        TIM_ETRPOLARITY_NONINVERTED            /*!< Polarity for ETRx trigger sources             */
+#define TIM_TRIGGERPOLARITY_RISING             TIM_INPUTCHANNELPOLARITY_RISING        /*!< Polarity for TIxFPx or TI1_ED trigger sources */
+#define TIM_TRIGGERPOLARITY_FALLING            TIM_INPUTCHANNELPOLARITY_FALLING       /*!< Polarity for TIxFPx or TI1_ED trigger sources */
+#define TIM_TRIGGERPOLARITY_BOTHEDGE           TIM_INPUTCHANNELPOLARITY_BOTHEDGE      /*!< Polarity for TIxFPx or TI1_ED trigger sources */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Trigger_Prescaler TIM Trigger Prescaler
+  * @{
+  */
+#define TIM_TRIGGERPRESCALER_DIV1             TIM_ETRPRESCALER_DIV1             /*!< No prescaler is used                                                       */
+#define TIM_TRIGGERPRESCALER_DIV2             TIM_ETRPRESCALER_DIV2             /*!< Prescaler for External ETR Trigger: Capture performed once every 2 events. */
+#define TIM_TRIGGERPRESCALER_DIV4             TIM_ETRPRESCALER_DIV4             /*!< Prescaler for External ETR Trigger: Capture performed once every 4 events. */
+#define TIM_TRIGGERPRESCALER_DIV8             TIM_ETRPRESCALER_DIV8             /*!< Prescaler for External ETR Trigger: Capture performed once every 8 events. */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_TI1_Selection TIM TI1 Input Selection
+  * @{
+  */
+#define TIM_TI1SELECTION_CH1               0x00000000U                          /*!< The TIMx_CH1 pin is connected to TI1 input */
+#define TIM_TI1SELECTION_XORCOMBINATION    TIM_CR2_TI1S                         /*!< The TIMx_CH1, CH2 and CH3 pins are connected to the TI1 input (XOR combination) */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_DMA_Burst_Length TIM DMA Burst Length
+  * @{
+  */
+#define TIM_DMABURSTLENGTH_1TRANSFER       0x00000000U                          /*!< The transfer is done to 1 register starting from TIMx_CR1 + TIMx_DCR.DBA   */
+#define TIM_DMABURSTLENGTH_2TRANSFERS      0x00000100U                          /*!< The transfer is done to 2 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_3TRANSFERS      0x00000200U                          /*!< The transfer is done to 3 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_4TRANSFERS      0x00000300U                          /*!< The transfer is done to 4 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_5TRANSFERS      0x00000400U                          /*!< The transfer is done to 5 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_6TRANSFERS      0x00000500U                          /*!< The transfer is done to 6 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_7TRANSFERS      0x00000600U                          /*!< The transfer is done to 7 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_8TRANSFERS      0x00000700U                          /*!< The transfer is done to 8 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_9TRANSFERS      0x00000800U                          /*!< The transfer is done to 9 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_10TRANSFERS     0x00000900U                          /*!< The transfer is done to 10 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_11TRANSFERS     0x00000A00U                          /*!< The transfer is done to 11 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_12TRANSFERS     0x00000B00U                          /*!< The transfer is done to 12 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_13TRANSFERS     0x00000C00U                          /*!< The transfer is done to 13 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_14TRANSFERS     0x00000D00U                          /*!< The transfer is done to 14 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_15TRANSFERS     0x00000E00U                          /*!< The transfer is done to 15 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_16TRANSFERS     0x00000F00U                          /*!< The transfer is done to 16 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_17TRANSFERS     0x00001000U                          /*!< The transfer is done to 17 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_18TRANSFERS     0x00001100U                          /*!< The transfer is done to 18 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+/**
+  * @}
+  */
+
+/** @defgroup DMA_Handle_index TIM DMA Handle Index
+  * @{
+  */
+#define TIM_DMA_ID_UPDATE                ((uint16_t) 0x0000)       /*!< Index of the DMA handle used for Update DMA requests */
+#define TIM_DMA_ID_CC1                   ((uint16_t) 0x0001)       /*!< Index of the DMA handle used for Capture/Compare 1 DMA requests */
+#define TIM_DMA_ID_CC2                   ((uint16_t) 0x0002)       /*!< Index of the DMA handle used for Capture/Compare 2 DMA requests */
+#define TIM_DMA_ID_CC3                   ((uint16_t) 0x0003)       /*!< Index of the DMA handle used for Capture/Compare 3 DMA requests */
+#define TIM_DMA_ID_CC4                   ((uint16_t) 0x0004)       /*!< Index of the DMA handle used for Capture/Compare 4 DMA requests */
+#define TIM_DMA_ID_COMMUTATION           ((uint16_t) 0x0005)       /*!< Index of the DMA handle used for Commutation DMA requests */
+#define TIM_DMA_ID_TRIGGER               ((uint16_t) 0x0006)       /*!< Index of the DMA handle used for Trigger DMA requests */
+/**
+  * @}
+  */
+
+/** @defgroup Channel_CC_State TIM Capture/Compare Channel State
+  * @{
+  */
+#define TIM_CCx_ENABLE                   0x00000001U                            /*!< Input or output channel is enabled */
+#define TIM_CCx_DISABLE                  0x00000000U                            /*!< Input or output channel is disabled */
+#define TIM_CCxN_ENABLE                  0x00000004U                            /*!< Complementary output channel is enabled */
+#define TIM_CCxN_DISABLE                 0x00000000U                            /*!< Complementary output channel is enabled */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+/* End of exported constants -------------------------------------------------*/
+
+/* Exported macros -----------------------------------------------------------*/
+/** @defgroup TIM_Exported_Macros TIM Exported Macros
+  * @{
+  */
+
+/** @brief  Reset TIM handle state.
+  * @param  __HANDLE__ TIM handle.
+  * @retval None
+  */
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+#define __HAL_TIM_RESET_HANDLE_STATE(__HANDLE__) do {                                                               \
+                                                      (__HANDLE__)->State            = HAL_TIM_STATE_RESET;         \
+                                                      (__HANDLE__)->ChannelState[0]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[1]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[2]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[3]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[0] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[1] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[2] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[3] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->DMABurstState    = HAL_DMA_BURST_STATE_RESET;   \
+                                                      (__HANDLE__)->Base_MspInitCallback         = NULL;            \
+                                                      (__HANDLE__)->Base_MspDeInitCallback       = NULL;            \
+                                                      (__HANDLE__)->IC_MspInitCallback           = NULL;            \
+                                                      (__HANDLE__)->IC_MspDeInitCallback         = NULL;            \
+                                                      (__HANDLE__)->OC_MspInitCallback           = NULL;            \
+                                                      (__HANDLE__)->OC_MspDeInitCallback         = NULL;            \
+                                                      (__HANDLE__)->PWM_MspInitCallback          = NULL;            \
+                                                      (__HANDLE__)->PWM_MspDeInitCallback        = NULL;            \
+                                                      (__HANDLE__)->OnePulse_MspInitCallback     = NULL;            \
+                                                      (__HANDLE__)->OnePulse_MspDeInitCallback   = NULL;            \
+                                                      (__HANDLE__)->Encoder_MspInitCallback      = NULL;            \
+                                                      (__HANDLE__)->Encoder_MspDeInitCallback    = NULL;            \
+                                                      (__HANDLE__)->HallSensor_MspInitCallback   = NULL;            \
+                                                      (__HANDLE__)->HallSensor_MspDeInitCallback = NULL;            \
+                                                     } while(0)
+#else
+#define __HAL_TIM_RESET_HANDLE_STATE(__HANDLE__) do {                                                               \
+                                                      (__HANDLE__)->State            = HAL_TIM_STATE_RESET;         \
+                                                      (__HANDLE__)->ChannelState[0]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[1]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[2]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[3]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[0] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[1] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[2] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[3] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->DMABurstState    = HAL_DMA_BURST_STATE_RESET;   \
+                                                     } while(0)
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @brief  Enable the TIM peripheral.
+  * @param  __HANDLE__ TIM handle
+  * @retval None
+  */
+#define __HAL_TIM_ENABLE(__HANDLE__)                 ((__HANDLE__)->Instance->CR1|=(TIM_CR1_CEN))
+
+/**
+  * @brief  Enable the TIM main Output.
+  * @param  __HANDLE__ TIM handle
+  * @retval None
+  */
+#define __HAL_TIM_MOE_ENABLE(__HANDLE__)             ((__HANDLE__)->Instance->BDTR|=(TIM_BDTR_MOE))
+
+/**
+  * @brief  Disable the TIM peripheral.
+  * @param  __HANDLE__ TIM handle
+  * @retval None
+  */
+#define __HAL_TIM_DISABLE(__HANDLE__) \
+  do { \
+    if (((__HANDLE__)->Instance->CCER & TIM_CCER_CCxE_MASK) == 0UL) \
+    { \
+      if(((__HANDLE__)->Instance->CCER & TIM_CCER_CCxNE_MASK) == 0UL) \
+      { \
+        (__HANDLE__)->Instance->CR1 &= ~(TIM_CR1_CEN); \
+      } \
+    } \
+  } while(0)
+
+/**
+  * @brief  Disable the TIM main Output.
+  * @param  __HANDLE__ TIM handle
+  * @retval None
+  * @note The Main Output Enable of a timer instance is disabled only if all the CCx and CCxN channels have been
+  *       disabled
+  */
+#define __HAL_TIM_MOE_DISABLE(__HANDLE__) \
+  do { \
+    if (((__HANDLE__)->Instance->CCER & TIM_CCER_CCxE_MASK) == 0UL) \
+    { \
+      if(((__HANDLE__)->Instance->CCER & TIM_CCER_CCxNE_MASK) == 0UL) \
+      { \
+        (__HANDLE__)->Instance->BDTR &= ~(TIM_BDTR_MOE); \
+      } \
+    } \
+  } while(0)
+
+/**
+  * @brief  Disable the TIM main Output.
+  * @param  __HANDLE__ TIM handle
+  * @retval None
+  * @note The Main Output Enable of a timer instance is disabled unconditionally
+  */
+#define __HAL_TIM_MOE_DISABLE_UNCONDITIONALLY(__HANDLE__)  (__HANDLE__)->Instance->BDTR &= ~(TIM_BDTR_MOE)
+
+/** @brief  Enable the specified TIM interrupt.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __INTERRUPT__ specifies the TIM interrupt source to enable.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_IT_UPDATE: Update interrupt
+  *            @arg TIM_IT_CC1:   Capture/Compare 1 interrupt
+  *            @arg TIM_IT_CC2:  Capture/Compare 2 interrupt
+  *            @arg TIM_IT_CC3:  Capture/Compare 3 interrupt
+  *            @arg TIM_IT_CC4:  Capture/Compare 4 interrupt
+  *            @arg TIM_IT_COM:   Commutation interrupt
+  *            @arg TIM_IT_TRIGGER: Trigger interrupt
+  *            @arg TIM_IT_BREAK: Break interrupt
+  * @retval None
+  */
+#define __HAL_TIM_ENABLE_IT(__HANDLE__, __INTERRUPT__)    ((__HANDLE__)->Instance->DIER |= (__INTERRUPT__))
+
+/** @brief  Disable the specified TIM interrupt.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __INTERRUPT__ specifies the TIM interrupt source to disable.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_IT_UPDATE: Update interrupt
+  *            @arg TIM_IT_CC1:   Capture/Compare 1 interrupt
+  *            @arg TIM_IT_CC2:  Capture/Compare 2 interrupt
+  *            @arg TIM_IT_CC3:  Capture/Compare 3 interrupt
+  *            @arg TIM_IT_CC4:  Capture/Compare 4 interrupt
+  *            @arg TIM_IT_COM:   Commutation interrupt
+  *            @arg TIM_IT_TRIGGER: Trigger interrupt
+  *            @arg TIM_IT_BREAK: Break interrupt
+  * @retval None
+  */
+#define __HAL_TIM_DISABLE_IT(__HANDLE__, __INTERRUPT__)   ((__HANDLE__)->Instance->DIER &= ~(__INTERRUPT__))
+
+/** @brief  Enable the specified DMA request.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __DMA__ specifies the TIM DMA request to enable.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: Update DMA request
+  *            @arg TIM_DMA_CC1:   Capture/Compare 1 DMA request
+  *            @arg TIM_DMA_CC2:  Capture/Compare 2 DMA request
+  *            @arg TIM_DMA_CC3:  Capture/Compare 3 DMA request
+  *            @arg TIM_DMA_CC4:  Capture/Compare 4 DMA request
+  *            @arg TIM_DMA_COM:   Commutation DMA request
+  *            @arg TIM_DMA_TRIGGER: Trigger DMA request
+  * @retval None
+  */
+#define __HAL_TIM_ENABLE_DMA(__HANDLE__, __DMA__)         ((__HANDLE__)->Instance->DIER |= (__DMA__))
+
+/** @brief  Disable the specified DMA request.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __DMA__ specifies the TIM DMA request to disable.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: Update DMA request
+  *            @arg TIM_DMA_CC1:   Capture/Compare 1 DMA request
+  *            @arg TIM_DMA_CC2:  Capture/Compare 2 DMA request
+  *            @arg TIM_DMA_CC3:  Capture/Compare 3 DMA request
+  *            @arg TIM_DMA_CC4:  Capture/Compare 4 DMA request
+  *            @arg TIM_DMA_COM:   Commutation DMA request
+  *            @arg TIM_DMA_TRIGGER: Trigger DMA request
+  * @retval None
+  */
+#define __HAL_TIM_DISABLE_DMA(__HANDLE__, __DMA__)        ((__HANDLE__)->Instance->DIER &= ~(__DMA__))
+
+/** @brief  Check whether the specified TIM interrupt flag is set or not.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __FLAG__ specifies the TIM interrupt flag to check.
+  *        This parameter can be one of the following values:
+  *            @arg TIM_FLAG_UPDATE: Update interrupt flag
+  *            @arg TIM_FLAG_CC1: Capture/Compare 1 interrupt flag
+  *            @arg TIM_FLAG_CC2: Capture/Compare 2 interrupt flag
+  *            @arg TIM_FLAG_CC3: Capture/Compare 3 interrupt flag
+  *            @arg TIM_FLAG_CC4: Capture/Compare 4 interrupt flag
+  *            @arg TIM_FLAG_COM:  Commutation interrupt flag
+  *            @arg TIM_FLAG_TRIGGER: Trigger interrupt flag
+  *            @arg TIM_FLAG_BREAK: Break interrupt flag
+  *            @arg TIM_FLAG_CC1OF: Capture/Compare 1 overcapture flag
+  *            @arg TIM_FLAG_CC2OF: Capture/Compare 2 overcapture flag
+  *            @arg TIM_FLAG_CC3OF: Capture/Compare 3 overcapture flag
+  *            @arg TIM_FLAG_CC4OF: Capture/Compare 4 overcapture flag
+  * @retval The new state of __FLAG__ (TRUE or FALSE).
+  */
+#define __HAL_TIM_GET_FLAG(__HANDLE__, __FLAG__)          (((__HANDLE__)->Instance->SR &(__FLAG__)) == (__FLAG__))
+
+/** @brief  Clear the specified TIM interrupt flag.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __FLAG__ specifies the TIM interrupt flag to clear.
+  *        This parameter can be one of the following values:
+  *            @arg TIM_FLAG_UPDATE: Update interrupt flag
+  *            @arg TIM_FLAG_CC1: Capture/Compare 1 interrupt flag
+  *            @arg TIM_FLAG_CC2: Capture/Compare 2 interrupt flag
+  *            @arg TIM_FLAG_CC3: Capture/Compare 3 interrupt flag
+  *            @arg TIM_FLAG_CC4: Capture/Compare 4 interrupt flag
+  *            @arg TIM_FLAG_COM:  Commutation interrupt flag
+  *            @arg TIM_FLAG_TRIGGER: Trigger interrupt flag
+  *            @arg TIM_FLAG_BREAK: Break interrupt flag
+  *            @arg TIM_FLAG_CC1OF: Capture/Compare 1 overcapture flag
+  *            @arg TIM_FLAG_CC2OF: Capture/Compare 2 overcapture flag
+  *            @arg TIM_FLAG_CC3OF: Capture/Compare 3 overcapture flag
+  *            @arg TIM_FLAG_CC4OF: Capture/Compare 4 overcapture flag
+  * @retval The new state of __FLAG__ (TRUE or FALSE).
+  */
+#define __HAL_TIM_CLEAR_FLAG(__HANDLE__, __FLAG__)        ((__HANDLE__)->Instance->SR = ~(__FLAG__))
+
+/**
+  * @brief  Check whether the specified TIM interrupt source is enabled or not.
+  * @param  __HANDLE__ TIM handle
+  * @param  __INTERRUPT__ specifies the TIM interrupt source to check.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_IT_UPDATE: Update interrupt
+  *            @arg TIM_IT_CC1:   Capture/Compare 1 interrupt
+  *            @arg TIM_IT_CC2:  Capture/Compare 2 interrupt
+  *            @arg TIM_IT_CC3:  Capture/Compare 3 interrupt
+  *            @arg TIM_IT_CC4:  Capture/Compare 4 interrupt
+  *            @arg TIM_IT_COM:   Commutation interrupt
+  *            @arg TIM_IT_TRIGGER: Trigger interrupt
+  *            @arg TIM_IT_BREAK: Break interrupt
+  * @retval The state of TIM_IT (SET or RESET).
+  */
+#define __HAL_TIM_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->DIER & (__INTERRUPT__)) \
+                                                             == (__INTERRUPT__)) ? SET : RESET)
+
+/** @brief Clear the TIM interrupt pending bits.
+  * @param  __HANDLE__ TIM handle
+  * @param  __INTERRUPT__ specifies the interrupt pending bit to clear.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_IT_UPDATE: Update interrupt
+  *            @arg TIM_IT_CC1:   Capture/Compare 1 interrupt
+  *            @arg TIM_IT_CC2:  Capture/Compare 2 interrupt
+  *            @arg TIM_IT_CC3:  Capture/Compare 3 interrupt
+  *            @arg TIM_IT_CC4:  Capture/Compare 4 interrupt
+  *            @arg TIM_IT_COM:   Commutation interrupt
+  *            @arg TIM_IT_TRIGGER: Trigger interrupt
+  *            @arg TIM_IT_BREAK: Break interrupt
+  * @retval None
+  */
+#define __HAL_TIM_CLEAR_IT(__HANDLE__, __INTERRUPT__)      ((__HANDLE__)->Instance->SR = ~(__INTERRUPT__))
+
+/**
+  * @brief  Indicates whether or not the TIM Counter is used as downcounter.
+  * @param  __HANDLE__ TIM handle.
+  * @retval False (Counter used as upcounter) or True (Counter used as downcounter)
+  * @note This macro is particularly useful to get the counting mode when the timer operates in Center-aligned mode
+  *       or Encoder mode.
+  */
+#define __HAL_TIM_IS_TIM_COUNTING_DOWN(__HANDLE__)    (((__HANDLE__)->Instance->CR1 &(TIM_CR1_DIR)) == (TIM_CR1_DIR))
+
+/**
+  * @brief  Set the TIM Prescaler on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __PRESC__ specifies the Prescaler new value.
+  * @retval None
+  */
+#define __HAL_TIM_SET_PRESCALER(__HANDLE__, __PRESC__)       ((__HANDLE__)->Instance->PSC = (__PRESC__))
+
+/**
+  * @brief  Set the TIM Counter Register value on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __COUNTER__ specifies the Counter register new value.
+  * @retval None
+  */
+#define __HAL_TIM_SET_COUNTER(__HANDLE__, __COUNTER__)  ((__HANDLE__)->Instance->CNT = (__COUNTER__))
+
+/**
+  * @brief  Get the TIM Counter Register value on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @retval 16-bit or 32-bit value of the timer counter register (TIMx_CNT)
+  */
+#define __HAL_TIM_GET_COUNTER(__HANDLE__)  ((__HANDLE__)->Instance->CNT)
+
+/**
+  * @brief  Set the TIM Autoreload Register value on runtime without calling another time any Init function.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __AUTORELOAD__ specifies the Counter register new value.
+  * @retval None
+  */
+#define __HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__) \
+  do{                                                    \
+    (__HANDLE__)->Instance->ARR = (__AUTORELOAD__);  \
+    (__HANDLE__)->Init.Period = (__AUTORELOAD__);    \
+  } while(0)
+
+/**
+  * @brief  Get the TIM Autoreload Register value on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @retval 16-bit or 32-bit value of the timer auto-reload register(TIMx_ARR)
+  */
+#define __HAL_TIM_GET_AUTORELOAD(__HANDLE__)  ((__HANDLE__)->Instance->ARR)
+
+/**
+  * @brief  Set the TIM Clock Division value on runtime without calling another time any Init function.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CKD__ specifies the clock division value.
+  *          This parameter can be one of the following value:
+  *            @arg TIM_CLOCKDIVISION_DIV1: tDTS=tCK_INT
+  *            @arg TIM_CLOCKDIVISION_DIV2: tDTS=2*tCK_INT
+  *            @arg TIM_CLOCKDIVISION_DIV4: tDTS=4*tCK_INT
+  * @retval None
+  */
+#define __HAL_TIM_SET_CLOCKDIVISION(__HANDLE__, __CKD__) \
+  do{                                                   \
+    (__HANDLE__)->Instance->CR1 &= (~TIM_CR1_CKD);  \
+    (__HANDLE__)->Instance->CR1 |= (__CKD__);       \
+    (__HANDLE__)->Init.ClockDivision = (__CKD__);   \
+  } while(0)
+
+/**
+  * @brief  Get the TIM Clock Division value on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @retval The clock division can be one of the following values:
+  *            @arg TIM_CLOCKDIVISION_DIV1: tDTS=tCK_INT
+  *            @arg TIM_CLOCKDIVISION_DIV2: tDTS=2*tCK_INT
+  *            @arg TIM_CLOCKDIVISION_DIV4: tDTS=4*tCK_INT
+  */
+#define __HAL_TIM_GET_CLOCKDIVISION(__HANDLE__)  ((__HANDLE__)->Instance->CR1 & TIM_CR1_CKD)
+
+/**
+  * @brief  Set the TIM Input Capture prescaler on runtime without calling another time HAL_TIM_IC_ConfigChannel()
+  *         function.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  __ICPSC__ specifies the Input Capture4 prescaler new value.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPSC_DIV1: no prescaler
+  *            @arg TIM_ICPSC_DIV2: capture is done once every 2 events
+  *            @arg TIM_ICPSC_DIV4: capture is done once every 4 events
+  *            @arg TIM_ICPSC_DIV8: capture is done once every 8 events
+  * @retval None
+  */
+#define __HAL_TIM_SET_ICPRESCALER(__HANDLE__, __CHANNEL__, __ICPSC__) \
+  do{                                                    \
+    TIM_RESET_ICPRESCALERVALUE((__HANDLE__), (__CHANNEL__));  \
+    TIM_SET_ICPRESCALERVALUE((__HANDLE__), (__CHANNEL__), (__ICPSC__)); \
+  } while(0)
+
+/**
+  * @brief  Get the TIM Input Capture prescaler on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: get input capture 1 prescaler value
+  *            @arg TIM_CHANNEL_2: get input capture 2 prescaler value
+  *            @arg TIM_CHANNEL_3: get input capture 3 prescaler value
+  *            @arg TIM_CHANNEL_4: get input capture 4 prescaler value
+  * @retval The input capture prescaler can be one of the following values:
+  *            @arg TIM_ICPSC_DIV1: no prescaler
+  *            @arg TIM_ICPSC_DIV2: capture is done once every 2 events
+  *            @arg TIM_ICPSC_DIV4: capture is done once every 4 events
+  *            @arg TIM_ICPSC_DIV8: capture is done once every 8 events
+  */
+#define __HAL_TIM_GET_ICPRESCALER(__HANDLE__, __CHANNEL__)  \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 & TIM_CCMR1_IC1PSC) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? (((__HANDLE__)->Instance->CCMR1 & TIM_CCMR1_IC2PSC) >> 8U) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 & TIM_CCMR2_IC3PSC) :\
+   (((__HANDLE__)->Instance->CCMR2 & TIM_CCMR2_IC4PSC)) >> 8U)
+
+/**
+  * @brief  Set the TIM Capture Compare Register value on runtime without calling another time ConfigChannel function.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  __COMPARE__ specifies the Capture Compare register new value.
+  * @retval None
+  */
+#define __HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1 = (__COMPARE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2 = (__COMPARE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3 = (__COMPARE__)) :\
+   ((__HANDLE__)->Instance->CCR4 = (__COMPARE__)))
+
+/**
+  * @brief  Get the TIM Capture Compare Register value on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channel associated with the capture compare register
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: get capture/compare 1 register value
+  *            @arg TIM_CHANNEL_2: get capture/compare 2 register value
+  *            @arg TIM_CHANNEL_3: get capture/compare 3 register value
+  *            @arg TIM_CHANNEL_4: get capture/compare 4 register value
+  * @retval 16-bit or 32-bit value of the capture/compare register (TIMx_CCRy)
+  */
+#define __HAL_TIM_GET_COMPARE(__HANDLE__, __CHANNEL__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3) :\
+   ((__HANDLE__)->Instance->CCR4))
+
+/**
+  * @brief  Set the TIM Output compare preload.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval None
+  */
+#define __HAL_TIM_ENABLE_OCxPRELOAD(__HANDLE__, __CHANNEL__)    \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC1PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC2PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC3PE) :\
+   ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC4PE))
+
+/**
+  * @brief  Reset the TIM Output compare preload.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval None
+  */
+#define __HAL_TIM_DISABLE_OCxPRELOAD(__HANDLE__, __CHANNEL__)    \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_OC1PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_OC2PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_OC3PE) :\
+   ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_OC4PE))
+
+/**
+  * @brief  Enable fast mode for a given channel.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @note  When fast mode is enabled an active edge on the trigger input acts
+  *        like a compare match on CCx output. Delay to sample the trigger
+  *        input and to activate CCx output is reduced to 3 clock cycles.
+  * @note  Fast mode acts only if the channel is configured in PWM1 or PWM2 mode.
+  * @retval None
+  */
+#define __HAL_TIM_ENABLE_OCxFAST(__HANDLE__, __CHANNEL__)    \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC1FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC2FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC3FE) :\
+   ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC4FE))
+
+/**
+  * @brief  Disable fast mode for a given channel.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @note  When fast mode is disabled CCx output behaves normally depending
+  *        on counter and CCRx values even when the trigger is ON. The minimum
+  *        delay to activate CCx output when an active edge occurs on the
+  *        trigger input is 5 clock cycles.
+  * @retval None
+  */
+#define __HAL_TIM_DISABLE_OCxFAST(__HANDLE__, __CHANNEL__)    \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_OC1FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_OC2FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_OC3FE) :\
+   ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_OC4FE))
+
+/**
+  * @brief  Set the Update Request Source (URS) bit of the TIMx_CR1 register.
+  * @param  __HANDLE__ TIM handle.
+  * @note  When the URS bit of the TIMx_CR1 register is set, only counter
+  *        overflow/underflow generates an update interrupt or DMA request (if
+  *        enabled)
+  * @retval None
+  */
+#define __HAL_TIM_URS_ENABLE(__HANDLE__)  ((__HANDLE__)->Instance->CR1|= TIM_CR1_URS)
+
+/**
+  * @brief  Reset the Update Request Source (URS) bit of the TIMx_CR1 register.
+  * @param  __HANDLE__ TIM handle.
+  * @note  When the URS bit of the TIMx_CR1 register is reset, any of the
+  *        following events generate an update interrupt or DMA request (if
+  *        enabled):
+  *           _ Counter overflow underflow
+  *           _ Setting the UG bit
+  *           _ Update generation through the slave mode controller
+  * @retval None
+  */
+#define __HAL_TIM_URS_DISABLE(__HANDLE__)  ((__HANDLE__)->Instance->CR1&=~TIM_CR1_URS)
+
+/**
+  * @brief  Set the TIM Capture x input polarity on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  __POLARITY__ Polarity for TIx source
+  *            @arg TIM_INPUTCHANNELPOLARITY_RISING: Rising Edge
+  *            @arg TIM_INPUTCHANNELPOLARITY_FALLING: Falling Edge
+  *            @arg TIM_INPUTCHANNELPOLARITY_BOTHEDGE: Rising and Falling Edge
+  * @retval None
+  */
+#define __HAL_TIM_SET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__, __POLARITY__)    \
+  do{                                                                     \
+    TIM_RESET_CAPTUREPOLARITY((__HANDLE__), (__CHANNEL__));               \
+    TIM_SET_CAPTUREPOLARITY((__HANDLE__), (__CHANNEL__), (__POLARITY__)); \
+  }while(0)
+
+/** @brief  Select the Capture/compare DMA request source.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __CCDMA__ specifies Capture/compare DMA request source
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CCDMAREQUEST_CC: CCx DMA request generated on Capture/Compare event
+  *            @arg TIM_CCDMAREQUEST_UPDATE: CCx DMA request generated on Update event
+  * @retval None
+  */
+#define __HAL_TIM_SELECT_CCDMAREQUEST(__HANDLE__, __CCDMA__)    \
+  MODIFY_REG((__HANDLE__)->Instance->CR2, TIM_CR2_CCDS, (__CCDMA__))
+
+/**
+  * @}
+  */
+/* End of exported macros ----------------------------------------------------*/
+
+/* Private constants ---------------------------------------------------------*/
+/** @defgroup TIM_Private_Constants TIM Private Constants
+  * @{
+  */
+/* The counter of a timer instance is disabled only if all the CCx and CCxN
+   channels have been disabled */
+#define TIM_CCER_CCxE_MASK  ((uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E))
+#define TIM_CCER_CCxNE_MASK ((uint32_t)(TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE))
+/**
+  * @}
+  */
+/* End of private constants --------------------------------------------------*/
+
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup TIM_Private_Macros TIM Private Macros
+  * @{
+  */
+#define IS_TIM_CLEARINPUT_SOURCE(__MODE__)  (((__MODE__) == TIM_CLEARINPUTSOURCE_NONE)      || \
+                                             ((__MODE__) == TIM_CLEARINPUTSOURCE_ETR))
+
+#define IS_TIM_DMA_BASE(__BASE__) (((__BASE__) == TIM_DMABASE_CR1)   || \
+                                   ((__BASE__) == TIM_DMABASE_CR2)   || \
+                                   ((__BASE__) == TIM_DMABASE_SMCR)  || \
+                                   ((__BASE__) == TIM_DMABASE_DIER)  || \
+                                   ((__BASE__) == TIM_DMABASE_SR)    || \
+                                   ((__BASE__) == TIM_DMABASE_EGR)   || \
+                                   ((__BASE__) == TIM_DMABASE_CCMR1) || \
+                                   ((__BASE__) == TIM_DMABASE_CCMR2) || \
+                                   ((__BASE__) == TIM_DMABASE_CCER)  || \
+                                   ((__BASE__) == TIM_DMABASE_CNT)   || \
+                                   ((__BASE__) == TIM_DMABASE_PSC)   || \
+                                   ((__BASE__) == TIM_DMABASE_ARR)   || \
+                                   ((__BASE__) == TIM_DMABASE_RCR)   || \
+                                   ((__BASE__) == TIM_DMABASE_CCR1)  || \
+                                   ((__BASE__) == TIM_DMABASE_CCR2)  || \
+                                   ((__BASE__) == TIM_DMABASE_CCR3)  || \
+                                   ((__BASE__) == TIM_DMABASE_CCR4)  || \
+                                   ((__BASE__) == TIM_DMABASE_BDTR))
+
+#define IS_TIM_EVENT_SOURCE(__SOURCE__) ((((__SOURCE__) & 0xFFFFFF00U) == 0x00000000U) && ((__SOURCE__) != 0x00000000U))
+
+#define IS_TIM_COUNTER_MODE(__MODE__)      (((__MODE__) == TIM_COUNTERMODE_UP)              || \
+                                            ((__MODE__) == TIM_COUNTERMODE_DOWN)            || \
+                                            ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED1)  || \
+                                            ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED2)  || \
+                                            ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED3))
+
+#define IS_TIM_CLOCKDIVISION_DIV(__DIV__)  (((__DIV__) == TIM_CLOCKDIVISION_DIV1) || \
+                                            ((__DIV__) == TIM_CLOCKDIVISION_DIV2) || \
+                                            ((__DIV__) == TIM_CLOCKDIVISION_DIV4))
+
+#define IS_TIM_AUTORELOAD_PRELOAD(PRELOAD) (((PRELOAD) == TIM_AUTORELOAD_PRELOAD_DISABLE) || \
+                                            ((PRELOAD) == TIM_AUTORELOAD_PRELOAD_ENABLE))
+
+#define IS_TIM_FAST_STATE(__STATE__)       (((__STATE__) == TIM_OCFAST_DISABLE) || \
+                                            ((__STATE__) == TIM_OCFAST_ENABLE))
+
+#define IS_TIM_OC_POLARITY(__POLARITY__)   (((__POLARITY__) == TIM_OCPOLARITY_HIGH) || \
+                                            ((__POLARITY__) == TIM_OCPOLARITY_LOW))
+
+#define IS_TIM_OCN_POLARITY(__POLARITY__)  (((__POLARITY__) == TIM_OCNPOLARITY_HIGH) || \
+                                            ((__POLARITY__) == TIM_OCNPOLARITY_LOW))
+
+#define IS_TIM_OCIDLE_STATE(__STATE__)     (((__STATE__) == TIM_OCIDLESTATE_SET) || \
+                                            ((__STATE__) == TIM_OCIDLESTATE_RESET))
+
+#define IS_TIM_OCNIDLE_STATE(__STATE__)    (((__STATE__) == TIM_OCNIDLESTATE_SET) || \
+                                            ((__STATE__) == TIM_OCNIDLESTATE_RESET))
+
+#define IS_TIM_ENCODERINPUT_POLARITY(__POLARITY__)   (((__POLARITY__) == TIM_ENCODERINPUTPOLARITY_RISING)   || \
+                                                      ((__POLARITY__) == TIM_ENCODERINPUTPOLARITY_FALLING))
+
+#define IS_TIM_IC_POLARITY(__POLARITY__)   (((__POLARITY__) == TIM_ICPOLARITY_RISING)   || \
+                                            ((__POLARITY__) == TIM_ICPOLARITY_FALLING)  || \
+                                            ((__POLARITY__) == TIM_ICPOLARITY_BOTHEDGE))
+
+#define IS_TIM_IC_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_ICSELECTION_DIRECTTI) || \
+                                            ((__SELECTION__) == TIM_ICSELECTION_INDIRECTTI) || \
+                                            ((__SELECTION__) == TIM_ICSELECTION_TRC))
+
+#define IS_TIM_IC_PRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_ICPSC_DIV1) || \
+                                            ((__PRESCALER__) == TIM_ICPSC_DIV2) || \
+                                            ((__PRESCALER__) == TIM_ICPSC_DIV4) || \
+                                            ((__PRESCALER__) == TIM_ICPSC_DIV8))
+
+#define IS_TIM_OPM_MODE(__MODE__)          (((__MODE__) == TIM_OPMODE_SINGLE) || \
+                                            ((__MODE__) == TIM_OPMODE_REPETITIVE))
+
+#define IS_TIM_ENCODER_MODE(__MODE__)      (((__MODE__) == TIM_ENCODERMODE_TI1) || \
+                                            ((__MODE__) == TIM_ENCODERMODE_TI2) || \
+                                            ((__MODE__) == TIM_ENCODERMODE_TI12))
+
+#define IS_TIM_DMA_SOURCE(__SOURCE__) ((((__SOURCE__) & 0xFFFF80FFU) == 0x00000000U) && ((__SOURCE__) != 0x00000000U))
+
+#define IS_TIM_CHANNELS(__CHANNEL__)       (((__CHANNEL__) == TIM_CHANNEL_1) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_2) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_3) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_4) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_ALL))
+
+#define IS_TIM_OPM_CHANNELS(__CHANNEL__)   (((__CHANNEL__) == TIM_CHANNEL_1) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_2))
+
+#define IS_TIM_PERIOD(__HANDLE__, __PERIOD__) ((IS_TIM_32B_COUNTER_INSTANCE(((__HANDLE__)->Instance)) == 0U) ? \
+                                               (((__PERIOD__) > 0U) && ((__PERIOD__) <= 0x0000FFFFU)) :        \
+                                               ((__PERIOD__) > 0U))
+
+#define IS_TIM_COMPLEMENTARY_CHANNELS(__CHANNEL__) (((__CHANNEL__) == TIM_CHANNEL_1) || \
+                                                    ((__CHANNEL__) == TIM_CHANNEL_2) || \
+                                                    ((__CHANNEL__) == TIM_CHANNEL_3))
+
+#define IS_TIM_CLOCKSOURCE(__CLOCK__) (((__CLOCK__) == TIM_CLOCKSOURCE_INTERNAL) || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ETRMODE1) || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ETRMODE2) || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_TI1ED)    || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_TI1)      || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_TI2)      || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ITR0)     || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ITR1)     || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ITR2)     || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ITR3))
+
+#define IS_TIM_CLOCKPOLARITY(__POLARITY__) (((__POLARITY__) == TIM_CLOCKPOLARITY_INVERTED)    || \
+                                            ((__POLARITY__) == TIM_CLOCKPOLARITY_NONINVERTED) || \
+                                            ((__POLARITY__) == TIM_CLOCKPOLARITY_RISING)      || \
+                                            ((__POLARITY__) == TIM_CLOCKPOLARITY_FALLING)     || \
+                                            ((__POLARITY__) == TIM_CLOCKPOLARITY_BOTHEDGE))
+
+#define IS_TIM_CLOCKPRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV1) || \
+                                              ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV2) || \
+                                              ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV4) || \
+                                              ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV8))
+
+#define IS_TIM_CLOCKFILTER(__ICFILTER__)      ((__ICFILTER__) <= 0xFU)
+
+#define IS_TIM_CLEARINPUT_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_CLEARINPUTPOLARITY_INVERTED) || \
+                                                  ((__POLARITY__) == TIM_CLEARINPUTPOLARITY_NONINVERTED))
+
+#define IS_TIM_CLEARINPUT_PRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV1) || \
+                                                    ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV2) || \
+                                                    ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV4) || \
+                                                    ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV8))
+
+#define IS_TIM_CLEARINPUT_FILTER(__ICFILTER__) ((__ICFILTER__) <= 0xFU)
+
+#define IS_TIM_OSSR_STATE(__STATE__)       (((__STATE__) == TIM_OSSR_ENABLE) || \
+                                            ((__STATE__) == TIM_OSSR_DISABLE))
+
+#define IS_TIM_OSSI_STATE(__STATE__)       (((__STATE__) == TIM_OSSI_ENABLE) || \
+                                            ((__STATE__) == TIM_OSSI_DISABLE))
+
+#define IS_TIM_LOCK_LEVEL(__LEVEL__)       (((__LEVEL__) == TIM_LOCKLEVEL_OFF) || \
+                                            ((__LEVEL__) == TIM_LOCKLEVEL_1)   || \
+                                            ((__LEVEL__) == TIM_LOCKLEVEL_2)   || \
+                                            ((__LEVEL__) == TIM_LOCKLEVEL_3))
+
+#define IS_TIM_BREAK_FILTER(__BRKFILTER__) ((__BRKFILTER__) <= 0xFUL)
+
+#define IS_TIM_BREAK_STATE(__STATE__)      (((__STATE__) == TIM_BREAK_ENABLE) || \
+                                            ((__STATE__) == TIM_BREAK_DISABLE))
+
+#define IS_TIM_BREAK_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_BREAKPOLARITY_LOW) || \
+                                             ((__POLARITY__) == TIM_BREAKPOLARITY_HIGH))
+
+#define IS_TIM_AUTOMATIC_OUTPUT_STATE(__STATE__) (((__STATE__) == TIM_AUTOMATICOUTPUT_ENABLE) || \
+                                                  ((__STATE__) == TIM_AUTOMATICOUTPUT_DISABLE))
+
+#define IS_TIM_TRGO_SOURCE(__SOURCE__) (((__SOURCE__) == TIM_TRGO_RESET)  || \
+                                        ((__SOURCE__) == TIM_TRGO_ENABLE) || \
+                                        ((__SOURCE__) == TIM_TRGO_UPDATE) || \
+                                        ((__SOURCE__) == TIM_TRGO_OC1)    || \
+                                        ((__SOURCE__) == TIM_TRGO_OC1REF) || \
+                                        ((__SOURCE__) == TIM_TRGO_OC2REF) || \
+                                        ((__SOURCE__) == TIM_TRGO_OC3REF) || \
+                                        ((__SOURCE__) == TIM_TRGO_OC4REF))
+
+#define IS_TIM_MSM_STATE(__STATE__)      (((__STATE__) == TIM_MASTERSLAVEMODE_ENABLE) || \
+                                          ((__STATE__) == TIM_MASTERSLAVEMODE_DISABLE))
+
+#define IS_TIM_SLAVE_MODE(__MODE__) (((__MODE__) == TIM_SLAVEMODE_DISABLE)   || \
+                                     ((__MODE__) == TIM_SLAVEMODE_RESET)     || \
+                                     ((__MODE__) == TIM_SLAVEMODE_GATED)     || \
+                                     ((__MODE__) == TIM_SLAVEMODE_TRIGGER)   || \
+                                     ((__MODE__) == TIM_SLAVEMODE_EXTERNAL1))
+
+#define IS_TIM_PWM_MODE(__MODE__) (((__MODE__) == TIM_OCMODE_PWM1)               || \
+                                   ((__MODE__) == TIM_OCMODE_PWM2))
+
+#define IS_TIM_OC_MODE(__MODE__)  (((__MODE__) == TIM_OCMODE_TIMING)             || \
+                                   ((__MODE__) == TIM_OCMODE_ACTIVE)             || \
+                                   ((__MODE__) == TIM_OCMODE_INACTIVE)           || \
+                                   ((__MODE__) == TIM_OCMODE_TOGGLE)             || \
+                                   ((__MODE__) == TIM_OCMODE_FORCED_ACTIVE)      || \
+                                   ((__MODE__) == TIM_OCMODE_FORCED_INACTIVE))
+
+#define IS_TIM_TRIGGER_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_TS_ITR0)    || \
+                                                 ((__SELECTION__) == TIM_TS_ITR1)    || \
+                                                 ((__SELECTION__) == TIM_TS_ITR2)    || \
+                                                 ((__SELECTION__) == TIM_TS_ITR3)    || \
+                                                 ((__SELECTION__) == TIM_TS_TI1F_ED) || \
+                                                 ((__SELECTION__) == TIM_TS_TI1FP1)  || \
+                                                 ((__SELECTION__) == TIM_TS_TI2FP2)  || \
+                                                 ((__SELECTION__) == TIM_TS_ETRF))
+
+#define IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_TS_ITR0) || \
+                                                               ((__SELECTION__) == TIM_TS_ITR1) || \
+                                                               ((__SELECTION__) == TIM_TS_ITR2) || \
+                                                               ((__SELECTION__) == TIM_TS_ITR3) || \
+                                                               ((__SELECTION__) == TIM_TS_NONE))
+
+#define IS_TIM_TRIGGERPOLARITY(__POLARITY__)   (((__POLARITY__) == TIM_TRIGGERPOLARITY_INVERTED   ) || \
+                                                ((__POLARITY__) == TIM_TRIGGERPOLARITY_NONINVERTED) || \
+                                                ((__POLARITY__) == TIM_TRIGGERPOLARITY_RISING     ) || \
+                                                ((__POLARITY__) == TIM_TRIGGERPOLARITY_FALLING    ) || \
+                                                ((__POLARITY__) == TIM_TRIGGERPOLARITY_BOTHEDGE   ))
+
+#define IS_TIM_TRIGGERPRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV1) || \
+                                                ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV2) || \
+                                                ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV4) || \
+                                                ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV8))
+
+#define IS_TIM_TRIGGERFILTER(__ICFILTER__) ((__ICFILTER__) <= 0xFU)
+
+#define IS_TIM_TI1SELECTION(__TI1SELECTION__)  (((__TI1SELECTION__) == TIM_TI1SELECTION_CH1) || \
+                                                ((__TI1SELECTION__) == TIM_TI1SELECTION_XORCOMBINATION))
+
+#define IS_TIM_DMA_LENGTH(__LENGTH__)      (((__LENGTH__) == TIM_DMABURSTLENGTH_1TRANSFER)   || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_2TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_3TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_4TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_5TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_6TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_7TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_8TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_9TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_10TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_11TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_12TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_13TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_14TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_15TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_16TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_17TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_18TRANSFERS))
+
+#define IS_TIM_DMA_DATA_LENGTH(LENGTH) (((LENGTH) >= 0x1U) && ((LENGTH) < 0x10000U))
+
+#define IS_TIM_IC_FILTER(__ICFILTER__)   ((__ICFILTER__) <= 0xFU)
+
+#define IS_TIM_DEADTIME(__DEADTIME__)    ((__DEADTIME__) <= 0xFFU)
+
+#define IS_TIM_SLAVEMODE_TRIGGER_ENABLED(__TRIGGER__) ((__TRIGGER__) == TIM_SLAVEMODE_TRIGGER)
+
+#define TIM_SET_ICPRESCALERVALUE(__HANDLE__, __CHANNEL__, __ICPSC__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 |= (__ICPSC__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 |= ((__ICPSC__) << 8U)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 |= (__ICPSC__)) :\
+   ((__HANDLE__)->Instance->CCMR2 |= ((__ICPSC__) << 8U)))
+
+#define TIM_RESET_ICPRESCALERVALUE(__HANDLE__, __CHANNEL__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_IC3PSC) :\
+   ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_IC4PSC))
+
+#define TIM_SET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__, __POLARITY__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCER |= (__POLARITY__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCER |= ((__POLARITY__) << 4U)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCER |= ((__POLARITY__) << 8U)) :\
+   ((__HANDLE__)->Instance->CCER |= (((__POLARITY__) << 12U))))
+
+#define TIM_RESET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCER &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCER &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP)) :\
+   ((__HANDLE__)->Instance->CCER &= ~(TIM_CCER_CC4P | TIM_CCER_CC4NP)))
+
+#define TIM_CHANNEL_STATE_GET(__HANDLE__, __CHANNEL__)\
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? (__HANDLE__)->ChannelState[0] :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? (__HANDLE__)->ChannelState[1] :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? (__HANDLE__)->ChannelState[2] :\
+   (__HANDLE__)->ChannelState[3])
+
+#define TIM_CHANNEL_STATE_SET(__HANDLE__, __CHANNEL__, __CHANNEL_STATE__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->ChannelState[0] = (__CHANNEL_STATE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->ChannelState[1] = (__CHANNEL_STATE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->ChannelState[2] = (__CHANNEL_STATE__)) :\
+   ((__HANDLE__)->ChannelState[3] = (__CHANNEL_STATE__)))
+
+#define TIM_CHANNEL_STATE_SET_ALL(__HANDLE__,  __CHANNEL_STATE__) do { \
+                                                                       (__HANDLE__)->ChannelState[0]  = (__CHANNEL_STATE__);  \
+                                                                       (__HANDLE__)->ChannelState[1]  = (__CHANNEL_STATE__);  \
+                                                                       (__HANDLE__)->ChannelState[2]  = (__CHANNEL_STATE__);  \
+                                                                       (__HANDLE__)->ChannelState[3]  = (__CHANNEL_STATE__);  \
+                                                                     } while(0)
+
+#define TIM_CHANNEL_N_STATE_GET(__HANDLE__, __CHANNEL__)\
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? (__HANDLE__)->ChannelNState[0] :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? (__HANDLE__)->ChannelNState[1] :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? (__HANDLE__)->ChannelNState[2] :\
+   (__HANDLE__)->ChannelNState[3])
+
+#define TIM_CHANNEL_N_STATE_SET(__HANDLE__, __CHANNEL__, __CHANNEL_STATE__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->ChannelNState[0] = (__CHANNEL_STATE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->ChannelNState[1] = (__CHANNEL_STATE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->ChannelNState[2] = (__CHANNEL_STATE__)) :\
+   ((__HANDLE__)->ChannelNState[3] = (__CHANNEL_STATE__)))
+
+#define TIM_CHANNEL_N_STATE_SET_ALL(__HANDLE__,  __CHANNEL_STATE__) do { \
+                                                                         (__HANDLE__)->ChannelNState[0] = \
+                                                                         (__CHANNEL_STATE__);  \
+                                                                         (__HANDLE__)->ChannelNState[1] = \
+                                                                         (__CHANNEL_STATE__);  \
+                                                                         (__HANDLE__)->ChannelNState[2] = \
+                                                                         (__CHANNEL_STATE__);  \
+                                                                         (__HANDLE__)->ChannelNState[3] = \
+                                                                         (__CHANNEL_STATE__);  \
+                                                                       } while(0)
+
+/**
+  * @}
+  */
+/* End of private macros -----------------------------------------------------*/
+
+/* Include TIM HAL Extended module */
+#include "stm32f4xx_hal_tim_ex.h"
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup TIM_Exported_Functions TIM Exported Functions
+  * @{
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group1 TIM Time Base functions
+  *  @brief   Time Base functions
+  * @{
+  */
+/* Time Base functions ********************************************************/
+HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, const uint32_t *pData, uint16_t Length);
+HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group2 TIM Output Compare functions
+  *  @brief   TIM Output Compare functions
+  * @{
+  */
+/* Timer Output Compare functions *********************************************/
+HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_OC_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                       uint16_t Length);
+HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group3 TIM PWM functions
+  *  @brief   TIM PWM functions
+  * @{
+  */
+/* Timer PWM functions ********************************************************/
+HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                        uint16_t Length);
+HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group4 TIM Input Capture functions
+  *  @brief   TIM Input Capture functions
+  * @{
+  */
+/* Timer Input Capture functions **********************************************/
+HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_IC_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_IC_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_IC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_IC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIM_IC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length);
+HAL_StatusTypeDef HAL_TIM_IC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group5 TIM One Pulse functions
+  *  @brief   TIM One Pulse functions
+  * @{
+  */
+/* Timer One Pulse functions **************************************************/
+HAL_StatusTypeDef HAL_TIM_OnePulse_Init(TIM_HandleTypeDef *htim, uint32_t OnePulseMode);
+HAL_StatusTypeDef HAL_TIM_OnePulse_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_OnePulse_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_OnePulse_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group6 TIM Encoder functions
+  *  @brief   TIM Encoder functions
+  * @{
+  */
+/* Timer Encoder functions ****************************************************/
+HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim, const TIM_Encoder_InitTypeDef *sConfig);
+HAL_StatusTypeDef HAL_TIM_Encoder_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData1,
+                                            uint32_t *pData2, uint16_t Length);
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group7 TIM IRQ handler management
+  *  @brief   IRQ handler management
+  * @{
+  */
+/* Interrupt Handler functions  ***********************************************/
+void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim);
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group8 TIM Peripheral Control functions
+  *  @brief   Peripheral Control functions
+  * @{
+  */
+/* Control functions  *********************************************************/
+HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_OC_InitTypeDef *sConfig,
+                                           uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_OC_InitTypeDef *sConfig,
+                                            uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_IC_InitTypeDef *sConfig,
+                                           uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OnePulse_InitTypeDef *sConfig,
+                                                 uint32_t OutputChannel,  uint32_t InputChannel);
+HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim,
+                                           const TIM_ClearInputConfigTypeDef *sClearInputConfig,
+                                           uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, const TIM_ClockConfigTypeDef *sClockSourceConfig);
+HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection);
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro(TIM_HandleTypeDef *htim, const TIM_SlaveConfigTypeDef *sSlaveConfig);
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro_IT(TIM_HandleTypeDef *htim, const TIM_SlaveConfigTypeDef *sSlaveConfig);
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                              uint32_t BurstRequestSrc, const uint32_t  *BurstBuffer,
+                                              uint32_t  BurstLength);
+HAL_StatusTypeDef HAL_TIM_DMABurst_MultiWriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                                   uint32_t BurstRequestSrc, const uint32_t *BurstBuffer,
+                                                   uint32_t BurstLength,  uint32_t DataLength);
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc);
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                             uint32_t BurstRequestSrc, uint32_t  *BurstBuffer, uint32_t  BurstLength);
+HAL_StatusTypeDef HAL_TIM_DMABurst_MultiReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                                  uint32_t BurstRequestSrc, uint32_t  *BurstBuffer,
+                                                  uint32_t  BurstLength, uint32_t  DataLength);
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc);
+HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource);
+uint32_t HAL_TIM_ReadCapturedValue(const TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group9 TIM Callbacks functions
+  *  @brief   TIM Callbacks functions
+  * @{
+  */
+/* Callback in non blocking modes (Interrupt and DMA) *************************/
+void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_IC_CaptureHalfCpltCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_PWM_PulseFinishedHalfCpltCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_TriggerHalfCpltCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_ErrorCallback(TIM_HandleTypeDef *htim);
+
+/* Callbacks Register/UnRegister functions  ***********************************/
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+HAL_StatusTypeDef HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID,
+                                           pTIM_CallbackTypeDef pCallback);
+HAL_StatusTypeDef HAL_TIM_UnRegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group10 TIM Peripheral State functions
+  *  @brief  Peripheral State functions
+  * @{
+  */
+/* Peripheral State functions  ************************************************/
+HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(const TIM_HandleTypeDef *htim);
+
+/* Peripheral Channel state functions  ************************************************/
+HAL_TIM_ActiveChannel HAL_TIM_GetActiveChannel(const TIM_HandleTypeDef *htim);
+HAL_TIM_ChannelStateTypeDef HAL_TIM_GetChannelState(const TIM_HandleTypeDef *htim,  uint32_t Channel);
+HAL_TIM_DMABurstStateTypeDef HAL_TIM_DMABurstState(const TIM_HandleTypeDef *htim);
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+/* End of exported functions -------------------------------------------------*/
+
+/* Private functions----------------------------------------------------------*/
+/** @defgroup TIM_Private_Functions TIM Private Functions
+  * @{
+  */
+void TIM_Base_SetConfig(TIM_TypeDef *TIMx, const TIM_Base_InitTypeDef *Structure);
+void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, uint32_t TIM_ICFilter);
+void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+void TIM_ETR_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ExtTRGPrescaler,
+                       uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter);
+
+void TIM_DMADelayPulseHalfCplt(DMA_HandleTypeDef *hdma);
+void TIM_DMAError(DMA_HandleTypeDef *hdma);
+void TIM_DMACaptureCplt(DMA_HandleTypeDef *hdma);
+void TIM_DMACaptureHalfCplt(DMA_HandleTypeDef *hdma);
+void TIM_CCxChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelState);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+void TIM_ResetCallback(TIM_HandleTypeDef *htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+/* End of private functions --------------------------------------------------*/
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32F4xx_HAL_TIM_H */

+ 355 - 0
Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h

@@ -0,0 +1,355 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_hal_tim_ex.h
+  * @author  MCD Application Team
+  * @brief   Header file of TIM HAL Extended module.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef STM32F4xx_HAL_TIM_EX_H
+#define STM32F4xx_HAL_TIM_EX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal_def.h"
+
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @addtogroup TIMEx
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup TIMEx_Exported_Types TIM Extended Exported Types
+  * @{
+  */
+
+/**
+  * @brief  TIM Hall sensor Configuration Structure definition
+  */
+
+typedef struct
+{
+  uint32_t IC1Polarity;         /*!< Specifies the active edge of the input signal.
+                                     This parameter can be a value of @ref TIM_Input_Capture_Polarity */
+
+  uint32_t IC1Prescaler;        /*!< Specifies the Input Capture Prescaler.
+                                     This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
+
+  uint32_t IC1Filter;           /*!< Specifies the input capture filter.
+                                     This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+
+  uint32_t Commutation_Delay;   /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
+                                     This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
+} TIM_HallSensor_InitTypeDef;
+/**
+  * @}
+  */
+/* End of exported types -----------------------------------------------------*/
+
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup TIMEx_Exported_Constants TIM Extended Exported Constants
+  * @{
+  */
+
+/** @defgroup TIMEx_Remap TIM Extended Remapping
+  * @{
+  */
+#if defined (TIM2)
+#if defined(TIM8)
+#define TIM_TIM2_TIM8_TRGO                     0x00000000U                              /*!< TIM2 ITR1 is connected to TIM8 TRGO */
+#endif /*  TIM8 */
+#define TIM_TIM2_ETH_PTP                       TIM_OR_ITR1_RMP_0                        /*!< TIM2 ITR1 is connected to PTP trigger output */
+#define TIM_TIM2_USBFS_SOF                     TIM_OR_ITR1_RMP_1                        /*!< TIM2 ITR1 is connected to OTG FS SOF */
+#define TIM_TIM2_USBHS_SOF                     (TIM_OR_ITR1_RMP_1 | TIM_OR_ITR1_RMP_0)  /*!< TIM2 ITR1 is connected to OTG HS SOF */
+#endif /* TIM2 */
+
+#define TIM_TIM5_GPIO                          0x00000000U                              /*!< TIM5 TI4 is connected to GPIO */
+#define TIM_TIM5_LSI                           TIM_OR_TI4_RMP_0                         /*!< TIM5 TI4 is connected to LSI */
+#define TIM_TIM5_LSE                           TIM_OR_TI4_RMP_1                         /*!< TIM5 TI4 is connected to LSE */
+#define TIM_TIM5_RTC                           (TIM_OR_TI4_RMP_1 | TIM_OR_TI4_RMP_0)    /*!< TIM5 TI4 is connected to the RTC wakeup interrupt */
+
+#define TIM_TIM11_GPIO                         0x00000000U                              /*!< TIM11 TI1 is connected to GPIO */
+#define TIM_TIM11_HSE                          TIM_OR_TI1_RMP_1                         /*!< TIM11 TI1 is connected to HSE_RTC clock */
+#if defined(SPDIFRX)
+#define TIM_TIM11_SPDIFRX                      TIM_OR_TI1_RMP_0                         /*!< TIM11 TI1 is connected to SPDIFRX_FRAME_SYNC */
+#endif /* SPDIFRX*/
+
+#if defined(LPTIM_OR_TIM1_ITR2_RMP) && defined(LPTIM_OR_TIM5_ITR1_RMP) && defined(LPTIM_OR_TIM5_ITR1_RMP)
+#define LPTIM_REMAP_MASK                       0x10000000U
+
+#define TIM_TIM9_TIM3_TRGO                     LPTIM_REMAP_MASK                             /*!< TIM9 ITR1 is connected to TIM3 TRGO */
+#define TIM_TIM9_LPTIM                         (LPTIM_REMAP_MASK | LPTIM_OR_TIM9_ITR1_RMP)  /*!< TIM9 ITR1 is connected to LPTIM1 output */
+
+#define TIM_TIM5_TIM3_TRGO                     LPTIM_REMAP_MASK                             /*!< TIM5 ITR1 is connected to TIM3 TRGO */
+#define TIM_TIM5_LPTIM                         (LPTIM_REMAP_MASK | LPTIM_OR_TIM5_ITR1_RMP)  /*!< TIM5 ITR1 is connected to LPTIM1 output */
+
+#define TIM_TIM1_TIM3_TRGO                     LPTIM_REMAP_MASK                             /*!< TIM1 ITR2 is connected to TIM3 TRGO */
+#define TIM_TIM1_LPTIM                         (LPTIM_REMAP_MASK | LPTIM_OR_TIM1_ITR2_RMP)  /*!< TIM1 ITR2 is connected to LPTIM1 output */
+#endif /* LPTIM_OR_TIM1_ITR2_RMP &&  LPTIM_OR_TIM5_ITR1_RMP && LPTIM_OR_TIM5_ITR1_RMP */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+/* End of exported constants -------------------------------------------------*/
+
+/* Exported macro ------------------------------------------------------------*/
+/** @defgroup TIMEx_Exported_Macros TIM Extended Exported Macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+/* End of exported macro -----------------------------------------------------*/
+
+/* Private macro -------------------------------------------------------------*/
+/** @defgroup TIMEx_Private_Macros TIM Extended Private Macros
+  * @{
+  */
+#if defined(SPDIFRX)
+#define IS_TIM_REMAP(INSTANCE, TIM_REMAP)                                 \
+  ((((INSTANCE) == TIM2)  && (((TIM_REMAP) == TIM_TIM2_TIM8_TRGO)      || \
+                              ((TIM_REMAP) == TIM_TIM2_USBFS_SOF)      || \
+                              ((TIM_REMAP) == TIM_TIM2_USBHS_SOF)))    || \
+   (((INSTANCE) == TIM5)  && (((TIM_REMAP) == TIM_TIM5_GPIO)           || \
+                              ((TIM_REMAP) == TIM_TIM5_LSI)            || \
+                              ((TIM_REMAP) == TIM_TIM5_LSE)            || \
+                              ((TIM_REMAP) == TIM_TIM5_RTC)))          || \
+   (((INSTANCE) == TIM11) && (((TIM_REMAP) == TIM_TIM11_GPIO)          || \
+                              ((TIM_REMAP) == TIM_TIM11_SPDIFRX)       || \
+                              ((TIM_REMAP) == TIM_TIM11_HSE))))
+#elif defined(TIM2)
+#if defined(LPTIM_OR_TIM1_ITR2_RMP) && defined(LPTIM_OR_TIM5_ITR1_RMP) && defined(LPTIM_OR_TIM5_ITR1_RMP)
+#define IS_TIM_REMAP(INSTANCE, TIM_REMAP)                                 \
+  ((((INSTANCE) == TIM2)  && (((TIM_REMAP) == TIM_TIM2_TIM8_TRGO)      || \
+                              ((TIM_REMAP) == TIM_TIM2_USBFS_SOF)      || \
+                              ((TIM_REMAP) == TIM_TIM2_USBHS_SOF)))    || \
+   (((INSTANCE) == TIM5)  && (((TIM_REMAP) == TIM_TIM5_GPIO)           || \
+                              ((TIM_REMAP) == TIM_TIM5_LSI)            || \
+                              ((TIM_REMAP) == TIM_TIM5_LSE)            || \
+                              ((TIM_REMAP) == TIM_TIM5_RTC)))          || \
+   (((INSTANCE) == TIM11) && (((TIM_REMAP) == TIM_TIM11_GPIO)          || \
+                              ((TIM_REMAP) == TIM_TIM11_HSE)))         || \
+   (((INSTANCE) == TIM1)  && (((TIM_REMAP) == TIM_TIM1_TIM3_TRGO)      || \
+                              ((TIM_REMAP) == TIM_TIM1_LPTIM)))        || \
+   (((INSTANCE) == TIM5)  && (((TIM_REMAP) == TIM_TIM5_TIM3_TRGO)      || \
+                              ((TIM_REMAP) == TIM_TIM5_LPTIM)))        || \
+   (((INSTANCE) == TIM9)  && (((TIM_REMAP) == TIM_TIM9_TIM3_TRGO)      || \
+                              ((TIM_REMAP) == TIM_TIM9_LPTIM))))
+#elif defined(TIM8)
+#define IS_TIM_REMAP(INSTANCE, TIM_REMAP)                                 \
+  ((((INSTANCE) == TIM2)  && (((TIM_REMAP) == TIM_TIM2_TIM8_TRGO)      || \
+                              ((TIM_REMAP) == TIM_TIM2_USBFS_SOF)      || \
+                              ((TIM_REMAP) == TIM_TIM2_USBHS_SOF)))    || \
+   (((INSTANCE) == TIM5)  && (((TIM_REMAP) == TIM_TIM5_GPIO)           || \
+                              ((TIM_REMAP) == TIM_TIM5_LSI)            || \
+                              ((TIM_REMAP) == TIM_TIM5_LSE)            || \
+                              ((TIM_REMAP) == TIM_TIM5_RTC)))          || \
+   (((INSTANCE) == TIM11) && (((TIM_REMAP) == TIM_TIM11_GPIO)          || \
+                              ((TIM_REMAP) == TIM_TIM11_HSE))))
+#else
+#define IS_TIM_REMAP(INSTANCE, TIM_REMAP)                                 \
+  ((((INSTANCE) == TIM2)  && (((TIM_REMAP) == TIM_TIM2_ETH_PTP)        || \
+                              ((TIM_REMAP) == TIM_TIM2_USBFS_SOF)      || \
+                              ((TIM_REMAP) == TIM_TIM2_USBHS_SOF)))    || \
+   (((INSTANCE) == TIM5)  && (((TIM_REMAP) == TIM_TIM5_GPIO)           || \
+                              ((TIM_REMAP) == TIM_TIM5_LSI)            || \
+                              ((TIM_REMAP) == TIM_TIM5_LSE)            || \
+                              ((TIM_REMAP) == TIM_TIM5_RTC)))          || \
+   (((INSTANCE) == TIM11) && (((TIM_REMAP) == TIM_TIM11_GPIO)          || \
+                              ((TIM_REMAP) == TIM_TIM11_HSE))))
+#endif /* LPTIM_OR_TIM1_ITR2_RMP &&  LPTIM_OR_TIM5_ITR1_RMP && LPTIM_OR_TIM5_ITR1_RMP */
+#else
+#define IS_TIM_REMAP(INSTANCE, TIM_REMAP)                                 \
+  ((((INSTANCE) == TIM5)  && (((TIM_REMAP) == TIM_TIM5_GPIO)           || \
+                              ((TIM_REMAP) == TIM_TIM5_LSI)            || \
+                              ((TIM_REMAP) == TIM_TIM5_LSE)            || \
+                              ((TIM_REMAP) == TIM_TIM5_RTC)))          || \
+   (((INSTANCE) == TIM11) && (((TIM_REMAP) == TIM_TIM11_GPIO)          || \
+                              ((TIM_REMAP) == TIM_TIM11_HSE))))
+#endif /* SPDIFRX */
+
+/**
+  * @}
+  */
+/* End of private macro ------------------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup TIMEx_Exported_Functions TIM Extended Exported Functions
+  * @{
+  */
+
+/** @addtogroup TIMEx_Exported_Functions_Group1 Extended Timer Hall Sensor functions
+  *  @brief    Timer Hall Sensor functions
+  * @{
+  */
+/*  Timer Hall Sensor functions  **********************************************/
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, const TIM_HallSensor_InitTypeDef *sConfig);
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim);
+
+void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *htim);
+
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length);
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim);
+/**
+  * @}
+  */
+
+/** @addtogroup TIMEx_Exported_Functions_Group2 Extended Timer Complementary Output Compare functions
+  *  @brief   Timer Complementary Output Compare functions
+  * @{
+  */
+/*  Timer Complementary Output Compare functions  *****************************/
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
+
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                          uint16_t Length);
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions
+  *  @brief    Timer Complementary PWM functions
+  * @{
+  */
+/*  Timer Complementary PWM functions  ****************************************/
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
+
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                           uint16_t Length);
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions
+  *  @brief    Timer Complementary One Pulse functions
+  * @{
+  */
+/*  Timer Complementary One Pulse functions  **********************************/
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions
+  *  @brief    Peripheral Control functions
+  * @{
+  */
+/* Extended Control functions  ************************************************/
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent(TIM_HandleTypeDef *htim, uint32_t  InputTrigger,
+                                              uint32_t  CommutationSource);
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_IT(TIM_HandleTypeDef *htim, uint32_t  InputTrigger,
+                                                 uint32_t  CommutationSource);
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_DMA(TIM_HandleTypeDef *htim, uint32_t  InputTrigger,
+                                                  uint32_t  CommutationSource);
+HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim,
+                                                        const TIM_MasterConfigTypeDef *sMasterConfig);
+HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim,
+                                                const TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig);
+HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap);
+/**
+  * @}
+  */
+
+/** @addtogroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions
+  * @brief    Extended Callbacks functions
+  * @{
+  */
+/* Extended Callback **********************************************************/
+void HAL_TIMEx_CommutCallback(TIM_HandleTypeDef *htim);
+void HAL_TIMEx_CommutHalfCpltCallback(TIM_HandleTypeDef *htim);
+void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim);
+/**
+  * @}
+  */
+
+/** @addtogroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions
+  * @brief    Extended Peripheral State functions
+  * @{
+  */
+/* Extended Peripheral State functions  ***************************************/
+HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_ChannelStateTypeDef HAL_TIMEx_GetChannelNState(const TIM_HandleTypeDef *htim,  uint32_t ChannelN);
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+/* End of exported functions -------------------------------------------------*/
+
+/* Private functions----------------------------------------------------------*/
+/** @addtogroup TIMEx_Private_Functions TIM Extended Private Functions
+  * @{
+  */
+void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma);
+void TIMEx_DMACommutationHalfCplt(DMA_HandleTypeDef *hdma);
+/**
+  * @}
+  */
+/* End of private functions --------------------------------------------------*/
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* STM32F4xx_HAL_TIM_EX_H */

+ 578 - 0
Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h

@@ -0,0 +1,578 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_ll_usb.h
+  * @author  MCD Application Team
+  * @brief   Header file of USB Low Layer HAL module.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef STM32F4xx_LL_USB_H
+#define STM32F4xx_LL_USB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal_def.h"
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @addtogroup USB_LL
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+#ifndef HAL_USB_TIMEOUT
+#define HAL_USB_TIMEOUT                                       0xF000000U
+#endif /* define HAL_USB_TIMEOUT */
+
+#ifndef HAL_USB_CURRENT_MODE_MAX_DELAY_MS
+#define HAL_USB_CURRENT_MODE_MAX_DELAY_MS                           200U
+#endif /* define HAL_USB_CURRENT_MODE_MAX_DELAY_MS */
+
+/**
+  * @brief  USB Mode definition
+  */
+
+typedef enum
+{
+  USB_DEVICE_MODE = 0,
+  USB_HOST_MODE   = 1,
+  USB_DRD_MODE    = 2
+} USB_ModeTypeDef;
+
+/**
+  * @brief  URB States definition
+  */
+typedef enum
+{
+  URB_IDLE = 0,
+  URB_DONE,
+  URB_NOTREADY,
+  URB_NYET,
+  URB_ERROR,
+  URB_STALL
+} USB_URBStateTypeDef;
+
+/**
+  * @brief  Host channel States  definition
+  */
+typedef enum
+{
+  HC_IDLE = 0,
+  HC_XFRC,
+  HC_HALTED,
+  HC_ACK,
+  HC_NAK,
+  HC_NYET,
+  HC_STALL,
+  HC_XACTERR,
+  HC_BBLERR,
+  HC_DATATGLERR
+} USB_HCStateTypeDef;
+
+
+/**
+  * @brief  USB Instance Initialization Structure definition
+  */
+typedef struct
+{
+  uint8_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 */
+
+  uint8_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 */
+
+  uint8_t dma_enable;              /*!< USB DMA state.
+                                         If DMA is not supported this parameter shall be set by default to zero */
+
+  uint8_t speed;                   /*!< USB Core speed.
+                                        This parameter can be any value of @ref PCD_Speed/HCD_Speed
+                                                                                (HCD_SPEED_xxx, HCD_SPEED_xxx) */
+
+  uint8_t ep0_mps;                 /*!< Set the Endpoint 0 Max Packet size.                                    */
+
+  uint8_t phy_itface;              /*!< Select the used PHY interface.
+                                        This parameter can be any value of @ref PCD_PHY_Module/HCD_PHY_Module  */
+
+  uint8_t Sof_enable;              /*!< Enable or disable the output of the SOF signal.                        */
+
+  uint8_t low_power_enable;        /*!< Enable or disable the low Power Mode.                                  */
+
+  uint8_t lpm_enable;              /*!< Enable or disable Link Power Management.                               */
+
+  uint8_t battery_charging_enable; /*!< Enable or disable Battery charging.                                    */
+
+  uint8_t vbus_sensing_enable;     /*!< Enable or disable the VBUS Sensing feature.                            */
+
+  uint8_t use_dedicated_ep1;       /*!< Enable or disable the use of the dedicated EP1 interrupt.              */
+
+  uint8_t use_external_vbus;       /*!< Enable or disable the use of the external VBUS.                        */
+
+} USB_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   is_iso_incomplete;    /*!< Endpoint isoc 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_LL_EP_Type                   */
+
+  uint8_t   data_pid_start;       /*!< Initial data PID
+                                       This parameter must be a number between Min_Data = 0 and Max_Data = 1    */
+
+  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  xfer_len;             /*!< Current transfer length                                                  */
+
+  uint32_t  xfer_count;           /*!< Partial transfer length in case of multi packet transfer                 */
+
+  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  dma_addr;             /*!< 32 bits aligned transfer buffer address                                  */
+
+  uint32_t  xfer_size;            /*!< requested transfer size                                                  */
+} USB_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 Channel speed.
+                                     This parameter can be any value of @ref HCD_Device_Speed:
+                                                                             (HCD_DEVICE_SPEED_xxx)             */
+
+  uint8_t   do_ping;            /*!< Enable or disable the use of the PING protocol for HS mode.                */
+  uint8_t   do_ssplit;          /*!< Enable start split transaction in HS mode.                                 */
+  uint8_t   do_csplit;          /*!< Enable complete split transaction in HS mode.                              */
+  uint8_t   ep_ss_schedule;     /*!< Enable periodic endpoint start split schedule .                            */
+  uint32_t  iso_splt_xactPos;   /*!< iso split transfer transaction position.                                   */
+
+  uint8_t   hub_port_nbr;       /*!< USB HUB port number                                                        */
+  uint8_t   hub_addr;           /*!< USB HUB address                                                            */
+
+  uint8_t   ep_type;            /*!< Endpoint Type.
+                                     This parameter can be any value of @ref USB_LL_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  XferSize;           /*!< OTG Channel transfer size.                                                 */
+
+  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.                                                  */
+  uint32_t  NyetErrCnt;         /*!< Complete Split NYET Host channel error count.                              */
+
+  USB_URBStateTypeDef urb_state;  /*!< URB state.
+                                       This parameter can be any value of @ref USB_URBStateTypeDef              */
+
+  USB_HCStateTypeDef state;       /*!< Host Channel state.
+                                       This parameter can be any value of @ref USB_HCStateTypeDef               */
+} USB_HCTypeDef;
+
+typedef USB_ModeTypeDef     USB_OTG_ModeTypeDef;
+typedef USB_CfgTypeDef      USB_OTG_CfgTypeDef;
+typedef USB_EPTypeDef       USB_OTG_EPTypeDef;
+typedef USB_URBStateTypeDef USB_OTG_URBStateTypeDef;
+typedef USB_HCStateTypeDef  USB_OTG_HCStateTypeDef;
+typedef USB_HCTypeDef       USB_OTG_HCTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup PCD_Exported_Constants PCD Exported Constants
+  * @{
+  */
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/** @defgroup USB_OTG_CORE VERSION ID
+  * @{
+  */
+#define USB_OTG_CORE_ID_300A          0x4F54300AU
+#define USB_OTG_CORE_ID_310A          0x4F54310AU
+/**
+  * @}
+  */
+
+/** @defgroup USB_Core_Mode_ USB Core Mode
+  * @{
+  */
+#define USB_OTG_MODE_DEVICE                    0U
+#define USB_OTG_MODE_HOST                      1U
+#define USB_OTG_MODE_DRD                       2U
+/**
+  * @}
+  */
+
+/** @defgroup USB_LL_Core_Speed USB Low Layer Core Speed
+  * @{
+  */
+#define USB_OTG_SPEED_HIGH                     0U
+#define USB_OTG_SPEED_HIGH_IN_FULL             1U
+#define USB_OTG_SPEED_FULL                     3U
+/**
+  * @}
+  */
+
+/** @defgroup USB_LL_Core_PHY USB Low Layer Core PHY
+  * @{
+  */
+#define USB_OTG_ULPI_PHY                       1U
+#define USB_OTG_EMBEDDED_PHY                   2U
+/**
+  * @}
+  */
+
+/** @defgroup USB_LL_Turnaround_Timeout Turnaround Timeout Value
+  * @{
+  */
+#ifndef USBD_HS_TRDT_VALUE
+#define USBD_HS_TRDT_VALUE                     9U
+#endif /* USBD_HS_TRDT_VALUE */
+#ifndef USBD_FS_TRDT_VALUE
+#define USBD_FS_TRDT_VALUE                     5U
+#define USBD_DEFAULT_TRDT_VALUE                9U
+#endif /* USBD_HS_TRDT_VALUE */
+/**
+  * @}
+  */
+
+/** @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
+  * @{
+  */
+#define DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ     (0U << 1)
+#define DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ     (1U << 1)
+#define DSTS_ENUMSPD_FS_PHY_48MHZ              (3U << 1)
+/**
+  * @}
+  */
+
+/** @defgroup USB_LL_CORE_Frame_Interval USB Low Layer Core Frame Interval
+  * @{
+  */
+#define DCFG_FRAME_INTERVAL_80                 0U
+#define DCFG_FRAME_INTERVAL_85                 1U
+#define DCFG_FRAME_INTERVAL_90                 2U
+#define DCFG_FRAME_INTERVAL_95                 3U
+/**
+  * @}
+  */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+/** @defgroup USB_LL_EP0_MPS USB Low Layer EP0 MPS
+  * @{
+  */
+#define EP_MPS_64                              0U
+#define EP_MPS_32                              1U
+#define EP_MPS_16                              2U
+#define EP_MPS_8                               3U
+/**
+  * @}
+  */
+
+/** @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
+/**
+  * @}
+  */
+
+/** @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_CH_PID_Type USB Low Layer Channel PID Type
+  * @{
+  */
+#define HC_PID_DATA0                           0U
+#define HC_PID_DATA2                           1U
+#define HC_PID_DATA1                           2U
+#define HC_PID_SETUP                           3U
+/**
+  * @}
+  */
+
+/** @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
+/**
+  * @}
+  */
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/** @defgroup USB_LL_STS_Defines USB Low Layer STS Defines
+  * @{
+  */
+#define STS_GOUT_NAK                           1U
+#define STS_DATA_UPDT                          2U
+#define STS_XFER_COMP                          3U
+#define STS_SETUP_COMP                         4U
+#define STS_SETUP_UPDT                         6U
+/**
+  * @}
+  */
+
+/** @defgroup USB_LL_HCFG_SPEED_Defines USB Low Layer HCFG Speed Defines
+  * @{
+  */
+#define HCFG_30_60_MHZ                         0U
+#define HCFG_48_MHZ                            1U
+#define HCFG_6_MHZ                             2U
+/**
+  * @}
+  */
+
+/** @defgroup USB_LL_HFIR_Defines USB Low Layer frame interval Defines
+  * @{
+  */
+#define HFIR_6_MHZ                          6000U
+#define HFIR_60_MHZ                        60000U
+#define HFIR_48_MHZ                        48000U
+/**
+  * @}
+  */
+
+/** @defgroup USB_LL_HPRT0_PRTSPD_SPEED_Defines USB Low Layer HPRT0 PRTSPD Speed Defines
+  * @{
+  */
+#define HPRT0_PRTSPD_HIGH_SPEED                0U
+#define HPRT0_PRTSPD_FULL_SPEED                1U
+#define HPRT0_PRTSPD_LOW_SPEED                 2U
+/**
+  * @}
+  */
+
+#define HCCHAR_CTRL                            0U
+#define HCCHAR_ISOC                            1U
+#define HCCHAR_BULK                            2U
+#define HCCHAR_INTR                            3U
+
+#define GRXSTS_PKTSTS_IN                       2U
+#define GRXSTS_PKTSTS_IN_XFER_COMP             3U
+#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR          5U
+#define GRXSTS_PKTSTS_CH_HALTED                7U
+
+#define CLEAR_INTERRUPT_MASK          0xFFFFFFFFU
+
+#define HC_MAX_PKT_CNT                       256U
+#define ISO_SPLT_MPS                         188U
+
+#define HCSPLT_BEGIN                           1U
+#define HCSPLT_MIDDLE                          2U
+#define HCSPLT_END                             3U
+#define HCSPLT_FULL                            4U
+
+#define TEST_J                                 1U
+#define TEST_K                                 2U
+#define TEST_SE0_NAK                           3U
+#define TEST_PACKET                            4U
+#define TEST_FORCE_EN                          5U
+
+#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
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/** @defgroup USB_LL_Exported_Macros USB Low Layer Exported Macros
+  * @{
+  */
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+#define USB_MASK_INTERRUPT(__INSTANCE__, __INTERRUPT__)     ((__INSTANCE__)->GINTMSK &= ~(__INTERRUPT__))
+#define USB_UNMASK_INTERRUPT(__INSTANCE__, __INTERRUPT__)   ((__INSTANCE__)->GINTMSK |= (__INTERRUPT__))
+
+#define CLEAR_IN_EP_INTR(__EPNUM__, __INTERRUPT__)          (USBx_INEP(__EPNUM__)->DIEPINT = (__INTERRUPT__))
+#define CLEAR_OUT_EP_INTR(__EPNUM__, __INTERRUPT__)         (USBx_OUTEP(__EPNUM__)->DOEPINT = (__INTERRUPT__))
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+/**
+  * @}
+  */
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup USB_LL_Exported_Functions USB Low Layer Exported Functions
+  * @{
+  */
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg);
+HAL_StatusTypeDef USB_DevInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg);
+HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_SetTurnaroundTime(USB_OTG_GlobalTypeDef *USBx, uint32_t hclk, uint8_t speed);
+HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx, USB_OTG_ModeTypeDef mode);
+HAL_StatusTypeDef USB_SetDevSpeed(const USB_OTG_GlobalTypeDef *USBx, uint8_t speed);
+HAL_StatusTypeDef USB_FlushRxFifo(USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_FlushTxFifo(USB_OTG_GlobalTypeDef *USBx, uint32_t num);
+HAL_StatusTypeDef USB_ActivateEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep);
+HAL_StatusTypeDef USB_DeactivateEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep);
+HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep);
+HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep);
+HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep, uint8_t dma);
+HAL_StatusTypeDef USB_WritePacket(const USB_OTG_GlobalTypeDef *USBx, uint8_t *src,
+                                  uint8_t ch_ep_num, uint16_t len, uint8_t dma);
+
+void             *USB_ReadPacket(const USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len);
+HAL_StatusTypeDef USB_EPSetStall(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep);
+HAL_StatusTypeDef USB_EPClearStall(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep);
+HAL_StatusTypeDef USB_EPStopXfer(const USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep);
+HAL_StatusTypeDef USB_SetDevAddress(const USB_OTG_GlobalTypeDef *USBx, uint8_t address);
+HAL_StatusTypeDef USB_DevConnect(const USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_DevDisconnect(const USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_ActivateSetup(const USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_EP0_OutStart(const USB_OTG_GlobalTypeDef *USBx, uint8_t dma, const uint8_t *psetup);
+uint8_t           USB_GetDevSpeed(const USB_OTG_GlobalTypeDef *USBx);
+uint32_t          USB_GetMode(const USB_OTG_GlobalTypeDef *USBx);
+uint32_t          USB_ReadInterrupts(USB_OTG_GlobalTypeDef const *USBx);
+uint32_t          USB_ReadChInterrupts(const USB_OTG_GlobalTypeDef *USBx, uint8_t chnum);
+uint32_t          USB_ReadDevAllOutEpInterrupt(const USB_OTG_GlobalTypeDef *USBx);
+uint32_t          USB_ReadDevOutEPInterrupt(const USB_OTG_GlobalTypeDef *USBx, uint8_t epnum);
+uint32_t          USB_ReadDevAllInEpInterrupt(const USB_OTG_GlobalTypeDef *USBx);
+uint32_t          USB_ReadDevInEPInterrupt(const USB_OTG_GlobalTypeDef *USBx, uint8_t epnum);
+void              USB_ClearInterrupts(USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt);
+
+HAL_StatusTypeDef USB_HostInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg);
+HAL_StatusTypeDef USB_InitFSLSPClkSel(const USB_OTG_GlobalTypeDef *USBx, uint8_t freq);
+HAL_StatusTypeDef USB_ResetPort(const USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_DriveVbus(const USB_OTG_GlobalTypeDef *USBx, uint8_t state);
+uint32_t          USB_GetHostSpeed(USB_OTG_GlobalTypeDef const *USBx);
+uint32_t          USB_GetCurrentFrame(USB_OTG_GlobalTypeDef const *USBx);
+HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num,
+                              uint8_t epnum, uint8_t dev_address, uint8_t speed,
+                              uint8_t ep_type, uint16_t mps);
+HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx,
+                                   USB_OTG_HCTypeDef *hc, uint8_t dma);
+
+uint32_t          USB_HC_ReadInterrupt(const USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_HC_Halt(const USB_OTG_GlobalTypeDef *USBx, uint8_t hc_num);
+HAL_StatusTypeDef USB_DoPing(const USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num);
+HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_ActivateRemoteWakeup(const USB_OTG_GlobalTypeDef *USBx);
+HAL_StatusTypeDef USB_DeActivateRemoteWakeup(const USB_OTG_GlobalTypeDef *USBx);
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* STM32F4xx_LL_USB_H */

+ 2395 - 0
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c

@@ -0,0 +1,2395 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_hal_pcd.c
+  * @author  MCD Application Team
+  * @brief   PCD HAL module driver.
+  *          This file provides firmware functions to manage the following
+  *          functionalities of the USB Peripheral Controller:
+  *           + Initialization and de-initialization functions
+  *           + IO operation functions
+  *           + Peripheral Control functions
+  *           + Peripheral State functions
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  @verbatim
+  ==============================================================================
+                    ##### How to use this driver #####
+  ==============================================================================
+    [..]
+      The PCD HAL driver can be used as follows:
+
+     (#) Declare a PCD_HandleTypeDef handle structure, for example:
+         PCD_HandleTypeDef  hpcd;
+
+     (#) Fill parameters of Init structure in HCD handle
+
+     (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
+
+     (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
+         (##) Enable the PCD/USB Low Level interface clock using
+              (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
+              (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
+
+         (##) Initialize the related GPIO clocks
+         (##) Configure PCD pin-out
+         (##) Configure PCD NVIC interrupt
+
+     (#)Associate the Upper USB device stack to the HAL PCD Driver:
+         (##) hpcd.pData = pdev;
+
+     (#)Enable PCD transmission and reception:
+         (##) HAL_PCD_Start();
+
+  @endverbatim
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal.h"
+
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup PCD PCD
+  * @brief PCD HAL module driver
+  * @{
+  */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup PCD_Private_Macros PCD Private Macros
+  * @{
+  */
+#define PCD_MIN(a, b)  (((a) < (b)) ? (a) : (b))
+#define PCD_MAX(a, b)  (((a) > (b)) ? (a) : (b))
+/**
+  * @}
+  */
+
+/* Private functions prototypes ----------------------------------------------*/
+/** @defgroup PCD_Private_Functions PCD Private Functions
+  * @{
+  */
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
+static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
+static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+/**
+  * @}
+  */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup PCD_Exported_Functions PCD Exported Functions
+  * @{
+  */
+
+/** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
+  *  @brief    Initialization and Configuration functions
+  *
+@verbatim
+ ===============================================================================
+            ##### Initialization and de-initialization functions #####
+ ===============================================================================
+    [..]  This section provides functions allowing to:
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Initializes the PCD according to the specified
+  *         parameters in the PCD_InitTypeDef and initialize the associated handle.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
+{
+#if defined (USB_OTG_FS)
+  const USB_OTG_GlobalTypeDef *USBx;
+#endif /* defined (USB_OTG_FS) */
+  uint8_t i;
+
+  /* Check the PCD handle allocation */
+  if (hpcd == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
+
+#if defined (USB_OTG_FS)
+  USBx = hpcd->Instance;
+#endif /* defined (USB_OTG_FS) */
+
+  if (hpcd->State == HAL_PCD_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    hpcd->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+    hpcd->SOFCallback = HAL_PCD_SOFCallback;
+    hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
+    hpcd->ResetCallback = HAL_PCD_ResetCallback;
+    hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
+    hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
+    hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
+    hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
+    hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
+    hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
+    hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
+    hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
+    hpcd->LPMCallback = HAL_PCDEx_LPM_Callback;
+    hpcd->BCDCallback = HAL_PCDEx_BCD_Callback;
+
+    if (hpcd->MspInitCallback == NULL)
+    {
+      hpcd->MspInitCallback = HAL_PCD_MspInit;
+    }
+
+    /* Init the low level hardware */
+    hpcd->MspInitCallback(hpcd);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+    HAL_PCD_MspInit(hpcd);
+#endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
+  }
+
+  hpcd->State = HAL_PCD_STATE_BUSY;
+
+#if defined (USB_OTG_FS)
+  /* Disable DMA mode for FS instance */
+  if (USBx == USB_OTG_FS)
+  {
+    hpcd->Init.dma_enable = 0U;
+  }
+#endif /* defined (USB_OTG_FS) */
+
+  /* Disable the Interrupts */
+  __HAL_PCD_DISABLE(hpcd);
+
+  /*Init the Core (common init.) */
+  if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK)
+  {
+    hpcd->State = HAL_PCD_STATE_ERROR;
+    return HAL_ERROR;
+  }
+
+  /* Force Device Mode */
+  if (USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE) != HAL_OK)
+  {
+    hpcd->State = HAL_PCD_STATE_ERROR;
+    return HAL_ERROR;
+  }
+
+  /* Init endpoints structures */
+  for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
+  {
+    /* Init ep structure */
+    hpcd->IN_ep[i].is_in = 1U;
+    hpcd->IN_ep[i].num = i;
+    hpcd->IN_ep[i].tx_fifo_num = i;
+    /* Control until ep is activated */
+    hpcd->IN_ep[i].type = EP_TYPE_CTRL;
+    hpcd->IN_ep[i].maxpacket = 0U;
+    hpcd->IN_ep[i].xfer_buff = 0U;
+    hpcd->IN_ep[i].xfer_len = 0U;
+  }
+
+  for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
+  {
+    hpcd->OUT_ep[i].is_in = 0U;
+    hpcd->OUT_ep[i].num = i;
+    /* Control until ep is activated */
+    hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
+    hpcd->OUT_ep[i].maxpacket = 0U;
+    hpcd->OUT_ep[i].xfer_buff = 0U;
+    hpcd->OUT_ep[i].xfer_len = 0U;
+  }
+
+  /* Init Device */
+  if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
+  {
+    hpcd->State = HAL_PCD_STATE_ERROR;
+    return HAL_ERROR;
+  }
+
+  hpcd->USB_Address = 0U;
+  hpcd->State = HAL_PCD_STATE_READY;
+#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) \
+ || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) \
+ || defined(STM32F423xx)
+  /* Activate LPM */
+  if (hpcd->Init.lpm_enable == 1U)
+  {
+    (void)HAL_PCDEx_ActivateLPM(hpcd);
+  }
+#endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||
+          defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) ||
+          defined(STM32F423xx) */
+  (void)USB_DevDisconnect(hpcd->Instance);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the PCD peripheral.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
+{
+  /* Check the PCD handle allocation */
+  if (hpcd == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  hpcd->State = HAL_PCD_STATE_BUSY;
+
+  /* Stop Device */
+  if (USB_StopDevice(hpcd->Instance) != HAL_OK)
+  {
+    return HAL_ERROR;
+  }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+  if (hpcd->MspDeInitCallback == NULL)
+  {
+    hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit  */
+  }
+
+  /* DeInit the low level hardware */
+  hpcd->MspDeInitCallback(hpcd);
+#else
+  /* DeInit the low level hardware: CLOCK, NVIC.*/
+  HAL_PCD_MspDeInit(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+  hpcd->State = HAL_PCD_STATE_RESET;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the PCD MSP.
+  * @param  hpcd PCD handle
+  * @retval None
+  */
+__weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes PCD MSP.
+  * @param  hpcd PCD handle
+  * @retval None
+  */
+__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_MspDeInit could be implemented in the user file
+   */
+}
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+/**
+  * @brief  Register a User USB PCD Callback
+  *         To be used instead of the weak predefined callback
+  * @param  hpcd USB PCD handle
+  * @param  CallbackID ID of the callback to be registered
+  *         This parameter can be one of the following values:
+  *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
+  *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
+  *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
+  *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
+  *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
+  *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
+  *          @arg @ref HAL_PCD_DISCONNECT_CB_ID USB PCD Disconnect callback ID
+  *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
+  *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
+  * @param  pCallback pointer to the Callback function
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
+                                           HAL_PCD_CallbackIDTypeDef CallbackID,
+                                           pPCD_CallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+    return HAL_ERROR;
+  }
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    switch (CallbackID)
+    {
+      case HAL_PCD_SOF_CB_ID :
+        hpcd->SOFCallback = pCallback;
+        break;
+
+      case HAL_PCD_SETUPSTAGE_CB_ID :
+        hpcd->SetupStageCallback = pCallback;
+        break;
+
+      case HAL_PCD_RESET_CB_ID :
+        hpcd->ResetCallback = pCallback;
+        break;
+
+      case HAL_PCD_SUSPEND_CB_ID :
+        hpcd->SuspendCallback = pCallback;
+        break;
+
+      case HAL_PCD_RESUME_CB_ID :
+        hpcd->ResumeCallback = pCallback;
+        break;
+
+      case HAL_PCD_CONNECT_CB_ID :
+        hpcd->ConnectCallback = pCallback;
+        break;
+
+      case HAL_PCD_DISCONNECT_CB_ID :
+        hpcd->DisconnectCallback = pCallback;
+        break;
+
+      case HAL_PCD_MSPINIT_CB_ID :
+        hpcd->MspInitCallback = pCallback;
+        break;
+
+      case HAL_PCD_MSPDEINIT_CB_ID :
+        hpcd->MspDeInitCallback = pCallback;
+        break;
+
+      default :
+        /* Update the error code */
+        hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+        /* Return error status */
+        status =  HAL_ERROR;
+        break;
+    }
+  }
+  else if (hpcd->State == HAL_PCD_STATE_RESET)
+  {
+    switch (CallbackID)
+    {
+      case HAL_PCD_MSPINIT_CB_ID :
+        hpcd->MspInitCallback = pCallback;
+        break;
+
+      case HAL_PCD_MSPDEINIT_CB_ID :
+        hpcd->MspDeInitCallback = pCallback;
+        break;
+
+      default :
+        /* Update the error code */
+        hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+        /* Return error status */
+        status =  HAL_ERROR;
+        break;
+    }
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+  return status;
+}
+
+/**
+  * @brief  Unregister an USB PCD Callback
+  *         USB PCD callback is redirected to the weak predefined callback
+  * @param  hpcd USB PCD handle
+  * @param  CallbackID ID of the callback to be unregistered
+  *         This parameter can be one of the following values:
+  *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
+  *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
+  *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
+  *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
+  *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
+  *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
+  *          @arg @ref HAL_PCD_DISCONNECT_CB_ID USB PCD Disconnect callback ID
+  *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
+  *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  /* Setup Legacy weak Callbacks  */
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    switch (CallbackID)
+    {
+      case HAL_PCD_SOF_CB_ID :
+        hpcd->SOFCallback = HAL_PCD_SOFCallback;
+        break;
+
+      case HAL_PCD_SETUPSTAGE_CB_ID :
+        hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
+        break;
+
+      case HAL_PCD_RESET_CB_ID :
+        hpcd->ResetCallback = HAL_PCD_ResetCallback;
+        break;
+
+      case HAL_PCD_SUSPEND_CB_ID :
+        hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
+        break;
+
+      case HAL_PCD_RESUME_CB_ID :
+        hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
+        break;
+
+      case HAL_PCD_CONNECT_CB_ID :
+        hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
+        break;
+
+      case HAL_PCD_DISCONNECT_CB_ID :
+        hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
+        break;
+
+      case HAL_PCD_MSPINIT_CB_ID :
+        hpcd->MspInitCallback = HAL_PCD_MspInit;
+        break;
+
+      case HAL_PCD_MSPDEINIT_CB_ID :
+        hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
+        break;
+
+      default :
+        /* Update the error code */
+        hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+        /* Return error status */
+        status =  HAL_ERROR;
+        break;
+    }
+  }
+  else if (hpcd->State == HAL_PCD_STATE_RESET)
+  {
+    switch (CallbackID)
+    {
+      case HAL_PCD_MSPINIT_CB_ID :
+        hpcd->MspInitCallback = HAL_PCD_MspInit;
+        break;
+
+      case HAL_PCD_MSPDEINIT_CB_ID :
+        hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
+        break;
+
+      default :
+        /* Update the error code */
+        hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+        /* Return error status */
+        status =  HAL_ERROR;
+        break;
+    }
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+  return status;
+}
+
+/**
+  * @brief  Register USB PCD Data OUT Stage Callback
+  *         To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
+  * @param  hpcd PCD handle
+  * @param  pCallback pointer to the USB PCD Data OUT Stage Callback function
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
+                                                       pPCD_DataOutStageCallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    return HAL_ERROR;
+  }
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->DataOutStageCallback = pCallback;
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Unregister the USB PCD Data OUT Stage Callback
+  *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback  */
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Register USB PCD Data IN Stage Callback
+  *         To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
+  * @param  hpcd PCD handle
+  * @param  pCallback pointer to the USB PCD Data IN Stage Callback function
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
+                                                      pPCD_DataInStageCallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    return HAL_ERROR;
+  }
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->DataInStageCallback = pCallback;
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Unregister the USB PCD Data IN Stage Callback
+  *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback  */
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Register USB PCD Iso OUT incomplete Callback
+  *         To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
+  * @param  hpcd PCD handle
+  * @param  pCallback pointer to the USB PCD Iso OUT incomplete Callback function
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
+                                                       pPCD_IsoOutIncpltCallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    return HAL_ERROR;
+  }
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->ISOOUTIncompleteCallback = pCallback;
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Unregister the USB PCD Iso OUT incomplete Callback
+  *         USB PCD Iso OUT incomplete Callback is redirected
+  *         to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback  */
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Register USB PCD Iso IN incomplete Callback
+  *         To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
+  * @param  hpcd PCD handle
+  * @param  pCallback pointer to the USB PCD Iso IN incomplete Callback function
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
+                                                      pPCD_IsoInIncpltCallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    return HAL_ERROR;
+  }
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->ISOINIncompleteCallback = pCallback;
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Unregister the USB PCD Iso IN incomplete Callback
+  *         USB PCD Iso IN incomplete Callback is redirected
+  *         to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback  */
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Register USB PCD BCD Callback
+  *         To be used instead of the weak HAL_PCDEx_BCD_Callback() predefined callback
+  * @param  hpcd PCD handle
+  * @param  pCallback pointer to the USB PCD BCD Callback function
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd, pPCD_BcdCallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    return HAL_ERROR;
+  }
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->BCDCallback = pCallback;
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Unregister the USB PCD BCD Callback
+  *         USB BCD Callback is redirected to the weak HAL_PCDEx_BCD_Callback() predefined callback
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->BCDCallback = HAL_PCDEx_BCD_Callback; /* Legacy weak HAL_PCDEx_BCD_Callback  */
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Register USB PCD LPM Callback
+  *         To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback
+  * @param  hpcd PCD handle
+  * @param  pCallback pointer to the USB PCD LPM Callback function
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd, pPCD_LpmCallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    return HAL_ERROR;
+  }
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->LPMCallback = pCallback;
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+
+/**
+  * @brief  Unregister the USB PCD LPM Callback
+  *         USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Process locked */
+  __HAL_LOCK(hpcd);
+
+  if (hpcd->State == HAL_PCD_STATE_READY)
+  {
+    hpcd->LPMCallback = HAL_PCDEx_LPM_Callback; /* Legacy weak HAL_PCDEx_LPM_Callback  */
+  }
+  else
+  {
+    /* Update the error code */
+    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hpcd);
+
+  return status;
+}
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+
+/** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
+  *  @brief   Data transfers functions
+  *
+@verbatim
+ ===============================================================================
+                      ##### IO operation functions #####
+ ===============================================================================
+    [..]
+    This subsection provides a set of functions allowing to manage the PCD data
+    transfers.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Start the USB device
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+  __HAL_LOCK(hpcd);
+
+  if (((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) != 0U) &&
+      (hpcd->Init.battery_charging_enable == 1U))
+  {
+    /* Enable USB Transceiver */
+    USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
+  }
+
+  __HAL_PCD_ENABLE(hpcd);
+  (void)USB_DevConnect(hpcd->Instance);
+  __HAL_UNLOCK(hpcd);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stop the USB device.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+  __HAL_LOCK(hpcd);
+  __HAL_PCD_DISABLE(hpcd);
+  (void)USB_DevDisconnect(hpcd->Instance);
+
+  (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
+
+  if (((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) != 0U) &&
+      (hpcd->Init.battery_charging_enable == 1U))
+  {
+    /* Disable USB Transceiver */
+    USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
+  }
+
+  __HAL_UNLOCK(hpcd);
+
+  return HAL_OK;
+}
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/**
+  * @brief  Handles PCD interrupt request.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  USB_OTG_EPTypeDef *ep;
+  uint32_t i;
+  uint32_t ep_intr;
+  uint32_t epint;
+  uint32_t epnum;
+  uint32_t fifoemptymsk;
+  uint32_t RegVal;
+
+  /* ensure that we are in device mode */
+  if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
+  {
+    /* avoid spurious interrupt */
+    if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
+    {
+      return;
+    }
+
+    /* store current frame number */
+    hpcd->FrameNumber = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF_Msk) >> USB_OTG_DSTS_FNSOF_Pos;
+
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
+    {
+      /* incorrect mode, acknowledge the interrupt */
+      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
+    }
+
+    /* Handle RxQLevel Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
+    {
+      USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+
+      RegVal = USBx->GRXSTSP;
+
+      ep = &hpcd->OUT_ep[RegVal & USB_OTG_GRXSTSP_EPNUM];
+
+      if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT)
+      {
+        if ((RegVal & USB_OTG_GRXSTSP_BCNT) != 0U)
+        {
+          (void)USB_ReadPacket(USBx, ep->xfer_buff,
+                               (uint16_t)((RegVal & USB_OTG_GRXSTSP_BCNT) >> 4));
+
+          ep->xfer_buff += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
+          ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
+        }
+      }
+      else if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
+      {
+        (void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
+        ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
+      }
+      else
+      {
+        /* ... */
+      }
+
+      USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+    }
+
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
+    {
+      epnum = 0U;
+
+      /* Read in the device interrupt bits */
+      ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
+
+      while (ep_intr != 0U)
+      {
+        if ((ep_intr & 0x1U) != 0U)
+        {
+          epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
+
+          if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
+          {
+            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
+            (void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
+          }
+
+          if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
+          {
+            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
+            /* Class B setup phase done for previous decoded setup */
+            (void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
+          }
+
+          if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
+          {
+            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
+          }
+
+          /* Clear OUT Endpoint disable interrupt */
+          if ((epint & USB_OTG_DOEPINT_EPDISD) == USB_OTG_DOEPINT_EPDISD)
+          {
+            if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == USB_OTG_GINTSTS_BOUTNAKEFF)
+            {
+              USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK;
+            }
+
+            ep = &hpcd->OUT_ep[epnum];
+
+            if (ep->is_iso_incomplete == 1U)
+            {
+              ep->is_iso_incomplete = 0U;
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+              hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
+#else
+              HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+            }
+
+            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_EPDISD);
+          }
+
+          /* Clear Status Phase Received interrupt */
+          if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
+          {
+            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
+          }
+
+          /* Clear OUT NAK interrupt */
+          if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
+          {
+            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
+          }
+        }
+        epnum++;
+        ep_intr >>= 1U;
+      }
+    }
+
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
+    {
+      /* Read in the device interrupt bits */
+      ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
+
+      epnum = 0U;
+
+      while (ep_intr != 0U)
+      {
+        if ((ep_intr & 0x1U) != 0U) /* In ITR */
+        {
+          epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
+
+          if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
+          {
+            fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
+            USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
+
+            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
+
+            if (hpcd->Init.dma_enable == 1U)
+            {
+              hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;
+
+              /* this is ZLP, so prepare EP0 for next setup */
+              if ((epnum == 0U) && (hpcd->IN_ep[epnum].xfer_len == 0U))
+              {
+                /* prepare to rx more setup packets */
+                (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
+              }
+            }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+            hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
+#else
+            HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+          }
+          if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
+          {
+            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
+          }
+          if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
+          {
+            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
+          }
+          if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
+          {
+            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
+          }
+          if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
+          {
+            (void)USB_FlushTxFifo(USBx, epnum);
+
+            ep = &hpcd->IN_ep[epnum];
+
+            if (ep->is_iso_incomplete == 1U)
+            {
+              ep->is_iso_incomplete = 0U;
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+              hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
+#else
+              HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+            }
+
+            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
+          }
+          if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
+          {
+            (void)PCD_WriteEmptyTxFifo(hpcd, epnum);
+          }
+        }
+        epnum++;
+        ep_intr >>= 1U;
+      }
+    }
+
+    /* Handle Resume Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
+    {
+      /* Clear the Remote Wake-up Signaling */
+      USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
+
+      if (hpcd->LPM_State == LPM_L1)
+      {
+        hpcd->LPM_State = LPM_L0;
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+        hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
+#else
+        HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+      }
+      else
+      {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+        hpcd->ResumeCallback(hpcd);
+#else
+        HAL_PCD_ResumeCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+      }
+
+      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
+    }
+
+    /* Handle Suspend Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
+    {
+      if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
+      {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+        hpcd->SuspendCallback(hpcd);
+#else
+        HAL_PCD_SuspendCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+      }
+      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
+    }
+#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) \
+ || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) \
+ || defined(STM32F423xx)
+    /* Handle LPM Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT))
+    {
+      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);
+
+      if (hpcd->LPM_State == LPM_L0)
+      {
+        hpcd->LPM_State = LPM_L1;
+        hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >> 2U;
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+        hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
+#else
+        HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+      }
+      else
+      {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+        hpcd->SuspendCallback(hpcd);
+#else
+        HAL_PCD_SuspendCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+      }
+    }
+#endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||
+          defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) ||
+          defined(STM32F423xx) */
+    /* Handle Reset Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
+    {
+      USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
+      (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
+
+      for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
+      {
+        USBx_INEP(i)->DIEPINT = 0xFB7FU;
+        USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
+        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;
+
+      if (hpcd->Init.use_dedicated_ep1 != 0U)
+      {
+        USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
+                                   USB_OTG_DOEPMSK_XFRCM |
+                                   USB_OTG_DOEPMSK_EPDM;
+
+        USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
+                                  USB_OTG_DIEPMSK_XFRCM |
+                                  USB_OTG_DIEPMSK_EPDM;
+      }
+      else
+      {
+        USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
+                                USB_OTG_DOEPMSK_XFRCM |
+                                USB_OTG_DOEPMSK_EPDM |
+                                USB_OTG_DOEPMSK_OTEPSPRM |
+                                USB_OTG_DOEPMSK_NAKM;
+
+        USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
+                                USB_OTG_DIEPMSK_XFRCM |
+                                USB_OTG_DIEPMSK_EPDM;
+      }
+
+      /* Set Default Address to 0 */
+      USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
+
+      /* setup EP0 to receive SETUP packets */
+      (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable,
+                             (uint8_t *)hpcd->Setup);
+
+      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
+    }
+
+    /* Handle Enumeration done Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
+    {
+      (void)USB_ActivateSetup(hpcd->Instance);
+      hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
+
+      /* Set USB Turnaround time */
+      (void)USB_SetTurnaroundTime(hpcd->Instance,
+                                  HAL_RCC_GetHCLKFreq(),
+                                  (uint8_t)hpcd->Init.speed);
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+      hpcd->ResetCallback(hpcd);
+#else
+      HAL_PCD_ResetCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
+    }
+
+    /* Handle SOF Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
+    {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+      hpcd->SOFCallback(hpcd);
+#else
+      HAL_PCD_SOFCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
+    }
+
+    /* Handle Global OUT NAK effective Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_BOUTNAKEFF))
+    {
+      USBx->GINTMSK &= ~USB_OTG_GINTMSK_GONAKEFFM;
+
+      for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
+      {
+        if (hpcd->OUT_ep[epnum].is_iso_incomplete == 1U)
+        {
+          /* Abort current transaction and disable the EP */
+          (void)HAL_PCD_EP_Abort(hpcd, (uint8_t)epnum);
+        }
+      }
+    }
+
+    /* Handle Incomplete ISO IN Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
+    {
+      for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
+      {
+        RegVal = USBx_INEP(epnum)->DIEPCTL;
+
+        if ((hpcd->IN_ep[epnum].type == EP_TYPE_ISOC) &&
+            ((RegVal & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA))
+        {
+          hpcd->IN_ep[epnum].is_iso_incomplete = 1U;
+
+          /* Abort current transaction and disable the EP */
+          (void)HAL_PCD_EP_Abort(hpcd, (uint8_t)(epnum | 0x80U));
+        }
+      }
+
+      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
+    }
+
+    /* Handle Incomplete ISO OUT Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
+    {
+      for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
+      {
+        RegVal = USBx_OUTEP(epnum)->DOEPCTL;
+
+        if ((hpcd->OUT_ep[epnum].type == EP_TYPE_ISOC) &&
+            ((RegVal & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) &&
+            ((RegVal & (0x1U << 16)) == (hpcd->FrameNumber & 0x1U)))
+        {
+          hpcd->OUT_ep[epnum].is_iso_incomplete = 1U;
+
+          USBx->GINTMSK |= USB_OTG_GINTMSK_GONAKEFFM;
+
+          if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == 0U)
+          {
+            USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK;
+            break;
+          }
+        }
+      }
+
+      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
+    }
+
+    /* Handle Connection event Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
+    {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+      hpcd->ConnectCallback(hpcd);
+#else
+      HAL_PCD_ConnectCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
+    }
+
+    /* Handle Disconnection event Interrupt */
+    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
+    {
+      RegVal = hpcd->Instance->GOTGINT;
+
+      if ((RegVal & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
+      {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+        hpcd->DisconnectCallback(hpcd);
+#else
+        HAL_PCD_DisconnectCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+      }
+      hpcd->Instance->GOTGINT |= RegVal;
+    }
+  }
+}
+
+
+/**
+  * @brief  Handles PCD Wakeup interrupt request.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
+{
+#if defined (USB_OTG_FS)
+  USB_OTG_GlobalTypeDef *USBx;
+  USBx = hpcd->Instance;
+
+  if (USBx == USB_OTG_FS)
+  {
+    /* Clear EXTI pending Bit */
+    __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG();
+  }
+  else
+#endif /* defined (USB_OTG_FS) */
+  {
+    /* Clear EXTI pending Bit */
+    __HAL_USB_OTG_HS_WAKEUP_EXTI_CLEAR_FLAG();
+  }
+}
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+
+/**
+  * @brief  Data OUT stage callback.
+  * @param  hpcd PCD handle
+  * @param  epnum endpoint number
+  * @retval None
+  */
+__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+  UNUSED(epnum);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_DataOutStageCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Data IN stage callback
+  * @param  hpcd PCD handle
+  * @param  epnum endpoint number
+  * @retval None
+  */
+__weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+  UNUSED(epnum);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_DataInStageCallback could be implemented in the user file
+   */
+}
+/**
+  * @brief  Setup stage callback
+  * @param  hpcd PCD handle
+  * @retval None
+  */
+__weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_SetupStageCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  USB Start Of Frame callback.
+  * @param  hpcd PCD handle
+  * @retval None
+  */
+__weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_SOFCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  USB Reset callback.
+  * @param  hpcd PCD handle
+  * @retval None
+  */
+__weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_ResetCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Suspend event callback.
+  * @param  hpcd PCD handle
+  * @retval None
+  */
+__weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_SuspendCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Resume event callback.
+  * @param  hpcd PCD handle
+  * @retval None
+  */
+__weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_ResumeCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Incomplete ISO OUT callback.
+  * @param  hpcd PCD handle
+  * @param  epnum endpoint number
+  * @retval None
+  */
+__weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+  UNUSED(epnum);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Incomplete ISO IN callback.
+  * @param  hpcd PCD handle
+  * @param  epnum endpoint number
+  * @retval None
+  */
+__weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+  UNUSED(epnum);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Connection event callback.
+  * @param  hpcd PCD handle
+  * @retval None
+  */
+__weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_ConnectCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Disconnection event callback.
+  * @param  hpcd PCD handle
+  * @retval None
+  */
+__weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCD_DisconnectCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
+  *  @brief   management functions
+  *
+@verbatim
+ ===============================================================================
+                      ##### Peripheral Control functions #####
+ ===============================================================================
+    [..]
+    This subsection provides a set of functions allowing to control the PCD data
+    transfers.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Connect the USB device
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+  __HAL_LOCK(hpcd);
+
+  if (((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) != 0U) &&
+      (hpcd->Init.battery_charging_enable == 1U))
+  {
+    /* Enable USB Transceiver */
+    USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
+  }
+  (void)USB_DevConnect(hpcd->Instance);
+  __HAL_UNLOCK(hpcd);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Disconnect the USB device.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+  __HAL_LOCK(hpcd);
+  (void)USB_DevDisconnect(hpcd->Instance);
+
+  if (((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) != 0U) &&
+      (hpcd->Init.battery_charging_enable == 1U))
+  {
+    /* Disable USB Transceiver */
+    USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
+  }
+
+  __HAL_UNLOCK(hpcd);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Set the USB Device address.
+  * @param  hpcd PCD handle
+  * @param  address new device address
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
+{
+  __HAL_LOCK(hpcd);
+  hpcd->USB_Address = address;
+  (void)USB_SetDevAddress(hpcd->Instance, address);
+  __HAL_UNLOCK(hpcd);
+
+  return HAL_OK;
+}
+/**
+  * @brief  Open and configure an endpoint.
+  * @param  hpcd PCD handle
+  * @param  ep_addr endpoint address
+  * @param  ep_mps endpoint max packet size
+  * @param  ep_type endpoint type
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
+                                  uint16_t ep_mps, uint8_t ep_type)
+{
+  HAL_StatusTypeDef  ret = HAL_OK;
+  PCD_EPTypeDef *ep;
+
+  if ((ep_addr & 0x80U) == 0x80U)
+  {
+    ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+    ep->is_in = 1U;
+  }
+  else
+  {
+    ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
+    ep->is_in = 0U;
+  }
+
+  ep->num = ep_addr & EP_ADDR_MSK;
+  ep->maxpacket = ep_mps;
+  ep->type = ep_type;
+
+  if (ep->is_in != 0U)
+  {
+    /* Assign a Tx FIFO */
+    ep->tx_fifo_num = ep->num;
+  }
+
+  /* Set initial data PID. */
+  if (ep_type == EP_TYPE_BULK)
+  {
+    ep->data_pid_start = 0U;
+  }
+
+  __HAL_LOCK(hpcd);
+  (void)USB_ActivateEndpoint(hpcd->Instance, ep);
+  __HAL_UNLOCK(hpcd);
+
+  return ret;
+}
+
+/**
+  * @brief  Deactivate an endpoint.
+  * @param  hpcd PCD handle
+  * @param  ep_addr endpoint address
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+  PCD_EPTypeDef *ep;
+
+  if ((ep_addr & 0x80U) == 0x80U)
+  {
+    ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+    ep->is_in = 1U;
+  }
+  else
+  {
+    ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
+    ep->is_in = 0U;
+  }
+  ep->num = ep_addr & EP_ADDR_MSK;
+
+  __HAL_LOCK(hpcd);
+  (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
+  __HAL_UNLOCK(hpcd);
+  return HAL_OK;
+}
+
+
+/**
+  * @brief  Receive an amount of data.
+  * @param  hpcd PCD handle
+  * @param  ep_addr endpoint address
+  * @param  pBuf pointer to the reception buffer
+  * @param  len amount of data to be received
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
+{
+  PCD_EPTypeDef *ep;
+
+  ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
+
+  /*setup and start the Xfer */
+  ep->xfer_buff = pBuf;
+  ep->xfer_len = len;
+  ep->xfer_count = 0U;
+  ep->is_in = 0U;
+  ep->num = ep_addr & EP_ADDR_MSK;
+
+  if (hpcd->Init.dma_enable == 1U)
+  {
+    ep->dma_addr = (uint32_t)pBuf;
+  }
+
+  (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Get Received Data Size
+  * @param  hpcd PCD handle
+  * @param  ep_addr endpoint address
+  * @retval Data Size
+  */
+uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef const *hpcd, uint8_t ep_addr)
+{
+  return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
+}
+/**
+  * @brief  Send an amount of data
+  * @param  hpcd PCD handle
+  * @param  ep_addr endpoint address
+  * @param  pBuf pointer to the transmission buffer
+  * @param  len amount of data to be sent
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
+{
+  PCD_EPTypeDef *ep;
+
+  ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+
+  /*setup and start the Xfer */
+  ep->xfer_buff = pBuf;
+  ep->xfer_len = len;
+  ep->xfer_count = 0U;
+  ep->is_in = 1U;
+  ep->num = ep_addr & EP_ADDR_MSK;
+
+  if (hpcd->Init.dma_enable == 1U)
+  {
+    ep->dma_addr = (uint32_t)pBuf;
+  }
+
+  (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Set a STALL condition over an endpoint
+  * @param  hpcd PCD handle
+  * @param  ep_addr endpoint address
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+  PCD_EPTypeDef *ep;
+
+  if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
+  {
+    return HAL_ERROR;
+  }
+
+  if ((0x80U & ep_addr) == 0x80U)
+  {
+    ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+    ep->is_in = 1U;
+  }
+  else
+  {
+    ep = &hpcd->OUT_ep[ep_addr];
+    ep->is_in = 0U;
+  }
+
+  ep->is_stall = 1U;
+  ep->num = ep_addr & EP_ADDR_MSK;
+
+  __HAL_LOCK(hpcd);
+
+  (void)USB_EPSetStall(hpcd->Instance, ep);
+
+  if ((ep_addr & EP_ADDR_MSK) == 0U)
+  {
+    (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
+  }
+
+  __HAL_UNLOCK(hpcd);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Clear a STALL condition over in an endpoint
+  * @param  hpcd PCD handle
+  * @param  ep_addr endpoint address
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+  PCD_EPTypeDef *ep;
+
+  if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
+  {
+    return HAL_ERROR;
+  }
+
+  if ((0x80U & ep_addr) == 0x80U)
+  {
+    ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+    ep->is_in = 1U;
+  }
+  else
+  {
+    ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
+    ep->is_in = 0U;
+  }
+
+  ep->is_stall = 0U;
+  ep->num = ep_addr & EP_ADDR_MSK;
+
+  __HAL_LOCK(hpcd);
+  (void)USB_EPClearStall(hpcd->Instance, ep);
+  __HAL_UNLOCK(hpcd);
+
+  return HAL_OK;
+}
+
+/**
+   * @brief  Abort an USB EP transaction.
+   * @param  hpcd PCD handle
+   * @param  ep_addr endpoint address
+   * @retval HAL status
+   */
+HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+  HAL_StatusTypeDef ret;
+  PCD_EPTypeDef *ep;
+
+  if ((0x80U & ep_addr) == 0x80U)
+  {
+    ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+  }
+  else
+  {
+    ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
+  }
+
+  /* Stop Xfer */
+  ret = USB_EPStopXfer(hpcd->Instance, ep);
+
+  return ret;
+}
+
+/**
+  * @brief  Flush an endpoint
+  * @param  hpcd PCD handle
+  * @param  ep_addr endpoint address
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+  __HAL_LOCK(hpcd);
+
+  if ((ep_addr & 0x80U) == 0x80U)
+  {
+    (void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);
+  }
+  else
+  {
+    (void)USB_FlushRxFifo(hpcd->Instance);
+  }
+
+  __HAL_UNLOCK(hpcd);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Activate remote wakeup signalling
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
+{
+  return (USB_ActivateRemoteWakeup(hpcd->Instance));
+}
+
+/**
+  * @brief  De-activate remote wakeup signalling.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
+{
+  return (USB_DeActivateRemoteWakeup(hpcd->Instance));
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
+  *  @brief   Peripheral State functions
+  *
+@verbatim
+ ===============================================================================
+                      ##### Peripheral State functions #####
+ ===============================================================================
+    [..]
+    This subsection permits to get in run-time the status of the peripheral
+    and the data flow.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Return the PCD handle state.
+  * @param  hpcd PCD handle
+  * @retval HAL state
+  */
+PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef const *hpcd)
+{
+  return hpcd->State;
+}
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/**
+  * @brief  Set the USB Device high speed test mode.
+  * @param  hpcd PCD handle
+  * @param  testmode USB Device high speed test mode
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCD_SetTestMode(const PCD_HandleTypeDef *hpcd, uint8_t testmode)
+{
+  const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  switch (testmode)
+  {
+    case TEST_J:
+    case TEST_K:
+    case TEST_SE0_NAK:
+    case TEST_PACKET:
+    case TEST_FORCE_EN:
+      USBx_DEVICE->DCTL |= (uint32_t)testmode << 4;
+      break;
+
+    default:
+      break;
+  }
+
+  return HAL_OK;
+}
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Private functions ---------------------------------------------------------*/
+/** @addtogroup PCD_Private_Functions
+  * @{
+  */
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/**
+  * @brief  Check FIFO for the next packet to be loaded.
+  * @param  hpcd PCD handle
+  * @param  epnum endpoint number
+  * @retval HAL status
+  */
+static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  USB_OTG_EPTypeDef *ep;
+  uint32_t len;
+  uint32_t len32b;
+  uint32_t fifoemptymsk;
+
+  ep = &hpcd->IN_ep[epnum];
+
+  if (ep->xfer_count > ep->xfer_len)
+  {
+    return HAL_ERROR;
+  }
+
+  len = ep->xfer_len - ep->xfer_count;
+
+  if (len > ep->maxpacket)
+  {
+    len = ep->maxpacket;
+  }
+
+  len32b = (len + 3U) / 4U;
+
+  while (((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&
+         (ep->xfer_count < ep->xfer_len) && (ep->xfer_len != 0U))
+  {
+    /* Write the FIFO */
+    len = ep->xfer_len - ep->xfer_count;
+
+    if (len > ep->maxpacket)
+    {
+      len = ep->maxpacket;
+    }
+    len32b = (len + 3U) / 4U;
+
+    (void)USB_WritePacket(USBx, ep->xfer_buff, (uint8_t)epnum, (uint16_t)len,
+                          (uint8_t)hpcd->Init.dma_enable);
+
+    ep->xfer_buff  += len;
+    ep->xfer_count += len;
+  }
+
+  if (ep->xfer_len <= ep->xfer_count)
+  {
+    fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
+    USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
+  }
+
+  return HAL_OK;
+}
+
+
+/**
+  * @brief  process EP OUT transfer complete interrupt.
+  * @param  hpcd PCD handle
+  * @param  epnum endpoint number
+  * @retval HAL status
+  */
+static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
+{
+  USB_OTG_EPTypeDef *ep;
+  const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
+  uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
+
+  if (hpcd->Init.dma_enable == 1U)
+  {
+    if ((DoepintReg & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) /* Class C */
+    {
+      /* StupPktRcvd = 1 this is a setup packet */
+      if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
+          ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
+      {
+        CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
+      }
+    }
+    else if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR) /* Class E */
+    {
+      CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
+    }
+    else if ((DoepintReg & (USB_OTG_DOEPINT_STUP | USB_OTG_DOEPINT_OTEPSPR)) == 0U)
+    {
+      /* StupPktRcvd = 1 this is a setup packet */
+      if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
+          ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
+      {
+        CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
+      }
+      else
+      {
+        ep = &hpcd->OUT_ep[epnum];
+
+        /* out data packet received over EP */
+        ep->xfer_count = ep->xfer_size - (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ);
+
+        if (epnum == 0U)
+        {
+          if (ep->xfer_len == 0U)
+          {
+            /* this is ZLP, so prepare EP0 for next setup */
+            (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
+          }
+          else
+          {
+            ep->xfer_buff += ep->xfer_count;
+          }
+        }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+        hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
+#else
+        HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+      }
+    }
+    else
+    {
+      /* ... */
+    }
+  }
+  else
+  {
+    if (gSNPSiD == USB_OTG_CORE_ID_310A)
+    {
+      /* StupPktRcvd = 1 this is a setup packet */
+      if ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)
+      {
+        CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
+      }
+      else
+      {
+        if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
+        {
+          CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
+        }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+        hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
+#else
+        HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+      }
+    }
+    else
+    {
+      if ((epnum == 0U) && (hpcd->OUT_ep[epnum].xfer_len == 0U))
+      {
+        /* this is ZLP, so prepare EP0 for next setup */
+        (void)USB_EP0_OutStart(hpcd->Instance, 0U, (uint8_t *)hpcd->Setup);
+      }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+      hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
+#else
+      HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+    }
+  }
+
+  return HAL_OK;
+}
+
+
+/**
+  * @brief  process EP OUT setup packet received interrupt.
+  * @param  hpcd PCD handle
+  * @param  epnum endpoint number
+  * @retval HAL status
+  */
+static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
+{
+  const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
+  uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
+
+  if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
+      ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
+  {
+    CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
+  }
+
+  /* Inform the upper layer that a setup packet is available */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+  hpcd->SetupStageCallback(hpcd);
+#else
+  HAL_PCD_SetupStageCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+  if ((gSNPSiD > USB_OTG_CORE_ID_300A) && (hpcd->Init.dma_enable == 1U))
+  {
+    (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
+  }
+
+  return HAL_OK;
+}
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+
+/**
+  * @}
+  */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 347 - 0
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c

@@ -0,0 +1,347 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_hal_pcd_ex.c
+  * @author  MCD Application Team
+  * @brief   PCD Extended HAL module driver.
+  *          This file provides firmware functions to manage the following
+  *          functionalities of the USB Peripheral Controller:
+  *           + Extended features functions
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal.h"
+
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup PCDEx PCDEx
+  * @brief PCD Extended HAL module driver
+  * @{
+  */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup PCDEx_Exported_Functions PCDEx Exported Functions
+  * @{
+  */
+
+/** @defgroup PCDEx_Exported_Functions_Group1 Peripheral Control functions
+  * @brief    PCDEx control functions
+  *
+@verbatim
+ ===============================================================================
+                 ##### Extended features functions #####
+ ===============================================================================
+    [..]  This section provides functions allowing to:
+      (+) Update FIFO configuration
+
+@endverbatim
+  * @{
+  */
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/**
+  * @brief  Set Tx FIFO
+  * @param  hpcd PCD handle
+  * @param  fifo The number of Tx fifo
+  * @param  size Fifo size
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, 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 = hpcd->Instance->GRXFSIZ;
+
+  if (fifo == 0U)
+  {
+    hpcd->Instance->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset;
+  }
+  else
+  {
+    Tx_Offset += (hpcd->Instance->DIEPTXF0_HNPTXFSIZ) >> 16;
+    for (i = 0U; i < (fifo - 1U); i++)
+    {
+      Tx_Offset += (hpcd->Instance->DIEPTXF[i] >> 16);
+    }
+
+    /* Multiply Tx_Size by 2 to get higher performance */
+    hpcd->Instance->DIEPTXF[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset;
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Set Rx FIFO
+  * @param  hpcd PCD handle
+  * @param  size Size of Rx fifo
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size)
+{
+  hpcd->Instance->GRXFSIZ = size;
+
+  return HAL_OK;
+}
+#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) \
+ || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) \
+ || defined(STM32F423xx)
+/**
+  * @brief  Activate LPM feature.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+  hpcd->lpm_active = 1U;
+  hpcd->LPM_State = LPM_L0;
+  USBx->GINTMSK |= USB_OTG_GINTMSK_LPMINTM;
+  USBx->GLPMCFG |= (USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Deactivate LPM feature.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+  hpcd->lpm_active = 0U;
+  USBx->GINTMSK &= ~USB_OTG_GINTMSK_LPMINTM;
+  USBx->GLPMCFG &= ~(USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL);
+
+  return HAL_OK;
+}
+#endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||
+          defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) ||
+          defined(STM32F423xx) */
+#if defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) \
+ || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
+/**
+  * @brief  Handle BatteryCharging Process.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+  uint32_t tickstart = HAL_GetTick();
+
+  /* Enable DCD : Data Contact Detect */
+  USBx->GCCFG |= USB_OTG_GCCFG_DCDEN;
+
+  /* Wait for Min DCD Timeout */
+  HAL_Delay(300U);
+
+  /* Check Detect flag */
+  if ((USBx->GCCFG & USB_OTG_GCCFG_DCDET) == USB_OTG_GCCFG_DCDET)
+  {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+    hpcd->BCDCallback(hpcd, PCD_BCD_CONTACT_DETECTION);
+#else
+    HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+  }
+
+  /* Primary detection: checks if connected to Standard Downstream Port
+  (without charging capability) */
+  USBx->GCCFG &= ~USB_OTG_GCCFG_DCDEN;
+  HAL_Delay(50U);
+  USBx->GCCFG |= USB_OTG_GCCFG_PDEN;
+  HAL_Delay(50U);
+
+  if ((USBx->GCCFG & USB_OTG_GCCFG_PDET) == 0U)
+  {
+    /* Case of Standard Downstream Port */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+    hpcd->BCDCallback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
+#else
+    HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+  }
+  else
+  {
+    /* start secondary detection to check connection to Charging Downstream
+    Port or Dedicated Charging Port */
+    USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
+    HAL_Delay(50U);
+    USBx->GCCFG |= USB_OTG_GCCFG_SDEN;
+    HAL_Delay(50U);
+
+    if ((USBx->GCCFG & USB_OTG_GCCFG_SDET) == USB_OTG_GCCFG_SDET)
+    {
+      /* case Dedicated Charging Port  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+      hpcd->BCDCallback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
+#else
+      HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+    }
+    else
+    {
+      /* case Charging Downstream Port */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+      hpcd->BCDCallback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
+#else
+      HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+    }
+  }
+
+  /* Battery Charging capability discovery finished */
+  (void)HAL_PCDEx_DeActivateBCD(hpcd);
+
+  /* Check for the Timeout, else start USB Device */
+  if ((HAL_GetTick() - tickstart) > 1000U)
+  {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+    hpcd->BCDCallback(hpcd, PCD_BCD_ERROR);
+#else
+    HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+  }
+  else
+  {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+    hpcd->BCDCallback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
+#else
+    HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+  }
+}
+
+/**
+  * @brief  Activate BatteryCharging feature.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+  USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
+  USBx->GCCFG &= ~(USB_OTG_GCCFG_SDEN);
+
+  /* Power Down USB transceiver  */
+  USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
+
+  /* Enable Battery charging */
+  USBx->GCCFG |= USB_OTG_GCCFG_BCDEN;
+
+  hpcd->battery_charging_active = 1U;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Deactivate BatteryCharging feature.
+  * @param  hpcd PCD handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+  USBx->GCCFG &= ~(USB_OTG_GCCFG_SDEN);
+  USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
+
+  /* Disable Battery charging */
+  USBx->GCCFG &= ~(USB_OTG_GCCFG_BCDEN);
+
+  hpcd->battery_charging_active = 0U;
+
+  return HAL_OK;
+}
+#endif /* defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) ||
+          defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+/**
+  * @brief  Send LPM message to user layer callback.
+  * @param  hpcd PCD handle
+  * @param  msg LPM message
+  * @retval HAL status
+  */
+__weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+  UNUSED(msg);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCDEx_LPM_Callback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Send BatteryCharging message to user layer callback.
+  * @param  hpcd PCD handle
+  * @param  msg LPM message
+  * @retval HAL status
+  */
+__weak void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hpcd);
+  UNUSED(msg);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_PCDEx_BCD_Callback could be implemented in the user file
+   */
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 7632 - 0
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c

@@ -0,0 +1,7632 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_hal_tim.c
+  * @author  MCD Application Team
+  * @brief   TIM HAL module driver.
+  *          This file provides firmware functions to manage the following
+  *          functionalities of the Timer (TIM) peripheral:
+  *           + TIM Time Base Initialization
+  *           + TIM Time Base Start
+  *           + TIM Time Base Start Interruption
+  *           + TIM Time Base Start DMA
+  *           + TIM Output Compare/PWM Initialization
+  *           + TIM Output Compare/PWM Channel Configuration
+  *           + TIM Output Compare/PWM  Start
+  *           + TIM Output Compare/PWM  Start Interruption
+  *           + TIM Output Compare/PWM Start DMA
+  *           + TIM Input Capture Initialization
+  *           + TIM Input Capture Channel Configuration
+  *           + TIM Input Capture Start
+  *           + TIM Input Capture Start Interruption
+  *           + TIM Input Capture Start DMA
+  *           + TIM One Pulse Initialization
+  *           + TIM One Pulse Channel Configuration
+  *           + TIM One Pulse Start
+  *           + TIM Encoder Interface Initialization
+  *           + TIM Encoder Interface Start
+  *           + TIM Encoder Interface Start Interruption
+  *           + TIM Encoder Interface Start DMA
+  *           + Commutation Event configuration with Interruption and DMA
+  *           + TIM OCRef clear configuration
+  *           + TIM External Clock configuration
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  @verbatim
+  ==============================================================================
+                      ##### TIMER Generic features #####
+  ==============================================================================
+  [..] The Timer features include:
+       (#) 16-bit up, down, up/down auto-reload counter.
+       (#) 16-bit programmable prescaler allowing dividing (also on the fly) the
+           counter clock frequency either by any factor between 1 and 65536.
+       (#) Up to 4 independent channels for:
+           (++) Input Capture
+           (++) Output Compare
+           (++) PWM generation (Edge and Center-aligned Mode)
+           (++) One-pulse mode output
+       (#) Synchronization circuit to control the timer with external signals and to interconnect
+            several timers together.
+       (#) Supports incremental encoder for positioning purposes
+
+            ##### How to use this driver #####
+  ==============================================================================
+    [..]
+     (#) Initialize the TIM low level resources by implementing the following functions
+         depending on the selected feature:
+           (++) Time Base : HAL_TIM_Base_MspInit()
+           (++) Input Capture : HAL_TIM_IC_MspInit()
+           (++) Output Compare : HAL_TIM_OC_MspInit()
+           (++) PWM generation : HAL_TIM_PWM_MspInit()
+           (++) One-pulse mode output : HAL_TIM_OnePulse_MspInit()
+           (++) Encoder mode output : HAL_TIM_Encoder_MspInit()
+
+     (#) Initialize the TIM low level resources :
+        (##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE();
+        (##) TIM pins configuration
+            (+++) Enable the clock for the TIM GPIOs using the following function:
+             __HAL_RCC_GPIOx_CLK_ENABLE();
+            (+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init();
+
+     (#) The external Clock can be configured, if needed (the default clock is the
+         internal clock from the APBx), using the following function:
+         HAL_TIM_ConfigClockSource, the clock configuration should be done before
+         any start function.
+
+     (#) Configure the TIM in the desired functioning mode using one of the
+       Initialization function of this driver:
+       (++) HAL_TIM_Base_Init: to use the Timer to generate a simple time base
+       (++) HAL_TIM_OC_Init and HAL_TIM_OC_ConfigChannel: to use the Timer to generate an
+            Output Compare signal.
+       (++) HAL_TIM_PWM_Init and HAL_TIM_PWM_ConfigChannel: to use the Timer to generate a
+            PWM signal.
+       (++) HAL_TIM_IC_Init and HAL_TIM_IC_ConfigChannel: to use the Timer to measure an
+            external signal.
+       (++) HAL_TIM_OnePulse_Init and HAL_TIM_OnePulse_ConfigChannel: to use the Timer
+            in One Pulse Mode.
+       (++) HAL_TIM_Encoder_Init: to use the Timer Encoder Interface.
+
+     (#) Activate the TIM peripheral using one of the start functions depending from the feature used:
+           (++) Time Base : HAL_TIM_Base_Start(), HAL_TIM_Base_Start_DMA(), HAL_TIM_Base_Start_IT()
+           (++) Input Capture :  HAL_TIM_IC_Start(), HAL_TIM_IC_Start_DMA(), HAL_TIM_IC_Start_IT()
+           (++) Output Compare : HAL_TIM_OC_Start(), HAL_TIM_OC_Start_DMA(), HAL_TIM_OC_Start_IT()
+           (++) PWM generation : HAL_TIM_PWM_Start(), HAL_TIM_PWM_Start_DMA(), HAL_TIM_PWM_Start_IT()
+           (++) One-pulse mode output : HAL_TIM_OnePulse_Start(), HAL_TIM_OnePulse_Start_IT()
+           (++) Encoder mode output : HAL_TIM_Encoder_Start(), HAL_TIM_Encoder_Start_DMA(), HAL_TIM_Encoder_Start_IT().
+
+     (#) The DMA Burst is managed with the two following functions:
+         HAL_TIM_DMABurst_WriteStart()
+         HAL_TIM_DMABurst_ReadStart()
+
+    *** Callback registration ***
+  =============================================
+
+  [..]
+  The compilation define  USE_HAL_TIM_REGISTER_CALLBACKS when set to 1
+  allows the user to configure dynamically the driver callbacks.
+
+  [..]
+  Use Function HAL_TIM_RegisterCallback() to register a callback.
+  HAL_TIM_RegisterCallback() takes as parameters the HAL peripheral handle,
+  the Callback ID and a pointer to the user callback function.
+
+  [..]
+  Use function HAL_TIM_UnRegisterCallback() to reset a callback to the default
+  weak function.
+  HAL_TIM_UnRegisterCallback takes as parameters the HAL peripheral handle,
+  and the Callback ID.
+
+  [..]
+  These functions allow to register/unregister following callbacks:
+    (+) Base_MspInitCallback              : TIM Base Msp Init Callback.
+    (+) Base_MspDeInitCallback            : TIM Base Msp DeInit Callback.
+    (+) IC_MspInitCallback                : TIM IC Msp Init Callback.
+    (+) IC_MspDeInitCallback              : TIM IC Msp DeInit Callback.
+    (+) OC_MspInitCallback                : TIM OC Msp Init Callback.
+    (+) OC_MspDeInitCallback              : TIM OC Msp DeInit Callback.
+    (+) PWM_MspInitCallback               : TIM PWM Msp Init Callback.
+    (+) PWM_MspDeInitCallback             : TIM PWM Msp DeInit Callback.
+    (+) OnePulse_MspInitCallback          : TIM One Pulse Msp Init Callback.
+    (+) OnePulse_MspDeInitCallback        : TIM One Pulse Msp DeInit Callback.
+    (+) Encoder_MspInitCallback           : TIM Encoder Msp Init Callback.
+    (+) Encoder_MspDeInitCallback         : TIM Encoder Msp DeInit Callback.
+    (+) HallSensor_MspInitCallback        : TIM Hall Sensor Msp Init Callback.
+    (+) HallSensor_MspDeInitCallback      : TIM Hall Sensor Msp DeInit Callback.
+    (+) PeriodElapsedCallback             : TIM Period Elapsed Callback.
+    (+) PeriodElapsedHalfCpltCallback     : TIM Period Elapsed half complete Callback.
+    (+) TriggerCallback                   : TIM Trigger Callback.
+    (+) TriggerHalfCpltCallback           : TIM Trigger half complete Callback.
+    (+) IC_CaptureCallback                : TIM Input Capture Callback.
+    (+) IC_CaptureHalfCpltCallback        : TIM Input Capture half complete Callback.
+    (+) OC_DelayElapsedCallback           : TIM Output Compare Delay Elapsed Callback.
+    (+) PWM_PulseFinishedCallback         : TIM PWM Pulse Finished Callback.
+    (+) PWM_PulseFinishedHalfCpltCallback : TIM PWM Pulse Finished half complete Callback.
+    (+) ErrorCallback                     : TIM Error Callback.
+    (+) CommutationCallback               : TIM Commutation Callback.
+    (+) CommutationHalfCpltCallback       : TIM Commutation half complete Callback.
+    (+) BreakCallback                     : TIM Break Callback.
+
+  [..]
+By default, after the Init and when the state is HAL_TIM_STATE_RESET
+all interrupt callbacks are set to the corresponding weak functions:
+  examples HAL_TIM_TriggerCallback(), HAL_TIM_ErrorCallback().
+
+  [..]
+  Exception done for MspInit and MspDeInit functions that are reset to the legacy weak
+  functionalities in the Init / DeInit only when these callbacks are null
+  (not registered beforehand). If not, MspInit or MspDeInit are not null, the Init / DeInit
+    keep and use the user MspInit / MspDeInit callbacks(registered beforehand)
+
+  [..]
+    Callbacks can be registered / unregistered in HAL_TIM_STATE_READY state only.
+    Exception done MspInit / MspDeInit that can be registered / unregistered
+    in HAL_TIM_STATE_READY or HAL_TIM_STATE_RESET state,
+    thus registered(user) MspInit / DeInit callbacks can be used during the Init / DeInit.
+  In that case first register the MspInit/MspDeInit user callbacks
+      using HAL_TIM_RegisterCallback() before calling DeInit or Init function.
+
+  [..]
+      When The compilation define USE_HAL_TIM_REGISTER_CALLBACKS is set to 0 or
+      not defined, the callback registration feature is not available and all callbacks
+      are set to the corresponding weak functions.
+
+  @endverbatim
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal.h"
+
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup TIM TIM
+  * @brief TIM HAL module driver
+  * @{
+  */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup TIM_Private_Functions
+  * @{
+  */
+static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter);
+static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter);
+static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter);
+static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter);
+static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter);
+static void TIM_ITRx_SetConfig(TIM_TypeDef *TIMx, uint32_t InputTriggerSource);
+static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMAPeriodElapsedHalfCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMATriggerHalfCplt(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim,
+                                                  const TIM_SlaveConfigTypeDef *sSlaveConfig);
+/**
+  * @}
+  */
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup TIM_Exported_Functions TIM Exported Functions
+  * @{
+  */
+
+/** @defgroup TIM_Exported_Functions_Group1 TIM Time Base functions
+  *  @brief    Time Base functions
+  *
+@verbatim
+  ==============================================================================
+              ##### Time Base functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure the TIM base.
+    (+) De-initialize the TIM base.
+    (+) Start the Time Base.
+    (+) Stop the Time Base.
+    (+) Start the Time Base and enable interrupt.
+    (+) Stop the Time Base and disable interrupt.
+    (+) Start the Time Base and enable DMA transfer.
+    (+) Stop the Time Base and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM Time base Unit according to the specified
+  *         parameters in the TIM_HandleTypeDef and initialize the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_Base_DeInit() before HAL_TIM_Base_Init()
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)
+{
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->Base_MspInitCallback == NULL)
+    {
+      htim->Base_MspInitCallback = HAL_TIM_Base_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->Base_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    HAL_TIM_Base_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Set the Time Base configuration */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM Base peripheral
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->Base_MspDeInitCallback == NULL)
+  {
+    htim->Base_MspDeInitCallback = HAL_TIM_Base_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->Base_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+  HAL_TIM_Base_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Change the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM Base MSP.
+  * @param  htim TIM Base handle
+  * @retval None
+  */
+__weak void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_Base_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM Base MSP.
+  * @param  htim TIM Base handle
+  * @retval None
+  */
+__weak void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_Base_MspDeInit could be implemented in the user file
+   */
+}
+
+
+/**
+  * @brief  Starts the TIM Base generation.
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  /* Check the TIM state */
+  if (htim->State != HAL_TIM_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Base generation.
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Base generation in interrupt mode.
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  /* Check the TIM state */
+  if (htim->State != HAL_TIM_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Enable the TIM Update interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Base generation in interrupt mode.
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  /* Disable the TIM Update interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Base generation in DMA mode.
+  * @param  htim TIM Base handle
+  * @param  pData The source Buffer address.
+  * @param  Length The length of data to be transferred from memory to peripheral.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, const uint32_t *pData, uint16_t Length)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_DMA_INSTANCE(htim->Instance));
+
+  /* Set the TIM state */
+  if (htim->State == HAL_TIM_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (htim->State == HAL_TIM_STATE_READY)
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      htim->State = HAL_TIM_STATE_BUSY;
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the DMA Period elapsed callbacks */
+  htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+  htim->hdma[TIM_DMA_ID_UPDATE]->XferHalfCpltCallback = TIM_DMAPeriodElapsedHalfCplt;
+
+  /* Set the DMA error callback */
+  htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+  /* Enable the DMA stream */
+  if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)pData, (uint32_t)&htim->Instance->ARR,
+                       Length) != HAL_OK)
+  {
+    /* Return error status */
+    return HAL_ERROR;
+  }
+
+  /* Enable the TIM Update DMA request */
+  __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_UPDATE);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Base generation in DMA mode.
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_DMA_INSTANCE(htim->Instance));
+
+  /* Disable the TIM Update DMA request */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_UPDATE);
+
+  (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group2 TIM Output Compare functions
+  *  @brief    TIM Output Compare functions
+  *
+@verbatim
+  ==============================================================================
+                  ##### TIM Output Compare functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure the TIM Output Compare.
+    (+) De-initialize the TIM Output Compare.
+    (+) Start the TIM Output Compare.
+    (+) Stop the TIM Output Compare.
+    (+) Start the TIM Output Compare and enable interrupt.
+    (+) Stop the TIM Output Compare and disable interrupt.
+    (+) Start the TIM Output Compare and enable DMA transfer.
+    (+) Stop the TIM Output Compare and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM Output Compare according to the specified
+  *         parameters in the TIM_HandleTypeDef and initializes the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_OC_DeInit() before HAL_TIM_OC_Init()
+  * @param  htim TIM Output Compare handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef *htim)
+{
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->OC_MspInitCallback == NULL)
+    {
+      htim->OC_MspInitCallback = HAL_TIM_OC_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->OC_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIM_OC_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Init the base time for the Output Compare */
+  TIM_Base_SetConfig(htim->Instance,  &htim->Init);
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM peripheral
+  * @param  htim TIM Output Compare handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->OC_MspDeInitCallback == NULL)
+  {
+    htim->OC_MspDeInitCallback = HAL_TIM_OC_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->OC_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+  HAL_TIM_OC_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Change the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM Output Compare MSP.
+  * @param  htim TIM Output Compare handle
+  * @retval None
+  */
+__weak void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_OC_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM Output Compare MSP.
+  * @param  htim TIM Output Compare handle
+  * @retval None
+  */
+__weak void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_OC_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Output compare channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Enable the main output */
+    __HAL_TIM_MOE_ENABLE(htim);
+  }
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Disable the Output compare channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation in interrupt mode.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Enable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Enable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Enable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Enable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Output compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Enable the main output */
+      __HAL_TIM_MOE_ENABLE(htim);
+    }
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation in interrupt mode.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Output compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Disable the Main Output */
+      __HAL_TIM_MOE_DISABLE(htim);
+    }
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation in DMA mode.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  pData The source Buffer address.
+  * @param  Length The length of data to be transferred from memory to TIM peripheral
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                       uint16_t Length)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Set the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+
+      /* Enable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+
+      /* Enable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 3 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 4 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Output compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Enable the main output */
+      __HAL_TIM_MOE_ENABLE(htim);
+    }
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation in DMA mode.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Output compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Disable the Main Output */
+      __HAL_TIM_MOE_DISABLE(htim);
+    }
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group3 TIM PWM functions
+  *  @brief    TIM PWM functions
+  *
+@verbatim
+  ==============================================================================
+                          ##### TIM PWM functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure the TIM PWM.
+    (+) De-initialize the TIM PWM.
+    (+) Start the TIM PWM.
+    (+) Stop the TIM PWM.
+    (+) Start the TIM PWM and enable interrupt.
+    (+) Stop the TIM PWM and disable interrupt.
+    (+) Start the TIM PWM and enable DMA transfer.
+    (+) Stop the TIM PWM and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM PWM Time Base according to the specified
+  *         parameters in the TIM_HandleTypeDef and initializes the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_PWM_DeInit() before HAL_TIM_PWM_Init()
+  * @param  htim TIM PWM handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim)
+{
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->PWM_MspInitCallback == NULL)
+    {
+      htim->PWM_MspInitCallback = HAL_TIM_PWM_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->PWM_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIM_PWM_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Init the base time for the PWM */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM peripheral
+  * @param  htim TIM PWM handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->PWM_MspDeInitCallback == NULL)
+  {
+    htim->PWM_MspDeInitCallback = HAL_TIM_PWM_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->PWM_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+  HAL_TIM_PWM_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Change the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM PWM MSP.
+  * @param  htim TIM PWM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PWM_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM PWM MSP.
+  * @param  htim TIM PWM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PWM_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the PWM signal generation.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Capture compare channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Enable the main output */
+    __HAL_TIM_MOE_ENABLE(htim);
+  }
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the PWM signal generation.
+  * @param  htim TIM PWM handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Disable the Capture compare channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the PWM signal generation in interrupt mode.
+  * @param  htim TIM PWM handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Enable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Enable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Enable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Enable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Capture compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Enable the main output */
+      __HAL_TIM_MOE_ENABLE(htim);
+    }
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the PWM signal generation in interrupt mode.
+  * @param  htim TIM PWM handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Capture compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Disable the Main Output */
+      __HAL_TIM_MOE_DISABLE(htim);
+    }
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Starts the TIM PWM signal generation in DMA mode.
+  * @param  htim TIM PWM handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  pData The source Buffer address.
+  * @param  Length The length of data to be transferred from memory to TIM peripheral
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                        uint16_t Length)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Set the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+
+      /* Enable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Output Capture/Compare 3 request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 4 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Capture compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Enable the main output */
+      __HAL_TIM_MOE_ENABLE(htim);
+    }
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM PWM signal generation in DMA mode.
+  * @param  htim TIM PWM handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Capture compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Disable the Main Output */
+      __HAL_TIM_MOE_DISABLE(htim);
+    }
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group4 TIM Input Capture functions
+  *  @brief    TIM Input Capture functions
+  *
+@verbatim
+  ==============================================================================
+              ##### TIM Input Capture functions #####
+  ==============================================================================
+ [..]
+   This section provides functions allowing to:
+   (+) Initialize and configure the TIM Input Capture.
+   (+) De-initialize the TIM Input Capture.
+   (+) Start the TIM Input Capture.
+   (+) Stop the TIM Input Capture.
+   (+) Start the TIM Input Capture and enable interrupt.
+   (+) Stop the TIM Input Capture and disable interrupt.
+   (+) Start the TIM Input Capture and enable DMA transfer.
+   (+) Stop the TIM Input Capture and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM Input Capture Time base according to the specified
+  *         parameters in the TIM_HandleTypeDef and initializes the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_IC_DeInit() before HAL_TIM_IC_Init()
+  * @param  htim TIM Input Capture handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim)
+{
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->IC_MspInitCallback == NULL)
+    {
+      htim->IC_MspInitCallback = HAL_TIM_IC_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->IC_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIM_IC_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Init the base time for the input capture */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM peripheral
+  * @param  htim TIM Input Capture handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->IC_MspDeInitCallback == NULL)
+  {
+    htim->IC_MspDeInitCallback = HAL_TIM_IC_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->IC_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+  HAL_TIM_IC_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Change the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM Input Capture MSP.
+  * @param  htim TIM Input Capture handle
+  * @retval None
+  */
+__weak void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_IC_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM Input Capture MSP.
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_IC_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the TIM Input Capture measurement.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpsmcr;
+  HAL_TIM_ChannelStateTypeDef channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_state = TIM_CHANNEL_N_STATE_GET(htim, Channel);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if ((channel_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Input Capture channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Input Capture measurement.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Disable the Input Capture channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Input Capture measurement in interrupt mode.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  HAL_TIM_ChannelStateTypeDef channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_state = TIM_CHANNEL_N_STATE_GET(htim, Channel);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if ((channel_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Enable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Enable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Enable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Enable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Input Capture channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Input Capture measurement in interrupt mode.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Input Capture channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Starts the TIM Input Capture measurement in DMA mode.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  pData The destination Buffer address.
+  * @param  Length The length of data to be transferred from TIM peripheral to memory.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  HAL_TIM_ChannelStateTypeDef channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_state = TIM_CHANNEL_N_STATE_GET(htim, Channel);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+  assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+  /* Set the TIM channel state */
+  if ((channel_state == HAL_TIM_CHANNEL_STATE_BUSY)
+      || (complementary_channel_state == HAL_TIM_CHANNEL_STATE_BUSY))
+  {
+    return HAL_BUSY;
+  }
+  else if ((channel_state == HAL_TIM_CHANNEL_STATE_READY)
+           && (complementary_channel_state == HAL_TIM_CHANNEL_STATE_READY))
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  /* Enable the Input Capture channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 2  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->CCR3, (uint32_t)pData,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 3  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->CCR4, (uint32_t)pData,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 4  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Input Capture measurement in DMA mode.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+  assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3  DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4  DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group5 TIM One Pulse functions
+  *  @brief    TIM One Pulse functions
+  *
+@verbatim
+  ==============================================================================
+                        ##### TIM One Pulse functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure the TIM One Pulse.
+    (+) De-initialize the TIM One Pulse.
+    (+) Start the TIM One Pulse.
+    (+) Stop the TIM One Pulse.
+    (+) Start the TIM One Pulse and enable interrupt.
+    (+) Stop the TIM One Pulse and disable interrupt.
+    (+) Start the TIM One Pulse and enable DMA transfer.
+    (+) Stop the TIM One Pulse and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM One Pulse Time Base according to the specified
+  *         parameters in the TIM_HandleTypeDef and initializes the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_OnePulse_DeInit() before HAL_TIM_OnePulse_Init()
+  * @note   When the timer instance is initialized in One Pulse mode, timer
+  *         channels 1 and channel 2 are reserved and cannot be used for other
+  *         purpose.
+  * @param  htim TIM One Pulse handle
+  * @param  OnePulseMode Select the One pulse mode.
+  *         This parameter can be one of the following values:
+  *            @arg TIM_OPMODE_SINGLE: Only one pulse will be generated.
+  *            @arg TIM_OPMODE_REPETITIVE: Repetitive pulses will be generated.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Init(TIM_HandleTypeDef *htim, uint32_t OnePulseMode)
+{
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_OPM_MODE(OnePulseMode));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->OnePulse_MspInitCallback == NULL)
+    {
+      htim->OnePulse_MspInitCallback = HAL_TIM_OnePulse_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->OnePulse_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIM_OnePulse_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Configure the Time base in the One Pulse Mode */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Reset the OPM Bit */
+  htim->Instance->CR1 &= ~TIM_CR1_OPM;
+
+  /* Configure the OPM Mode */
+  htim->Instance->CR1 |= OnePulseMode;
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM One Pulse
+  * @param  htim TIM One Pulse handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->OnePulse_MspDeInitCallback == NULL)
+  {
+    htim->OnePulse_MspDeInitCallback = HAL_TIM_OnePulse_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->OnePulse_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+  HAL_TIM_OnePulse_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM One Pulse MSP.
+  * @param  htim TIM One Pulse handle
+  * @retval None
+  */
+__weak void HAL_TIM_OnePulse_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_OnePulse_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM One Pulse MSP.
+  * @param  htim TIM One Pulse handle
+  * @retval None
+  */
+__weak void HAL_TIM_OnePulse_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_OnePulse_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the TIM One Pulse signal generation.
+  * @note Though OutputChannel parameter is deprecated and ignored by the function
+  *        it has been kept to avoid HAL_TIM API compatibility break.
+  * @note The pulse output channel is determined when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel See note above
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(OutputChannel);
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Capture compare and the Input Capture channels
+    (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+    if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+    if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+    whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together
+
+    No need to enable the counter, it's enabled automatically by hardware
+    (the counter starts in response to a stimulus and generate a pulse */
+
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Enable the main output */
+    __HAL_TIM_MOE_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM One Pulse signal generation.
+  * @note Though OutputChannel parameter is deprecated and ignored by the function
+  *        it has been kept to avoid HAL_TIM API compatibility break.
+  * @note The pulse output channel is determined when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel See note above
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(OutputChannel);
+
+  /* Disable the Capture compare and the Input Capture channels
+  (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+  if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+  if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+  whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */
+
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM One Pulse signal generation in interrupt mode.
+  * @note Though OutputChannel parameter is deprecated and ignored by the function
+  *        it has been kept to avoid HAL_TIM API compatibility break.
+  * @note The pulse output channel is determined when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel See note above
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(OutputChannel);
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Capture compare and the Input Capture channels
+    (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+    if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+    if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+    whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together
+
+    No need to enable the counter, it's enabled automatically by hardware
+    (the counter starts in response to a stimulus and generate a pulse */
+
+  /* Enable the TIM Capture/Compare 1 interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+  /* Enable the TIM Capture/Compare 2 interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Enable the main output */
+    __HAL_TIM_MOE_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM One Pulse signal generation in interrupt mode.
+  * @note Though OutputChannel parameter is deprecated and ignored by the function
+  *        it has been kept to avoid HAL_TIM API compatibility break.
+  * @note The pulse output channel is determined when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel See note above
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(OutputChannel);
+
+  /* Disable the TIM Capture/Compare 1 interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+  /* Disable the TIM Capture/Compare 2 interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+
+  /* Disable the Capture compare and the Input Capture channels
+  (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+  if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+  if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+  whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group6 TIM Encoder functions
+  *  @brief    TIM Encoder functions
+  *
+@verbatim
+  ==============================================================================
+                          ##### TIM Encoder functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure the TIM Encoder.
+    (+) De-initialize the TIM Encoder.
+    (+) Start the TIM Encoder.
+    (+) Stop the TIM Encoder.
+    (+) Start the TIM Encoder and enable interrupt.
+    (+) Stop the TIM Encoder and disable interrupt.
+    (+) Start the TIM Encoder and enable DMA transfer.
+    (+) Stop the TIM Encoder and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM Encoder Interface and initialize the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_Encoder_DeInit() before HAL_TIM_Encoder_Init()
+  * @note   Encoder mode and External clock mode 2 are not compatible and must not be selected together
+  *         Ex: A call for @ref HAL_TIM_Encoder_Init will erase the settings of @ref HAL_TIM_ConfigClockSource
+  *         using TIM_CLOCKSOURCE_ETRMODE2 and vice versa
+  * @note   When the timer instance is initialized in Encoder mode, timer
+  *         channels 1 and channel 2 are reserved and cannot be used for other
+  *         purpose.
+  * @param  htim TIM Encoder Interface handle
+  * @param  sConfig TIM Encoder Interface configuration structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim, const TIM_Encoder_InitTypeDef *sConfig)
+{
+  uint32_t tmpsmcr;
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+  assert_param(IS_TIM_ENCODER_MODE(sConfig->EncoderMode));
+  assert_param(IS_TIM_IC_SELECTION(sConfig->IC1Selection));
+  assert_param(IS_TIM_IC_SELECTION(sConfig->IC2Selection));
+  assert_param(IS_TIM_ENCODERINPUT_POLARITY(sConfig->IC1Polarity));
+  assert_param(IS_TIM_ENCODERINPUT_POLARITY(sConfig->IC2Polarity));
+  assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler));
+  assert_param(IS_TIM_IC_PRESCALER(sConfig->IC2Prescaler));
+  assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter));
+  assert_param(IS_TIM_IC_FILTER(sConfig->IC2Filter));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->Encoder_MspInitCallback == NULL)
+    {
+      htim->Encoder_MspInitCallback = HAL_TIM_Encoder_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->Encoder_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIM_Encoder_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Reset the SMS and ECE bits */
+  htim->Instance->SMCR &= ~(TIM_SMCR_SMS | TIM_SMCR_ECE);
+
+  /* Configure the Time base in the Encoder Mode */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Get the TIMx SMCR register value */
+  tmpsmcr = htim->Instance->SMCR;
+
+  /* Get the TIMx CCMR1 register value */
+  tmpccmr1 = htim->Instance->CCMR1;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = htim->Instance->CCER;
+
+  /* Set the encoder Mode */
+  tmpsmcr |= sConfig->EncoderMode;
+
+  /* Select the Capture Compare 1 and the Capture Compare 2 as input */
+  tmpccmr1 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_CC2S);
+  tmpccmr1 |= (sConfig->IC1Selection | (sConfig->IC2Selection << 8U));
+
+  /* Set the Capture Compare 1 and the Capture Compare 2 prescalers and filters */
+  tmpccmr1 &= ~(TIM_CCMR1_IC1PSC | TIM_CCMR1_IC2PSC);
+  tmpccmr1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_IC2F);
+  tmpccmr1 |= sConfig->IC1Prescaler | (sConfig->IC2Prescaler << 8U);
+  tmpccmr1 |= (sConfig->IC1Filter << 4U) | (sConfig->IC2Filter << 12U);
+
+  /* Set the TI1 and the TI2 Polarities */
+  tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC2P);
+  tmpccer &= ~(TIM_CCER_CC1NP | TIM_CCER_CC2NP);
+  tmpccer |= sConfig->IC1Polarity | (sConfig->IC2Polarity << 4U);
+
+  /* Write to TIMx SMCR */
+  htim->Instance->SMCR = tmpsmcr;
+
+  /* Write to TIMx CCMR1 */
+  htim->Instance->CCMR1 = tmpccmr1;
+
+  /* Write to TIMx CCER */
+  htim->Instance->CCER = tmpccer;
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+
+/**
+  * @brief  DeInitializes the TIM Encoder interface
+  * @param  htim TIM Encoder Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->Encoder_MspDeInitCallback == NULL)
+  {
+    htim->Encoder_MspDeInitCallback = HAL_TIM_Encoder_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->Encoder_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+  HAL_TIM_Encoder_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM Encoder Interface MSP.
+  * @param  htim TIM Encoder Interface handle
+  * @retval None
+  */
+__weak void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_Encoder_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM Encoder Interface MSP.
+  * @param  htim TIM Encoder Interface handle
+  * @retval None
+  */
+__weak void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_Encoder_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the TIM Encoder Interface.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Set the TIM channel(s) state */
+  if (Channel == TIM_CHANNEL_1)
+  {
+    if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    if ((channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+
+  /* Enable the encoder interface channels */
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+      break;
+    }
+
+    default :
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+      break;
+    }
+  }
+  /* Enable the Peripheral */
+  __HAL_TIM_ENABLE(htim);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Encoder Interface.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channels 1 and 2
+    (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+      break;
+    }
+
+    default :
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+      break;
+    }
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel(s) state */
+  if ((Channel == TIM_CHANNEL_1) || (Channel == TIM_CHANNEL_2))
+  {
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else
+  {
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Encoder Interface in interrupt mode.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Set the TIM channel(s) state */
+  if (Channel == TIM_CHANNEL_1)
+  {
+    if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    if ((channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+
+  /* Enable the encoder interface channels */
+  /* Enable the capture compare Interrupts 1 and/or 2 */
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    default :
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+  }
+
+  /* Enable the Peripheral */
+  __HAL_TIM_ENABLE(htim);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Encoder Interface in interrupt mode.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channels 1 and 2
+    (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */
+  if (Channel == TIM_CHANNEL_1)
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare Interrupts 1 */
+    __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare Interrupts 2 */
+    __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+  }
+  else
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare Interrupts 1 and 2 */
+    __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+    __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel(s) state */
+  if ((Channel == TIM_CHANNEL_1) || (Channel == TIM_CHANNEL_2))
+  {
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else
+  {
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Encoder Interface in DMA mode.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @param  pData1 The destination Buffer address for IC1.
+  * @param  pData2 The destination Buffer address for IC2.
+  * @param  Length The length of data to be transferred from TIM peripheral to memory.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData1,
+                                            uint32_t *pData2, uint16_t Length)
+{
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Set the TIM channel(s) state */
+  if (Channel == TIM_CHANNEL_1)
+  {
+    if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+        || (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY))
+    {
+      return HAL_BUSY;
+    }
+    else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+             && (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY))
+    {
+      if ((pData1 == NULL) || (Length == 0U))
+      {
+        return HAL_ERROR;
+      }
+      else
+      {
+        TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+        TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      }
+    }
+    else
+    {
+      return HAL_ERROR;
+    }
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    if ((channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY)
+        || (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY))
+    {
+      return HAL_BUSY;
+    }
+    else if ((channel_2_state == HAL_TIM_CHANNEL_STATE_READY)
+             && (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_READY))
+    {
+      if ((pData2 == NULL) || (Length == 0U))
+      {
+        return HAL_ERROR;
+      }
+      else
+      {
+        TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+        TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      }
+    }
+    else
+    {
+      return HAL_ERROR;
+    }
+  }
+  else
+  {
+    if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+        || (channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY)
+        || (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+        || (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY))
+    {
+      return HAL_BUSY;
+    }
+    else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+             && (channel_2_state == HAL_TIM_CHANNEL_STATE_READY)
+             && (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+             && (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_READY))
+    {
+      if ((((pData1 == NULL) || (pData2 == NULL))) || (Length == 0U))
+      {
+        return HAL_ERROR;
+      }
+      else
+      {
+        TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+        TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+        TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+        TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      }
+    }
+    else
+    {
+      return HAL_ERROR;
+    }
+  }
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Input Capture DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+
+      /* Enable the Capture compare channel */
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+      /* Enable the Peripheral */
+      __HAL_TIM_ENABLE(htim);
+
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError;
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Input Capture  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+
+      /* Enable the Capture compare channel */
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+      /* Enable the Peripheral */
+      __HAL_TIM_ENABLE(htim);
+
+      break;
+    }
+
+    default:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+
+      /* Enable the TIM Input Capture  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      /* Enable the TIM Input Capture  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+
+      /* Enable the Capture compare channel */
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+      /* Enable the Peripheral */
+      __HAL_TIM_ENABLE(htim);
+
+      break;
+    }
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Encoder Interface in DMA mode.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channels 1 and 2
+    (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */
+  if (Channel == TIM_CHANNEL_1)
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare DMA Request 1 */
+    __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+    (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare DMA Request 2 */
+    __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+    (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+  }
+  else
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare DMA Request 1 and 2 */
+    __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+    __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+    (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+    (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel(s) state */
+  if ((Channel == TIM_CHANNEL_1) || (Channel == TIM_CHANNEL_2))
+  {
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else
+  {
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+/** @defgroup TIM_Exported_Functions_Group7 TIM IRQ handler management
+  *  @brief    TIM IRQ handler management
+  *
+@verbatim
+  ==============================================================================
+                        ##### IRQ handler management #####
+  ==============================================================================
+  [..]
+    This section provides Timer IRQ handler function.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  This function handles TIM interrupts requests.
+  * @param  htim TIM  handle
+  * @retval None
+  */
+void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
+{
+  uint32_t itsource = htim->Instance->DIER;
+  uint32_t itflag   = htim->Instance->SR;
+
+  /* Capture compare 1 event */
+  if ((itflag & (TIM_FLAG_CC1)) == (TIM_FLAG_CC1))
+  {
+    if ((itsource & (TIM_IT_CC1)) == (TIM_IT_CC1))
+    {
+      {
+        __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC1);
+        htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+        /* Input capture event */
+        if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
+        {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+          htim->IC_CaptureCallback(htim);
+#else
+          HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+        }
+        /* Output compare event */
+        else
+        {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+          htim->OC_DelayElapsedCallback(htim);
+          htim->PWM_PulseFinishedCallback(htim);
+#else
+          HAL_TIM_OC_DelayElapsedCallback(htim);
+          HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+        }
+        htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+      }
+    }
+  }
+  /* Capture compare 2 event */
+  if ((itflag & (TIM_FLAG_CC2)) == (TIM_FLAG_CC2))
+  {
+    if ((itsource & (TIM_IT_CC2)) == (TIM_IT_CC2))
+    {
+      __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC2);
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+      /* Input capture event */
+      if ((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U)
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->IC_CaptureCallback(htim);
+#else
+        HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      /* Output compare event */
+      else
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->OC_DelayElapsedCallback(htim);
+        htim->PWM_PulseFinishedCallback(htim);
+#else
+        HAL_TIM_OC_DelayElapsedCallback(htim);
+        HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+    }
+  }
+  /* Capture compare 3 event */
+  if ((itflag & (TIM_FLAG_CC3)) == (TIM_FLAG_CC3))
+  {
+    if ((itsource & (TIM_IT_CC3)) == (TIM_IT_CC3))
+    {
+      __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC3);
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+      /* Input capture event */
+      if ((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U)
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->IC_CaptureCallback(htim);
+#else
+        HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      /* Output compare event */
+      else
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->OC_DelayElapsedCallback(htim);
+        htim->PWM_PulseFinishedCallback(htim);
+#else
+        HAL_TIM_OC_DelayElapsedCallback(htim);
+        HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+    }
+  }
+  /* Capture compare 4 event */
+  if ((itflag & (TIM_FLAG_CC4)) == (TIM_FLAG_CC4))
+  {
+    if ((itsource & (TIM_IT_CC4)) == (TIM_IT_CC4))
+    {
+      __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC4);
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+      /* Input capture event */
+      if ((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U)
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->IC_CaptureCallback(htim);
+#else
+        HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      /* Output compare event */
+      else
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->OC_DelayElapsedCallback(htim);
+        htim->PWM_PulseFinishedCallback(htim);
+#else
+        HAL_TIM_OC_DelayElapsedCallback(htim);
+        HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+    }
+  }
+  /* TIM Update event */
+  if ((itflag & (TIM_FLAG_UPDATE)) == (TIM_FLAG_UPDATE))
+  {
+    if ((itsource & (TIM_IT_UPDATE)) == (TIM_IT_UPDATE))
+    {
+      __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_UPDATE);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+      htim->PeriodElapsedCallback(htim);
+#else
+      HAL_TIM_PeriodElapsedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+    }
+  }
+  /* TIM Break input event */
+  if ((itflag & (TIM_FLAG_BREAK)) == (TIM_FLAG_BREAK))
+  {
+    if ((itsource & (TIM_IT_BREAK)) == (TIM_IT_BREAK))
+    {
+      __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_BREAK);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+      htim->BreakCallback(htim);
+#else
+      HAL_TIMEx_BreakCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+    }
+  }
+  /* TIM Trigger detection event */
+  if ((itflag & (TIM_FLAG_TRIGGER)) == (TIM_FLAG_TRIGGER))
+  {
+    if ((itsource & (TIM_IT_TRIGGER)) == (TIM_IT_TRIGGER))
+    {
+      __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_TRIGGER);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+      htim->TriggerCallback(htim);
+#else
+      HAL_TIM_TriggerCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+    }
+  }
+  /* TIM commutation event */
+  if ((itflag & (TIM_FLAG_COM)) == (TIM_FLAG_COM))
+  {
+    if ((itsource & (TIM_IT_COM)) == (TIM_IT_COM))
+    {
+      __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_COM);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+      htim->CommutationCallback(htim);
+#else
+      HAL_TIMEx_CommutCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+    }
+  }
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group8 TIM Peripheral Control functions
+  *  @brief    TIM Peripheral Control functions
+  *
+@verbatim
+  ==============================================================================
+                   ##### Peripheral Control functions #####
+  ==============================================================================
+ [..]
+   This section provides functions allowing to:
+      (+) Configure The Input Output channels for OC, PWM, IC or One Pulse mode.
+      (+) Configure External Clock source.
+      (+) Configure Complementary channels, break features and dead time.
+      (+) Configure Master and the Slave synchronization.
+      (+) Configure the DMA Burst Mode.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Initializes the TIM Output Compare Channels according to the specified
+  *         parameters in the TIM_OC_InitTypeDef.
+  * @param  htim TIM Output Compare handle
+  * @param  sConfig TIM Output Compare configuration structure
+  * @param  Channel TIM Channels to configure
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim,
+                                           const TIM_OC_InitTypeDef *sConfig,
+                                           uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CHANNELS(Channel));
+  assert_param(IS_TIM_OC_MODE(sConfig->OCMode));
+  assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+      /* Configure the TIM Channel 1 in Output Compare */
+      TIM_OC1_SetConfig(htim->Instance, sConfig);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+      /* Configure the TIM Channel 2 in Output Compare */
+      TIM_OC2_SetConfig(htim->Instance, sConfig);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+      /* Configure the TIM Channel 3 in Output Compare */
+      TIM_OC3_SetConfig(htim->Instance, sConfig);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+      /* Configure the TIM Channel 4 in Output Compare */
+      TIM_OC4_SetConfig(htim->Instance, sConfig);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief  Initializes the TIM Input Capture Channels according to the specified
+  *         parameters in the TIM_IC_InitTypeDef.
+  * @param  htim TIM IC handle
+  * @param  sConfig TIM Input Capture configuration structure
+  * @param  Channel TIM Channel to configure
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_IC_InitTypeDef *sConfig, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_IC_POLARITY(sConfig->ICPolarity));
+  assert_param(IS_TIM_IC_SELECTION(sConfig->ICSelection));
+  assert_param(IS_TIM_IC_PRESCALER(sConfig->ICPrescaler));
+  assert_param(IS_TIM_IC_FILTER(sConfig->ICFilter));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  if (Channel == TIM_CHANNEL_1)
+  {
+    /* TI1 Configuration */
+    TIM_TI1_SetConfig(htim->Instance,
+                      sConfig->ICPolarity,
+                      sConfig->ICSelection,
+                      sConfig->ICFilter);
+
+    /* Reset the IC1PSC Bits */
+    htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+
+    /* Set the IC1PSC value */
+    htim->Instance->CCMR1 |= sConfig->ICPrescaler;
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    /* TI2 Configuration */
+    assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+    TIM_TI2_SetConfig(htim->Instance,
+                      sConfig->ICPolarity,
+                      sConfig->ICSelection,
+                      sConfig->ICFilter);
+
+    /* Reset the IC2PSC Bits */
+    htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC;
+
+    /* Set the IC2PSC value */
+    htim->Instance->CCMR1 |= (sConfig->ICPrescaler << 8U);
+  }
+  else if (Channel == TIM_CHANNEL_3)
+  {
+    /* TI3 Configuration */
+    assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+    TIM_TI3_SetConfig(htim->Instance,
+                      sConfig->ICPolarity,
+                      sConfig->ICSelection,
+                      sConfig->ICFilter);
+
+    /* Reset the IC3PSC Bits */
+    htim->Instance->CCMR2 &= ~TIM_CCMR2_IC3PSC;
+
+    /* Set the IC3PSC value */
+    htim->Instance->CCMR2 |= sConfig->ICPrescaler;
+  }
+  else if (Channel == TIM_CHANNEL_4)
+  {
+    /* TI4 Configuration */
+    assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+    TIM_TI4_SetConfig(htim->Instance,
+                      sConfig->ICPolarity,
+                      sConfig->ICSelection,
+                      sConfig->ICFilter);
+
+    /* Reset the IC4PSC Bits */
+    htim->Instance->CCMR2 &= ~TIM_CCMR2_IC4PSC;
+
+    /* Set the IC4PSC value */
+    htim->Instance->CCMR2 |= (sConfig->ICPrescaler << 8U);
+  }
+  else
+  {
+    status = HAL_ERROR;
+  }
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief  Initializes the TIM PWM  channels according to the specified
+  *         parameters in the TIM_OC_InitTypeDef.
+  * @param  htim TIM PWM handle
+  * @param  sConfig TIM PWM configuration structure
+  * @param  Channel TIM Channels to be configured
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
+                                            const TIM_OC_InitTypeDef *sConfig,
+                                            uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CHANNELS(Channel));
+  assert_param(IS_TIM_PWM_MODE(sConfig->OCMode));
+  assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity));
+  assert_param(IS_TIM_FAST_STATE(sConfig->OCFastMode));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+      /* Configure the Channel 1 in PWM mode */
+      TIM_OC1_SetConfig(htim->Instance, sConfig);
+
+      /* Set the Preload enable bit for channel1 */
+      htim->Instance->CCMR1 |= TIM_CCMR1_OC1PE;
+
+      /* Configure the Output Fast mode */
+      htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1FE;
+      htim->Instance->CCMR1 |= sConfig->OCFastMode;
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+      /* Configure the Channel 2 in PWM mode */
+      TIM_OC2_SetConfig(htim->Instance, sConfig);
+
+      /* Set the Preload enable bit for channel2 */
+      htim->Instance->CCMR1 |= TIM_CCMR1_OC2PE;
+
+      /* Configure the Output Fast mode */
+      htim->Instance->CCMR1 &= ~TIM_CCMR1_OC2FE;
+      htim->Instance->CCMR1 |= sConfig->OCFastMode << 8U;
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+      /* Configure the Channel 3 in PWM mode */
+      TIM_OC3_SetConfig(htim->Instance, sConfig);
+
+      /* Set the Preload enable bit for channel3 */
+      htim->Instance->CCMR2 |= TIM_CCMR2_OC3PE;
+
+      /* Configure the Output Fast mode */
+      htim->Instance->CCMR2 &= ~TIM_CCMR2_OC3FE;
+      htim->Instance->CCMR2 |= sConfig->OCFastMode;
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+      /* Configure the Channel 4 in PWM mode */
+      TIM_OC4_SetConfig(htim->Instance, sConfig);
+
+      /* Set the Preload enable bit for channel4 */
+      htim->Instance->CCMR2 |= TIM_CCMR2_OC4PE;
+
+      /* Configure the Output Fast mode */
+      htim->Instance->CCMR2 &= ~TIM_CCMR2_OC4FE;
+      htim->Instance->CCMR2 |= sConfig->OCFastMode << 8U;
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief  Initializes the TIM One Pulse Channels according to the specified
+  *         parameters in the TIM_OnePulse_InitTypeDef.
+  * @param  htim TIM One Pulse handle
+  * @param  sConfig TIM One Pulse configuration structure
+  * @param  OutputChannel TIM output channel to configure
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @param  InputChannel TIM input Channel to configure
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @note  To output a waveform with a minimum delay user can enable the fast
+  *        mode by calling the @ref __HAL_TIM_ENABLE_OCxFAST macro. Then CCx
+  *        output is forced in response to the edge detection on TIx input,
+  *        without taking in account the comparison.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim,  TIM_OnePulse_InitTypeDef *sConfig,
+                                                 uint32_t OutputChannel,  uint32_t InputChannel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  TIM_OC_InitTypeDef temp1;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_OPM_CHANNELS(OutputChannel));
+  assert_param(IS_TIM_OPM_CHANNELS(InputChannel));
+
+  if (OutputChannel != InputChannel)
+  {
+    /* Process Locked */
+    __HAL_LOCK(htim);
+
+    htim->State = HAL_TIM_STATE_BUSY;
+
+    /* Extract the Output compare configuration from sConfig structure */
+    temp1.OCMode = sConfig->OCMode;
+    temp1.Pulse = sConfig->Pulse;
+    temp1.OCPolarity = sConfig->OCPolarity;
+    temp1.OCNPolarity = sConfig->OCNPolarity;
+    temp1.OCIdleState = sConfig->OCIdleState;
+    temp1.OCNIdleState = sConfig->OCNIdleState;
+
+    switch (OutputChannel)
+    {
+      case TIM_CHANNEL_1:
+      {
+        assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+        TIM_OC1_SetConfig(htim->Instance, &temp1);
+        break;
+      }
+
+      case TIM_CHANNEL_2:
+      {
+        assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+        TIM_OC2_SetConfig(htim->Instance, &temp1);
+        break;
+      }
+
+      default:
+        status = HAL_ERROR;
+        break;
+    }
+
+    if (status == HAL_OK)
+    {
+      switch (InputChannel)
+      {
+        case TIM_CHANNEL_1:
+        {
+          assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+          TIM_TI1_SetConfig(htim->Instance, sConfig->ICPolarity,
+                            sConfig->ICSelection, sConfig->ICFilter);
+
+          /* Reset the IC1PSC Bits */
+          htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+
+          /* Select the Trigger source */
+          htim->Instance->SMCR &= ~TIM_SMCR_TS;
+          htim->Instance->SMCR |= TIM_TS_TI1FP1;
+
+          /* Select the Slave Mode */
+          htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+          htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER;
+          break;
+        }
+
+        case TIM_CHANNEL_2:
+        {
+          assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+          TIM_TI2_SetConfig(htim->Instance, sConfig->ICPolarity,
+                            sConfig->ICSelection, sConfig->ICFilter);
+
+          /* Reset the IC2PSC Bits */
+          htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC;
+
+          /* Select the Trigger source */
+          htim->Instance->SMCR &= ~TIM_SMCR_TS;
+          htim->Instance->SMCR |= TIM_TS_TI2FP2;
+
+          /* Select the Slave Mode */
+          htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+          htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER;
+          break;
+        }
+
+        default:
+          status = HAL_ERROR;
+          break;
+      }
+    }
+
+    htim->State = HAL_TIM_STATE_READY;
+
+    __HAL_UNLOCK(htim);
+
+    return status;
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+}
+
+/**
+  * @brief  Configure the DMA Burst to transfer Data from the memory to the TIM peripheral
+  * @param  htim TIM handle
+  * @param  BurstBaseAddress TIM Base address from where the DMA  will start the Data write
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMABASE_CR1
+  *            @arg TIM_DMABASE_CR2
+  *            @arg TIM_DMABASE_SMCR
+  *            @arg TIM_DMABASE_DIER
+  *            @arg TIM_DMABASE_SR
+  *            @arg TIM_DMABASE_EGR
+  *            @arg TIM_DMABASE_CCMR1
+  *            @arg TIM_DMABASE_CCMR2
+  *            @arg TIM_DMABASE_CCER
+  *            @arg TIM_DMABASE_CNT
+  *            @arg TIM_DMABASE_PSC
+  *            @arg TIM_DMABASE_ARR
+  *            @arg TIM_DMABASE_RCR
+  *            @arg TIM_DMABASE_CCR1
+  *            @arg TIM_DMABASE_CCR2
+  *            @arg TIM_DMABASE_CCR3
+  *            @arg TIM_DMABASE_CCR4
+  *            @arg TIM_DMABASE_BDTR
+  * @param  BurstRequestSrc TIM DMA Request sources
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: TIM update Interrupt source
+  *            @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+  *            @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+  *            @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+  *            @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+  *            @arg TIM_DMA_COM: TIM Commutation DMA source
+  *            @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+  * @param  BurstBuffer The Buffer address.
+  * @param  BurstLength DMA Burst length. This parameter can be one value
+  *         between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+  * @note   This function should be used only when BurstLength is equal to DMA data transfer length.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                              uint32_t BurstRequestSrc, const uint32_t *BurstBuffer,
+                                              uint32_t  BurstLength)
+{
+  HAL_StatusTypeDef status;
+
+  status = HAL_TIM_DMABurst_MultiWriteStart(htim, BurstBaseAddress, BurstRequestSrc, BurstBuffer, BurstLength,
+                                            ((BurstLength) >> 8U) + 1U);
+
+
+
+  return status;
+}
+
+/**
+  * @brief  Configure the DMA Burst to transfer multiple Data from the memory to the TIM peripheral
+  * @param  htim TIM handle
+  * @param  BurstBaseAddress TIM Base address from where the DMA will start the Data write
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMABASE_CR1
+  *            @arg TIM_DMABASE_CR2
+  *            @arg TIM_DMABASE_SMCR
+  *            @arg TIM_DMABASE_DIER
+  *            @arg TIM_DMABASE_SR
+  *            @arg TIM_DMABASE_EGR
+  *            @arg TIM_DMABASE_CCMR1
+  *            @arg TIM_DMABASE_CCMR2
+  *            @arg TIM_DMABASE_CCER
+  *            @arg TIM_DMABASE_CNT
+  *            @arg TIM_DMABASE_PSC
+  *            @arg TIM_DMABASE_ARR
+  *            @arg TIM_DMABASE_RCR
+  *            @arg TIM_DMABASE_CCR1
+  *            @arg TIM_DMABASE_CCR2
+  *            @arg TIM_DMABASE_CCR3
+  *            @arg TIM_DMABASE_CCR4
+  *            @arg TIM_DMABASE_BDTR
+  * @param  BurstRequestSrc TIM DMA Request sources
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: TIM update Interrupt source
+  *            @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+  *            @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+  *            @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+  *            @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+  *            @arg TIM_DMA_COM: TIM Commutation DMA source
+  *            @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+  * @param  BurstBuffer The Buffer address.
+  * @param  BurstLength DMA Burst length. This parameter can be one value
+  *         between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+  * @param  DataLength Data length. This parameter can be one value
+  *         between 1 and 0xFFFF.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_MultiWriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                                   uint32_t BurstRequestSrc, const uint32_t *BurstBuffer,
+                                                   uint32_t  BurstLength,  uint32_t  DataLength)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_DMA_BASE(BurstBaseAddress));
+  assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+  assert_param(IS_TIM_DMA_LENGTH(BurstLength));
+  assert_param(IS_TIM_DMA_DATA_LENGTH(DataLength));
+
+  if (htim->DMABurstState == HAL_DMA_BURST_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (htim->DMABurstState == HAL_DMA_BURST_STATE_READY)
+  {
+    if ((BurstBuffer == NULL) && (BurstLength > 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      htim->DMABurstState = HAL_DMA_BURST_STATE_BUSY;
+    }
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+  switch (BurstRequestSrc)
+  {
+    case TIM_DMA_UPDATE:
+    {
+      /* Set the DMA Period elapsed callbacks */
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferHalfCpltCallback = TIM_DMAPeriodElapsedHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC1:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC2:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC3:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC4:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_COM:
+    {
+      /* Set the DMA commutation callbacks */
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback =  TIMEx_DMACommutationCplt;
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback =  TIMEx_DMACommutationHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_TRIGGER:
+    {
+      /* Set the DMA trigger callbacks */
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt;
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferHalfCpltCallback = TIM_DMATriggerHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Configure the DMA Burst Mode */
+    htim->Instance->DCR = (BurstBaseAddress | BurstLength);
+    /* Enable the TIM DMA Request */
+    __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM DMA Burst mode
+  * @param  htim TIM handle
+  * @param  BurstRequestSrc TIM DMA Request sources to disable
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+
+  /* Abort the DMA transfer (at least disable the DMA stream) */
+  switch (BurstRequestSrc)
+  {
+    case TIM_DMA_UPDATE:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+      break;
+    }
+    case TIM_DMA_CC1:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+    case TIM_DMA_CC2:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+    case TIM_DMA_CC3:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+    case TIM_DMA_CC4:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+      break;
+    }
+    case TIM_DMA_COM:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_COMMUTATION]);
+      break;
+    }
+    case TIM_DMA_TRIGGER:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_TRIGGER]);
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the TIM Update DMA request */
+    __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc);
+
+    /* Change the DMA burst operation state */
+    htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Configure the DMA Burst to transfer Data from the TIM peripheral to the memory
+  * @param  htim TIM handle
+  * @param  BurstBaseAddress TIM Base address from where the DMA  will start the Data read
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMABASE_CR1
+  *            @arg TIM_DMABASE_CR2
+  *            @arg TIM_DMABASE_SMCR
+  *            @arg TIM_DMABASE_DIER
+  *            @arg TIM_DMABASE_SR
+  *            @arg TIM_DMABASE_EGR
+  *            @arg TIM_DMABASE_CCMR1
+  *            @arg TIM_DMABASE_CCMR2
+  *            @arg TIM_DMABASE_CCER
+  *            @arg TIM_DMABASE_CNT
+  *            @arg TIM_DMABASE_PSC
+  *            @arg TIM_DMABASE_ARR
+  *            @arg TIM_DMABASE_RCR
+  *            @arg TIM_DMABASE_CCR1
+  *            @arg TIM_DMABASE_CCR2
+  *            @arg TIM_DMABASE_CCR3
+  *            @arg TIM_DMABASE_CCR4
+  *            @arg TIM_DMABASE_BDTR
+  * @param  BurstRequestSrc TIM DMA Request sources
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: TIM update Interrupt source
+  *            @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+  *            @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+  *            @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+  *            @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+  *            @arg TIM_DMA_COM: TIM Commutation DMA source
+  *            @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+  * @param  BurstBuffer The Buffer address.
+  * @param  BurstLength DMA Burst length. This parameter can be one value
+  *         between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+  * @note   This function should be used only when BurstLength is equal to DMA data transfer length.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                             uint32_t BurstRequestSrc, uint32_t  *BurstBuffer, uint32_t  BurstLength)
+{
+  HAL_StatusTypeDef status;
+
+  status = HAL_TIM_DMABurst_MultiReadStart(htim, BurstBaseAddress, BurstRequestSrc, BurstBuffer, BurstLength,
+                                           ((BurstLength) >> 8U) + 1U);
+
+
+  return status;
+}
+
+/**
+  * @brief  Configure the DMA Burst to transfer Data from the TIM peripheral to the memory
+  * @param  htim TIM handle
+  * @param  BurstBaseAddress TIM Base address from where the DMA  will start the Data read
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMABASE_CR1
+  *            @arg TIM_DMABASE_CR2
+  *            @arg TIM_DMABASE_SMCR
+  *            @arg TIM_DMABASE_DIER
+  *            @arg TIM_DMABASE_SR
+  *            @arg TIM_DMABASE_EGR
+  *            @arg TIM_DMABASE_CCMR1
+  *            @arg TIM_DMABASE_CCMR2
+  *            @arg TIM_DMABASE_CCER
+  *            @arg TIM_DMABASE_CNT
+  *            @arg TIM_DMABASE_PSC
+  *            @arg TIM_DMABASE_ARR
+  *            @arg TIM_DMABASE_RCR
+  *            @arg TIM_DMABASE_CCR1
+  *            @arg TIM_DMABASE_CCR2
+  *            @arg TIM_DMABASE_CCR3
+  *            @arg TIM_DMABASE_CCR4
+  *            @arg TIM_DMABASE_BDTR
+  * @param  BurstRequestSrc TIM DMA Request sources
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: TIM update Interrupt source
+  *            @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+  *            @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+  *            @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+  *            @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+  *            @arg TIM_DMA_COM: TIM Commutation DMA source
+  *            @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+  * @param  BurstBuffer The Buffer address.
+  * @param  BurstLength DMA Burst length. This parameter can be one value
+  *         between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+  * @param  DataLength Data length. This parameter can be one value
+  *         between 1 and 0xFFFF.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_MultiReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                                  uint32_t BurstRequestSrc, uint32_t  *BurstBuffer,
+                                                  uint32_t  BurstLength, uint32_t  DataLength)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_DMA_BASE(BurstBaseAddress));
+  assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+  assert_param(IS_TIM_DMA_LENGTH(BurstLength));
+  assert_param(IS_TIM_DMA_DATA_LENGTH(DataLength));
+
+  if (htim->DMABurstState == HAL_DMA_BURST_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (htim->DMABurstState == HAL_DMA_BURST_STATE_READY)
+  {
+    if ((BurstBuffer == NULL) && (BurstLength > 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      htim->DMABurstState = HAL_DMA_BURST_STATE_BUSY;
+    }
+  }
+  else
+  {
+    /* nothing to do */
+  }
+  switch (BurstRequestSrc)
+  {
+    case TIM_DMA_UPDATE:
+    {
+      /* Set the DMA Period elapsed callbacks */
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferHalfCpltCallback = TIM_DMAPeriodElapsedHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC1:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC2:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC3:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC4:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_COM:
+    {
+      /* Set the DMA commutation callbacks */
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback =  TIMEx_DMACommutationCplt;
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback =  TIMEx_DMACommutationHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_TRIGGER:
+    {
+      /* Set the DMA trigger callbacks */
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt;
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferHalfCpltCallback = TIM_DMATriggerHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Configure the DMA Burst Mode */
+    htim->Instance->DCR = (BurstBaseAddress | BurstLength);
+
+    /* Enable the TIM DMA Request */
+    __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stop the DMA burst reading
+  * @param  htim TIM handle
+  * @param  BurstRequestSrc TIM DMA Request sources to disable.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+
+  /* Abort the DMA transfer (at least disable the DMA stream) */
+  switch (BurstRequestSrc)
+  {
+    case TIM_DMA_UPDATE:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+      break;
+    }
+    case TIM_DMA_CC1:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+    case TIM_DMA_CC2:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+    case TIM_DMA_CC3:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+    case TIM_DMA_CC4:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+      break;
+    }
+    case TIM_DMA_COM:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_COMMUTATION]);
+      break;
+    }
+    case TIM_DMA_TRIGGER:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_TRIGGER]);
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the TIM Update DMA request */
+    __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc);
+
+    /* Change the DMA burst operation state */
+    htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Generate a software event
+  * @param  htim TIM handle
+  * @param  EventSource specifies the event source.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_EVENTSOURCE_UPDATE: Timer update Event source
+  *            @arg TIM_EVENTSOURCE_CC1: Timer Capture Compare 1 Event source
+  *            @arg TIM_EVENTSOURCE_CC2: Timer Capture Compare 2 Event source
+  *            @arg TIM_EVENTSOURCE_CC3: Timer Capture Compare 3 Event source
+  *            @arg TIM_EVENTSOURCE_CC4: Timer Capture Compare 4 Event source
+  *            @arg TIM_EVENTSOURCE_COM: Timer COM event source
+  *            @arg TIM_EVENTSOURCE_TRIGGER: Timer Trigger Event source
+  *            @arg TIM_EVENTSOURCE_BREAK: Timer Break event source
+  * @note   Basic timers can only generate an update event.
+  * @note   TIM_EVENTSOURCE_COM is relevant only with advanced timer instances.
+  * @note   TIM_EVENTSOURCE_BREAK are relevant only for timer instances
+  *         supporting a break input.
+  * @retval HAL status
+  */
+
+HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_EVENT_SOURCE(EventSource));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  /* Change the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Set the event sources */
+  htim->Instance->EGR = EventSource;
+
+  /* Change the TIM state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the OCRef clear feature
+  * @param  htim TIM handle
+  * @param  sClearInputConfig pointer to a TIM_ClearInputConfigTypeDef structure that
+  *         contains the OCREF clear feature and parameters for the TIM peripheral.
+  * @param  Channel specifies the TIM Channel
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1
+  *            @arg TIM_CHANNEL_2: TIM Channel 2
+  *            @arg TIM_CHANNEL_3: TIM Channel 3
+  *            @arg TIM_CHANNEL_4: TIM Channel 4
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim,
+                                           const TIM_ClearInputConfigTypeDef *sClearInputConfig,
+                                           uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_OCXREF_CLEAR_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_CLEARINPUT_SOURCE(sClearInputConfig->ClearInputSource));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  switch (sClearInputConfig->ClearInputSource)
+  {
+    case TIM_CLEARINPUTSOURCE_NONE:
+    {
+      /* Clear the OCREF clear selection bit and the the ETR Bits */
+      CLEAR_BIT(htim->Instance->SMCR, (TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP));
+      break;
+    }
+
+    case TIM_CLEARINPUTSOURCE_ETR:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CLEARINPUT_POLARITY(sClearInputConfig->ClearInputPolarity));
+      assert_param(IS_TIM_CLEARINPUT_PRESCALER(sClearInputConfig->ClearInputPrescaler));
+      assert_param(IS_TIM_CLEARINPUT_FILTER(sClearInputConfig->ClearInputFilter));
+
+      /* When OCRef clear feature is used with ETR source, ETR prescaler must be off */
+      if (sClearInputConfig->ClearInputPrescaler != TIM_CLEARINPUTPRESCALER_DIV1)
+      {
+        htim->State = HAL_TIM_STATE_READY;
+        __HAL_UNLOCK(htim);
+        return HAL_ERROR;
+      }
+
+      TIM_ETR_SetConfig(htim->Instance,
+                        sClearInputConfig->ClearInputPrescaler,
+                        sClearInputConfig->ClearInputPolarity,
+                        sClearInputConfig->ClearInputFilter);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    switch (Channel)
+    {
+      case TIM_CHANNEL_1:
+      {
+        if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+        {
+          /* Enable the OCREF clear feature for Channel 1 */
+          SET_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC1CE);
+        }
+        else
+        {
+          /* Disable the OCREF clear feature for Channel 1 */
+          CLEAR_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC1CE);
+        }
+        break;
+      }
+      case TIM_CHANNEL_2:
+      {
+        if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+        {
+          /* Enable the OCREF clear feature for Channel 2 */
+          SET_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC2CE);
+        }
+        else
+        {
+          /* Disable the OCREF clear feature for Channel 2 */
+          CLEAR_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC2CE);
+        }
+        break;
+      }
+      case TIM_CHANNEL_3:
+      {
+        if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+        {
+          /* Enable the OCREF clear feature for Channel 3 */
+          SET_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC3CE);
+        }
+        else
+        {
+          /* Disable the OCREF clear feature for Channel 3 */
+          CLEAR_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC3CE);
+        }
+        break;
+      }
+      case TIM_CHANNEL_4:
+      {
+        if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+        {
+          /* Enable the OCREF clear feature for Channel 4 */
+          SET_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC4CE);
+        }
+        else
+        {
+          /* Disable the OCREF clear feature for Channel 4 */
+          CLEAR_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC4CE);
+        }
+        break;
+      }
+      default:
+        break;
+    }
+  }
+
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief   Configures the clock source to be used
+  * @param  htim TIM handle
+  * @param  sClockSourceConfig pointer to a TIM_ClockConfigTypeDef structure that
+  *         contains the clock source information for the TIM peripheral.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, const TIM_ClockConfigTypeDef *sClockSourceConfig)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CLOCKSOURCE(sClockSourceConfig->ClockSource));
+
+  /* Reset the SMS, TS, ECE, ETPS and ETRF bits */
+  tmpsmcr = htim->Instance->SMCR;
+  tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS);
+  tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);
+  htim->Instance->SMCR = tmpsmcr;
+
+  switch (sClockSourceConfig->ClockSource)
+  {
+    case TIM_CLOCKSOURCE_INTERNAL:
+    {
+      assert_param(IS_TIM_INSTANCE(htim->Instance));
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_ETRMODE1:
+    {
+      /* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/
+      assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance));
+
+      /* Check ETR input conditioning related parameters */
+      assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
+      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+      /* Configure the ETR Clock source */
+      TIM_ETR_SetConfig(htim->Instance,
+                        sClockSourceConfig->ClockPrescaler,
+                        sClockSourceConfig->ClockPolarity,
+                        sClockSourceConfig->ClockFilter);
+
+      /* Select the External clock mode1 and the ETRF trigger */
+      tmpsmcr = htim->Instance->SMCR;
+      tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1);
+      /* Write to TIMx SMCR */
+      htim->Instance->SMCR = tmpsmcr;
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_ETRMODE2:
+    {
+      /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/
+      assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance));
+
+      /* Check ETR input conditioning related parameters */
+      assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
+      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+      /* Configure the ETR Clock source */
+      TIM_ETR_SetConfig(htim->Instance,
+                        sClockSourceConfig->ClockPrescaler,
+                        sClockSourceConfig->ClockPolarity,
+                        sClockSourceConfig->ClockFilter);
+      /* Enable the External clock mode2 */
+      htim->Instance->SMCR |= TIM_SMCR_ECE;
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_TI1:
+    {
+      /* Check whether or not the timer instance supports external clock mode 1 */
+      assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+
+      /* Check TI1 input conditioning related parameters */
+      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+      TIM_TI1_ConfigInputStage(htim->Instance,
+                               sClockSourceConfig->ClockPolarity,
+                               sClockSourceConfig->ClockFilter);
+      TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1);
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_TI2:
+    {
+      /* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/
+      assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+
+      /* Check TI2 input conditioning related parameters */
+      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+      TIM_TI2_ConfigInputStage(htim->Instance,
+                               sClockSourceConfig->ClockPolarity,
+                               sClockSourceConfig->ClockFilter);
+      TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2);
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_TI1ED:
+    {
+      /* Check whether or not the timer instance supports external clock mode 1 */
+      assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+
+      /* Check TI1 input conditioning related parameters */
+      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+      TIM_TI1_ConfigInputStage(htim->Instance,
+                               sClockSourceConfig->ClockPolarity,
+                               sClockSourceConfig->ClockFilter);
+      TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED);
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_ITR0:
+    case TIM_CLOCKSOURCE_ITR1:
+    case TIM_CLOCKSOURCE_ITR2:
+    case TIM_CLOCKSOURCE_ITR3:
+    {
+      /* Check whether or not the timer instance supports internal trigger input */
+      assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
+
+      TIM_ITRx_SetConfig(htim->Instance, sClockSourceConfig->ClockSource);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief  Selects the signal connected to the TI1 input: direct from CH1_input
+  *         or a XOR combination between CH1_input, CH2_input & CH3_input
+  * @param  htim TIM handle.
+  * @param  TI1_Selection Indicate whether or not channel 1 is connected to the
+  *         output of a XOR gate.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_TI1SELECTION_CH1: The TIMx_CH1 pin is connected to TI1 input
+  *            @arg TIM_TI1SELECTION_XORCOMBINATION: The TIMx_CH1, CH2 and CH3
+  *            pins are connected to the TI1 input (XOR combination)
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection)
+{
+  uint32_t tmpcr2;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_XOR_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_TI1SELECTION(TI1_Selection));
+
+  /* Get the TIMx CR2 register value */
+  tmpcr2 = htim->Instance->CR2;
+
+  /* Reset the TI1 selection */
+  tmpcr2 &= ~TIM_CR2_TI1S;
+
+  /* Set the TI1 selection */
+  tmpcr2 |= TI1_Selection;
+
+  /* Write to TIMxCR2 */
+  htim->Instance->CR2 = tmpcr2;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the TIM in Slave mode
+  * @param  htim TIM handle.
+  * @param  sSlaveConfig pointer to a TIM_SlaveConfigTypeDef structure that
+  *         contains the selected trigger (internal trigger input, filtered
+  *         timer input or external trigger input) and the Slave mode
+  *         (Disable, Reset, Gated, Trigger, External clock mode 1).
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro(TIM_HandleTypeDef *htim, const TIM_SlaveConfigTypeDef *sSlaveConfig)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_SLAVE_MODE(sSlaveConfig->SlaveMode));
+  assert_param(IS_TIM_TRIGGER_SELECTION(sSlaveConfig->InputTrigger));
+
+  __HAL_LOCK(htim);
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  if (TIM_SlaveTimer_SetConfig(htim, sSlaveConfig) != HAL_OK)
+  {
+    htim->State = HAL_TIM_STATE_READY;
+    __HAL_UNLOCK(htim);
+    return HAL_ERROR;
+  }
+
+  /* Disable Trigger Interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_TRIGGER);
+
+  /* Disable Trigger DMA request */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_TRIGGER);
+
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the TIM in Slave mode in interrupt mode
+  * @param  htim TIM handle.
+  * @param  sSlaveConfig pointer to a TIM_SlaveConfigTypeDef structure that
+  *         contains the selected trigger (internal trigger input, filtered
+  *         timer input or external trigger input) and the Slave mode
+  *         (Disable, Reset, Gated, Trigger, External clock mode 1).
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro_IT(TIM_HandleTypeDef *htim,
+                                                const TIM_SlaveConfigTypeDef *sSlaveConfig)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_SLAVE_MODE(sSlaveConfig->SlaveMode));
+  assert_param(IS_TIM_TRIGGER_SELECTION(sSlaveConfig->InputTrigger));
+
+  __HAL_LOCK(htim);
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  if (TIM_SlaveTimer_SetConfig(htim, sSlaveConfig) != HAL_OK)
+  {
+    htim->State = HAL_TIM_STATE_READY;
+    __HAL_UNLOCK(htim);
+    return HAL_ERROR;
+  }
+
+  /* Enable Trigger Interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_TRIGGER);
+
+  /* Disable Trigger DMA request */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_TRIGGER);
+
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Read the captured value from Capture Compare unit
+  * @param  htim TIM handle.
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval Captured value
+  */
+uint32_t HAL_TIM_ReadCapturedValue(const TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpreg = 0U;
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+      /* Return the capture 1 value */
+      tmpreg =  htim->Instance->CCR1;
+
+      break;
+    }
+    case TIM_CHANNEL_2:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+      /* Return the capture 2 value */
+      tmpreg =   htim->Instance->CCR2;
+
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+      /* Return the capture 3 value */
+      tmpreg =   htim->Instance->CCR3;
+
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+      /* Return the capture 4 value */
+      tmpreg =   htim->Instance->CCR4;
+
+      break;
+    }
+
+    default:
+      break;
+  }
+
+  return tmpreg;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group9 TIM Callbacks functions
+  *  @brief    TIM Callbacks functions
+  *
+@verbatim
+  ==============================================================================
+                        ##### TIM Callbacks functions #####
+  ==============================================================================
+ [..]
+   This section provides TIM callback functions:
+   (+) TIM Period elapsed callback
+   (+) TIM Output Compare callback
+   (+) TIM Input capture callback
+   (+) TIM Trigger callback
+   (+) TIM Error callback
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Period elapsed callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PeriodElapsedCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Period elapsed half complete callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PeriodElapsedHalfCpltCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Output Compare callback in non-blocking mode
+  * @param  htim TIM OC handle
+  * @retval None
+  */
+__weak void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_OC_DelayElapsedCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Input Capture callback in non-blocking mode
+  * @param  htim TIM IC handle
+  * @retval None
+  */
+__weak void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_IC_CaptureCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Input Capture half complete callback in non-blocking mode
+  * @param  htim TIM IC handle
+  * @retval None
+  */
+__weak void HAL_TIM_IC_CaptureHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_IC_CaptureHalfCpltCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  PWM Pulse finished callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PWM_PulseFinishedCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  PWM Pulse finished half complete callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PWM_PulseFinishedHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PWM_PulseFinishedHalfCpltCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Hall Trigger detection callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_TriggerCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Hall Trigger detection half complete callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_TriggerHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_TriggerHalfCpltCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Timer error callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_ErrorCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_ErrorCallback could be implemented in the user file
+   */
+}
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+/**
+  * @brief  Register a User TIM callback to be used instead of the weak predefined callback
+  * @param htim tim handle
+  * @param CallbackID ID of the callback to be registered
+  *        This parameter can be one of the following values:
+  *          @arg @ref HAL_TIM_BASE_MSPINIT_CB_ID Base MspInit Callback ID
+  *          @arg @ref HAL_TIM_BASE_MSPDEINIT_CB_ID Base MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_IC_MSPINIT_CB_ID IC MspInit Callback ID
+  *          @arg @ref HAL_TIM_IC_MSPDEINIT_CB_ID IC MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_OC_MSPINIT_CB_ID OC MspInit Callback ID
+  *          @arg @ref HAL_TIM_OC_MSPDEINIT_CB_ID OC MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_PWM_MSPINIT_CB_ID PWM MspInit Callback ID
+  *          @arg @ref HAL_TIM_PWM_MSPDEINIT_CB_ID PWM MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_ONE_PULSE_MSPINIT_CB_ID One Pulse MspInit Callback ID
+  *          @arg @ref HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID One Pulse MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_ENCODER_MSPINIT_CB_ID Encoder MspInit Callback ID
+  *          @arg @ref HAL_TIM_ENCODER_MSPDEINIT_CB_ID Encoder MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID Hall Sensor MspInit Callback ID
+  *          @arg @ref HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID Hall Sensor MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_PERIOD_ELAPSED_CB_ID Period Elapsed Callback ID
+  *          @arg @ref HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID Period Elapsed half complete Callback ID
+  *          @arg @ref HAL_TIM_TRIGGER_CB_ID Trigger Callback ID
+  *          @arg @ref HAL_TIM_TRIGGER_HALF_CB_ID Trigger half complete Callback ID
+  *          @arg @ref HAL_TIM_IC_CAPTURE_CB_ID Input Capture Callback ID
+  *          @arg @ref HAL_TIM_IC_CAPTURE_HALF_CB_ID Input Capture half complete Callback ID
+  *          @arg @ref HAL_TIM_OC_DELAY_ELAPSED_CB_ID Output Compare Delay Elapsed Callback ID
+  *          @arg @ref HAL_TIM_PWM_PULSE_FINISHED_CB_ID PWM Pulse Finished Callback ID
+  *          @arg @ref HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID PWM Pulse Finished half complete Callback ID
+  *          @arg @ref HAL_TIM_ERROR_CB_ID Error Callback ID
+  *          @arg @ref HAL_TIM_COMMUTATION_CB_ID Commutation Callback ID
+  *          @arg @ref HAL_TIM_COMMUTATION_HALF_CB_ID Commutation half complete Callback ID
+  *          @arg @ref HAL_TIM_BREAK_CB_ID Break Callback ID
+  *          @param pCallback pointer to the callback function
+  *          @retval status
+  */
+HAL_StatusTypeDef HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID,
+                                           pTIM_CallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  if (htim->State == HAL_TIM_STATE_READY)
+  {
+    switch (CallbackID)
+    {
+      case HAL_TIM_BASE_MSPINIT_CB_ID :
+        htim->Base_MspInitCallback                 = pCallback;
+        break;
+
+      case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+        htim->Base_MspDeInitCallback               = pCallback;
+        break;
+
+      case HAL_TIM_IC_MSPINIT_CB_ID :
+        htim->IC_MspInitCallback                   = pCallback;
+        break;
+
+      case HAL_TIM_IC_MSPDEINIT_CB_ID :
+        htim->IC_MspDeInitCallback                 = pCallback;
+        break;
+
+      case HAL_TIM_OC_MSPINIT_CB_ID :
+        htim->OC_MspInitCallback                   = pCallback;
+        break;
+
+      case HAL_TIM_OC_MSPDEINIT_CB_ID :
+        htim->OC_MspDeInitCallback                 = pCallback;
+        break;
+
+      case HAL_TIM_PWM_MSPINIT_CB_ID :
+        htim->PWM_MspInitCallback                  = pCallback;
+        break;
+
+      case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+        htim->PWM_MspDeInitCallback                = pCallback;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+        htim->OnePulse_MspInitCallback             = pCallback;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+        htim->OnePulse_MspDeInitCallback           = pCallback;
+        break;
+
+      case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+        htim->Encoder_MspInitCallback              = pCallback;
+        break;
+
+      case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+        htim->Encoder_MspDeInitCallback            = pCallback;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+        htim->HallSensor_MspInitCallback           = pCallback;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+        htim->HallSensor_MspDeInitCallback         = pCallback;
+        break;
+
+      case HAL_TIM_PERIOD_ELAPSED_CB_ID :
+        htim->PeriodElapsedCallback                = pCallback;
+        break;
+
+      case HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID :
+        htim->PeriodElapsedHalfCpltCallback        = pCallback;
+        break;
+
+      case HAL_TIM_TRIGGER_CB_ID :
+        htim->TriggerCallback                      = pCallback;
+        break;
+
+      case HAL_TIM_TRIGGER_HALF_CB_ID :
+        htim->TriggerHalfCpltCallback              = pCallback;
+        break;
+
+      case HAL_TIM_IC_CAPTURE_CB_ID :
+        htim->IC_CaptureCallback                   = pCallback;
+        break;
+
+      case HAL_TIM_IC_CAPTURE_HALF_CB_ID :
+        htim->IC_CaptureHalfCpltCallback           = pCallback;
+        break;
+
+      case HAL_TIM_OC_DELAY_ELAPSED_CB_ID :
+        htim->OC_DelayElapsedCallback              = pCallback;
+        break;
+
+      case HAL_TIM_PWM_PULSE_FINISHED_CB_ID :
+        htim->PWM_PulseFinishedCallback            = pCallback;
+        break;
+
+      case HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID :
+        htim->PWM_PulseFinishedHalfCpltCallback    = pCallback;
+        break;
+
+      case HAL_TIM_ERROR_CB_ID :
+        htim->ErrorCallback                        = pCallback;
+        break;
+
+      case HAL_TIM_COMMUTATION_CB_ID :
+        htim->CommutationCallback                  = pCallback;
+        break;
+
+      case HAL_TIM_COMMUTATION_HALF_CB_ID :
+        htim->CommutationHalfCpltCallback          = pCallback;
+        break;
+
+      case HAL_TIM_BREAK_CB_ID :
+        htim->BreakCallback                        = pCallback;
+        break;
+
+      default :
+        /* Return error status */
+        status = HAL_ERROR;
+        break;
+    }
+  }
+  else if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    switch (CallbackID)
+    {
+      case HAL_TIM_BASE_MSPINIT_CB_ID :
+        htim->Base_MspInitCallback         = pCallback;
+        break;
+
+      case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+        htim->Base_MspDeInitCallback       = pCallback;
+        break;
+
+      case HAL_TIM_IC_MSPINIT_CB_ID :
+        htim->IC_MspInitCallback           = pCallback;
+        break;
+
+      case HAL_TIM_IC_MSPDEINIT_CB_ID :
+        htim->IC_MspDeInitCallback         = pCallback;
+        break;
+
+      case HAL_TIM_OC_MSPINIT_CB_ID :
+        htim->OC_MspInitCallback           = pCallback;
+        break;
+
+      case HAL_TIM_OC_MSPDEINIT_CB_ID :
+        htim->OC_MspDeInitCallback         = pCallback;
+        break;
+
+      case HAL_TIM_PWM_MSPINIT_CB_ID :
+        htim->PWM_MspInitCallback          = pCallback;
+        break;
+
+      case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+        htim->PWM_MspDeInitCallback        = pCallback;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+        htim->OnePulse_MspInitCallback     = pCallback;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+        htim->OnePulse_MspDeInitCallback   = pCallback;
+        break;
+
+      case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+        htim->Encoder_MspInitCallback      = pCallback;
+        break;
+
+      case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+        htim->Encoder_MspDeInitCallback    = pCallback;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+        htim->HallSensor_MspInitCallback   = pCallback;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+        htim->HallSensor_MspDeInitCallback = pCallback;
+        break;
+
+      default :
+        /* Return error status */
+        status = HAL_ERROR;
+        break;
+    }
+  }
+  else
+  {
+    /* Return error status */
+    status = HAL_ERROR;
+  }
+
+  return status;
+}
+
+/**
+  * @brief  Unregister a TIM callback
+  *         TIM callback is redirected to the weak predefined callback
+  * @param htim tim handle
+  * @param CallbackID ID of the callback to be unregistered
+  *        This parameter can be one of the following values:
+  *          @arg @ref HAL_TIM_BASE_MSPINIT_CB_ID Base MspInit Callback ID
+  *          @arg @ref HAL_TIM_BASE_MSPDEINIT_CB_ID Base MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_IC_MSPINIT_CB_ID IC MspInit Callback ID
+  *          @arg @ref HAL_TIM_IC_MSPDEINIT_CB_ID IC MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_OC_MSPINIT_CB_ID OC MspInit Callback ID
+  *          @arg @ref HAL_TIM_OC_MSPDEINIT_CB_ID OC MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_PWM_MSPINIT_CB_ID PWM MspInit Callback ID
+  *          @arg @ref HAL_TIM_PWM_MSPDEINIT_CB_ID PWM MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_ONE_PULSE_MSPINIT_CB_ID One Pulse MspInit Callback ID
+  *          @arg @ref HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID One Pulse MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_ENCODER_MSPINIT_CB_ID Encoder MspInit Callback ID
+  *          @arg @ref HAL_TIM_ENCODER_MSPDEINIT_CB_ID Encoder MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID Hall Sensor MspInit Callback ID
+  *          @arg @ref HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID Hall Sensor MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_PERIOD_ELAPSED_CB_ID Period Elapsed Callback ID
+  *          @arg @ref HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID Period Elapsed half complete Callback ID
+  *          @arg @ref HAL_TIM_TRIGGER_CB_ID Trigger Callback ID
+  *          @arg @ref HAL_TIM_TRIGGER_HALF_CB_ID Trigger half complete Callback ID
+  *          @arg @ref HAL_TIM_IC_CAPTURE_CB_ID Input Capture Callback ID
+  *          @arg @ref HAL_TIM_IC_CAPTURE_HALF_CB_ID Input Capture half complete Callback ID
+  *          @arg @ref HAL_TIM_OC_DELAY_ELAPSED_CB_ID Output Compare Delay Elapsed Callback ID
+  *          @arg @ref HAL_TIM_PWM_PULSE_FINISHED_CB_ID PWM Pulse Finished Callback ID
+  *          @arg @ref HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID PWM Pulse Finished half complete Callback ID
+  *          @arg @ref HAL_TIM_ERROR_CB_ID Error Callback ID
+  *          @arg @ref HAL_TIM_COMMUTATION_CB_ID Commutation Callback ID
+  *          @arg @ref HAL_TIM_COMMUTATION_HALF_CB_ID Commutation half complete Callback ID
+  *          @arg @ref HAL_TIM_BREAK_CB_ID Break Callback ID
+  *          @retval status
+  */
+HAL_StatusTypeDef HAL_TIM_UnRegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (htim->State == HAL_TIM_STATE_READY)
+  {
+    switch (CallbackID)
+    {
+      case HAL_TIM_BASE_MSPINIT_CB_ID :
+        /* Legacy weak Base MspInit Callback */
+        htim->Base_MspInitCallback              = HAL_TIM_Base_MspInit;
+        break;
+
+      case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+        /* Legacy weak Base Msp DeInit Callback */
+        htim->Base_MspDeInitCallback            = HAL_TIM_Base_MspDeInit;
+        break;
+
+      case HAL_TIM_IC_MSPINIT_CB_ID :
+        /* Legacy weak IC Msp Init Callback */
+        htim->IC_MspInitCallback                = HAL_TIM_IC_MspInit;
+        break;
+
+      case HAL_TIM_IC_MSPDEINIT_CB_ID :
+        /* Legacy weak IC Msp DeInit Callback */
+        htim->IC_MspDeInitCallback              = HAL_TIM_IC_MspDeInit;
+        break;
+
+      case HAL_TIM_OC_MSPINIT_CB_ID :
+        /* Legacy weak OC Msp Init Callback */
+        htim->OC_MspInitCallback                = HAL_TIM_OC_MspInit;
+        break;
+
+      case HAL_TIM_OC_MSPDEINIT_CB_ID :
+        /* Legacy weak OC Msp DeInit Callback */
+        htim->OC_MspDeInitCallback              = HAL_TIM_OC_MspDeInit;
+        break;
+
+      case HAL_TIM_PWM_MSPINIT_CB_ID :
+        /* Legacy weak PWM Msp Init Callback */
+        htim->PWM_MspInitCallback               = HAL_TIM_PWM_MspInit;
+        break;
+
+      case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+        /* Legacy weak PWM Msp DeInit Callback */
+        htim->PWM_MspDeInitCallback             = HAL_TIM_PWM_MspDeInit;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+        /* Legacy weak One Pulse Msp Init Callback */
+        htim->OnePulse_MspInitCallback          = HAL_TIM_OnePulse_MspInit;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+        /* Legacy weak One Pulse Msp DeInit Callback */
+        htim->OnePulse_MspDeInitCallback        = HAL_TIM_OnePulse_MspDeInit;
+        break;
+
+      case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+        /* Legacy weak Encoder Msp Init Callback */
+        htim->Encoder_MspInitCallback           = HAL_TIM_Encoder_MspInit;
+        break;
+
+      case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+        /* Legacy weak Encoder Msp DeInit Callback */
+        htim->Encoder_MspDeInitCallback         = HAL_TIM_Encoder_MspDeInit;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+        /* Legacy weak Hall Sensor Msp Init Callback */
+        htim->HallSensor_MspInitCallback        = HAL_TIMEx_HallSensor_MspInit;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+        /* Legacy weak Hall Sensor Msp DeInit Callback */
+        htim->HallSensor_MspDeInitCallback      = HAL_TIMEx_HallSensor_MspDeInit;
+        break;
+
+      case HAL_TIM_PERIOD_ELAPSED_CB_ID :
+        /* Legacy weak Period Elapsed Callback */
+        htim->PeriodElapsedCallback             = HAL_TIM_PeriodElapsedCallback;
+        break;
+
+      case HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID :
+        /* Legacy weak Period Elapsed half complete Callback */
+        htim->PeriodElapsedHalfCpltCallback     = HAL_TIM_PeriodElapsedHalfCpltCallback;
+        break;
+
+      case HAL_TIM_TRIGGER_CB_ID :
+        /* Legacy weak Trigger Callback */
+        htim->TriggerCallback                   = HAL_TIM_TriggerCallback;
+        break;
+
+      case HAL_TIM_TRIGGER_HALF_CB_ID :
+        /* Legacy weak Trigger half complete Callback */
+        htim->TriggerHalfCpltCallback           = HAL_TIM_TriggerHalfCpltCallback;
+        break;
+
+      case HAL_TIM_IC_CAPTURE_CB_ID :
+        /* Legacy weak IC Capture Callback */
+        htim->IC_CaptureCallback                = HAL_TIM_IC_CaptureCallback;
+        break;
+
+      case HAL_TIM_IC_CAPTURE_HALF_CB_ID :
+        /* Legacy weak IC Capture half complete Callback */
+        htim->IC_CaptureHalfCpltCallback        = HAL_TIM_IC_CaptureHalfCpltCallback;
+        break;
+
+      case HAL_TIM_OC_DELAY_ELAPSED_CB_ID :
+        /* Legacy weak OC Delay Elapsed Callback */
+        htim->OC_DelayElapsedCallback           = HAL_TIM_OC_DelayElapsedCallback;
+        break;
+
+      case HAL_TIM_PWM_PULSE_FINISHED_CB_ID :
+        /* Legacy weak PWM Pulse Finished Callback */
+        htim->PWM_PulseFinishedCallback         = HAL_TIM_PWM_PulseFinishedCallback;
+        break;
+
+      case HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID :
+        /* Legacy weak PWM Pulse Finished half complete Callback */
+        htim->PWM_PulseFinishedHalfCpltCallback = HAL_TIM_PWM_PulseFinishedHalfCpltCallback;
+        break;
+
+      case HAL_TIM_ERROR_CB_ID :
+        /* Legacy weak Error Callback */
+        htim->ErrorCallback                     = HAL_TIM_ErrorCallback;
+        break;
+
+      case HAL_TIM_COMMUTATION_CB_ID :
+        /* Legacy weak Commutation Callback */
+        htim->CommutationCallback               = HAL_TIMEx_CommutCallback;
+        break;
+
+      case HAL_TIM_COMMUTATION_HALF_CB_ID :
+        /* Legacy weak Commutation half complete Callback */
+        htim->CommutationHalfCpltCallback       = HAL_TIMEx_CommutHalfCpltCallback;
+        break;
+
+      case HAL_TIM_BREAK_CB_ID :
+        /* Legacy weak Break Callback */
+        htim->BreakCallback                     = HAL_TIMEx_BreakCallback;
+        break;
+
+      default :
+        /* Return error status */
+        status = HAL_ERROR;
+        break;
+    }
+  }
+  else if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    switch (CallbackID)
+    {
+      case HAL_TIM_BASE_MSPINIT_CB_ID :
+        /* Legacy weak Base MspInit Callback */
+        htim->Base_MspInitCallback         = HAL_TIM_Base_MspInit;
+        break;
+
+      case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+        /* Legacy weak Base Msp DeInit Callback */
+        htim->Base_MspDeInitCallback       = HAL_TIM_Base_MspDeInit;
+        break;
+
+      case HAL_TIM_IC_MSPINIT_CB_ID :
+        /* Legacy weak IC Msp Init Callback */
+        htim->IC_MspInitCallback           = HAL_TIM_IC_MspInit;
+        break;
+
+      case HAL_TIM_IC_MSPDEINIT_CB_ID :
+        /* Legacy weak IC Msp DeInit Callback */
+        htim->IC_MspDeInitCallback         = HAL_TIM_IC_MspDeInit;
+        break;
+
+      case HAL_TIM_OC_MSPINIT_CB_ID :
+        /* Legacy weak OC Msp Init Callback */
+        htim->OC_MspInitCallback           = HAL_TIM_OC_MspInit;
+        break;
+
+      case HAL_TIM_OC_MSPDEINIT_CB_ID :
+        /* Legacy weak OC Msp DeInit Callback */
+        htim->OC_MspDeInitCallback         = HAL_TIM_OC_MspDeInit;
+        break;
+
+      case HAL_TIM_PWM_MSPINIT_CB_ID :
+        /* Legacy weak PWM Msp Init Callback */
+        htim->PWM_MspInitCallback          = HAL_TIM_PWM_MspInit;
+        break;
+
+      case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+        /* Legacy weak PWM Msp DeInit Callback */
+        htim->PWM_MspDeInitCallback        = HAL_TIM_PWM_MspDeInit;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+        /* Legacy weak One Pulse Msp Init Callback */
+        htim->OnePulse_MspInitCallback     = HAL_TIM_OnePulse_MspInit;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+        /* Legacy weak One Pulse Msp DeInit Callback */
+        htim->OnePulse_MspDeInitCallback   = HAL_TIM_OnePulse_MspDeInit;
+        break;
+
+      case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+        /* Legacy weak Encoder Msp Init Callback */
+        htim->Encoder_MspInitCallback      = HAL_TIM_Encoder_MspInit;
+        break;
+
+      case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+        /* Legacy weak Encoder Msp DeInit Callback */
+        htim->Encoder_MspDeInitCallback    = HAL_TIM_Encoder_MspDeInit;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+        /* Legacy weak Hall Sensor Msp Init Callback */
+        htim->HallSensor_MspInitCallback   = HAL_TIMEx_HallSensor_MspInit;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+        /* Legacy weak Hall Sensor Msp DeInit Callback */
+        htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit;
+        break;
+
+      default :
+        /* Return error status */
+        status = HAL_ERROR;
+        break;
+    }
+  }
+  else
+  {
+    /* Return error status */
+    status = HAL_ERROR;
+  }
+
+  return status;
+}
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group10 TIM Peripheral State functions
+  *  @brief   TIM Peripheral State functions
+  *
+@verbatim
+  ==============================================================================
+                        ##### Peripheral State functions #####
+  ==============================================================================
+    [..]
+    This subsection permits to get in run-time the status of the peripheral
+    and the data flow.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Return the TIM Base handle state.
+  * @param  htim TIM Base handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM OC handle state.
+  * @param  htim TIM Output Compare handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM PWM handle state.
+  * @param  htim TIM handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM Input Capture handle state.
+  * @param  htim TIM IC handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM One Pulse Mode handle state.
+  * @param  htim TIM OPM handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM Encoder Mode handle state.
+  * @param  htim TIM Encoder Interface handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM Encoder Mode handle state.
+  * @param  htim TIM handle
+  * @retval Active channel
+  */
+HAL_TIM_ActiveChannel HAL_TIM_GetActiveChannel(const TIM_HandleTypeDef *htim)
+{
+  return htim->Channel;
+}
+
+/**
+  * @brief  Return actual state of the TIM channel.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1
+  *            @arg TIM_CHANNEL_2: TIM Channel 2
+  *            @arg TIM_CHANNEL_3: TIM Channel 3
+  *            @arg TIM_CHANNEL_4: TIM Channel 4
+  *            @arg TIM_CHANNEL_5: TIM Channel 5
+  *            @arg TIM_CHANNEL_6: TIM Channel 6
+  * @retval TIM Channel state
+  */
+HAL_TIM_ChannelStateTypeDef HAL_TIM_GetChannelState(const TIM_HandleTypeDef *htim,  uint32_t Channel)
+{
+  HAL_TIM_ChannelStateTypeDef channel_state;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+
+  return channel_state;
+}
+
+/**
+  * @brief  Return actual state of a DMA burst operation.
+  * @param  htim TIM handle
+  * @retval DMA burst state
+  */
+HAL_TIM_DMABurstStateTypeDef HAL_TIM_DMABurstState(const TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance));
+
+  return htim->DMABurstState;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Private_Functions TIM Private Functions
+  * @{
+  */
+
+/**
+  * @brief  TIM DMA error callback
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIM_DMAError(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else
+  {
+    htim->State = HAL_TIM_STATE_READY;
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->ErrorCallback(htim);
+#else
+  HAL_TIM_ErrorCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA Delay Pulse complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->PWM_PulseFinishedCallback(htim);
+#else
+  HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA Delay Pulse half complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIM_DMADelayPulseHalfCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->PWM_PulseFinishedHalfCpltCallback(htim);
+#else
+  HAL_TIM_PWM_PulseFinishedHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA Capture complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIM_DMACaptureCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->IC_CaptureCallback(htim);
+#else
+  HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA Capture half complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIM_DMACaptureHalfCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->IC_CaptureHalfCpltCallback(htim);
+#else
+  HAL_TIM_IC_CaptureHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA Period Elapse complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (htim->hdma[TIM_DMA_ID_UPDATE]->Init.Mode == DMA_NORMAL)
+  {
+    htim->State = HAL_TIM_STATE_READY;
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->PeriodElapsedCallback(htim);
+#else
+  HAL_TIM_PeriodElapsedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  TIM DMA Period Elapse half complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMAPeriodElapsedHalfCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->PeriodElapsedHalfCpltCallback(htim);
+#else
+  HAL_TIM_PeriodElapsedHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  TIM DMA Trigger callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (htim->hdma[TIM_DMA_ID_TRIGGER]->Init.Mode == DMA_NORMAL)
+  {
+    htim->State = HAL_TIM_STATE_READY;
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->TriggerCallback(htim);
+#else
+  HAL_TIM_TriggerCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  TIM DMA Trigger half complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMATriggerHalfCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->TriggerHalfCpltCallback(htim);
+#else
+  HAL_TIM_TriggerHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  Time Base configuration
+  * @param  TIMx TIM peripheral
+  * @param  Structure TIM Base configuration structure
+  * @retval None
+  */
+void TIM_Base_SetConfig(TIM_TypeDef *TIMx, const TIM_Base_InitTypeDef *Structure)
+{
+  uint32_t tmpcr1;
+  tmpcr1 = TIMx->CR1;
+
+  /* Set TIM Time Base Unit parameters ---------------------------------------*/
+  if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx))
+  {
+    /* Select the Counter Mode */
+    tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
+    tmpcr1 |= Structure->CounterMode;
+  }
+
+  if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
+  {
+    /* Set the clock division */
+    tmpcr1 &= ~TIM_CR1_CKD;
+    tmpcr1 |= (uint32_t)Structure->ClockDivision;
+  }
+
+  /* Set the auto-reload preload */
+  MODIFY_REG(tmpcr1, TIM_CR1_ARPE, Structure->AutoReloadPreload);
+
+  TIMx->CR1 = tmpcr1;
+
+  /* Set the Autoreload value */
+  TIMx->ARR = (uint32_t)Structure->Period ;
+
+  /* Set the Prescaler value */
+  TIMx->PSC = Structure->Prescaler;
+
+  if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx))
+  {
+    /* Set the Repetition Counter value */
+    TIMx->RCR = Structure->RepetitionCounter;
+  }
+
+  /* Generate an update event to reload the Prescaler
+     and the repetition counter (only for advanced timer) value immediately */
+  TIMx->EGR = TIM_EGR_UG;
+
+  /* Check if the update flag is set after the Update Generation, if so clear the UIF flag */
+  if (HAL_IS_BIT_SET(TIMx->SR, TIM_FLAG_UPDATE))
+  {
+    /* Clear the update flag */
+    CLEAR_BIT(TIMx->SR, TIM_FLAG_UPDATE);
+  }
+}
+
+/**
+  * @brief  Timer Output Compare 1 configuration
+  * @param  TIMx to select the TIM peripheral
+  * @param  OC_Config The output configuration structure
+  * @retval None
+  */
+static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+  uint32_t tmpccmrx;
+  uint32_t tmpccer;
+  uint32_t tmpcr2;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = TIMx->CCER;
+
+  /* Disable the Channel 1: Reset the CC1E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC1E;
+
+  /* Get the TIMx CR2 register value */
+  tmpcr2 =  TIMx->CR2;
+
+  /* Get the TIMx CCMR1 register value */
+  tmpccmrx = TIMx->CCMR1;
+
+  /* Reset the Output Compare Mode Bits */
+  tmpccmrx &= ~TIM_CCMR1_OC1M;
+  tmpccmrx &= ~TIM_CCMR1_CC1S;
+  /* Select the Output Compare Mode */
+  tmpccmrx |= OC_Config->OCMode;
+
+  /* Reset the Output Polarity level */
+  tmpccer &= ~TIM_CCER_CC1P;
+  /* Set the Output Compare Polarity */
+  tmpccer |= OC_Config->OCPolarity;
+
+  if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1))
+  {
+    /* Check parameters */
+    assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+    /* Reset the Output N Polarity level */
+    tmpccer &= ~TIM_CCER_CC1NP;
+    /* Set the Output N Polarity */
+    tmpccer |= OC_Config->OCNPolarity;
+    /* Reset the Output N State */
+    tmpccer &= ~TIM_CCER_CC1NE;
+  }
+
+  if (IS_TIM_BREAK_INSTANCE(TIMx))
+  {
+    /* Check parameters */
+    assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+    assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+    /* Reset the Output Compare and Output Compare N IDLE State */
+    tmpcr2 &= ~TIM_CR2_OIS1;
+    tmpcr2 &= ~TIM_CR2_OIS1N;
+    /* Set the Output Idle state */
+    tmpcr2 |= OC_Config->OCIdleState;
+    /* Set the Output N Idle state */
+    tmpcr2 |= OC_Config->OCNIdleState;
+  }
+
+  /* Write to TIMx CR2 */
+  TIMx->CR2 = tmpcr2;
+
+  /* Write to TIMx CCMR1 */
+  TIMx->CCMR1 = tmpccmrx;
+
+  /* Set the Capture Compare Register value */
+  TIMx->CCR1 = OC_Config->Pulse;
+
+  /* Write to TIMx CCER */
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Timer Output Compare 2 configuration
+  * @param  TIMx to select the TIM peripheral
+  * @param  OC_Config The output configuration structure
+  * @retval None
+  */
+void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+  uint32_t tmpccmrx;
+  uint32_t tmpccer;
+  uint32_t tmpcr2;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = TIMx->CCER;
+
+  /* Disable the Channel 2: Reset the CC2E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC2E;
+
+  /* Get the TIMx CR2 register value */
+  tmpcr2 =  TIMx->CR2;
+
+  /* Get the TIMx CCMR1 register value */
+  tmpccmrx = TIMx->CCMR1;
+
+  /* Reset the Output Compare mode and Capture/Compare selection Bits */
+  tmpccmrx &= ~TIM_CCMR1_OC2M;
+  tmpccmrx &= ~TIM_CCMR1_CC2S;
+
+  /* Select the Output Compare Mode */
+  tmpccmrx |= (OC_Config->OCMode << 8U);
+
+  /* Reset the Output Polarity level */
+  tmpccer &= ~TIM_CCER_CC2P;
+  /* Set the Output Compare Polarity */
+  tmpccer |= (OC_Config->OCPolarity << 4U);
+
+  if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_2))
+  {
+    assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+    /* Reset the Output N Polarity level */
+    tmpccer &= ~TIM_CCER_CC2NP;
+    /* Set the Output N Polarity */
+    tmpccer |= (OC_Config->OCNPolarity << 4U);
+    /* Reset the Output N State */
+    tmpccer &= ~TIM_CCER_CC2NE;
+  }
+
+  if (IS_TIM_BREAK_INSTANCE(TIMx))
+  {
+    /* Check parameters */
+    assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+    assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+    /* Reset the Output Compare and Output Compare N IDLE State */
+    tmpcr2 &= ~TIM_CR2_OIS2;
+    tmpcr2 &= ~TIM_CR2_OIS2N;
+    /* Set the Output Idle state */
+    tmpcr2 |= (OC_Config->OCIdleState << 2U);
+    /* Set the Output N Idle state */
+    tmpcr2 |= (OC_Config->OCNIdleState << 2U);
+  }
+
+  /* Write to TIMx CR2 */
+  TIMx->CR2 = tmpcr2;
+
+  /* Write to TIMx CCMR1 */
+  TIMx->CCMR1 = tmpccmrx;
+
+  /* Set the Capture Compare Register value */
+  TIMx->CCR2 = OC_Config->Pulse;
+
+  /* Write to TIMx CCER */
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Timer Output Compare 3 configuration
+  * @param  TIMx to select the TIM peripheral
+  * @param  OC_Config The output configuration structure
+  * @retval None
+  */
+static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+  uint32_t tmpccmrx;
+  uint32_t tmpccer;
+  uint32_t tmpcr2;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = TIMx->CCER;
+
+  /* Disable the Channel 3: Reset the CC2E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC3E;
+
+  /* Get the TIMx CR2 register value */
+  tmpcr2 =  TIMx->CR2;
+
+  /* Get the TIMx CCMR2 register value */
+  tmpccmrx = TIMx->CCMR2;
+
+  /* Reset the Output Compare mode and Capture/Compare selection Bits */
+  tmpccmrx &= ~TIM_CCMR2_OC3M;
+  tmpccmrx &= ~TIM_CCMR2_CC3S;
+  /* Select the Output Compare Mode */
+  tmpccmrx |= OC_Config->OCMode;
+
+  /* Reset the Output Polarity level */
+  tmpccer &= ~TIM_CCER_CC3P;
+  /* Set the Output Compare Polarity */
+  tmpccer |= (OC_Config->OCPolarity << 8U);
+
+  if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_3))
+  {
+    assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+    /* Reset the Output N Polarity level */
+    tmpccer &= ~TIM_CCER_CC3NP;
+    /* Set the Output N Polarity */
+    tmpccer |= (OC_Config->OCNPolarity << 8U);
+    /* Reset the Output N State */
+    tmpccer &= ~TIM_CCER_CC3NE;
+  }
+
+  if (IS_TIM_BREAK_INSTANCE(TIMx))
+  {
+    /* Check parameters */
+    assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+    assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+    /* Reset the Output Compare and Output Compare N IDLE State */
+    tmpcr2 &= ~TIM_CR2_OIS3;
+    tmpcr2 &= ~TIM_CR2_OIS3N;
+    /* Set the Output Idle state */
+    tmpcr2 |= (OC_Config->OCIdleState << 4U);
+    /* Set the Output N Idle state */
+    tmpcr2 |= (OC_Config->OCNIdleState << 4U);
+  }
+
+  /* Write to TIMx CR2 */
+  TIMx->CR2 = tmpcr2;
+
+  /* Write to TIMx CCMR2 */
+  TIMx->CCMR2 = tmpccmrx;
+
+  /* Set the Capture Compare Register value */
+  TIMx->CCR3 = OC_Config->Pulse;
+
+  /* Write to TIMx CCER */
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Timer Output Compare 4 configuration
+  * @param  TIMx to select the TIM peripheral
+  * @param  OC_Config The output configuration structure
+  * @retval None
+  */
+static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+  uint32_t tmpccmrx;
+  uint32_t tmpccer;
+  uint32_t tmpcr2;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = TIMx->CCER;
+
+  /* Disable the Channel 4: Reset the CC4E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC4E;
+
+  /* Get the TIMx CR2 register value */
+  tmpcr2 =  TIMx->CR2;
+
+  /* Get the TIMx CCMR2 register value */
+  tmpccmrx = TIMx->CCMR2;
+
+  /* Reset the Output Compare mode and Capture/Compare selection Bits */
+  tmpccmrx &= ~TIM_CCMR2_OC4M;
+  tmpccmrx &= ~TIM_CCMR2_CC4S;
+
+  /* Select the Output Compare Mode */
+  tmpccmrx |= (OC_Config->OCMode << 8U);
+
+  /* Reset the Output Polarity level */
+  tmpccer &= ~TIM_CCER_CC4P;
+  /* Set the Output Compare Polarity */
+  tmpccer |= (OC_Config->OCPolarity << 12U);
+
+  if (IS_TIM_BREAK_INSTANCE(TIMx))
+  {
+    /* Check parameters */
+    assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+    /* Reset the Output Compare IDLE State */
+    tmpcr2 &= ~TIM_CR2_OIS4;
+
+    /* Set the Output Idle state */
+    tmpcr2 |= (OC_Config->OCIdleState << 6U);
+  }
+
+  /* Write to TIMx CR2 */
+  TIMx->CR2 = tmpcr2;
+
+  /* Write to TIMx CCMR2 */
+  TIMx->CCMR2 = tmpccmrx;
+
+  /* Set the Capture Compare Register value */
+  TIMx->CCR4 = OC_Config->Pulse;
+
+  /* Write to TIMx CCER */
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Slave Timer configuration function
+  * @param  htim TIM handle
+  * @param  sSlaveConfig Slave timer configuration
+  * @retval None
+  */
+static HAL_StatusTypeDef TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim,
+                                                  const TIM_SlaveConfigTypeDef *sSlaveConfig)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Get the TIMx SMCR register value */
+  tmpsmcr = htim->Instance->SMCR;
+
+  /* Reset the Trigger Selection Bits */
+  tmpsmcr &= ~TIM_SMCR_TS;
+  /* Set the Input Trigger source */
+  tmpsmcr |= sSlaveConfig->InputTrigger;
+
+  /* Reset the slave mode Bits */
+  tmpsmcr &= ~TIM_SMCR_SMS;
+  /* Set the slave mode */
+  tmpsmcr |= sSlaveConfig->SlaveMode;
+
+  /* Write to TIMx SMCR */
+  htim->Instance->SMCR = tmpsmcr;
+
+  /* Configure the trigger prescaler, filter, and polarity */
+  switch (sSlaveConfig->InputTrigger)
+  {
+    case TIM_TS_ETRF:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance));
+      assert_param(IS_TIM_TRIGGERPRESCALER(sSlaveConfig->TriggerPrescaler));
+      assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity));
+      assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+      /* Configure the ETR Trigger source */
+      TIM_ETR_SetConfig(htim->Instance,
+                        sSlaveConfig->TriggerPrescaler,
+                        sSlaveConfig->TriggerPolarity,
+                        sSlaveConfig->TriggerFilter);
+      break;
+    }
+
+    case TIM_TS_TI1F_ED:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+      assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+
+      if (sSlaveConfig->SlaveMode == TIM_SLAVEMODE_GATED)
+      {
+        return HAL_ERROR;
+      }
+
+      /* Disable the Channel 1: Reset the CC1E Bit */
+      tmpccer = htim->Instance->CCER;
+      htim->Instance->CCER &= ~TIM_CCER_CC1E;
+      tmpccmr1 = htim->Instance->CCMR1;
+
+      /* Set the filter */
+      tmpccmr1 &= ~TIM_CCMR1_IC1F;
+      tmpccmr1 |= ((sSlaveConfig->TriggerFilter) << 4U);
+
+      /* Write to TIMx CCMR1 and CCER registers */
+      htim->Instance->CCMR1 = tmpccmr1;
+      htim->Instance->CCER = tmpccer;
+      break;
+    }
+
+    case TIM_TS_TI1FP1:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+      assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity));
+      assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+
+      /* Configure TI1 Filter and Polarity */
+      TIM_TI1_ConfigInputStage(htim->Instance,
+                               sSlaveConfig->TriggerPolarity,
+                               sSlaveConfig->TriggerFilter);
+      break;
+    }
+
+    case TIM_TS_TI2FP2:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+      assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity));
+      assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+
+      /* Configure TI2 Filter and Polarity */
+      TIM_TI2_ConfigInputStage(htim->Instance,
+                               sSlaveConfig->TriggerPolarity,
+                               sSlaveConfig->TriggerFilter);
+      break;
+    }
+
+    case TIM_TS_ITR0:
+    case TIM_TS_ITR1:
+    case TIM_TS_ITR2:
+    case TIM_TS_ITR3:
+    {
+      /* Check the parameter */
+      assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  return status;
+}
+
+/**
+  * @brief  Configure the TI1 as Input.
+  * @param  TIMx to select the TIM peripheral.
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICSelection specifies the input to be used.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICSELECTION_DIRECTTI: TIM Input 1 is selected to be connected to IC1.
+  *            @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 1 is selected to be connected to IC2.
+  *            @arg TIM_ICSELECTION_TRC: TIM Input 1 is selected to be connected to TRC.
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @retval None
+  * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI2FP1
+  *       (on channel2 path) is used as the input signal. Therefore CCMR1 must be
+  *        protected against un-initialized filter and polarity values.
+  */
+void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                       uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 1: Reset the CC1E Bit */
+  tmpccer = TIMx->CCER;
+  TIMx->CCER &= ~TIM_CCER_CC1E;
+  tmpccmr1 = TIMx->CCMR1;
+
+  /* Select the Input */
+  if (IS_TIM_CC2_INSTANCE(TIMx) != RESET)
+  {
+    tmpccmr1 &= ~TIM_CCMR1_CC1S;
+    tmpccmr1 |= TIM_ICSelection;
+  }
+  else
+  {
+    tmpccmr1 |= TIM_CCMR1_CC1S_0;
+  }
+
+  /* Set the filter */
+  tmpccmr1 &= ~TIM_CCMR1_IC1F;
+  tmpccmr1 |= ((TIM_ICFilter << 4U) & TIM_CCMR1_IC1F);
+
+  /* Select the Polarity and set the CC1E Bit */
+  tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
+  tmpccer |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP));
+
+  /* Write to TIMx CCMR1 and CCER registers */
+  TIMx->CCMR1 = tmpccmr1;
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Configure the Polarity and Filter for TI1.
+  * @param  TIMx to select the TIM peripheral.
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @retval None
+  */
+static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 1: Reset the CC1E Bit */
+  tmpccer = TIMx->CCER;
+  TIMx->CCER &= ~TIM_CCER_CC1E;
+  tmpccmr1 = TIMx->CCMR1;
+
+  /* Set the filter */
+  tmpccmr1 &= ~TIM_CCMR1_IC1F;
+  tmpccmr1 |= (TIM_ICFilter << 4U);
+
+  /* Select the Polarity and set the CC1E Bit */
+  tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
+  tmpccer |= TIM_ICPolarity;
+
+  /* Write to TIMx CCMR1 and CCER registers */
+  TIMx->CCMR1 = tmpccmr1;
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Configure the TI2 as Input.
+  * @param  TIMx to select the TIM peripheral
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICSelection specifies the input to be used.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICSELECTION_DIRECTTI: TIM Input 2 is selected to be connected to IC2.
+  *            @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 2 is selected to be connected to IC1.
+  *            @arg TIM_ICSELECTION_TRC: TIM Input 2 is selected to be connected to TRC.
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @retval None
+  * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI1FP2
+  *       (on channel1 path) is used as the input signal. Therefore CCMR1 must be
+  *        protected against un-initialized filter and polarity values.
+  */
+static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 2: Reset the CC2E Bit */
+  tmpccer = TIMx->CCER;
+  TIMx->CCER &= ~TIM_CCER_CC2E;
+  tmpccmr1 = TIMx->CCMR1;
+
+  /* Select the Input */
+  tmpccmr1 &= ~TIM_CCMR1_CC2S;
+  tmpccmr1 |= (TIM_ICSelection << 8U);
+
+  /* Set the filter */
+  tmpccmr1 &= ~TIM_CCMR1_IC2F;
+  tmpccmr1 |= ((TIM_ICFilter << 12U) & TIM_CCMR1_IC2F);
+
+  /* Select the Polarity and set the CC2E Bit */
+  tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+  tmpccer |= ((TIM_ICPolarity << 4U) & (TIM_CCER_CC2P | TIM_CCER_CC2NP));
+
+  /* Write to TIMx CCMR1 and CCER registers */
+  TIMx->CCMR1 = tmpccmr1 ;
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Configure the Polarity and Filter for TI2.
+  * @param  TIMx to select the TIM peripheral.
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @retval None
+  */
+static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 2: Reset the CC2E Bit */
+  tmpccer = TIMx->CCER;
+  TIMx->CCER &= ~TIM_CCER_CC2E;
+  tmpccmr1 = TIMx->CCMR1;
+
+  /* Set the filter */
+  tmpccmr1 &= ~TIM_CCMR1_IC2F;
+  tmpccmr1 |= (TIM_ICFilter << 12U);
+
+  /* Select the Polarity and set the CC2E Bit */
+  tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+  tmpccer |= (TIM_ICPolarity << 4U);
+
+  /* Write to TIMx CCMR1 and CCER registers */
+  TIMx->CCMR1 = tmpccmr1 ;
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Configure the TI3 as Input.
+  * @param  TIMx to select the TIM peripheral
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICSelection specifies the input to be used.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICSELECTION_DIRECTTI: TIM Input 3 is selected to be connected to IC3.
+  *            @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 3 is selected to be connected to IC4.
+  *            @arg TIM_ICSELECTION_TRC: TIM Input 3 is selected to be connected to TRC.
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @retval None
+  * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI3FP4
+  *       (on channel1 path) is used as the input signal. Therefore CCMR2 must be
+  *        protected against un-initialized filter and polarity values.
+  */
+static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr2;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 3: Reset the CC3E Bit */
+  tmpccer = TIMx->CCER;
+  TIMx->CCER &= ~TIM_CCER_CC3E;
+  tmpccmr2 = TIMx->CCMR2;
+
+  /* Select the Input */
+  tmpccmr2 &= ~TIM_CCMR2_CC3S;
+  tmpccmr2 |= TIM_ICSelection;
+
+  /* Set the filter */
+  tmpccmr2 &= ~TIM_CCMR2_IC3F;
+  tmpccmr2 |= ((TIM_ICFilter << 4U) & TIM_CCMR2_IC3F);
+
+  /* Select the Polarity and set the CC3E Bit */
+  tmpccer &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP);
+  tmpccer |= ((TIM_ICPolarity << 8U) & (TIM_CCER_CC3P | TIM_CCER_CC3NP));
+
+  /* Write to TIMx CCMR2 and CCER registers */
+  TIMx->CCMR2 = tmpccmr2;
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Configure the TI4 as Input.
+  * @param  TIMx to select the TIM peripheral
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICSelection specifies the input to be used.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICSELECTION_DIRECTTI: TIM Input 4 is selected to be connected to IC4.
+  *            @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 4 is selected to be connected to IC3.
+  *            @arg TIM_ICSELECTION_TRC: TIM Input 4 is selected to be connected to TRC.
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI4FP3
+  *       (on channel1 path) is used as the input signal. Therefore CCMR2 must be
+  *        protected against un-initialized filter and polarity values.
+  * @retval None
+  */
+static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr2;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 4: Reset the CC4E Bit */
+  tmpccer = TIMx->CCER;
+  TIMx->CCER &= ~TIM_CCER_CC4E;
+  tmpccmr2 = TIMx->CCMR2;
+
+  /* Select the Input */
+  tmpccmr2 &= ~TIM_CCMR2_CC4S;
+  tmpccmr2 |= (TIM_ICSelection << 8U);
+
+  /* Set the filter */
+  tmpccmr2 &= ~TIM_CCMR2_IC4F;
+  tmpccmr2 |= ((TIM_ICFilter << 12U) & TIM_CCMR2_IC4F);
+
+  /* Select the Polarity and set the CC4E Bit */
+  tmpccer &= ~(TIM_CCER_CC4P | TIM_CCER_CC4NP);
+  tmpccer |= ((TIM_ICPolarity << 12U) & (TIM_CCER_CC4P | TIM_CCER_CC4NP));
+
+  /* Write to TIMx CCMR2 and CCER registers */
+  TIMx->CCMR2 = tmpccmr2;
+  TIMx->CCER = tmpccer ;
+}
+
+/**
+  * @brief  Selects the Input Trigger source
+  * @param  TIMx to select the TIM peripheral
+  * @param  InputTriggerSource The Input Trigger source.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_TS_ITR0: Internal Trigger 0
+  *            @arg TIM_TS_ITR1: Internal Trigger 1
+  *            @arg TIM_TS_ITR2: Internal Trigger 2
+  *            @arg TIM_TS_ITR3: Internal Trigger 3
+  *            @arg TIM_TS_TI1F_ED: TI1 Edge Detector
+  *            @arg TIM_TS_TI1FP1: Filtered Timer Input 1
+  *            @arg TIM_TS_TI2FP2: Filtered Timer Input 2
+  *            @arg TIM_TS_ETRF: External Trigger input
+  * @retval None
+  */
+static void TIM_ITRx_SetConfig(TIM_TypeDef *TIMx, uint32_t InputTriggerSource)
+{
+  uint32_t tmpsmcr;
+
+  /* Get the TIMx SMCR register value */
+  tmpsmcr = TIMx->SMCR;
+  /* Reset the TS Bits */
+  tmpsmcr &= ~TIM_SMCR_TS;
+  /* Set the Input Trigger source and the slave mode*/
+  tmpsmcr |= (InputTriggerSource | TIM_SLAVEMODE_EXTERNAL1);
+  /* Write to TIMx SMCR */
+  TIMx->SMCR = tmpsmcr;
+}
+/**
+  * @brief  Configures the TIMx External Trigger (ETR).
+  * @param  TIMx to select the TIM peripheral
+  * @param  TIM_ExtTRGPrescaler The external Trigger Prescaler.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ETRPRESCALER_DIV1: ETRP Prescaler OFF.
+  *            @arg TIM_ETRPRESCALER_DIV2: ETRP frequency divided by 2.
+  *            @arg TIM_ETRPRESCALER_DIV4: ETRP frequency divided by 4.
+  *            @arg TIM_ETRPRESCALER_DIV8: ETRP frequency divided by 8.
+  * @param  TIM_ExtTRGPolarity The external Trigger Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ETRPOLARITY_INVERTED: active low or falling edge active.
+  *            @arg TIM_ETRPOLARITY_NONINVERTED: active high or rising edge active.
+  * @param  ExtTRGFilter External Trigger Filter.
+  *          This parameter must be a value between 0x00 and 0x0F
+  * @retval None
+  */
+void TIM_ETR_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ExtTRGPrescaler,
+                       uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter)
+{
+  uint32_t tmpsmcr;
+
+  tmpsmcr = TIMx->SMCR;
+
+  /* Reset the ETR Bits */
+  tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);
+
+  /* Set the Prescaler, the Filter value and the Polarity */
+  tmpsmcr |= (uint32_t)(TIM_ExtTRGPrescaler | (TIM_ExtTRGPolarity | (ExtTRGFilter << 8U)));
+
+  /* Write to TIMx SMCR */
+  TIMx->SMCR = tmpsmcr;
+}
+
+/**
+  * @brief  Enables or disables the TIM Capture Compare Channel x.
+  * @param  TIMx to select the TIM peripheral
+  * @param  Channel specifies the TIM Channel
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1
+  *            @arg TIM_CHANNEL_2: TIM Channel 2
+  *            @arg TIM_CHANNEL_3: TIM Channel 3
+  *            @arg TIM_CHANNEL_4: TIM Channel 4
+  * @param  ChannelState specifies the TIM Channel CCxE bit new state.
+  *          This parameter can be: TIM_CCx_ENABLE or TIM_CCx_DISABLE.
+  * @retval None
+  */
+void TIM_CCxChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelState)
+{
+  uint32_t tmp;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CC1_INSTANCE(TIMx));
+  assert_param(IS_TIM_CHANNELS(Channel));
+
+  tmp = TIM_CCER_CC1E << (Channel & 0x1FU); /* 0x1FU = 31 bits max shift */
+
+  /* Reset the CCxE Bit */
+  TIMx->CCER &= ~tmp;
+
+  /* Set or reset the CCxE Bit */
+  TIMx->CCER |= (uint32_t)(ChannelState << (Channel & 0x1FU)); /* 0x1FU = 31 bits max shift */
+}
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+/**
+  * @brief  Reset interrupt callbacks to the legacy weak callbacks.
+  * @param  htim pointer to a TIM_HandleTypeDef structure that contains
+  *                the configuration information for TIM module.
+  * @retval None
+  */
+void TIM_ResetCallback(TIM_HandleTypeDef *htim)
+{
+  /* Reset the TIM callback to the legacy weak callbacks */
+  htim->PeriodElapsedCallback             = HAL_TIM_PeriodElapsedCallback;
+  htim->PeriodElapsedHalfCpltCallback     = HAL_TIM_PeriodElapsedHalfCpltCallback;
+  htim->TriggerCallback                   = HAL_TIM_TriggerCallback;
+  htim->TriggerHalfCpltCallback           = HAL_TIM_TriggerHalfCpltCallback;
+  htim->IC_CaptureCallback                = HAL_TIM_IC_CaptureCallback;
+  htim->IC_CaptureHalfCpltCallback        = HAL_TIM_IC_CaptureHalfCpltCallback;
+  htim->OC_DelayElapsedCallback           = HAL_TIM_OC_DelayElapsedCallback;
+  htim->PWM_PulseFinishedCallback         = HAL_TIM_PWM_PulseFinishedCallback;
+  htim->PWM_PulseFinishedHalfCpltCallback = HAL_TIM_PWM_PulseFinishedHalfCpltCallback;
+  htim->ErrorCallback                     = HAL_TIM_ErrorCallback;
+  htim->CommutationCallback               = HAL_TIMEx_CommutCallback;
+  htim->CommutationHalfCpltCallback       = HAL_TIMEx_CommutHalfCpltCallback;
+  htim->BreakCallback                     = HAL_TIMEx_BreakCallback;
+}
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 2410 - 0
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c

@@ -0,0 +1,2410 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_hal_tim_ex.c
+  * @author  MCD Application Team
+  * @brief   TIM HAL module driver.
+  *          This file provides firmware functions to manage the following
+  *          functionalities of the Timer Extended peripheral:
+  *           + Time Hall Sensor Interface Initialization
+  *           + Time Hall Sensor Interface Start
+  *           + Time Complementary signal break and dead time configuration
+  *           + Time Master and Slave synchronization configuration
+  *           + Timer remapping capabilities configuration
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  @verbatim
+  ==============================================================================
+                      ##### TIMER Extended features #####
+  ==============================================================================
+  [..]
+    The Timer Extended features include:
+    (#) Complementary outputs with programmable dead-time for :
+        (++) Output Compare
+        (++) PWM generation (Edge and Center-aligned Mode)
+        (++) One-pulse mode output
+    (#) Synchronization circuit to control the timer with external signals and to
+        interconnect several timers together.
+    (#) Break input to put the timer output signals in reset state or in a known state.
+    (#) Supports incremental (quadrature) encoder and hall-sensor circuitry for
+        positioning purposes
+
+            ##### How to use this driver #####
+  ==============================================================================
+    [..]
+     (#) Initialize the TIM low level resources by implementing the following functions
+         depending on the selected feature:
+           (++) Hall Sensor output : HAL_TIMEx_HallSensor_MspInit()
+
+     (#) Initialize the TIM low level resources :
+        (##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE();
+        (##) TIM pins configuration
+            (+++) Enable the clock for the TIM GPIOs using the following function:
+              __HAL_RCC_GPIOx_CLK_ENABLE();
+            (+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init();
+
+     (#) The external Clock can be configured, if needed (the default clock is the
+         internal clock from the APBx), using the following function:
+         HAL_TIM_ConfigClockSource, the clock configuration should be done before
+         any start function.
+
+     (#) Configure the TIM in the desired functioning mode using one of the
+         initialization function of this driver:
+          (++) HAL_TIMEx_HallSensor_Init() and HAL_TIMEx_ConfigCommutEvent(): to use the
+               Timer Hall Sensor Interface and the commutation event with the corresponding
+               Interrupt and DMA request if needed (Note that One Timer is used to interface
+               with the Hall sensor Interface and another Timer should be used to use
+               the commutation event).
+
+     (#) Activate the TIM peripheral using one of the start functions:
+           (++) Complementary Output Compare : HAL_TIMEx_OCN_Start(), HAL_TIMEx_OCN_Start_DMA(),
+                HAL_TIMEx_OCN_Start_IT()
+           (++) Complementary PWM generation : HAL_TIMEx_PWMN_Start(), HAL_TIMEx_PWMN_Start_DMA(),
+                HAL_TIMEx_PWMN_Start_IT()
+           (++) Complementary One-pulse mode output : HAL_TIMEx_OnePulseN_Start(), HAL_TIMEx_OnePulseN_Start_IT()
+           (++) Hall Sensor output : HAL_TIMEx_HallSensor_Start(), HAL_TIMEx_HallSensor_Start_DMA(),
+                HAL_TIMEx_HallSensor_Start_IT().
+
+  @endverbatim
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal.h"
+
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup TIMEx TIMEx
+  * @brief TIM Extended HAL module driver
+  * @{
+  */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void TIM_DMADelayPulseNCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMAErrorCCxN(DMA_HandleTypeDef *hdma);
+static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState);
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup TIMEx_Exported_Functions TIM Extended Exported Functions
+  * @{
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group1 Extended Timer Hall Sensor functions
+  * @brief    Timer Hall Sensor functions
+  *
+@verbatim
+  ==============================================================================
+                      ##### Timer Hall Sensor functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure TIM HAL Sensor.
+    (+) De-initialize TIM HAL Sensor.
+    (+) Start the Hall Sensor Interface.
+    (+) Stop the Hall Sensor Interface.
+    (+) Start the Hall Sensor Interface and enable interrupts.
+    (+) Stop the Hall Sensor Interface and disable interrupts.
+    (+) Start the Hall Sensor Interface and enable DMA transfers.
+    (+) Stop the Hall Sensor Interface and disable DMA transfers.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM Hall Sensor Interface and initialize the associated handle.
+  * @note   When the timer instance is initialized in Hall Sensor Interface mode,
+  *         timer channels 1 and channel 2 are reserved and cannot be used for
+  *         other purpose.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @param  sConfig TIM Hall Sensor configuration structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, const TIM_HallSensor_InitTypeDef *sConfig)
+{
+  TIM_OC_InitTypeDef OC_Config;
+
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+  assert_param(IS_TIM_IC_POLARITY(sConfig->IC1Polarity));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler));
+  assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy week callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->HallSensor_MspInitCallback == NULL)
+    {
+      htim->HallSensor_MspInitCallback = HAL_TIMEx_HallSensor_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->HallSensor_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIMEx_HallSensor_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Configure the Time base in the Encoder Mode */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Configure the Channel 1 as Input Channel to interface with the three Outputs of the  Hall sensor */
+  TIM_TI1_SetConfig(htim->Instance, sConfig->IC1Polarity, TIM_ICSELECTION_TRC, sConfig->IC1Filter);
+
+  /* Reset the IC1PSC Bits */
+  htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+  /* Set the IC1PSC value */
+  htim->Instance->CCMR1 |= sConfig->IC1Prescaler;
+
+  /* Enable the Hall sensor interface (XOR function of the three inputs) */
+  htim->Instance->CR2 |= TIM_CR2_TI1S;
+
+  /* Select the TIM_TS_TI1F_ED signal as Input trigger for the TIM */
+  htim->Instance->SMCR &= ~TIM_SMCR_TS;
+  htim->Instance->SMCR |= TIM_TS_TI1F_ED;
+
+  /* Use the TIM_TS_TI1F_ED signal to reset the TIM counter each edge detection */
+  htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+  htim->Instance->SMCR |= TIM_SLAVEMODE_RESET;
+
+  /* Program channel 2 in PWM 2 mode with the desired Commutation_Delay*/
+  OC_Config.OCFastMode = TIM_OCFAST_DISABLE;
+  OC_Config.OCIdleState = TIM_OCIDLESTATE_RESET;
+  OC_Config.OCMode = TIM_OCMODE_PWM2;
+  OC_Config.OCNIdleState = TIM_OCNIDLESTATE_RESET;
+  OC_Config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
+  OC_Config.OCPolarity = TIM_OCPOLARITY_HIGH;
+  OC_Config.Pulse = sConfig->Commutation_Delay;
+
+  TIM_OC2_SetConfig(htim->Instance, &OC_Config);
+
+  /* Select OC2REF as trigger output on TRGO: write the MMS bits in the TIMx_CR2
+    register to 101 */
+  htim->Instance->CR2 &= ~TIM_CR2_MMS;
+  htim->Instance->CR2 |= TIM_TRGO_OC2REF;
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM Hall Sensor interface
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->HallSensor_MspDeInitCallback == NULL)
+  {
+    htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->HallSensor_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+  HAL_TIMEx_HallSensor_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Change the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM Hall Sensor MSP.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIMEx_HallSensor_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM Hall Sensor MSP.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIMEx_HallSensor_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the TIM Hall Sensor Interface.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim)
+{
+  uint32_t tmpsmcr;
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Input Capture channel 1
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Hall sensor Interface.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channels 1, 2 and 3
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Hall Sensor Interface in interrupt mode.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim)
+{
+  uint32_t tmpsmcr;
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the capture compare Interrupts 1 event */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+  /* Enable the Input Capture channel 1
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Hall Sensor Interface in interrupt mode.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channel 1
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+  /* Disable the capture compare Interrupts event */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Hall Sensor Interface in DMA mode.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @param  pData The destination Buffer address.
+  * @param  Length The length of data to be transferred from TIM peripheral to memory.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length)
+{
+  uint32_t tmpsmcr;
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Set the TIM channel state */
+  if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+      || (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY))
+  {
+    return HAL_BUSY;
+  }
+  else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+           && (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY))
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  /* Enable the Input Capture channel 1
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+  /* Set the DMA Input Capture 1 Callbacks */
+  htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+  htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+  /* Set the DMA error callback */
+  htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+  /* Enable the DMA stream for Capture 1*/
+  if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length) != HAL_OK)
+  {
+    /* Return error status */
+    return HAL_ERROR;
+  }
+  /* Enable the capture compare 1 Interrupt */
+  __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Hall Sensor Interface in DMA mode.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channel 1
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+
+  /* Disable the capture compare Interrupts 1 event */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+
+  (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group2 Extended Timer Complementary Output Compare functions
+  *  @brief   Timer Complementary Output Compare functions
+  *
+@verbatim
+  ==============================================================================
+              ##### Timer Complementary Output Compare functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Start the Complementary Output Compare/PWM.
+    (+) Stop the Complementary Output Compare/PWM.
+    (+) Start the Complementary Output Compare/PWM and enable interrupts.
+    (+) Stop the Complementary Output Compare/PWM and disable interrupts.
+    (+) Start the Complementary Output Compare/PWM and enable DMA transfers.
+    (+) Stop the Complementary Output Compare/PWM and disable DMA transfers.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation on the complementary
+  *         output.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Capture compare channel N */
+  TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+  /* Enable the Main Output */
+  __HAL_TIM_MOE_ENABLE(htim);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation on the complementary
+  *         output.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Disable the Capture compare channel N */
+  TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+  /* Disable the Main Output */
+  __HAL_TIM_MOE_DISABLE(htim);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation in interrupt mode
+  *         on the complementary output.
+  * @param  htim TIM OC handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Enable the TIM Output Compare interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Enable the TIM Output Compare interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Enable the TIM Output Compare interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the TIM Break interrupt */
+    __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
+
+    /* Enable the Capture compare channel N */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+    /* Enable the Main Output */
+    __HAL_TIM_MOE_ENABLE(htim);
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation in interrupt mode
+  *         on the complementary output.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpccer;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Output Compare interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Output Compare interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Output Compare interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Capture compare channel N */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+    /* Disable the TIM Break interrupt (only if no more channel is active) */
+    tmpccer = htim->Instance->CCER;
+    if ((tmpccer & TIM_CCER_CCxNE_MASK) == (uint32_t)RESET)
+    {
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
+    }
+
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM complementary channel state */
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation in DMA mode
+  *         on the complementary output.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @param  pData The source Buffer address.
+  * @param  Length The length of data to be transferred from memory to TIM peripheral
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                          uint16_t Length)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Set the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Output Compare DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Output Compare DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Output Compare DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Capture compare channel N */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+    /* Enable the Main Output */
+    __HAL_TIM_MOE_ENABLE(htim);
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation in DMA mode
+  *         on the complementary output.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Output Compare DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Output Compare DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Output Compare DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Capture compare channel N */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM complementary channel state */
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions
+  * @brief    Timer Complementary PWM functions
+  *
+@verbatim
+  ==============================================================================
+                 ##### Timer Complementary PWM functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Start the Complementary PWM.
+    (+) Stop the Complementary PWM.
+    (+) Start the Complementary PWM and enable interrupts.
+    (+) Stop the Complementary PWM and disable interrupts.
+    (+) Start the Complementary PWM and enable DMA transfers.
+    (+) Stop the Complementary PWM and disable DMA transfers.
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Starts the PWM signal generation on the complementary output.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the complementary PWM output  */
+  TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+  /* Enable the Main Output */
+  __HAL_TIM_MOE_ENABLE(htim);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the PWM signal generation on the complementary output.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Disable the complementary PWM output  */
+  TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+  /* Disable the Main Output */
+  __HAL_TIM_MOE_DISABLE(htim);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the PWM signal generation in interrupt mode on the
+  *         complementary output.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Enable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Enable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Enable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the TIM Break interrupt */
+    __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
+
+    /* Enable the complementary PWM output  */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+    /* Enable the Main Output */
+    __HAL_TIM_MOE_ENABLE(htim);
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the PWM signal generation in interrupt mode on the
+  *         complementary output.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpccer;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the complementary PWM output  */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+    /* Disable the TIM Break interrupt (only if no more channel is active) */
+    tmpccer = htim->Instance->CCER;
+    if ((tmpccer & TIM_CCER_CCxNE_MASK) == (uint32_t)RESET)
+    {
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
+    }
+
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM complementary channel state */
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Starts the TIM PWM signal generation in DMA mode on the
+  *         complementary output
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @param  pData The source Buffer address.
+  * @param  Length The length of data to be transferred from memory to TIM peripheral
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                           uint16_t Length)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Set the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA stream */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 3 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the complementary PWM output  */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+    /* Enable the Main Output */
+    __HAL_TIM_MOE_ENABLE(htim);
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM PWM signal generation in DMA mode on the complementary
+  *         output
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the complementary PWM output */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM complementary channel state */
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions
+  * @brief    Timer Complementary One Pulse functions
+  *
+@verbatim
+  ==============================================================================
+                ##### Timer Complementary One Pulse functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Start the Complementary One Pulse generation.
+    (+) Stop the Complementary One Pulse.
+    (+) Start the Complementary One Pulse and enable interrupts.
+    (+) Stop the Complementary One Pulse and disable interrupts.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Starts the TIM One Pulse signal generation on the complementary
+  *         output.
+  * @note OutputChannel must match the pulse output channel chosen when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel pulse output channel to enable
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the complementary One Pulse output channel and the Input Capture channel */
+  TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
+  TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_ENABLE);
+
+  /* Enable the Main Output */
+  __HAL_TIM_MOE_ENABLE(htim);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM One Pulse signal generation on the complementary
+  *         output.
+  * @note OutputChannel must match the pulse output channel chosen when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel pulse output channel to disable
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+  /* Disable the complementary One Pulse output channel and the Input Capture channel */
+  TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
+  TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_DISABLE);
+
+  /* Disable the Main Output */
+  __HAL_TIM_MOE_DISABLE(htim);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM  channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM One Pulse signal generation in interrupt mode on the
+  *         complementary channel.
+  * @note OutputChannel must match the pulse output channel chosen when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel pulse output channel to enable
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the TIM Capture/Compare 1 interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+  /* Enable the TIM Capture/Compare 2 interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+
+  /* Enable the complementary One Pulse output channel and the Input Capture channel */
+  TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
+  TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_ENABLE);
+
+  /* Enable the Main Output */
+  __HAL_TIM_MOE_ENABLE(htim);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM One Pulse signal generation in interrupt mode on the
+  *         complementary channel.
+  * @note OutputChannel must match the pulse output channel chosen when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel pulse output channel to disable
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+  /* Disable the TIM Capture/Compare 1 interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+  /* Disable the TIM Capture/Compare 2 interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+
+  /* Disable the complementary One Pulse output channel and the Input Capture channel */
+  TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
+  TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_DISABLE);
+
+  /* Disable the Main Output */
+  __HAL_TIM_MOE_DISABLE(htim);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM  channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions
+  * @brief    Peripheral Control functions
+  *
+@verbatim
+  ==============================================================================
+                    ##### Peripheral Control functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+      (+) Configure the commutation event in case of use of the Hall sensor interface.
+      (+) Configure Output channels for OC and PWM mode.
+
+      (+) Configure Complementary channels, break features and dead time.
+      (+) Configure Master synchronization.
+      (+) Configure timer remapping capabilities.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Configure the TIM commutation event sequence.
+  * @note  This function is mandatory to use the commutation event in order to
+  *        update the configuration at each commutation detection on the TRGI input of the Timer,
+  *        the typical use of this feature is with the use of another Timer(interface Timer)
+  *        configured in Hall sensor interface, this interface Timer will generate the
+  *        commutation at its TRGO output (connected to Timer used in this function) each time
+  *        the TI1 of the Interface Timer detect a commutation at its input TI1.
+  * @param  htim TIM handle
+  * @param  InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
+  *          This parameter can be one of the following values:
+  *            @arg TIM_TS_ITR0: Internal trigger 0 selected
+  *            @arg TIM_TS_ITR1: Internal trigger 1 selected
+  *            @arg TIM_TS_ITR2: Internal trigger 2 selected
+  *            @arg TIM_TS_ITR3: Internal trigger 3 selected
+  *            @arg TIM_TS_NONE: No trigger is needed
+  * @param  CommutationSource the Commutation Event source
+  *          This parameter can be one of the following values:
+  *            @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
+  *            @arg TIM_COMMUTATION_SOFTWARE:  Commutation source is set by software using the COMG bit
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent(TIM_HandleTypeDef *htim, uint32_t  InputTrigger,
+                                              uint32_t  CommutationSource)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
+
+  __HAL_LOCK(htim);
+
+  if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
+      (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
+  {
+    /* Select the Input trigger */
+    htim->Instance->SMCR &= ~TIM_SMCR_TS;
+    htim->Instance->SMCR |= InputTrigger;
+  }
+
+  /* Select the Capture Compare preload feature */
+  htim->Instance->CR2 |= TIM_CR2_CCPC;
+  /* Select the Commutation event source */
+  htim->Instance->CR2 &= ~TIM_CR2_CCUS;
+  htim->Instance->CR2 |= CommutationSource;
+
+  /* Disable Commutation Interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_COM);
+
+  /* Disable Commutation DMA request */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_COM);
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configure the TIM commutation event sequence with interrupt.
+  * @note  This function is mandatory to use the commutation event in order to
+  *        update the configuration at each commutation detection on the TRGI input of the Timer,
+  *        the typical use of this feature is with the use of another Timer(interface Timer)
+  *        configured in Hall sensor interface, this interface Timer will generate the
+  *        commutation at its TRGO output (connected to Timer used in this function) each time
+  *        the TI1 of the Interface Timer detect a commutation at its input TI1.
+  * @param  htim TIM handle
+  * @param  InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
+  *          This parameter can be one of the following values:
+  *            @arg TIM_TS_ITR0: Internal trigger 0 selected
+  *            @arg TIM_TS_ITR1: Internal trigger 1 selected
+  *            @arg TIM_TS_ITR2: Internal trigger 2 selected
+  *            @arg TIM_TS_ITR3: Internal trigger 3 selected
+  *            @arg TIM_TS_NONE: No trigger is needed
+  * @param  CommutationSource the Commutation Event source
+  *          This parameter can be one of the following values:
+  *            @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
+  *            @arg TIM_COMMUTATION_SOFTWARE:  Commutation source is set by software using the COMG bit
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_IT(TIM_HandleTypeDef *htim, uint32_t  InputTrigger,
+                                                 uint32_t  CommutationSource)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
+
+  __HAL_LOCK(htim);
+
+  if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
+      (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
+  {
+    /* Select the Input trigger */
+    htim->Instance->SMCR &= ~TIM_SMCR_TS;
+    htim->Instance->SMCR |= InputTrigger;
+  }
+
+  /* Select the Capture Compare preload feature */
+  htim->Instance->CR2 |= TIM_CR2_CCPC;
+  /* Select the Commutation event source */
+  htim->Instance->CR2 &= ~TIM_CR2_CCUS;
+  htim->Instance->CR2 |= CommutationSource;
+
+  /* Disable Commutation DMA request */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_COM);
+
+  /* Enable the Commutation Interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_COM);
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configure the TIM commutation event sequence with DMA.
+  * @note  This function is mandatory to use the commutation event in order to
+  *        update the configuration at each commutation detection on the TRGI input of the Timer,
+  *        the typical use of this feature is with the use of another Timer(interface Timer)
+  *        configured in Hall sensor interface, this interface Timer will generate the
+  *        commutation at its TRGO output (connected to Timer used in this function) each time
+  *        the TI1 of the Interface Timer detect a commutation at its input TI1.
+  * @note  The user should configure the DMA in his own software, in This function only the COMDE bit is set
+  * @param  htim TIM handle
+  * @param  InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
+  *          This parameter can be one of the following values:
+  *            @arg TIM_TS_ITR0: Internal trigger 0 selected
+  *            @arg TIM_TS_ITR1: Internal trigger 1 selected
+  *            @arg TIM_TS_ITR2: Internal trigger 2 selected
+  *            @arg TIM_TS_ITR3: Internal trigger 3 selected
+  *            @arg TIM_TS_NONE: No trigger is needed
+  * @param  CommutationSource the Commutation Event source
+  *          This parameter can be one of the following values:
+  *            @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
+  *            @arg TIM_COMMUTATION_SOFTWARE:  Commutation source is set by software using the COMG bit
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_DMA(TIM_HandleTypeDef *htim, uint32_t  InputTrigger,
+                                                  uint32_t  CommutationSource)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
+
+  __HAL_LOCK(htim);
+
+  if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
+      (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
+  {
+    /* Select the Input trigger */
+    htim->Instance->SMCR &= ~TIM_SMCR_TS;
+    htim->Instance->SMCR |= InputTrigger;
+  }
+
+  /* Select the Capture Compare preload feature */
+  htim->Instance->CR2 |= TIM_CR2_CCPC;
+  /* Select the Commutation event source */
+  htim->Instance->CR2 &= ~TIM_CR2_CCUS;
+  htim->Instance->CR2 |= CommutationSource;
+
+  /* Enable the Commutation DMA Request */
+  /* Set the DMA Commutation Callback */
+  htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt;
+  htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback = TIMEx_DMACommutationHalfCplt;
+  /* Set the DMA error callback */
+  htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError;
+
+  /* Disable Commutation Interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_COM);
+
+  /* Enable the Commutation DMA Request */
+  __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_COM);
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the TIM in master mode.
+  * @param  htim TIM handle.
+  * @param  sMasterConfig pointer to a TIM_MasterConfigTypeDef structure that
+  *         contains the selected trigger output (TRGO) and the Master/Slave
+  *         mode.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim,
+                                                        const TIM_MasterConfigTypeDef *sMasterConfig)
+{
+  uint32_t tmpcr2;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_MASTER_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_TRGO_SOURCE(sMasterConfig->MasterOutputTrigger));
+  assert_param(IS_TIM_MSM_STATE(sMasterConfig->MasterSlaveMode));
+
+  /* Check input state */
+  __HAL_LOCK(htim);
+
+  /* Change the handler state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Get the TIMx CR2 register value */
+  tmpcr2 = htim->Instance->CR2;
+
+  /* Get the TIMx SMCR register value */
+  tmpsmcr = htim->Instance->SMCR;
+
+  /* Reset the MMS Bits */
+  tmpcr2 &= ~TIM_CR2_MMS;
+  /* Select the TRGO source */
+  tmpcr2 |=  sMasterConfig->MasterOutputTrigger;
+
+  /* Update TIMx CR2 */
+  htim->Instance->CR2 = tmpcr2;
+
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    /* Reset the MSM Bit */
+    tmpsmcr &= ~TIM_SMCR_MSM;
+    /* Set master mode */
+    tmpsmcr |= sMasterConfig->MasterSlaveMode;
+
+    /* Update TIMx SMCR */
+    htim->Instance->SMCR = tmpsmcr;
+  }
+
+  /* Change the htim state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the Break feature, dead time, Lock level, OSSI/OSSR State
+  *         and the AOE(automatic output enable).
+  * @param  htim TIM handle
+  * @param  sBreakDeadTimeConfig pointer to a TIM_ConfigBreakDeadConfigTypeDef structure that
+  *         contains the BDTR Register configuration  information for the TIM peripheral.
+  * @note   Interrupts can be generated when an active level is detected on the
+  *         break input, the break 2 input or the system break input. Break
+  *         interrupt can be enabled by calling the @ref __HAL_TIM_ENABLE_IT macro.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim,
+                                                const TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig)
+{
+  /* Keep this variable initialized to 0 as it is used to configure BDTR register */
+  uint32_t tmpbdtr = 0U;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_OSSR_STATE(sBreakDeadTimeConfig->OffStateRunMode));
+  assert_param(IS_TIM_OSSI_STATE(sBreakDeadTimeConfig->OffStateIDLEMode));
+  assert_param(IS_TIM_LOCK_LEVEL(sBreakDeadTimeConfig->LockLevel));
+  assert_param(IS_TIM_DEADTIME(sBreakDeadTimeConfig->DeadTime));
+  assert_param(IS_TIM_BREAK_STATE(sBreakDeadTimeConfig->BreakState));
+  assert_param(IS_TIM_BREAK_POLARITY(sBreakDeadTimeConfig->BreakPolarity));
+  assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(sBreakDeadTimeConfig->AutomaticOutput));
+
+  /* Check input state */
+  __HAL_LOCK(htim);
+
+  /* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State,
+     the OSSI State, the dead time value and the Automatic Output Enable Bit */
+
+  /* Set the BDTR bits */
+  MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, sBreakDeadTimeConfig->DeadTime);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, sBreakDeadTimeConfig->LockLevel);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, sBreakDeadTimeConfig->OffStateIDLEMode);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, sBreakDeadTimeConfig->OffStateRunMode);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, sBreakDeadTimeConfig->BreakState);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, sBreakDeadTimeConfig->BreakPolarity);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, sBreakDeadTimeConfig->AutomaticOutput);
+
+
+  /* Set TIMx_BDTR */
+  htim->Instance->BDTR = tmpbdtr;
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the TIMx Remapping input capabilities.
+  * @param  htim TIM handle.
+  * @param  Remap specifies the TIM remapping source.
+  *         For TIM1, the parameter can have the following values:                   (**)
+  *           @arg TIM_TIM1_TIM3_TRGO:  TIM1 ITR2 is connected to TIM3 TRGO
+  *           @arg TIM_TIM1_LPTIM:      TIM1 ITR2 is connected to LPTIM1 output
+  *
+  *         For TIM2, the parameter can have the following values:                   (**)
+  *           @arg TIM_TIM2_TIM8_TRGO:  TIM2 ITR1 is connected to TIM8 TRGO          (*)
+  *           @arg TIM_TIM2_ETH_PTP:    TIM2 ITR1 is connected to PTP trigger output (*)
+  *           @arg TIM_TIM2_USBFS_SOF:  TIM2 ITR1 is connected to OTG FS SOF
+  *           @arg TIM_TIM2_USBHS_SOF:  TIM2 ITR1 is connected to OTG FS SOF
+  *
+  *         For TIM5, the parameter can have the following values:
+  *           @arg TIM_TIM5_GPIO:       TIM5 TI4 is connected to GPIO
+  *           @arg TIM_TIM5_LSI:        TIM5 TI4 is connected to LSI
+  *           @arg TIM_TIM5_LSE:        TIM5 TI4 is connected to LSE
+  *           @arg TIM_TIM5_RTC:        TIM5 TI4 is connected to the RTC wakeup interrupt
+  *           @arg TIM_TIM5_TIM3_TRGO:  TIM5 ITR1 is connected to TIM3 TRGO          (*)
+  *           @arg TIM_TIM5_LPTIM:      TIM5 ITR1 is connected to LPTIM1 output      (*)
+  *
+  *         For TIM9, the parameter can have the following values:                   (**)
+  *           @arg TIM_TIM9_TIM3_TRGO:  TIM9 ITR1 is connected to TIM3 TRGO
+  *           @arg TIM_TIM9_LPTIM:      TIM9 ITR1 is connected to LPTIM1 output
+  *
+  *         For TIM11, the parameter can have the following values:
+  *           @arg TIM_TIM11_GPIO:     TIM11 TI1 is connected to GPIO
+  *           @arg TIM_TIM11_HSE:      TIM11 TI1 is connected to HSE_RTC clock
+  *           @arg TIM_TIM11_SPDIFRX:  TIM11 TI1 is connected to SPDIFRX_FRAME_SYNC  (*)
+  *
+  *         (*)  Value not defined in all devices. \n
+  *         (**) Register not available in all devices.
+  *
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap)
+{
+  /* Check parameters */
+  assert_param(IS_TIM_REMAP(htim->Instance, Remap));
+
+  __HAL_LOCK(htim);
+
+#if defined(LPTIM_OR_TIM1_ITR2_RMP) && defined(LPTIM_OR_TIM5_ITR1_RMP) && defined(LPTIM_OR_TIM9_ITR1_RMP)
+  if ((Remap & LPTIM_REMAP_MASK) == LPTIM_REMAP_MASK)
+  {
+    /* Connect TIMx internal trigger to LPTIM1 output */
+    __HAL_RCC_LPTIM1_CLK_ENABLE();
+    MODIFY_REG(LPTIM1->OR,
+               (LPTIM_OR_TIM1_ITR2_RMP | LPTIM_OR_TIM5_ITR1_RMP | LPTIM_OR_TIM9_ITR1_RMP),
+               Remap & ~(LPTIM_REMAP_MASK));
+  }
+  else
+  {
+    /* Set the Timer remapping configuration */
+    WRITE_REG(htim->Instance->OR, Remap);
+  }
+#else
+  /* Set the Timer remapping configuration */
+  WRITE_REG(htim->Instance->OR, Remap);
+#endif /* LPTIM_OR_TIM1_ITR2_RMP &&  LPTIM_OR_TIM5_ITR1_RMP && LPTIM_OR_TIM9_ITR1_RMP */
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions
+  * @brief    Extended Callbacks functions
+  *
+@verbatim
+  ==============================================================================
+                    ##### Extended Callbacks functions #####
+  ==============================================================================
+  [..]
+    This section provides Extended TIM callback functions:
+    (+) Timer Commutation callback
+    (+) Timer Break callback
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Commutation callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_CommutCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIMEx_CommutCallback could be implemented in the user file
+   */
+}
+/**
+  * @brief  Commutation half complete callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_CommutHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIMEx_CommutHalfCpltCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Break detection callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIMEx_BreakCallback could be implemented in the user file
+   */
+}
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions
+  * @brief    Extended Peripheral State functions
+  *
+@verbatim
+  ==============================================================================
+                ##### Extended Peripheral State functions #####
+  ==============================================================================
+  [..]
+    This subsection permits to get in run-time the status of the peripheral
+    and the data flow.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Return the TIM Hall Sensor interface handle state.
+  * @param  htim TIM Hall Sensor handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return actual state of the TIM complementary channel.
+  * @param  htim TIM handle
+  * @param  ChannelN TIM Complementary channel
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1
+  *            @arg TIM_CHANNEL_2: TIM Channel 2
+  *            @arg TIM_CHANNEL_3: TIM Channel 3
+  * @retval TIM Complementary channel state
+  */
+HAL_TIM_ChannelStateTypeDef HAL_TIMEx_GetChannelNState(const TIM_HandleTypeDef *htim,  uint32_t ChannelN)
+{
+  HAL_TIM_ChannelStateTypeDef channel_state;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, ChannelN));
+
+  channel_state = TIM_CHANNEL_N_STATE_GET(htim, ChannelN);
+
+  return channel_state;
+}
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup TIMEx_Private_Functions TIM Extended Private Functions
+  * @{
+  */
+
+/**
+  * @brief  TIM DMA Commutation callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  /* Change the htim state */
+  htim->State = HAL_TIM_STATE_READY;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->CommutationCallback(htim);
+#else
+  HAL_TIMEx_CommutCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  TIM DMA Commutation half complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIMEx_DMACommutationHalfCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  /* Change the htim state */
+  htim->State = HAL_TIM_STATE_READY;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->CommutationHalfCpltCallback(htim);
+#else
+  HAL_TIMEx_CommutHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+
+/**
+  * @brief  TIM DMA Delay Pulse complete callback (complementary channel).
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMADelayPulseNCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->PWM_PulseFinishedCallback(htim);
+#else
+  HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA error callback (complementary channel)
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMAErrorCCxN(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->ErrorCallback(htim);
+#else
+  HAL_TIM_ErrorCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  Enables or disables the TIM Capture Compare Channel xN.
+  * @param  TIMx to select the TIM peripheral
+  * @param  Channel specifies the TIM Channel
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1
+  *            @arg TIM_CHANNEL_2: TIM Channel 2
+  *            @arg TIM_CHANNEL_3: TIM Channel 3
+  * @param  ChannelNState specifies the TIM Channel CCxNE bit new state.
+  *          This parameter can be: TIM_CCxN_ENABLE or TIM_CCxN_Disable.
+  * @retval None
+  */
+static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState)
+{
+  uint32_t tmp;
+
+  tmp = TIM_CCER_CC1NE << (Channel & 0xFU); /* 0xFU = 15 bits max shift */
+
+  /* Reset the CCxNE Bit */
+  TIMx->CCER &=  ~tmp;
+
+  /* Set or reset the CCxNE Bit */
+  TIMx->CCER |= (uint32_t)(ChannelNState << (Channel & 0xFU)); /* 0xFU = 15 bits max shift */
+}
+/**
+  * @}
+  */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 2316 - 0
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c

@@ -0,0 +1,2316 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_ll_usb.c
+  * @author  MCD Application Team
+  * @brief   USB Low Layer HAL module driver.
+  *
+  *          This file provides firmware functions to manage the following
+  *          functionalities of the USB Peripheral Controller:
+  *           + Initialization/de-initialization functions
+  *           + I/O operation functions
+  *           + Peripheral Control functions
+  *           + Peripheral State functions
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  @verbatim
+  ==============================================================================
+                    ##### How to use this driver #####
+  ==============================================================================
+    [..]
+      (#) Fill parameters of Init structure in USB_CfgTypeDef structure.
+
+      (#) Call USB_CoreInit() API to initialize the USB Core peripheral.
+
+      (#) The upper HAL HCD/PCD driver will call the right routines for its internal processes.
+
+  @endverbatim
+
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal.h"
+
+/** @addtogroup STM32F4xx_LL_USB_DRIVER
+  * @{
+  */
+
+#if defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED)
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx);
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup USB_LL_Exported_Functions USB Low Layer Exported Functions
+  * @{
+  */
+
+/** @defgroup USB_LL_Exported_Functions_Group1 Initialization/de-initialization functions
+  *  @brief    Initialization and Configuration functions
+  *
+@verbatim
+ ===============================================================================
+                      ##### Initialization/de-initialization functions #####
+ ===============================================================================
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Initializes the USB Core
+  * @param  USBx USB Instance
+  * @param  cfg pointer to a USB_OTG_CfgTypeDef structure that contains
+  *         the configuration information for the specified USBx peripheral.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
+{
+  HAL_StatusTypeDef ret;
+  if (cfg.phy_itface == USB_OTG_ULPI_PHY)
+  {
+    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);
+    if (cfg.use_external_vbus == 1U)
+    {
+      USBx->GUSBCFG |= USB_OTG_GUSBCFG_ULPIEVBUSD;
+    }
+
+    /* Reset after a PHY select */
+    ret = USB_CoreReset(USBx);
+  }
+  else /* FS interface (embedded Phy) */
+  {
+    /* Select FS Embedded PHY */
+    USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
+
+    /* Reset after a PHY select */
+    ret = USB_CoreReset(USBx);
+
+    if (cfg.battery_charging_enable == 0U)
+    {
+      /* Activate the USB Transceiver */
+      USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
+    }
+    else
+    {
+      /* Deactivate the USB Transceiver */
+      USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
+    }
+  }
+
+  if (cfg.dma_enable == 1U)
+  {
+    USBx->GAHBCFG |= USB_OTG_GAHBCFG_HBSTLEN_2;
+    USBx->GAHBCFG |= USB_OTG_GAHBCFG_DMAEN;
+  }
+
+  return ret;
+}
+
+
+/**
+  * @brief  Set the USB turnaround time
+  * @param  USBx USB Instance
+  * @param  hclk: AHB clock frequency
+  * @retval USB turnaround time In PHY Clocks number
+  */
+HAL_StatusTypeDef USB_SetTurnaroundTime(USB_OTG_GlobalTypeDef *USBx,
+                                        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 == USBD_FS_SPEED)
+  {
+    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 == USBD_HS_SPEED)
+  {
+    UsbTrd = USBD_HS_TRDT_VALUE;
+  }
+  else
+  {
+    UsbTrd = USBD_DEFAULT_TRDT_VALUE;
+  }
+
+  USBx->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
+  USBx->GUSBCFG |= (uint32_t)((UsbTrd << 10) & USB_OTG_GUSBCFG_TRDT);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_EnableGlobalInt
+  *         Enables the controller's Global Int in the AHB Config reg
+  * @param  USBx  Selected device
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
+{
+  USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_DisableGlobalInt
+  *         Disable the controller's Global Int in the AHB Config reg
+  * @param  USBx  Selected device
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
+{
+  USBx->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_SetCurrentMode Set functional mode
+  * @param  USBx  Selected device
+  * @param  mode  current core mode
+  *          This parameter can be one of these values:
+  *            @arg USB_DEVICE_MODE Peripheral mode
+  *            @arg USB_HOST_MODE Host mode
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx, USB_OTG_ModeTypeDef mode)
+{
+  uint32_t ms = 0U;
+
+  USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD);
+
+  if (mode == USB_HOST_MODE)
+  {
+    USBx->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD;
+
+    do
+    {
+      HAL_Delay(10U);
+      ms += 10U;
+    } while ((USB_GetMode(USBx) != (uint32_t)USB_HOST_MODE) && (ms < HAL_USB_CURRENT_MODE_MAX_DELAY_MS));
+  }
+  else if (mode == USB_DEVICE_MODE)
+  {
+    USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
+
+    do
+    {
+      HAL_Delay(10U);
+      ms += 10U;
+    } while ((USB_GetMode(USBx) != (uint32_t)USB_DEVICE_MODE) && (ms < HAL_USB_CURRENT_MODE_MAX_DELAY_MS));
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  if (ms == HAL_USB_CURRENT_MODE_MAX_DELAY_MS)
+  {
+    return HAL_ERROR;
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_DevInit Initializes the USB_OTG controller registers
+  *         for device mode
+  * @param  USBx  Selected device
+  * @param  cfg   pointer to a USB_OTG_CfgTypeDef structure that contains
+  *         the configuration information for the specified USBx peripheral.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_DevInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
+{
+  HAL_StatusTypeDef ret = HAL_OK;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t i;
+
+  for (i = 0U; i < 15U; i++)
+  {
+    USBx->DIEPTXF[i] = 0U;
+  }
+
+#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) \
+ || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) \
+ || defined(STM32F423xx)
+  /* VBUS Sensing setup */
+  if (cfg.vbus_sensing_enable == 0U)
+  {
+    USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS;
+
+    /* 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
+  {
+    /* Enable HW VBUS sensing */
+    USBx->GCCFG |= USB_OTG_GCCFG_VBDEN;
+  }
+#else
+  /* VBUS Sensing setup */
+  if (cfg.vbus_sensing_enable == 0U)
+  {
+    /*
+     * Disable HW VBUS sensing. VBUS is internally considered to be always
+     * at VBUS-Valid level (5V).
+     */
+    USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS;
+    USBx->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS;
+    USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN;
+    USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN;
+  }
+  else
+  {
+    /* Enable HW VBUS sensing */
+    USBx->GCCFG &= ~USB_OTG_GCCFG_NOVBUSSENS;
+    USBx->GCCFG |= USB_OTG_GCCFG_VBUSBSEN;
+  }
+#endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||
+          defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) ||
+          defined(STM32F423xx) */
+
+  /* Restart the Phy Clock */
+  USBx_PCGCCTL = 0U;
+
+  if (cfg.phy_itface == USB_OTG_ULPI_PHY)
+  {
+    if (cfg.speed == USBD_HS_SPEED)
+    {
+      /* Set Core speed to High speed mode */
+      (void)USB_SetDevSpeed(USBx, USB_OTG_SPEED_HIGH);
+    }
+    else
+    {
+      /* Set Core speed to Full speed mode */
+      (void)USB_SetDevSpeed(USBx, USB_OTG_SPEED_HIGH_IN_FULL);
+    }
+  }
+  else
+  {
+    /* Set Core speed to Full speed mode */
+    (void)USB_SetDevSpeed(USBx, USB_OTG_SPEED_FULL);
+  }
+
+  /* Flush the FIFOs */
+  if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
+  {
+    ret = HAL_ERROR;
+  }
+
+  if (USB_FlushRxFifo(USBx) != HAL_OK)
+  {
+    ret = HAL_ERROR;
+  }
+
+  /* Clear all pending Device Interrupts */
+  USBx_DEVICE->DIEPMSK = 0U;
+  USBx_DEVICE->DOEPMSK = 0U;
+  USBx_DEVICE->DAINTMSK = 0U;
+
+  for (i = 0U; i < cfg.dev_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 (i = 0U; i < cfg.dev_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;
+  }
+
+  USBx_DEVICE->DIEPMSK &= ~(USB_OTG_DIEPMSK_TXFURM);
+
+  /* Disable all interrupts. */
+  USBx->GINTMSK = 0U;
+
+  /* Clear any pending interrupts */
+  USBx->GINTSTS = 0xBFFFFFFFU;
+
+  /* Enable the common interrupts */
+  if (cfg.dma_enable == 0U)
+  {
+    USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
+  }
+
+  /* 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_IEPINT |
+                   USB_OTG_GINTMSK_OEPINT   | USB_OTG_GINTMSK_IISOIXFRM |
+                   USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM;
+
+  if (cfg.Sof_enable != 0U)
+  {
+    USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM;
+  }
+
+  if (cfg.vbus_sensing_enable == 1U)
+  {
+    USBx->GINTMSK |= (USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_OTGINT);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  USB_FlushTxFifo Flush a Tx FIFO
+  * @param  USBx  Selected device
+  * @param  num  FIFO number
+  *         This parameter can be a value from 1 to 15
+            15 means Flush all Tx FIFOs
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_FlushTxFifo(USB_OTG_GlobalTypeDef *USBx, uint32_t num)
+{
+  __IO uint32_t count = 0U;
+
+  /* Wait for AHB master IDLE state. */
+  do
+  {
+    count++;
+
+    if (count > HAL_USB_TIMEOUT)
+    {
+      return HAL_TIMEOUT;
+    }
+  } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
+
+  /* Flush TX Fifo */
+  count = 0U;
+  USBx->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (num << 6));
+
+  do
+  {
+    count++;
+
+    if (count > HAL_USB_TIMEOUT)
+    {
+      return HAL_TIMEOUT;
+    }
+  } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_FlushRxFifo  Flush Rx FIFO
+  * @param  USBx  Selected device
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_FlushRxFifo(USB_OTG_GlobalTypeDef *USBx)
+{
+  __IO uint32_t count = 0U;
+
+  /* Wait for AHB master IDLE state. */
+  do
+  {
+    count++;
+
+    if (count > HAL_USB_TIMEOUT)
+    {
+      return HAL_TIMEOUT;
+    }
+  } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
+
+  /* Flush RX Fifo */
+  count = 0U;
+  USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;
+
+  do
+  {
+    count++;
+
+    if (count > HAL_USB_TIMEOUT)
+    {
+      return HAL_TIMEOUT;
+    }
+  } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_SetDevSpeed  Initializes the DevSpd field of DCFG register
+  *         depending the PHY type and the enumeration speed of the device.
+  * @param  USBx  Selected device
+  * @param  speed  device speed
+  *          This parameter can be one of these values:
+  *            @arg USB_OTG_SPEED_HIGH: High speed mode
+  *            @arg USB_OTG_SPEED_HIGH_IN_FULL: High speed core in Full Speed mode
+  *            @arg USB_OTG_SPEED_FULL: Full speed mode
+  * @retval  Hal status
+  */
+HAL_StatusTypeDef USB_SetDevSpeed(const USB_OTG_GlobalTypeDef *USBx, uint8_t speed)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  USBx_DEVICE->DCFG |= speed;
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_GetDevSpeed  Return the Dev Speed
+  * @param  USBx  Selected device
+  * @retval speed  device speed
+  *          This parameter can be one of these values:
+  *            @arg USBD_HS_SPEED: High speed mode
+  *            @arg USBD_FS_SPEED: Full speed mode
+  */
+uint8_t USB_GetDevSpeed(const USB_OTG_GlobalTypeDef *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint8_t speed;
+  uint32_t DevEnumSpeed = USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD;
+
+  if (DevEnumSpeed == DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ)
+  {
+    speed = USBD_HS_SPEED;
+  }
+  else if ((DevEnumSpeed == DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ) ||
+           (DevEnumSpeed == DSTS_ENUMSPD_FS_PHY_48MHZ))
+  {
+    speed = USBD_FS_SPEED;
+  }
+  else
+  {
+    speed = 0xFU;
+  }
+
+  return speed;
+}
+
+/**
+  * @brief  Activate and configure an endpoint
+  * @param  USBx  Selected device
+  * @param  ep pointer to endpoint structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_ActivateEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t epnum = (uint32_t)ep->num;
+
+  if (ep->is_in == 1U)
+  {
+    USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK));
+
+    if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_USBAEP) == 0U)
+    {
+      USBx_INEP(epnum)->DIEPCTL |= (ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ) |
+                                   ((uint32_t)ep->type << 18) | (epnum << 22) |
+                                   USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
+                                   USB_OTG_DIEPCTL_USBAEP;
+    }
+  }
+  else
+  {
+    USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16);
+
+    if (((USBx_OUTEP(epnum)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0U)
+    {
+      USBx_OUTEP(epnum)->DOEPCTL |= (ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ) |
+                                    ((uint32_t)ep->type << 18) |
+                                    USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
+                                    USB_OTG_DOEPCTL_USBAEP;
+    }
+  }
+  return HAL_OK;
+}
+
+/**
+  * @brief  Activate and configure a dedicated endpoint
+  * @param  USBx  Selected device
+  * @param  ep pointer to endpoint structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t epnum = (uint32_t)ep->num;
+
+  /* Read DEPCTLn register */
+  if (ep->is_in == 1U)
+  {
+    if (((USBx_INEP(epnum)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0U)
+    {
+      USBx_INEP(epnum)->DIEPCTL |= (ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ) |
+                                   ((uint32_t)ep->type << 18) | (epnum << 22) |
+                                   USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
+                                   USB_OTG_DIEPCTL_USBAEP;
+    }
+
+    USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK));
+  }
+  else
+  {
+    if (((USBx_OUTEP(epnum)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0U)
+    {
+      USBx_OUTEP(epnum)->DOEPCTL |= (ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ) |
+                                    ((uint32_t)ep->type << 18) | (epnum << 22) |
+                                    USB_OTG_DOEPCTL_USBAEP;
+    }
+
+    USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16);
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  De-activate and de-initialize an endpoint
+  * @param  USBx  Selected device
+  * @param  ep pointer to endpoint structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_DeactivateEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t epnum = (uint32_t)ep->num;
+
+  /* Read DEPCTLn register */
+  if (ep->is_in == 1U)
+  {
+    if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
+    {
+      USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
+      USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS;
+    }
+
+    USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
+    USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
+    USBx_INEP(epnum)->DIEPCTL &= ~(USB_OTG_DIEPCTL_USBAEP |
+                                   USB_OTG_DIEPCTL_MPSIZ |
+                                   USB_OTG_DIEPCTL_TXFNUM |
+                                   USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
+                                   USB_OTG_DIEPCTL_EPTYP);
+  }
+  else
+  {
+    if ((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
+    {
+      USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
+      USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_EPDIS;
+    }
+
+    USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
+    USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
+    USBx_OUTEP(epnum)->DOEPCTL &= ~(USB_OTG_DOEPCTL_USBAEP |
+                                    USB_OTG_DOEPCTL_MPSIZ |
+                                    USB_OTG_DOEPCTL_SD0PID_SEVNFRM |
+                                    USB_OTG_DOEPCTL_EPTYP);
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  De-activate and de-initialize a dedicated endpoint
+  * @param  USBx  Selected device
+  * @param  ep pointer to endpoint structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t epnum = (uint32_t)ep->num;
+
+  /* Read DEPCTLn register */
+  if (ep->is_in == 1U)
+  {
+    if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
+    {
+      USBx_INEP(epnum)->DIEPCTL  |= USB_OTG_DIEPCTL_SNAK;
+      USBx_INEP(epnum)->DIEPCTL  |= USB_OTG_DIEPCTL_EPDIS;
+    }
+
+    USBx_INEP(epnum)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP;
+    USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
+  }
+  else
+  {
+    if ((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
+    {
+      USBx_OUTEP(epnum)->DOEPCTL  |= USB_OTG_DOEPCTL_SNAK;
+      USBx_OUTEP(epnum)->DOEPCTL  |= USB_OTG_DOEPCTL_EPDIS;
+    }
+
+    USBx_OUTEP(epnum)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP;
+    USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_EPStartXfer : setup and starts a transfer over an EP
+  * @param  USBx  Selected device
+  * @param  ep pointer to endpoint structure
+  * @param  dma USB dma enabled or disabled
+  *          This parameter can be one of these values:
+  *           0 : DMA feature not used
+  *           1 : DMA feature used
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep, uint8_t dma)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t epnum = (uint32_t)ep->num;
+  uint16_t pktcnt;
+
+  /* IN endpoint */
+  if (ep->is_in == 1U)
+  {
+    /* Zero Length Packet? */
+    if (ep->xfer_len == 0U)
+    {
+      USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
+      USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19));
+      USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+    }
+    else
+    {
+      /* Program the transfer size and packet count
+      * as follows: xfersize = N * maxpacket +
+      * short_packet pktcnt = N + (short_packet
+      * exist ? 1 : 0)
+      */
+      USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+      USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
+
+      if (epnum == 0U)
+      {
+        if (ep->xfer_len > ep->maxpacket)
+        {
+          ep->xfer_len = ep->maxpacket;
+        }
+
+        USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19));
+      }
+      else
+      {
+        USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT &
+                                       (((ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket) << 19));
+      }
+
+      USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len);
+
+      if (ep->type == EP_TYPE_ISOC)
+      {
+        USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT);
+        USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1U << 29));
+      }
+    }
+
+    if (dma == 1U)
+    {
+      if ((uint32_t)ep->dma_addr != 0U)
+      {
+        USBx_INEP(epnum)->DIEPDMA = (uint32_t)(ep->dma_addr);
+      }
+
+      if (ep->type == EP_TYPE_ISOC)
+      {
+        if ((USBx_DEVICE->DSTS & (1U << 8)) == 0U)
+        {
+          USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
+        }
+        else
+        {
+          USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
+        }
+      }
+
+      /* EP enable, IN data in FIFO */
+      USBx_INEP(epnum)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
+    }
+    else
+    {
+      /* EP enable, IN data in FIFO */
+      USBx_INEP(epnum)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
+
+      if (ep->type != EP_TYPE_ISOC)
+      {
+        /* Enable the Tx FIFO Empty Interrupt for this EP */
+        if (ep->xfer_len > 0U)
+        {
+          USBx_DEVICE->DIEPEMPMSK |= 1UL << (ep->num & EP_ADDR_MSK);
+        }
+      }
+      else
+      {
+        if ((USBx_DEVICE->DSTS & (1U << 8)) == 0U)
+        {
+          USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
+        }
+        else
+        {
+          USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
+        }
+
+        (void)USB_WritePacket(USBx, ep->xfer_buff, ep->num, (uint16_t)ep->xfer_len, dma);
+      }
+    }
+  }
+  else /* OUT endpoint */
+  {
+    /* Program the transfer size and packet count as follows:
+    * pktcnt = N
+    * xfersize = N * maxpacket
+    */
+    USBx_OUTEP(epnum)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ);
+    USBx_OUTEP(epnum)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT);
+
+    if (epnum == 0U)
+    {
+      if (ep->xfer_len > 0U)
+      {
+        ep->xfer_len = ep->maxpacket;
+      }
+
+      /* Store transfer size, for EP0 this is equal to endpoint max packet size */
+      ep->xfer_size = ep->maxpacket;
+
+      USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->xfer_size);
+      USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
+    }
+    else
+    {
+      if (ep->xfer_len == 0U)
+      {
+        USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->maxpacket);
+        USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
+      }
+      else
+      {
+        pktcnt = (uint16_t)((ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket);
+        ep->xfer_size = ep->maxpacket * pktcnt;
+
+        USBx_OUTEP(epnum)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_PKTCNT & ((uint32_t)pktcnt << 19);
+        USBx_OUTEP(epnum)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_XFRSIZ & ep->xfer_size;
+      }
+    }
+
+    if (dma == 1U)
+    {
+      if ((uint32_t)ep->xfer_buff != 0U)
+      {
+        USBx_OUTEP(epnum)->DOEPDMA = (uint32_t)(ep->xfer_buff);
+      }
+    }
+
+    if (ep->type == EP_TYPE_ISOC)
+    {
+      if ((USBx_DEVICE->DSTS & (1U << 8)) == 0U)
+      {
+        USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM;
+      }
+      else
+      {
+        USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
+      }
+    }
+    /* EP enable */
+    USBx_OUTEP(epnum)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
+  }
+
+  return HAL_OK;
+}
+
+
+/**
+   * @brief  USB_EPStoptXfer  Stop transfer on an EP
+   * @param  USBx  usb device instance
+   * @param  ep pointer to endpoint structure
+   * @retval HAL status
+   */
+HAL_StatusTypeDef USB_EPStopXfer(const USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
+{
+  __IO uint32_t count = 0U;
+  HAL_StatusTypeDef ret = HAL_OK;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  /* IN endpoint */
+  if (ep->is_in == 1U)
+  {
+    /* EP enable, IN data in FIFO */
+    if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
+    {
+      USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_SNAK);
+      USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_EPDIS);
+
+      do
+      {
+        count++;
+
+        if (count > 10000U)
+        {
+          ret = HAL_ERROR;
+          break;
+        }
+      } while (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) ==  USB_OTG_DIEPCTL_EPENA);
+    }
+  }
+  else /* OUT endpoint */
+  {
+    if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
+    {
+      USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_SNAK);
+      USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_EPDIS);
+
+      do
+      {
+        count++;
+
+        if (count > 10000U)
+        {
+          ret = HAL_ERROR;
+          break;
+        }
+      } while (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) ==  USB_OTG_DOEPCTL_EPENA);
+    }
+  }
+
+  return ret;
+}
+
+
+/**
+  * @brief  USB_WritePacket : Writes a packet into the Tx FIFO associated
+  *         with the EP/channel
+  * @param  USBx  Selected device
+  * @param  src   pointer to source buffer
+  * @param  ch_ep_num  endpoint or host channel number
+  * @param  len  Number of bytes to write
+  * @param  dma USB dma enabled or disabled
+  *          This parameter can be one of these values:
+  *           0 : DMA feature not used
+  *           1 : DMA feature used
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_WritePacket(const USB_OTG_GlobalTypeDef *USBx, uint8_t *src,
+                                  uint8_t ch_ep_num, uint16_t len, uint8_t dma)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint8_t *pSrc = src;
+  uint32_t count32b;
+  uint32_t i;
+
+  if (dma == 0U)
+  {
+    count32b = ((uint32_t)len + 3U) / 4U;
+    for (i = 0U; i < count32b; i++)
+    {
+      USBx_DFIFO((uint32_t)ch_ep_num) = __UNALIGNED_UINT32_READ(pSrc);
+      pSrc++;
+      pSrc++;
+      pSrc++;
+      pSrc++;
+    }
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_ReadPacket : read a packet from the RX FIFO
+  * @param  USBx  Selected device
+  * @param  dest  source pointer
+  * @param  len  Number of bytes to read
+  * @retval pointer to destination buffer
+  */
+void *USB_ReadPacket(const USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint8_t *pDest = dest;
+  uint32_t pData;
+  uint32_t i;
+  uint32_t count32b = (uint32_t)len >> 2U;
+  uint16_t remaining_bytes = len % 4U;
+
+  for (i = 0U; i < count32b; i++)
+  {
+    __UNALIGNED_UINT32_WRITE(pDest, USBx_DFIFO(0U));
+    pDest++;
+    pDest++;
+    pDest++;
+    pDest++;
+  }
+
+  /* When Number of data is not word aligned, read the remaining byte */
+  if (remaining_bytes != 0U)
+  {
+    i = 0U;
+    __UNALIGNED_UINT32_WRITE(&pData, USBx_DFIFO(0U));
+
+    do
+    {
+      *(uint8_t *)pDest = (uint8_t)(pData >> (8U * (uint8_t)(i)));
+      i++;
+      pDest++;
+      remaining_bytes--;
+    } while (remaining_bytes != 0U);
+  }
+
+  return ((void *)pDest);
+}
+
+/**
+  * @brief  USB_EPSetStall : set a stall condition over an EP
+  * @param  USBx  Selected device
+  * @param  ep pointer to endpoint structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_EPSetStall(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t epnum = (uint32_t)ep->num;
+
+  if (ep->is_in == 1U)
+  {
+    if (((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == 0U) && (epnum != 0U))
+    {
+      USBx_INEP(epnum)->DIEPCTL &= ~(USB_OTG_DIEPCTL_EPDIS);
+    }
+    USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
+  }
+  else
+  {
+    if (((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == 0U) && (epnum != 0U))
+    {
+      USBx_OUTEP(epnum)->DOEPCTL &= ~(USB_OTG_DOEPCTL_EPDIS);
+    }
+    USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_STALL;
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_EPClearStall : Clear a stall condition over an EP
+  * @param  USBx  Selected device
+  * @param  ep pointer to endpoint structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_EPClearStall(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t epnum = (uint32_t)ep->num;
+
+  if (ep->is_in == 1U)
+  {
+    USBx_INEP(epnum)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
+    if ((ep->type == EP_TYPE_INTR) || (ep->type == EP_TYPE_BULK))
+    {
+      USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; /* DATA0 */
+    }
+  }
+  else
+  {
+    USBx_OUTEP(epnum)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
+    if ((ep->type == EP_TYPE_INTR) || (ep->type == EP_TYPE_BULK))
+    {
+      USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; /* DATA0 */
+    }
+  }
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_StopDevice : Stop the usb device mode
+  * @param  USBx  Selected device
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx)
+{
+  HAL_StatusTypeDef ret;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t i;
+
+  /* Clear Pending interrupt */
+  for (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 */
+  ret = USB_FlushRxFifo(USBx);
+  if (ret != HAL_OK)
+  {
+    return ret;
+  }
+
+  ret = USB_FlushTxFifo(USBx,  0x10U);
+  if (ret != HAL_OK)
+  {
+    return ret;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  USB_SetDevAddress : Stop the usb device mode
+  * @param  USBx  Selected device
+  * @param  address  new device address to be assigned
+  *          This parameter can be a value from 0 to 255
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_SetDevAddress(const USB_OTG_GlobalTypeDef *USBx, uint8_t address)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  USBx_DEVICE->DCFG &= ~(USB_OTG_DCFG_DAD);
+  USBx_DEVICE->DCFG |= ((uint32_t)address << 4) & USB_OTG_DCFG_DAD;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_DevConnect : Connect the USB device by enabling Rpu
+  * @param  USBx  Selected device
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_DevConnect(const USB_OTG_GlobalTypeDef *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  /* In case phy is stopped, ensure to ungate and restore the phy CLK */
+  USBx_PCGCCTL &= ~(USB_OTG_PCGCCTL_STOPCLK | USB_OTG_PCGCCTL_GATECLK);
+
+  USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_DevDisconnect : Disconnect the USB device by disabling Rpu
+  * @param  USBx  Selected device
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_DevDisconnect(const USB_OTG_GlobalTypeDef *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  /* In case phy is stopped, ensure to ungate and restore the phy CLK */
+  USBx_PCGCCTL &= ~(USB_OTG_PCGCCTL_STOPCLK | USB_OTG_PCGCCTL_GATECLK);
+
+  USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_ReadInterrupts: return the global USB interrupt status
+  * @param  USBx  Selected device
+  * @retval USB Global Interrupt status
+  */
+uint32_t USB_ReadInterrupts(USB_OTG_GlobalTypeDef const *USBx)
+{
+  uint32_t tmpreg;
+
+  tmpreg = USBx->GINTSTS;
+  tmpreg &= USBx->GINTMSK;
+
+  return tmpreg;
+}
+
+/**
+  * @brief  USB_ReadChInterrupts: return USB channel interrupt status
+  * @param  USBx  Selected device
+  * @param  chnum Channel number
+  * @retval USB Channel Interrupt status
+  */
+uint32_t USB_ReadChInterrupts(const USB_OTG_GlobalTypeDef *USBx, uint8_t chnum)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t tmpreg;
+
+  tmpreg = USBx_HC(chnum)->HCINT;
+  tmpreg &= USBx_HC(chnum)->HCINTMSK;
+
+  return tmpreg;
+}
+
+/**
+  * @brief  USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status
+  * @param  USBx  Selected device
+  * @retval USB Device OUT EP interrupt status
+  */
+uint32_t USB_ReadDevAllOutEpInterrupt(const USB_OTG_GlobalTypeDef *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t tmpreg;
+
+  tmpreg  = USBx_DEVICE->DAINT;
+  tmpreg &= USBx_DEVICE->DAINTMSK;
+
+  return ((tmpreg & 0xffff0000U) >> 16);
+}
+
+/**
+  * @brief  USB_ReadDevAllInEpInterrupt: return the USB device IN endpoints interrupt status
+  * @param  USBx  Selected device
+  * @retval USB Device IN EP interrupt status
+  */
+uint32_t USB_ReadDevAllInEpInterrupt(const USB_OTG_GlobalTypeDef *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t tmpreg;
+
+  tmpreg  = USBx_DEVICE->DAINT;
+  tmpreg &= USBx_DEVICE->DAINTMSK;
+
+  return ((tmpreg & 0xFFFFU));
+}
+
+/**
+  * @brief  Returns Device OUT EP Interrupt register
+  * @param  USBx  Selected device
+  * @param  epnum  endpoint number
+  *          This parameter can be a value from 0 to 15
+  * @retval Device OUT EP Interrupt register
+  */
+uint32_t USB_ReadDevOutEPInterrupt(const USB_OTG_GlobalTypeDef *USBx, uint8_t epnum)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t tmpreg;
+
+  tmpreg  = USBx_OUTEP((uint32_t)epnum)->DOEPINT;
+  tmpreg &= USBx_DEVICE->DOEPMSK;
+
+  return tmpreg;
+}
+
+/**
+  * @brief  Returns Device IN EP Interrupt register
+  * @param  USBx  Selected device
+  * @param  epnum  endpoint number
+  *          This parameter can be a value from 0 to 15
+  * @retval Device IN EP Interrupt register
+  */
+uint32_t USB_ReadDevInEPInterrupt(const USB_OTG_GlobalTypeDef *USBx, uint8_t epnum)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t tmpreg;
+  uint32_t msk;
+  uint32_t emp;
+
+  msk = USBx_DEVICE->DIEPMSK;
+  emp = USBx_DEVICE->DIEPEMPMSK;
+  msk |= ((emp >> (epnum & EP_ADDR_MSK)) & 0x1U) << 7;
+  tmpreg = USBx_INEP((uint32_t)epnum)->DIEPINT & msk;
+
+  return tmpreg;
+}
+
+/**
+  * @brief  USB_ClearInterrupts: clear a USB interrupt
+  * @param  USBx  Selected device
+  * @param  interrupt  flag
+  * @retval None
+  */
+void  USB_ClearInterrupts(USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt)
+{
+  USBx->GINTSTS &= interrupt;
+}
+
+/**
+  * @brief  Returns USB core mode
+  * @param  USBx  Selected device
+  * @retval return core mode : Host or Device
+  *          This parameter can be one of these values:
+  *           0 : Host
+  *           1 : Device
+  */
+uint32_t USB_GetMode(const USB_OTG_GlobalTypeDef *USBx)
+{
+  return ((USBx->GINTSTS) & 0x1U);
+}
+
+/**
+  * @brief  Activate EP0 for Setup transactions
+  * @param  USBx  Selected device
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_ActivateSetup(const USB_OTG_GlobalTypeDef *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  /* 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;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Prepare the EP0 to start the first control setup
+  * @param  USBx  Selected device
+  * @param  dma USB dma enabled or disabled
+  *          This parameter can be one of these values:
+  *           0 : DMA feature not used
+  *           1 : DMA feature used
+  * @param  psetup  pointer to setup packet
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_EP0_OutStart(const USB_OTG_GlobalTypeDef *USBx, uint8_t dma, const uint8_t *psetup)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
+
+  if (gSNPSiD > USB_OTG_CORE_ID_300A)
+  {
+    if ((USBx_OUTEP(0U)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
+    {
+      return HAL_OK;
+    }
+  }
+
+  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;
+
+  if (dma == 1U)
+  {
+    USBx_OUTEP(0U)->DOEPDMA = (uint32_t)psetup;
+    /* EP enable */
+    USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_USBAEP;
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Reset the USB Core (needed after USB clock settings change)
+  * @param  USBx  Selected device
+  * @retval HAL status
+  */
+static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx)
+{
+  __IO uint32_t count = 0U;
+
+  /* Wait for AHB master IDLE state. */
+  do
+  {
+    count++;
+
+    if (count > HAL_USB_TIMEOUT)
+    {
+      return HAL_TIMEOUT;
+    }
+  } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
+
+  /* Core Soft Reset */
+  count = 0U;
+  USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
+
+  do
+  {
+    count++;
+
+    if (count > HAL_USB_TIMEOUT)
+    {
+      return HAL_TIMEOUT;
+    }
+  } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_HostInit : Initializes the USB OTG controller registers
+  *         for Host mode
+  * @param  USBx  Selected device
+  * @param  cfg   pointer to a USB_OTG_CfgTypeDef structure that contains
+  *         the configuration information for the specified USBx peripheral.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_HostInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
+{
+  HAL_StatusTypeDef ret = HAL_OK;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t i;
+
+  /* Restart the Phy Clock */
+  USBx_PCGCCTL = 0U;
+
+#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) \
+ || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) \
+ || defined(STM32F423xx)
+  /* Disable HW VBUS sensing */
+  USBx->GCCFG &= ~(USB_OTG_GCCFG_VBDEN);
+#else
+  /*
+  * Disable HW VBUS sensing. VBUS is internally considered to be always
+  * at VBUS-Valid level (5V).
+  */
+  USBx->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS;
+  USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN;
+  USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN;
+#endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||
+          defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) ||
+          defined(STM32F423xx) */
+#if defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) \
+ || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
+  /* Disable Battery chargin detector */
+  USBx->GCCFG &= ~(USB_OTG_GCCFG_BCDEN);
+#endif /* defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) ||
+          defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) */
+
+  if ((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) == 0U)
+  {
+    if (cfg.speed == USBH_FSLS_SPEED)
+    {
+      /* Force Device Enumeration to FS/LS mode only */
+      USBx_HOST->HCFG |= USB_OTG_HCFG_FSLSS;
+    }
+    else
+    {
+      /* Set default Max speed support */
+      USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
+    }
+  }
+  else
+  {
+    /* Set default Max speed support */
+    USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
+  }
+
+  /* Make sure the FIFOs are flushed. */
+  if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
+  {
+    ret = HAL_ERROR;
+  }
+
+  if (USB_FlushRxFifo(USBx) != HAL_OK)
+  {
+    ret = HAL_ERROR;
+  }
+
+  /* Clear all pending HC Interrupts */
+  for (i = 0U; i < cfg.Host_channels; i++)
+  {
+    USBx_HC(i)->HCINT = CLEAR_INTERRUPT_MASK;
+    USBx_HC(i)->HCINTMSK = 0U;
+  }
+
+  /* Disable all interrupts. */
+  USBx->GINTMSK = 0U;
+
+  /* Clear any pending interrupts */
+  USBx->GINTSTS = CLEAR_INTERRUPT_MASK;
+#if defined (USB_OTG_HS)
+  if (USBx == USB_OTG_HS)
+  {
+    /* set Rx FIFO size */
+    USBx->GRXFSIZ  = 0x200U;
+    USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((0x100U << 16) & USB_OTG_NPTXFD) | 0x200U);
+    USBx->HPTXFSIZ = (uint32_t)(((0xE0U << 16) & USB_OTG_HPTXFSIZ_PTXFD) | 0x300U);
+  }
+  else
+#endif /* defined (USB_OTG_HS) */
+  {
+    /* set Rx FIFO size */
+    USBx->GRXFSIZ  = 0x80U;
+    USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((0x60U << 16) & USB_OTG_NPTXFD) | 0x80U);
+    USBx->HPTXFSIZ = (uint32_t)(((0x40U << 16)& USB_OTG_HPTXFSIZ_PTXFD) | 0xE0U);
+  }
+
+  /* Enable the common interrupts */
+  if (cfg.dma_enable == 0U)
+  {
+    USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
+  }
+
+  /* Enable interrupts matching to the Host mode ONLY */
+  USBx->GINTMSK |= (USB_OTG_GINTMSK_PRTIM            | USB_OTG_GINTMSK_HCIM | \
+                    USB_OTG_GINTMSK_SOFM             | USB_OTG_GINTSTS_DISCINT | \
+                    USB_OTG_GINTMSK_PXFRM_IISOOXFRM  | USB_OTG_GINTMSK_WUIM);
+
+  return ret;
+}
+
+/**
+  * @brief  USB_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the
+  *         HCFG register on the PHY type and set the right frame interval
+  * @param  USBx  Selected device
+  * @param  freq  clock frequency
+  *          This parameter can be one of these values:
+  *           HCFG_48_MHZ : Full Speed 48 MHz Clock
+  *           HCFG_6_MHZ : Low Speed 6 MHz Clock
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_InitFSLSPClkSel(const USB_OTG_GlobalTypeDef *USBx, uint8_t freq)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSPCS);
+  USBx_HOST->HCFG |= (uint32_t)freq & USB_OTG_HCFG_FSLSPCS;
+
+  if (freq == HCFG_48_MHZ)
+  {
+    USBx_HOST->HFIR = HFIR_48_MHZ;
+  }
+  else if (freq == HCFG_6_MHZ)
+  {
+    USBx_HOST->HFIR = HFIR_6_MHZ;
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_OTG_ResetPort : Reset Host Port
+  * @param  USBx  Selected device
+  * @retval HAL status
+  * @note (1)The application must wait at least 10 ms
+  *   before clearing the reset bit.
+  */
+HAL_StatusTypeDef USB_ResetPort(const USB_OTG_GlobalTypeDef *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  __IO uint32_t hprt0 = 0U;
+
+  hprt0 = USBx_HPRT0;
+
+  hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |
+             USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
+
+  USBx_HPRT0 = (USB_OTG_HPRT_PRST | hprt0);
+  HAL_Delay(100U);                                 /* See Note #1 */
+  USBx_HPRT0 = ((~USB_OTG_HPRT_PRST) & hprt0);
+  HAL_Delay(10U);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_DriveVbus : activate or de-activate vbus
+  * @param  state  VBUS state
+  *          This parameter can be one of these values:
+  *           0 : Deactivate VBUS
+  *           1 : Activate VBUS
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_DriveVbus(const USB_OTG_GlobalTypeDef *USBx, uint8_t state)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  __IO uint32_t hprt0 = 0U;
+
+  hprt0 = USBx_HPRT0;
+
+  hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |
+             USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
+
+  if (((hprt0 & USB_OTG_HPRT_PPWR) == 0U) && (state == 1U))
+  {
+    USBx_HPRT0 = (USB_OTG_HPRT_PPWR | hprt0);
+  }
+  if (((hprt0 & USB_OTG_HPRT_PPWR) == USB_OTG_HPRT_PPWR) && (state == 0U))
+  {
+    USBx_HPRT0 = ((~USB_OTG_HPRT_PPWR) & hprt0);
+  }
+  return HAL_OK;
+}
+
+/**
+  * @brief  Return Host Core speed
+  * @param  USBx  Selected device
+  * @retval speed : Host speed
+  *          This parameter can be one of these values:
+  *            @arg HCD_SPEED_HIGH: High speed mode
+  *            @arg HCD_SPEED_FULL: Full speed mode
+  *            @arg HCD_SPEED_LOW: Low speed mode
+  */
+uint32_t USB_GetHostSpeed(USB_OTG_GlobalTypeDef const *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  __IO uint32_t hprt0 = 0U;
+
+  hprt0 = USBx_HPRT0;
+  return ((hprt0 & USB_OTG_HPRT_PSPD) >> 17);
+}
+
+/**
+  * @brief  Return Host Current Frame number
+  * @param  USBx  Selected device
+  * @retval current frame number
+  */
+uint32_t USB_GetCurrentFrame(USB_OTG_GlobalTypeDef const *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  return (USBx_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
+}
+
+/**
+  * @brief  Initialize a host channel
+  * @param  USBx  Selected device
+  * @param  ch_num  Channel number
+  *         This parameter can be a value from 1 to 15
+  * @param  epnum  Endpoint number
+  *          This parameter can be a value from 1 to 15
+  * @param  dev_address  Current device address
+  *          This parameter can be a value from 0 to 255
+  * @param  speed  Current device speed
+  *          This parameter can be one of these values:
+  *            @arg USB_OTG_SPEED_HIGH: High speed mode
+  *            @arg USB_OTG_SPEED_FULL: Full speed mode
+  *            @arg USB_OTG_SPEED_LOW: Low speed mode
+  * @param  ep_type  Endpoint Type
+  *          This parameter can be one of these values:
+  *            @arg EP_TYPE_CTRL: Control type
+  *            @arg EP_TYPE_ISOC: Isochronous type
+  *            @arg EP_TYPE_BULK: Bulk type
+  *            @arg EP_TYPE_INTR: Interrupt type
+  * @param  mps  Max Packet Size
+  *          This parameter can be a value from 0 to 32K
+  * @retval HAL state
+  */
+HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num,
+                              uint8_t epnum, uint8_t dev_address, uint8_t speed,
+                              uint8_t ep_type, uint16_t mps)
+{
+  HAL_StatusTypeDef ret = HAL_OK;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t HCcharEpDir;
+  uint32_t HCcharLowSpeed;
+  uint32_t HostCoreSpeed;
+
+  /* Clear old interrupt conditions for this host channel. */
+  USBx_HC((uint32_t)ch_num)->HCINT = CLEAR_INTERRUPT_MASK;
+
+  /* Enable channel interrupts required for this transfer. */
+  switch (ep_type)
+  {
+    case EP_TYPE_CTRL:
+    case EP_TYPE_BULK:
+      USBx_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM  |
+                                            USB_OTG_HCINTMSK_STALLM |
+                                            USB_OTG_HCINTMSK_TXERRM |
+                                            USB_OTG_HCINTMSK_DTERRM |
+                                            USB_OTG_HCINTMSK_AHBERR |
+                                            USB_OTG_HCINTMSK_NAKM;
+
+      if ((epnum & 0x80U) == 0x80U)
+      {
+        USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
+      }
+      else
+      {
+#if defined (USB_OTG_HS)
+        if (USBx == USB_OTG_HS)
+        {
+          USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_NYET |
+                                                 USB_OTG_HCINTMSK_ACKM;
+        }
+#endif /* defined (USB_OTG_HS) */
+      }
+      break;
+
+    case EP_TYPE_INTR:
+      USBx_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM  |
+                                            USB_OTG_HCINTMSK_STALLM |
+                                            USB_OTG_HCINTMSK_TXERRM |
+                                            USB_OTG_HCINTMSK_DTERRM |
+                                            USB_OTG_HCINTMSK_NAKM   |
+                                            USB_OTG_HCINTMSK_AHBERR |
+                                            USB_OTG_HCINTMSK_FRMORM;
+
+      if ((epnum & 0x80U) == 0x80U)
+      {
+        USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
+      }
+
+      break;
+
+    case EP_TYPE_ISOC:
+      USBx_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM  |
+                                            USB_OTG_HCINTMSK_ACKM   |
+                                            USB_OTG_HCINTMSK_AHBERR |
+                                            USB_OTG_HCINTMSK_FRMORM;
+
+      if ((epnum & 0x80U) == 0x80U)
+      {
+        USBx_HC((uint32_t)ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_TXERRM | USB_OTG_HCINTMSK_BBERRM);
+      }
+      break;
+
+    default:
+      ret = HAL_ERROR;
+      break;
+  }
+
+  /* Clear Hub Start Split transaction */
+  USBx_HC((uint32_t)ch_num)->HCSPLT = 0U;
+
+  /* Enable host channel Halt interrupt */
+  USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_CHHM;
+
+  /* Enable the top level host channel interrupt. */
+  USBx_HOST->HAINTMSK |= 1UL << (ch_num & 0xFU);
+
+  /* Make sure host channel interrupts are enabled. */
+  USBx->GINTMSK |= USB_OTG_GINTMSK_HCIM;
+
+  /* Program the HCCHAR register */
+  if ((epnum & 0x80U) == 0x80U)
+  {
+    HCcharEpDir = (0x1U << 15) & USB_OTG_HCCHAR_EPDIR;
+  }
+  else
+  {
+    HCcharEpDir = 0U;
+  }
+
+  HostCoreSpeed = USB_GetHostSpeed(USBx);
+
+  /* LS device plugged to HUB */
+  if ((speed == HPRT0_PRTSPD_LOW_SPEED) && (HostCoreSpeed != HPRT0_PRTSPD_LOW_SPEED))
+  {
+    HCcharLowSpeed = (0x1U << 17) & USB_OTG_HCCHAR_LSDEV;
+  }
+  else
+  {
+    HCcharLowSpeed = 0U;
+  }
+
+  USBx_HC((uint32_t)ch_num)->HCCHAR = (((uint32_t)dev_address << 22) & USB_OTG_HCCHAR_DAD) |
+                                      ((((uint32_t)epnum & 0x7FU) << 11) & USB_OTG_HCCHAR_EPNUM) |
+                                      (((uint32_t)ep_type << 18) & USB_OTG_HCCHAR_EPTYP) |
+                                      ((uint32_t)mps & USB_OTG_HCCHAR_MPSIZ) |
+                                      USB_OTG_HCCHAR_MC_0 | HCcharEpDir | HCcharLowSpeed;
+
+  if ((ep_type == EP_TYPE_INTR) || (ep_type == EP_TYPE_ISOC))
+  {
+    USBx_HC((uint32_t)ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Start a transfer over a host channel
+  * @param  USBx  Selected device
+  * @param  hc  pointer to host channel structure
+  * @param  dma USB dma enabled or disabled
+  *          This parameter can be one of these values:
+  *           0 : DMA feature not used
+  *           1 : DMA feature used
+  * @retval HAL state
+  */
+HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDef *hc, uint8_t dma)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t ch_num = (uint32_t)hc->ch_num;
+  __IO uint32_t tmpreg;
+  uint8_t  is_oddframe;
+  uint16_t len_words;
+  uint16_t num_packets;
+  uint16_t max_hc_pkt_count = HC_MAX_PKT_CNT;
+
+#if defined (USB_OTG_HS)
+  if (USBx == USB_OTG_HS)
+  {
+    /* in DMA mode host Core automatically issues ping in case of NYET/NAK */
+    if (dma == 1U)
+    {
+      if (((hc->ep_type == EP_TYPE_CTRL) || (hc->ep_type == EP_TYPE_BULK)) && (hc->do_ssplit == 0U))
+      {
+
+        USBx_HC((uint32_t)ch_num)->HCINTMSK &= ~(USB_OTG_HCINTMSK_NYET |
+                                                 USB_OTG_HCINTMSK_ACKM |
+                                                 USB_OTG_HCINTMSK_NAKM);
+      }
+    }
+    else
+    {
+      if ((hc->speed == USBH_HS_SPEED) && (hc->do_ping == 1U))
+      {
+        (void)USB_DoPing(USBx, hc->ch_num);
+        return HAL_OK;
+      }
+    }
+  }
+#endif /* defined (USB_OTG_HS) */
+
+  if (hc->do_ssplit == 1U)
+  {
+    /* Set number of packet to 1 for Split transaction */
+    num_packets = 1U;
+
+    if (hc->ep_is_in != 0U)
+    {
+      hc->XferSize = (uint32_t)num_packets * hc->max_packet;
+    }
+    else
+    {
+      if (hc->ep_type == EP_TYPE_ISOC)
+      {
+        if (hc->xfer_len > ISO_SPLT_MPS)
+        {
+          /* Isochrone Max Packet Size for Split mode */
+          hc->XferSize = hc->max_packet;
+          hc->xfer_len = hc->XferSize;
+
+          if ((hc->iso_splt_xactPos == HCSPLT_BEGIN) || (hc->iso_splt_xactPos == HCSPLT_MIDDLE))
+          {
+            hc->iso_splt_xactPos = HCSPLT_MIDDLE;
+          }
+          else
+          {
+            hc->iso_splt_xactPos = HCSPLT_BEGIN;
+          }
+        }
+        else
+        {
+          hc->XferSize = hc->xfer_len;
+
+          if ((hc->iso_splt_xactPos != HCSPLT_BEGIN) && (hc->iso_splt_xactPos != HCSPLT_MIDDLE))
+          {
+            hc->iso_splt_xactPos = HCSPLT_FULL;
+          }
+          else
+          {
+            hc->iso_splt_xactPos = HCSPLT_END;
+          }
+        }
+      }
+      else
+      {
+        if ((dma == 1U) && (hc->xfer_len > hc->max_packet))
+        {
+          hc->XferSize = (uint32_t)num_packets * hc->max_packet;
+        }
+        else
+        {
+          hc->XferSize = hc->xfer_len;
+        }
+      }
+    }
+  }
+  else
+  {
+    /* Compute the expected number of packets associated to the transfer */
+    if (hc->xfer_len > 0U)
+    {
+      num_packets = (uint16_t)((hc->xfer_len + hc->max_packet - 1U) / hc->max_packet);
+
+      if (num_packets > max_hc_pkt_count)
+      {
+        num_packets = max_hc_pkt_count;
+        hc->XferSize = (uint32_t)num_packets * hc->max_packet;
+      }
+    }
+    else
+    {
+      num_packets = 1U;
+    }
+
+    /*
+    * For IN channel HCTSIZ.XferSize is expected to be an integer multiple of
+    * max_packet size.
+    */
+    if (hc->ep_is_in != 0U)
+    {
+      hc->XferSize = (uint32_t)num_packets * hc->max_packet;
+    }
+    else
+    {
+      hc->XferSize = hc->xfer_len;
+    }
+  }
+
+  /* Initialize the HCTSIZn register */
+  USBx_HC(ch_num)->HCTSIZ = (hc->XferSize & USB_OTG_HCTSIZ_XFRSIZ) |
+                            (((uint32_t)num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |
+                            (((uint32_t)hc->data_pid << 29) & USB_OTG_HCTSIZ_DPID);
+
+  if (dma != 0U)
+  {
+    /* xfer_buff MUST be 32-bits aligned */
+    USBx_HC(ch_num)->HCDMA = (uint32_t)hc->xfer_buff;
+  }
+
+  is_oddframe = (((uint32_t)USBx_HOST->HFNUM & 0x01U) != 0U) ? 0U : 1U;
+  USBx_HC(ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_ODDFRM;
+  USBx_HC(ch_num)->HCCHAR |= (uint32_t)is_oddframe << 29;
+
+  if (hc->do_ssplit == 1U)
+  {
+    /* Set Hub start Split transaction */
+    USBx_HC((uint32_t)ch_num)->HCSPLT = ((uint32_t)hc->hub_addr << USB_OTG_HCSPLT_HUBADDR_Pos) |
+                                        (uint32_t)hc->hub_port_nbr | USB_OTG_HCSPLT_SPLITEN;
+
+    /* unmask ack & nyet for IN/OUT transactions */
+    USBx_HC((uint32_t)ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_ACKM |
+                                            USB_OTG_HCINTMSK_NYET);
+
+    if ((hc->do_csplit == 1U) && (hc->ep_is_in == 0U))
+    {
+      USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_COMPLSPLT;
+      USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_NYET;
+    }
+
+    if (((hc->ep_type == EP_TYPE_ISOC) || (hc->ep_type == EP_TYPE_INTR)) &&
+        (hc->do_csplit == 1U) && (hc->ep_is_in == 1U))
+    {
+      USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_COMPLSPLT;
+    }
+
+    /* Position management for iso out transaction on split mode */
+    if ((hc->ep_type == EP_TYPE_ISOC) && (hc->ep_is_in == 0U))
+    {
+      /* Set data payload position */
+      switch (hc->iso_splt_xactPos)
+      {
+        case HCSPLT_BEGIN:
+          /* First data payload for OUT Transaction */
+          USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS_1;
+          break;
+
+        case HCSPLT_MIDDLE:
+          /* Middle data payload for OUT Transaction */
+          USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS_Pos;
+          break;
+
+        case HCSPLT_END:
+          /* End data payload for OUT Transaction */
+          USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS_0;
+          break;
+
+        case HCSPLT_FULL:
+          /* Entire data payload for OUT Transaction */
+          USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS;
+          break;
+
+        default:
+          break;
+      }
+    }
+  }
+  else
+  {
+    /* Clear Hub Start Split transaction */
+    USBx_HC((uint32_t)ch_num)->HCSPLT = 0U;
+  }
+
+  /* Set host channel enable */
+  tmpreg = USBx_HC(ch_num)->HCCHAR;
+  tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+
+  /* make sure to set the correct ep direction */
+  if (hc->ep_is_in != 0U)
+  {
+    tmpreg |= USB_OTG_HCCHAR_EPDIR;
+  }
+  else
+  {
+    tmpreg &= ~USB_OTG_HCCHAR_EPDIR;
+  }
+  tmpreg |= USB_OTG_HCCHAR_CHENA;
+  USBx_HC(ch_num)->HCCHAR = tmpreg;
+
+  if (dma != 0U) /* dma mode */
+  {
+    return HAL_OK;
+  }
+
+  if ((hc->ep_is_in == 0U) && (hc->xfer_len > 0U) && (hc->do_csplit == 0U))
+  {
+    switch (hc->ep_type)
+    {
+      /* Non periodic transfer */
+      case EP_TYPE_CTRL:
+      case EP_TYPE_BULK:
+
+        len_words = (uint16_t)((hc->xfer_len + 3U) / 4U);
+
+        /* check if there is enough space in FIFO space */
+        if (len_words > (USBx->HNPTXSTS & 0xFFFFU))
+        {
+          /* need to process data in nptxfempty interrupt */
+          USBx->GINTMSK |= USB_OTG_GINTMSK_NPTXFEM;
+        }
+        break;
+
+      /* Periodic transfer */
+      case EP_TYPE_INTR:
+      case EP_TYPE_ISOC:
+        len_words = (uint16_t)((hc->xfer_len + 3U) / 4U);
+        /* check if there is enough space in FIFO space */
+        if (len_words > (USBx_HOST->HPTXSTS & 0xFFFFU)) /* split the transfer */
+        {
+          /* need to process data in ptxfempty interrupt */
+          USBx->GINTMSK |= USB_OTG_GINTMSK_PTXFEM;
+        }
+        break;
+
+      default:
+        break;
+    }
+
+    /* Write packet into the Tx FIFO. */
+    (void)USB_WritePacket(USBx, hc->xfer_buff, hc->ch_num, (uint16_t)hc->xfer_len, 0);
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief Read all host channel interrupts status
+  * @param  USBx  Selected device
+  * @retval HAL state
+  */
+uint32_t USB_HC_ReadInterrupt(const USB_OTG_GlobalTypeDef *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  return ((USBx_HOST->HAINT) & 0xFFFFU);
+}
+
+/**
+  * @brief  Halt a host channel
+  * @param  USBx  Selected device
+  * @param  hc_num  Host Channel number
+  *         This parameter can be a value from 1 to 15
+  * @retval HAL state
+  */
+HAL_StatusTypeDef USB_HC_Halt(const USB_OTG_GlobalTypeDef *USBx, uint8_t hc_num)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t hcnum = (uint32_t)hc_num;
+  __IO uint32_t count = 0U;
+  uint32_t HcEpType = (USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_EPTYP) >> 18;
+  uint32_t ChannelEna = (USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) >> 31;
+  uint32_t SplitEna = (USBx_HC(hcnum)->HCSPLT & USB_OTG_HCSPLT_SPLITEN) >> 31;
+
+  /* In buffer DMA, Channel disable must not be programmed for non-split periodic channels.
+     At the end of the next uframe/frame (in the worst case), the core generates a channel halted
+     and disables the channel automatically. */
+
+  if ((((USBx->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == USB_OTG_GAHBCFG_DMAEN) && (SplitEna == 0U)) &&
+      ((ChannelEna == 0U) || (((HcEpType == HCCHAR_ISOC) || (HcEpType == HCCHAR_INTR)))))
+  {
+    return HAL_OK;
+  }
+
+  /* Check for space in the request queue to issue the halt. */
+  if ((HcEpType == HCCHAR_CTRL) || (HcEpType == HCCHAR_BULK))
+  {
+    USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
+
+    if ((USBx->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == 0U)
+    {
+      if ((USBx->HNPTXSTS & (0xFFU << 16)) == 0U)
+      {
+        USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
+        USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+        do
+        {
+          count++;
+
+          if (count > 1000U)
+          {
+            break;
+          }
+        } while ((USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
+      }
+      else
+      {
+        USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+      }
+    }
+    else
+    {
+      USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+    }
+  }
+  else
+  {
+    USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
+
+    if ((USBx_HOST->HPTXSTS & (0xFFU << 16)) == 0U)
+    {
+      USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
+      USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+      do
+      {
+        count++;
+
+        if (count > 1000U)
+        {
+          break;
+        }
+      } while ((USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
+    }
+    else
+    {
+      USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+    }
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initiate Do Ping protocol
+  * @param  USBx  Selected device
+  * @param  hc_num  Host Channel number
+  *         This parameter can be a value from 1 to 15
+  * @retval HAL state
+  */
+HAL_StatusTypeDef USB_DoPing(const USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  uint32_t chnum = (uint32_t)ch_num;
+  uint32_t num_packets = 1U;
+  uint32_t tmpreg;
+
+  USBx_HC(chnum)->HCTSIZ = ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |
+                           USB_OTG_HCTSIZ_DOPING;
+
+  /* Set host channel enable */
+  tmpreg = USBx_HC(chnum)->HCCHAR;
+  tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+  tmpreg |= USB_OTG_HCCHAR_CHENA;
+  USBx_HC(chnum)->HCCHAR = tmpreg;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stop Host Core
+  * @param  USBx  Selected device
+  * @retval HAL state
+  */
+HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx)
+{
+  HAL_StatusTypeDef ret = HAL_OK;
+  uint32_t USBx_BASE = (uint32_t)USBx;
+  __IO uint32_t count = 0U;
+  uint32_t value;
+  uint32_t i;
+
+  (void)USB_DisableGlobalInt(USBx);
+
+  /* Flush USB FIFO */
+  if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
+  {
+    ret = HAL_ERROR;
+  }
+
+  if (USB_FlushRxFifo(USBx) != HAL_OK)
+  {
+    ret = HAL_ERROR;
+  }
+
+  /* Flush out any leftover queued requests. */
+  for (i = 0U; i <= 15U; i++)
+  {
+    value = USBx_HC(i)->HCCHAR;
+    value |=  USB_OTG_HCCHAR_CHDIS;
+    value &= ~USB_OTG_HCCHAR_CHENA;
+    value &= ~USB_OTG_HCCHAR_EPDIR;
+    USBx_HC(i)->HCCHAR = value;
+  }
+
+  /* Halt all channels to put them into a known state. */
+  for (i = 0U; i <= 15U; i++)
+  {
+    value = USBx_HC(i)->HCCHAR;
+    value |= USB_OTG_HCCHAR_CHDIS;
+    value |= USB_OTG_HCCHAR_CHENA;
+    value &= ~USB_OTG_HCCHAR_EPDIR;
+    USBx_HC(i)->HCCHAR = value;
+
+    do
+    {
+      count++;
+
+      if (count > 1000U)
+      {
+        break;
+      }
+    } while ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
+  }
+
+  /* Clear any pending Host interrupts */
+  USBx_HOST->HAINT = CLEAR_INTERRUPT_MASK;
+  USBx->GINTSTS = CLEAR_INTERRUPT_MASK;
+
+  (void)USB_EnableGlobalInt(USBx);
+
+  return ret;
+}
+
+/**
+  * @brief  USB_ActivateRemoteWakeup active remote wakeup signalling
+  * @param  USBx Selected device
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_ActivateRemoteWakeup(const USB_OTG_GlobalTypeDef *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
+  {
+    /* active Remote wakeup signalling */
+    USBx_DEVICE->DCTL |= USB_OTG_DCTL_RWUSIG;
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  USB_DeActivateRemoteWakeup de-active remote wakeup signalling
+  * @param  USBx Selected device
+  * @retval HAL status
+  */
+HAL_StatusTypeDef USB_DeActivateRemoteWakeup(const USB_OTG_GlobalTypeDef *USBx)
+{
+  uint32_t USBx_BASE = (uint32_t)USBx;
+
+  /* active Remote wakeup signalling */
+  USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_RWUSIG);
+
+  return HAL_OK;
+}
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+#endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
+
+/**
+  * @}
+  */

+ 332 - 0
Middlewares/ST/STM32_USB_Device_Library/Class/AUDIO/Inc/usbd_audio.h

@@ -0,0 +1,332 @@
+/**
+  ******************************************************************************
+  * @file    usbd_audio.h
+  * @author  MCD Application Team
+  * @brief   header file for the usbd_audio.c file.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2015 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_AUDIO_H
+#define __USB_AUDIO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include  "usbd_ioreq.h"
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+  * @{
+  */
+
+/** @defgroup USBD_AUDIO
+  * @brief This file is the Header file for usbd_audio.c
+  * @{
+  */
+
+
+/** @defgroup USBD_AUDIO_Exported_Defines
+  * @{
+  */
+#ifndef USBD_AUDIO_FREQ
+/* AUDIO Class Config */
+#define USBD_AUDIO_FREQ                               48000U
+#endif /* USBD_AUDIO_FREQ */
+
+#ifndef USBD_MAX_NUM_INTERFACES
+#define USBD_MAX_NUM_INTERFACES                       1U
+#endif /* USBD_AUDIO_FREQ */
+
+#ifndef AUDIO_HS_BINTERVAL
+#define AUDIO_HS_BINTERVAL                            0x01U
+#endif /* AUDIO_HS_BINTERVAL */
+
+#ifndef AUDIO_FS_BINTERVAL
+#define AUDIO_FS_BINTERVAL                            0x01U
+#endif /* AUDIO_FS_BINTERVAL */
+
+#ifndef AUDIO_OUT_EP
+#define AUDIO_OUT_EP                                  0x01U
+#endif /* AUDIO_OUT_EP */
+
+#define USB_AUDIO_CONFIG_DESC_SIZ                     0x6DU
+#define AUDIO_INTERFACE_DESC_SIZE                     0x09U
+#define USB_AUDIO_DESC_SIZ                            0x09U
+#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE             0x09U
+#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE            0x07U
+
+#define AUDIO_DESCRIPTOR_TYPE                         0x21U
+#define USB_DEVICE_CLASS_AUDIO                        0x01U
+#define AUDIO_SUBCLASS_AUDIOCONTROL                   0x01U
+#define AUDIO_SUBCLASS_AUDIOSTREAMING                 0x02U
+#define AUDIO_PROTOCOL_UNDEFINED                      0x00U
+#define AUDIO_STREAMING_GENERAL                       0x01U
+#define AUDIO_STREAMING_FORMAT_TYPE                   0x02U
+
+/* Audio Descriptor Types */
+#define AUDIO_INTERFACE_DESCRIPTOR_TYPE               0x24U
+#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE                0x25U
+
+/* Audio Control Interface Descriptor Subtypes */
+#define AUDIO_CONTROL_HEADER                          0x01U
+#define AUDIO_CONTROL_INPUT_TERMINAL                  0x02U
+#define AUDIO_CONTROL_OUTPUT_TERMINAL                 0x03U
+#define AUDIO_CONTROL_FEATURE_UNIT                    0x06U
+
+#define AUDIO_INPUT_TERMINAL_DESC_SIZE                0x0CU
+#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE               0x09U
+#define AUDIO_STREAMING_INTERFACE_DESC_SIZE           0x07U
+
+#define AUDIO_CONTROL_MUTE                            0x0001U
+
+#define AUDIO_FORMAT_TYPE_I                           0x01U
+#define AUDIO_FORMAT_TYPE_III                         0x03U
+
+#define AUDIO_ENDPOINT_GENERAL                        0x01U
+
+#define AUDIO_REQ_GET_CUR                             0x81U
+#define AUDIO_REQ_SET_CUR                             0x01U
+
+#define AUDIO_OUT_STREAMING_CTRL                      0x02U
+
+#define AUDIO_OUT_TC                                  0x01U
+#define AUDIO_IN_TC                                   0x02U
+
+
+#define AUDIO_OUT_PACKET                              (uint16_t)(((USBD_AUDIO_FREQ * 2U * 2U) / 1000U))
+#define AUDIO_DEFAULT_VOLUME                          70U
+
+/* Number of sub-packets in the audio transfer buffer. You can modify this value but always make sure
+  that it is an even number and higher than 3 */
+#define AUDIO_OUT_PACKET_NUM                          80U
+/* Total size of the audio transfer buffer */
+#define AUDIO_TOTAL_BUF_SIZE                          ((uint16_t)(AUDIO_OUT_PACKET * AUDIO_OUT_PACKET_NUM))
+
+/* Audio Commands enumeration */
+typedef enum
+{
+  AUDIO_CMD_START = 1,
+  AUDIO_CMD_PLAY,
+  AUDIO_CMD_STOP,
+} AUDIO_CMD_TypeDef;
+
+
+typedef enum
+{
+  AUDIO_OFFSET_NONE = 0,
+  AUDIO_OFFSET_HALF,
+  AUDIO_OFFSET_FULL,
+  AUDIO_OFFSET_UNKNOWN,
+} AUDIO_OffsetTypeDef;
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_CORE_Exported_TypesDefinitions
+  * @{
+  */
+typedef struct
+{
+  uint8_t cmd;
+  uint8_t data[USB_MAX_EP0_SIZE];
+  uint8_t len;
+  uint8_t unit;
+} USBD_AUDIO_ControlTypeDef;
+
+
+typedef struct
+{
+  uint32_t alt_setting;
+  uint8_t buffer[AUDIO_TOTAL_BUF_SIZE];
+  AUDIO_OffsetTypeDef offset;
+  uint8_t rd_enable;
+  uint16_t rd_ptr;
+  uint16_t wr_ptr;
+  USBD_AUDIO_ControlTypeDef control;
+} USBD_AUDIO_HandleTypeDef;
+
+
+typedef struct
+{
+  int8_t (*Init)(uint32_t AudioFreq, uint32_t Volume, uint32_t options);
+  int8_t (*DeInit)(uint32_t options);
+  int8_t (*AudioCmd)(uint8_t *pbuf, uint32_t size, uint8_t cmd);
+  int8_t (*VolumeCtl)(uint8_t vol);
+  int8_t (*MuteCtl)(uint8_t cmd);
+  int8_t (*PeriodicTC)(uint8_t *pbuf, uint32_t size, uint8_t cmd);
+  int8_t (*GetState)(void);
+} USBD_AUDIO_ItfTypeDef;
+
+/*
+ * Audio Class specification release 1.0
+ */
+
+/* Table 4-2: Class-Specific AC Interface Header Descriptor */
+typedef struct
+{
+  uint8_t           bLength;
+  uint8_t           bDescriptorType;
+  uint8_t           bDescriptorSubtype;
+  uint16_t          bcdADC;
+  uint16_t          wTotalLength;
+  uint8_t           bInCollection;
+  uint8_t           baInterfaceNr;
+} __PACKED USBD_SpeakerIfDescTypeDef;
+
+/* Table 4-3: Input Terminal Descriptor */
+typedef struct
+{
+  uint8_t           bLength;
+  uint8_t           bDescriptorType;
+  uint8_t           bDescriptorSubtype;
+  uint8_t           bTerminalID;
+  uint16_t          wTerminalType;
+  uint8_t           bAssocTerminal;
+  uint8_t           bNrChannels;
+  uint16_t          wChannelConfig;
+  uint8_t           iChannelNames;
+  uint8_t           iTerminal;
+} __PACKED USBD_SpeakerInDescTypeDef;
+
+/* USB Speaker Audio Feature Unit Descriptor */
+typedef struct
+{
+  uint8_t           bLength;
+  uint8_t           bDescriptorType;
+  uint8_t           bDescriptorSubtype;
+  uint8_t           bUnitID;
+  uint8_t           bSourceID;
+  uint8_t           bControlSize;
+  uint16_t          bmaControls;
+  uint8_t           iTerminal;
+} __PACKED USBD_SpeakerFeatureDescTypeDef;
+
+/* Table 4-4: Output Terminal Descriptor */
+typedef struct
+{
+  uint8_t           bLength;
+  uint8_t           bDescriptorType;
+  uint8_t           bDescriptorSubtype;
+  uint8_t           bTerminalID;
+  uint16_t          wTerminalType;
+  uint8_t           bAssocTerminal;
+  uint8_t           bSourceID;
+  uint8_t           iTerminal;
+} __PACKED USBD_SpeakerOutDescTypeDef;
+
+/* Table 4-19: Class-Specific AS Interface Descriptor */
+typedef struct
+{
+  uint8_t           bLength;
+  uint8_t           bDescriptorType;
+  uint8_t           bDescriptorSubtype;
+  uint8_t           bTerminalLink;
+  uint8_t           bDelay;
+  uint16_t          wFormatTag;
+} __PACKED USBD_SpeakerStreamIfDescTypeDef;
+
+/* USB Speaker Audio Type III Format Interface Descriptor */
+typedef struct
+{
+  uint8_t           bLength;
+  uint8_t           bDescriptorType;
+  uint8_t           bDescriptorSubtype;
+  uint8_t           bFormatType;
+  uint8_t           bNrChannels;
+  uint8_t           bSubFrameSize;
+  uint8_t           bBitResolution;
+  uint8_t           bSamFreqType;
+  uint8_t           tSamFreq2;
+  uint8_t           tSamFreq1;
+  uint8_t           tSamFreq0;
+} USBD_SpeakerIIIFormatIfDescTypeDef;
+
+/* Table 4-17: Standard AC Interrupt Endpoint Descriptor */
+typedef struct
+{
+  uint8_t           bLength;
+  uint8_t           bDescriptorType;
+  uint8_t           bEndpointAddress;
+  uint8_t           bmAttributes;
+  uint16_t          wMaxPacketSize;
+  uint8_t           bInterval;
+  uint8_t           bRefresh;
+  uint8_t           bSynchAddress;
+} __PACKED USBD_SpeakerEndDescTypeDef;
+
+/* Table 4-21: Class-Specific AS Isochronous Audio Data Endpoint Descriptor        */
+typedef struct
+{
+  uint8_t           bLength;
+  uint8_t           bDescriptorType;
+  uint8_t           bDescriptor;
+  uint8_t           bmAttributes;
+  uint8_t           bLockDelayUnits;
+  uint16_t          wLockDelay;
+} __PACKED USBD_SpeakerEndStDescTypeDef;
+
+/**
+  * @}
+  */
+
+
+
+/** @defgroup USBD_CORE_Exported_Macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_CORE_Exported_Variables
+  * @{
+  */
+
+extern USBD_ClassTypeDef USBD_AUDIO;
+#define USBD_AUDIO_CLASS &USBD_AUDIO
+/**
+  * @}
+  */
+
+/** @defgroup USB_CORE_Exported_Functions
+  * @{
+  */
+uint8_t USBD_AUDIO_RegisterInterface(USBD_HandleTypeDef *pdev,
+                                     USBD_AUDIO_ItfTypeDef *fops);
+
+void USBD_AUDIO_Sync(USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset);
+
+#ifdef USE_USBD_COMPOSITE
+uint32_t USBD_AUDIO_GetEpPcktSze(USBD_HandleTypeDef *pdev, uint8_t If, uint8_t Ep);
+#endif /* USE_USBD_COMPOSITE */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __USB_AUDIO_H */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 980 - 0
Middlewares/ST/STM32_USB_Device_Library/Class/AUDIO/Src/usbd_audio.c

@@ -0,0 +1,980 @@
+/**
+  ******************************************************************************
+  * @file    usbd_audio.c
+  * @author  MCD Application Team
+  * @brief   This file provides the Audio core functions.
+  *
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2015 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  * @verbatim
+  *
+  *          ===================================================================
+  *                                AUDIO Class  Description
+  *          ===================================================================
+  *           This driver manages the Audio Class 1.0 following the "USB Device Class Definition for
+  *           Audio Devices V1.0 Mar 18, 98".
+  *           This driver implements the following aspects of the specification:
+  *             - Device descriptor management
+  *             - Configuration descriptor management
+  *             - Standard AC Interface Descriptor management
+  *             - 1 Audio Streaming Interface (with single channel, PCM, Stereo mode)
+  *             - 1 Audio Streaming Endpoint
+  *             - 1 Audio Terminal Input (1 channel)
+  *             - Audio Class-Specific AC Interfaces
+  *             - Audio Class-Specific AS Interfaces
+  *             - AudioControl Requests: only SET_CUR and GET_CUR requests are supported (for Mute)
+  *             - Audio Feature Unit (limited to Mute control)
+  *             - Audio Synchronization type: Asynchronous
+  *             - Single fixed audio sampling rate (configurable in usbd_conf.h file)
+  *          The current audio class version supports the following audio features:
+  *             - Pulse Coded Modulation (PCM) format
+  *             - sampling rate: 48KHz.
+  *             - Bit resolution: 16
+  *             - Number of channels: 2
+  *             - No volume control
+  *             - Mute/Unmute capability
+  *             - Asynchronous Endpoints
+  *
+  * @note     In HS mode and when the DMA is used, all variables and data structures
+  *           dealing with the DMA during the transaction process should be 32-bit aligned.
+  *
+  *
+  *  @endverbatim
+  ******************************************************************************
+  */
+
+/* BSPDependencies
+- "stm32xxxxx_{eval}{discovery}.c"
+- "stm32xxxxx_{eval}{discovery}_io.c"
+- "stm32xxxxx_{eval}{discovery}_audio.c"
+EndBSPDependencies */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_audio.h"
+#include "usbd_ctlreq.h"
+
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+  * @{
+  */
+
+
+/** @defgroup USBD_AUDIO
+  * @brief usbd core module
+  * @{
+  */
+
+/** @defgroup USBD_AUDIO_Private_TypesDefinitions
+  * @{
+  */
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_AUDIO_Private_Defines
+  * @{
+  */
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_AUDIO_Private_Macros
+  * @{
+  */
+#define AUDIO_SAMPLE_FREQ(frq) \
+  (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))
+
+#define AUDIO_PACKET_SZE(frq) \
+  (uint8_t)(((frq * 2U * 2U) / 1000U) & 0xFFU), (uint8_t)((((frq * 2U * 2U) / 1000U) >> 8) & 0xFFU)
+
+#ifdef USE_USBD_COMPOSITE
+#define AUDIO_PACKET_SZE_WORD(frq)     (uint32_t)((((frq) * 2U * 2U)/1000U))
+#endif /* USE_USBD_COMPOSITE  */
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_AUDIO_Private_FunctionPrototypes
+  * @{
+  */
+static uint8_t USBD_AUDIO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+static uint8_t USBD_AUDIO_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+
+static uint8_t USBD_AUDIO_Setup(USBD_HandleTypeDef *pdev,
+                                USBD_SetupReqTypedef *req);
+#ifndef USE_USBD_COMPOSITE
+static uint8_t *USBD_AUDIO_GetCfgDesc(uint16_t *length);
+static uint8_t *USBD_AUDIO_GetDeviceQualifierDesc(uint16_t *length);
+#endif /* USE_USBD_COMPOSITE  */
+static uint8_t USBD_AUDIO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
+static uint8_t USBD_AUDIO_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
+static uint8_t USBD_AUDIO_EP0_RxReady(USBD_HandleTypeDef *pdev);
+static uint8_t USBD_AUDIO_EP0_TxReady(USBD_HandleTypeDef *pdev);
+static uint8_t USBD_AUDIO_SOF(USBD_HandleTypeDef *pdev);
+
+static uint8_t USBD_AUDIO_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
+static uint8_t USBD_AUDIO_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
+static void AUDIO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void AUDIO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void *USBD_AUDIO_GetAudioHeaderDesc(uint8_t *pConfDesc);
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_Private_Variables
+  * @{
+  */
+
+USBD_ClassTypeDef USBD_AUDIO =
+{
+  USBD_AUDIO_Init,
+  USBD_AUDIO_DeInit,
+  USBD_AUDIO_Setup,
+  USBD_AUDIO_EP0_TxReady,
+  USBD_AUDIO_EP0_RxReady,
+  USBD_AUDIO_DataIn,
+  USBD_AUDIO_DataOut,
+  USBD_AUDIO_SOF,
+  USBD_AUDIO_IsoINIncomplete,
+  USBD_AUDIO_IsoOutIncomplete,
+#ifdef USE_USBD_COMPOSITE
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+#else
+  USBD_AUDIO_GetCfgDesc,
+  USBD_AUDIO_GetCfgDesc,
+  USBD_AUDIO_GetCfgDesc,
+  USBD_AUDIO_GetDeviceQualifierDesc,
+#endif /* USE_USBD_COMPOSITE  */
+};
+
+#ifndef USE_USBD_COMPOSITE
+/* USB AUDIO device Configuration Descriptor */
+__ALIGN_BEGIN static uint8_t USBD_AUDIO_CfgDesc[USB_AUDIO_CONFIG_DESC_SIZ] __ALIGN_END =
+{
+  /* Configuration 1 */
+  0x09,                                 /* bLength */
+  USB_DESC_TYPE_CONFIGURATION,          /* bDescriptorType */
+  LOBYTE(USB_AUDIO_CONFIG_DESC_SIZ),    /* wTotalLength */
+  HIBYTE(USB_AUDIO_CONFIG_DESC_SIZ),
+  0x02,                                 /* bNumInterfaces */
+  0x01,                                 /* bConfigurationValue */
+  0x00,                                 /* iConfiguration */
+#if (USBD_SELF_POWERED == 1U)
+  0xC0,                                 /* bmAttributes: Bus Powered according to user configuration */
+#else
+  0x80,                                 /* bmAttributes: Bus Powered according to user configuration */
+#endif /* USBD_SELF_POWERED */
+  USBD_MAX_POWER,                       /* MaxPower (mA) */
+  /* 09 byte*/
+
+  /* USB Speaker Standard interface descriptor */
+  AUDIO_INTERFACE_DESC_SIZE,            /* bLength */
+  USB_DESC_TYPE_INTERFACE,              /* bDescriptorType */
+  0x00,                                 /* bInterfaceNumber */
+  0x00,                                 /* bAlternateSetting */
+  0x00,                                 /* bNumEndpoints */
+  USB_DEVICE_CLASS_AUDIO,               /* bInterfaceClass */
+  AUDIO_SUBCLASS_AUDIOCONTROL,          /* bInterfaceSubClass */
+  AUDIO_PROTOCOL_UNDEFINED,             /* bInterfaceProtocol */
+  0x00,                                 /* iInterface */
+  /* 09 byte*/
+
+  /* USB Speaker Class-specific AC Interface Descriptor */
+  AUDIO_INTERFACE_DESC_SIZE,            /* bLength */
+  AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */
+  AUDIO_CONTROL_HEADER,                 /* bDescriptorSubtype */
+  0x00,          /* 1.00 */             /* bcdADC */
+  0x01,
+  0x27,                                 /* wTotalLength */
+  0x00,
+  0x01,                                 /* bInCollection */
+  0x01,                                 /* baInterfaceNr */
+  /* 09 byte*/
+
+  /* USB Speaker Input Terminal Descriptor */
+  AUDIO_INPUT_TERMINAL_DESC_SIZE,       /* bLength */
+  AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */
+  AUDIO_CONTROL_INPUT_TERMINAL,         /* bDescriptorSubtype */
+  0x01,                                 /* bTerminalID */
+  0x01,                                 /* wTerminalType AUDIO_TERMINAL_USB_STREAMING   0x0101 */
+  0x01,
+  0x00,                                 /* bAssocTerminal */
+  0x01,                                 /* bNrChannels */
+  0x00,                                 /* wChannelConfig 0x0000  Mono */
+  0x00,
+  0x00,                                 /* iChannelNames */
+  0x00,                                 /* iTerminal */
+  /* 12 byte*/
+
+  /* USB Speaker Audio Feature Unit Descriptor */
+  0x09,                                 /* bLength */
+  AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */
+  AUDIO_CONTROL_FEATURE_UNIT,           /* bDescriptorSubtype */
+  AUDIO_OUT_STREAMING_CTRL,             /* bUnitID */
+  0x01,                                 /* bSourceID */
+  0x01,                                 /* bControlSize */
+  AUDIO_CONTROL_MUTE,                   /* bmaControls(0) */
+  0,                                    /* bmaControls(1) */
+  0x00,                                 /* iTerminal */
+  /* 09 byte */
+
+  /* USB Speaker Output Terminal Descriptor */
+  0x09,      /* bLength */
+  AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */
+  AUDIO_CONTROL_OUTPUT_TERMINAL,        /* bDescriptorSubtype */
+  0x03,                                 /* bTerminalID */
+  0x01,                                 /* wTerminalType  0x0301 */
+  0x03,
+  0x00,                                 /* bAssocTerminal */
+  0x02,                                 /* bSourceID */
+  0x00,                                 /* iTerminal */
+  /* 09 byte */
+
+  /* USB Speaker Standard AS Interface Descriptor - Audio Streaming Zero Bandwidth */
+  /* Interface 1, Alternate Setting 0                                              */
+  AUDIO_INTERFACE_DESC_SIZE,            /* bLength */
+  USB_DESC_TYPE_INTERFACE,              /* bDescriptorType */
+  0x01,                                 /* bInterfaceNumber */
+  0x00,                                 /* bAlternateSetting */
+  0x00,                                 /* bNumEndpoints */
+  USB_DEVICE_CLASS_AUDIO,               /* bInterfaceClass */
+  AUDIO_SUBCLASS_AUDIOSTREAMING,        /* bInterfaceSubClass */
+  AUDIO_PROTOCOL_UNDEFINED,             /* bInterfaceProtocol */
+  0x00,                                 /* iInterface */
+  /* 09 byte*/
+
+  /* USB Speaker Standard AS Interface Descriptor - Audio Streaming Operational */
+  /* Interface 1, Alternate Setting 1                                           */
+  AUDIO_INTERFACE_DESC_SIZE,            /* bLength */
+  USB_DESC_TYPE_INTERFACE,              /* bDescriptorType */
+  0x01,                                 /* bInterfaceNumber */
+  0x01,                                 /* bAlternateSetting */
+  0x01,                                 /* bNumEndpoints */
+  USB_DEVICE_CLASS_AUDIO,               /* bInterfaceClass */
+  AUDIO_SUBCLASS_AUDIOSTREAMING,        /* bInterfaceSubClass */
+  AUDIO_PROTOCOL_UNDEFINED,             /* bInterfaceProtocol */
+  0x00,                                 /* iInterface */
+  /* 09 byte*/
+
+  /* USB Speaker Audio Streaming Interface Descriptor */
+  AUDIO_STREAMING_INTERFACE_DESC_SIZE,  /* bLength */
+  AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */
+  AUDIO_STREAMING_GENERAL,              /* bDescriptorSubtype */
+  0x01,                                 /* bTerminalLink */
+  0x01,                                 /* bDelay */
+  0x01,                                 /* wFormatTag AUDIO_FORMAT_PCM  0x0001 */
+  0x00,
+  /* 07 byte*/
+
+  /* USB Speaker Audio Type III Format Interface Descriptor */
+  0x0B,                                 /* bLength */
+  AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */
+  AUDIO_STREAMING_FORMAT_TYPE,          /* bDescriptorSubtype */
+  AUDIO_FORMAT_TYPE_I,                  /* bFormatType */
+  0x02,                                 /* bNrChannels */
+  0x02,                                 /* bSubFrameSize :  2 Bytes per frame (16bits) */
+  16,                                   /* bBitResolution (16-bits per sample) */
+  0x01,                                 /* bSamFreqType only one frequency supported */
+  AUDIO_SAMPLE_FREQ(USBD_AUDIO_FREQ),   /* Audio sampling frequency coded on 3 bytes */
+  /* 11 byte*/
+
+  /* Endpoint 1 - Standard Descriptor */
+  AUDIO_STANDARD_ENDPOINT_DESC_SIZE,    /* bLength */
+  USB_DESC_TYPE_ENDPOINT,               /* bDescriptorType */
+  AUDIO_OUT_EP,                         /* bEndpointAddress 1 out endpoint */
+  USBD_EP_TYPE_ISOC,                    /* bmAttributes */
+  AUDIO_PACKET_SZE(USBD_AUDIO_FREQ),    /* wMaxPacketSize in Bytes (Freq(Samples)*2(Stereo)*2(HalfWord)) */
+  AUDIO_FS_BINTERVAL,                   /* bInterval */
+  0x00,                                 /* bRefresh */
+  0x00,                                 /* bSynchAddress */
+  /* 09 byte*/
+
+  /* Endpoint - Audio Streaming Descriptor */
+  AUDIO_STREAMING_ENDPOINT_DESC_SIZE,   /* bLength */
+  AUDIO_ENDPOINT_DESCRIPTOR_TYPE,       /* bDescriptorType */
+  AUDIO_ENDPOINT_GENERAL,               /* bDescriptor */
+  0x00,                                 /* bmAttributes */
+  0x00,                                 /* bLockDelayUnits */
+  0x00,                                 /* wLockDelay */
+  0x00,
+  /* 07 byte*/
+} ;
+
+/* USB Standard Device Descriptor */
+__ALIGN_BEGIN static uint8_t USBD_AUDIO_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
+{
+  USB_LEN_DEV_QUALIFIER_DESC,
+  USB_DESC_TYPE_DEVICE_QUALIFIER,
+  0x00,
+  0x02,
+  0x00,
+  0x00,
+  0x00,
+  0x40,
+  0x01,
+  0x00,
+};
+#endif /* USE_USBD_COMPOSITE  */
+
+static uint8_t AUDIOOutEpAdd = AUDIO_OUT_EP;
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_Private_Functions
+  * @{
+  */
+
+/**
+  * @brief  USBD_AUDIO_Init
+  *         Initialize the AUDIO interface
+  * @param  pdev: device instance
+  * @param  cfgidx: Configuration index
+  * @retval status
+  */
+static uint8_t USBD_AUDIO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+  UNUSED(cfgidx);
+  USBD_AUDIO_HandleTypeDef *haudio;
+
+  /* Allocate Audio structure */
+  haudio = (USBD_AUDIO_HandleTypeDef *)USBD_malloc(sizeof(USBD_AUDIO_HandleTypeDef));
+
+  if (haudio == NULL)
+  {
+    pdev->pClassDataCmsit[pdev->classId] = NULL;
+    return (uint8_t)USBD_EMEM;
+  }
+
+  pdev->pClassDataCmsit[pdev->classId] = (void *)haudio;
+  pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
+
+#ifdef USE_USBD_COMPOSITE
+  /* Get the Endpoints addresses allocated for this class instance */
+  AUDIOOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_ISOC, (uint8_t)pdev->classId);
+#endif /* USE_USBD_COMPOSITE */
+
+  if (pdev->dev_speed == USBD_SPEED_HIGH)
+  {
+    pdev->ep_out[AUDIOOutEpAdd & 0xFU].bInterval = AUDIO_HS_BINTERVAL;
+  }
+  else   /* LOW and FULL-speed endpoints */
+  {
+    pdev->ep_out[AUDIOOutEpAdd & 0xFU].bInterval = AUDIO_FS_BINTERVAL;
+  }
+
+  /* Open EP OUT */
+  (void)USBD_LL_OpenEP(pdev, AUDIOOutEpAdd, USBD_EP_TYPE_ISOC, AUDIO_OUT_PACKET);
+  pdev->ep_out[AUDIOOutEpAdd & 0xFU].is_used = 1U;
+
+  haudio->alt_setting = 0U;
+  haudio->offset = AUDIO_OFFSET_UNKNOWN;
+  haudio->wr_ptr = 0U;
+  haudio->rd_ptr = 0U;
+  haudio->rd_enable = 0U;
+
+  /* Initialize the Audio output Hardware layer */
+  if (((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->Init(USBD_AUDIO_FREQ,
+                                                                      AUDIO_DEFAULT_VOLUME,
+                                                                      0U) != 0U)
+  {
+    return (uint8_t)USBD_FAIL;
+  }
+
+  /* Prepare Out endpoint to receive 1st packet */
+  (void)USBD_LL_PrepareReceive(pdev, AUDIOOutEpAdd, haudio->buffer,
+                               AUDIO_OUT_PACKET);
+
+  return (uint8_t)USBD_OK;
+}
+
+/**
+  * @brief  USBD_AUDIO_Init
+  *         DeInitialize the AUDIO layer
+  * @param  pdev: device instance
+  * @param  cfgidx: Configuration index
+  * @retval status
+  */
+static uint8_t USBD_AUDIO_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+  UNUSED(cfgidx);
+
+#ifdef USE_USBD_COMPOSITE
+  /* Get the Endpoints addresses allocated for this class instance */
+  AUDIOOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_ISOC, (uint8_t)pdev->classId);
+#endif /* USE_USBD_COMPOSITE */
+
+  /* Open EP OUT */
+  (void)USBD_LL_CloseEP(pdev, AUDIOOutEpAdd);
+  pdev->ep_out[AUDIOOutEpAdd & 0xFU].is_used = 0U;
+  pdev->ep_out[AUDIOOutEpAdd & 0xFU].bInterval = 0U;
+
+  /* DeInit  physical Interface components */
+  if (pdev->pClassDataCmsit[pdev->classId] != NULL)
+  {
+    ((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->DeInit(0U);
+    (void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
+    pdev->pClassDataCmsit[pdev->classId] = NULL;
+    pdev->pClassData = NULL;
+  }
+
+  return (uint8_t)USBD_OK;
+}
+
+/**
+  * @brief  USBD_AUDIO_Setup
+  *         Handle the AUDIO specific requests
+  * @param  pdev: instance
+  * @param  req: usb requests
+  * @retval status
+  */
+static uint8_t USBD_AUDIO_Setup(USBD_HandleTypeDef *pdev,
+                                USBD_SetupReqTypedef *req)
+{
+  USBD_AUDIO_HandleTypeDef *haudio;
+  uint16_t len;
+  uint8_t *pbuf;
+  uint16_t status_info = 0U;
+  USBD_StatusTypeDef ret = USBD_OK;
+
+  haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
+
+  if (haudio == NULL)
+  {
+    return (uint8_t)USBD_FAIL;
+  }
+
+  switch (req->bmRequest & USB_REQ_TYPE_MASK)
+  {
+    case USB_REQ_TYPE_CLASS:
+      switch (req->bRequest)
+      {
+        case AUDIO_REQ_GET_CUR:
+          AUDIO_REQ_GetCurrent(pdev, req);
+          break;
+
+        case AUDIO_REQ_SET_CUR:
+          AUDIO_REQ_SetCurrent(pdev, req);
+          break;
+
+        default:
+          USBD_CtlError(pdev, req);
+          ret = USBD_FAIL;
+          break;
+      }
+      break;
+
+    case USB_REQ_TYPE_STANDARD:
+      switch (req->bRequest)
+      {
+        case USB_REQ_GET_STATUS:
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
+          {
+            (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+            ret = USBD_FAIL;
+          }
+          break;
+
+        case USB_REQ_GET_DESCRIPTOR:
+          if ((req->wValue >> 8) == AUDIO_DESCRIPTOR_TYPE)
+          {
+            pbuf = (uint8_t *)USBD_AUDIO_GetAudioHeaderDesc(pdev->pConfDesc);
+            if (pbuf != NULL)
+            {
+              len = MIN(USB_AUDIO_DESC_SIZ, req->wLength);
+              (void)USBD_CtlSendData(pdev, pbuf, len);
+            }
+            else
+            {
+              USBD_CtlError(pdev, req);
+              ret = USBD_FAIL;
+            }
+          }
+          break;
+
+        case USB_REQ_GET_INTERFACE:
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
+          {
+            (void)USBD_CtlSendData(pdev, (uint8_t *)&haudio->alt_setting, 1U);
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+            ret = USBD_FAIL;
+          }
+          break;
+
+        case USB_REQ_SET_INTERFACE:
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
+          {
+            if ((uint8_t)(req->wValue) <= USBD_MAX_NUM_INTERFACES)
+            {
+              haudio->alt_setting = (uint8_t)(req->wValue);
+            }
+            else
+            {
+              /* Call the error management function (command will be NAKed */
+              USBD_CtlError(pdev, req);
+              ret = USBD_FAIL;
+            }
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+            ret = USBD_FAIL;
+          }
+          break;
+
+        case USB_REQ_CLEAR_FEATURE:
+          break;
+
+        default:
+          USBD_CtlError(pdev, req);
+          ret = USBD_FAIL;
+          break;
+      }
+      break;
+    default:
+      USBD_CtlError(pdev, req);
+      ret = USBD_FAIL;
+      break;
+  }
+
+  return (uint8_t)ret;
+}
+
+#ifndef USE_USBD_COMPOSITE
+/**
+  * @brief  USBD_AUDIO_GetCfgDesc
+  *         return configuration descriptor
+  * @param  length : pointer data length
+  * @retval pointer to descriptor buffer
+  */
+static uint8_t *USBD_AUDIO_GetCfgDesc(uint16_t *length)
+{
+  *length = (uint16_t)sizeof(USBD_AUDIO_CfgDesc);
+
+  return USBD_AUDIO_CfgDesc;
+}
+#endif /* USE_USBD_COMPOSITE  */
+/**
+  * @brief  USBD_AUDIO_DataIn
+  *         handle data IN Stage
+  * @param  pdev: device instance
+  * @param  epnum: endpoint index
+  * @retval status
+  */
+static uint8_t USBD_AUDIO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+  UNUSED(pdev);
+  UNUSED(epnum);
+
+  /* Only OUT data are processed */
+  return (uint8_t)USBD_OK;
+}
+
+/**
+  * @brief  USBD_AUDIO_EP0_RxReady
+  *         handle EP0 Rx Ready event
+  * @param  pdev: device instance
+  * @retval status
+  */
+static uint8_t USBD_AUDIO_EP0_RxReady(USBD_HandleTypeDef *pdev)
+{
+  USBD_AUDIO_HandleTypeDef *haudio;
+  haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
+
+  if (haudio == NULL)
+  {
+    return (uint8_t)USBD_FAIL;
+  }
+
+  if (haudio->control.cmd == AUDIO_REQ_SET_CUR)
+  {
+    /* In this driver, to simplify code, only SET_CUR request is managed */
+
+    if (haudio->control.unit == AUDIO_OUT_STREAMING_CTRL)
+    {
+      ((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->MuteCtl(haudio->control.data[0]);
+      haudio->control.cmd = 0U;
+      haudio->control.len = 0U;
+    }
+  }
+
+  return (uint8_t)USBD_OK;
+}
+/**
+  * @brief  USBD_AUDIO_EP0_TxReady
+  *         handle EP0 TRx Ready event
+  * @param  pdev: device instance
+  * @retval status
+  */
+static uint8_t USBD_AUDIO_EP0_TxReady(USBD_HandleTypeDef *pdev)
+{
+  UNUSED(pdev);
+
+  /* Only OUT control data are processed */
+  return (uint8_t)USBD_OK;
+}
+/**
+  * @brief  USBD_AUDIO_SOF
+  *         handle SOF event
+  * @param  pdev: device instance
+  * @retval status
+  */
+static uint8_t USBD_AUDIO_SOF(USBD_HandleTypeDef *pdev)
+{
+  UNUSED(pdev);
+
+  return (uint8_t)USBD_OK;
+}
+
+/**
+  * @brief  USBD_AUDIO_SOF
+  *         handle SOF event
+  * @param  pdev: device instance
+  * @param  offset: audio offset
+  * @retval status
+  */
+void USBD_AUDIO_Sync(USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset)
+{
+  USBD_AUDIO_HandleTypeDef *haudio;
+  uint32_t BufferSize = AUDIO_TOTAL_BUF_SIZE / 2U;
+
+  if (pdev->pClassDataCmsit[pdev->classId] == NULL)
+  {
+    return;
+  }
+
+  haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
+
+  haudio->offset = offset;
+
+  if (haudio->rd_enable == 1U)
+  {
+    haudio->rd_ptr += (uint16_t)BufferSize;
+
+    if (haudio->rd_ptr == AUDIO_TOTAL_BUF_SIZE)
+    {
+      /* roll back */
+      haudio->rd_ptr = 0U;
+    }
+  }
+
+  if (haudio->rd_ptr > haudio->wr_ptr)
+  {
+    if ((haudio->rd_ptr - haudio->wr_ptr) < AUDIO_OUT_PACKET)
+    {
+      BufferSize += 4U;
+    }
+    else
+    {
+      if ((haudio->rd_ptr - haudio->wr_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET))
+      {
+        BufferSize -= 4U;
+      }
+    }
+  }
+  else
+  {
+    if ((haudio->wr_ptr - haudio->rd_ptr) < AUDIO_OUT_PACKET)
+    {
+      BufferSize -= 4U;
+    }
+    else
+    {
+      if ((haudio->wr_ptr - haudio->rd_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET))
+      {
+        BufferSize += 4U;
+      }
+    }
+  }
+
+  if (haudio->offset == AUDIO_OFFSET_FULL)
+  {
+    ((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->AudioCmd(&haudio->buffer[0],
+                                                                        BufferSize, AUDIO_CMD_PLAY);
+    haudio->offset = AUDIO_OFFSET_NONE;
+  }
+}
+
+/**
+  * @brief  USBD_AUDIO_IsoINIncomplete
+  *         handle data ISO IN Incomplete event
+  * @param  pdev: device instance
+  * @param  epnum: endpoint index
+  * @retval status
+  */
+static uint8_t USBD_AUDIO_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+  UNUSED(pdev);
+  UNUSED(epnum);
+
+  return (uint8_t)USBD_OK;
+}
+/**
+  * @brief  USBD_AUDIO_IsoOutIncomplete
+  *         handle data ISO OUT Incomplete event
+  * @param  pdev: device instance
+  * @param  epnum: endpoint index
+  * @retval status
+  */
+static uint8_t USBD_AUDIO_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+  USBD_AUDIO_HandleTypeDef *haudio;
+
+  if (pdev->pClassDataCmsit[pdev->classId] == NULL)
+  {
+    return (uint8_t)USBD_FAIL;
+  }
+
+  haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
+
+  /* Prepare Out endpoint to receive next audio packet */
+  (void)USBD_LL_PrepareReceive(pdev, epnum,
+                               &haudio->buffer[haudio->wr_ptr],
+                               AUDIO_OUT_PACKET);
+
+  return (uint8_t)USBD_OK;
+}
+/**
+  * @brief  USBD_AUDIO_DataOut
+  *         handle data OUT Stage
+  * @param  pdev: device instance
+  * @param  epnum: endpoint index
+  * @retval status
+  */
+static uint8_t USBD_AUDIO_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+  uint16_t PacketSize;
+  USBD_AUDIO_HandleTypeDef *haudio;
+
+#ifdef USE_USBD_COMPOSITE
+  /* Get the Endpoints addresses allocated for this class instance */
+  AUDIOOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_ISOC, (uint8_t)pdev->classId);
+#endif /* USE_USBD_COMPOSITE */
+
+  haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
+
+  if (haudio == NULL)
+  {
+    return (uint8_t)USBD_FAIL;
+  }
+
+  if (epnum == AUDIOOutEpAdd)
+  {
+    /* Get received data packet length */
+    PacketSize = (uint16_t)USBD_LL_GetRxDataSize(pdev, epnum);
+
+    /* Packet received Callback */
+    ((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->PeriodicTC(&haudio->buffer[haudio->wr_ptr],
+                                                                          PacketSize, AUDIO_OUT_TC);
+
+    /* Increment the Buffer pointer or roll it back when all buffers are full */
+    haudio->wr_ptr += PacketSize;
+
+    if (haudio->wr_ptr >= AUDIO_TOTAL_BUF_SIZE)
+    {
+      /* All buffers are full: roll back */
+      haudio->wr_ptr = 0U;
+
+      if (haudio->offset == AUDIO_OFFSET_UNKNOWN)
+      {
+        ((USBD_AUDIO_ItfTypeDef *)pdev->pUserData[pdev->classId])->AudioCmd(&haudio->buffer[0],
+                                                                            AUDIO_TOTAL_BUF_SIZE / 2U,
+                                                                            AUDIO_CMD_START);
+        haudio->offset = AUDIO_OFFSET_NONE;
+      }
+    }
+
+    if (haudio->rd_enable == 0U)
+    {
+      if (haudio->wr_ptr == (AUDIO_TOTAL_BUF_SIZE / 2U))
+      {
+        haudio->rd_enable = 1U;
+      }
+    }
+
+    /* Prepare Out endpoint to receive next audio packet */
+    (void)USBD_LL_PrepareReceive(pdev, AUDIOOutEpAdd,
+                                 &haudio->buffer[haudio->wr_ptr],
+                                 AUDIO_OUT_PACKET);
+  }
+
+  return (uint8_t)USBD_OK;
+}
+
+/**
+  * @brief  AUDIO_Req_GetCurrent
+  *         Handles the GET_CUR Audio control request.
+  * @param  pdev: device instance
+  * @param  req: setup class request
+  * @retval status
+  */
+static void AUDIO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  USBD_AUDIO_HandleTypeDef *haudio;
+  haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
+
+  if (haudio == NULL)
+  {
+    return;
+  }
+
+  (void)USBD_memset(haudio->control.data, 0, USB_MAX_EP0_SIZE);
+
+  /* Send the current mute state */
+  (void)USBD_CtlSendData(pdev, haudio->control.data,
+                         MIN(req->wLength, USB_MAX_EP0_SIZE));
+}
+
+/**
+  * @brief  AUDIO_Req_SetCurrent
+  *         Handles the SET_CUR Audio control request.
+  * @param  pdev: device instance
+  * @param  req: setup class request
+  * @retval status
+  */
+static void AUDIO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  USBD_AUDIO_HandleTypeDef *haudio;
+  haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
+
+  if (haudio == NULL)
+  {
+    return;
+  }
+
+  if (req->wLength != 0U)
+  {
+    haudio->control.cmd = AUDIO_REQ_SET_CUR;     /* Set the request value */
+    haudio->control.len = (uint8_t)MIN(req->wLength, USB_MAX_EP0_SIZE);  /* Set the request data length */
+    haudio->control.unit = HIBYTE(req->wIndex);  /* Set the request target unit */
+
+    /* Prepare the reception of the buffer over EP0 */
+    (void)USBD_CtlPrepareRx(pdev, haudio->control.data, haudio->control.len);
+  }
+}
+
+#ifndef USE_USBD_COMPOSITE
+/**
+  * @brief  DeviceQualifierDescriptor
+  *         return Device Qualifier descriptor
+  * @param  length : pointer data length
+  * @retval pointer to descriptor buffer
+  */
+static uint8_t *USBD_AUDIO_GetDeviceQualifierDesc(uint16_t *length)
+{
+  *length = (uint16_t)sizeof(USBD_AUDIO_DeviceQualifierDesc);
+
+  return USBD_AUDIO_DeviceQualifierDesc;
+}
+#endif /* USE_USBD_COMPOSITE  */
+/**
+  * @brief  USBD_AUDIO_RegisterInterface
+  * @param  pdev: device instance
+  * @param  fops: Audio interface callback
+  * @retval status
+  */
+uint8_t USBD_AUDIO_RegisterInterface(USBD_HandleTypeDef *pdev,
+                                     USBD_AUDIO_ItfTypeDef *fops)
+{
+  if (fops == NULL)
+  {
+    return (uint8_t)USBD_FAIL;
+  }
+
+  pdev->pUserData[pdev->classId] = fops;
+
+  return (uint8_t)USBD_OK;
+}
+
+#ifdef USE_USBD_COMPOSITE
+/**
+  * @brief  USBD_AUDIO_GetEpPcktSze
+  * @param  pdev: device instance (reserved for future use)
+  * @param  If: Interface number (reserved for future use)
+  * @param  Ep: Endpoint number (reserved for future use)
+  * @retval status
+  */
+uint32_t USBD_AUDIO_GetEpPcktSze(USBD_HandleTypeDef *pdev, uint8_t If, uint8_t Ep)
+{
+  uint32_t mps;
+
+  UNUSED(pdev);
+  UNUSED(If);
+  UNUSED(Ep);
+
+  mps = AUDIO_PACKET_SZE_WORD(USBD_AUDIO_FREQ);
+
+  /* Return the wMaxPacketSize value in Bytes (Freq(Samples)*2(Stereo)*2(HalfWord)) */
+  return mps;
+}
+#endif /* USE_USBD_COMPOSITE */
+
+/**
+  * @brief  USBD_AUDIO_GetAudioHeaderDesc
+  *         This function return the Audio descriptor
+  * @param  pdev: device instance
+  * @param  pConfDesc:  pointer to Bos descriptor
+  * @retval pointer to the Audio AC Header descriptor
+  */
+static void *USBD_AUDIO_GetAudioHeaderDesc(uint8_t *pConfDesc)
+{
+  USBD_ConfigDescTypeDef *desc = (USBD_ConfigDescTypeDef *)(void *)pConfDesc;
+  USBD_DescHeaderTypeDef *pdesc = (USBD_DescHeaderTypeDef *)(void *)pConfDesc;
+  uint8_t *pAudioDesc =  NULL;
+  uint16_t ptr;
+
+  if (desc->wTotalLength > desc->bLength)
+  {
+    ptr = desc->bLength;
+
+    while (ptr < desc->wTotalLength)
+    {
+      pdesc = USBD_GetNextDesc((uint8_t *)pdesc, &ptr);
+      if ((pdesc->bDescriptorType == AUDIO_INTERFACE_DESCRIPTOR_TYPE) &&
+          (pdesc->bDescriptorSubType == AUDIO_CONTROL_HEADER))
+      {
+        pAudioDesc = (uint8_t *)pdesc;
+        break;
+      }
+    }
+  }
+  return pAudioDesc;
+}
+
+/**
+  * @}
+  */
+
+
+/**
+  * @}
+  */
+
+
+/**
+  * @}
+  */

+ 175 - 0
Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h

@@ -0,0 +1,175 @@
+/**
+  ******************************************************************************
+  * @file    usbd_core.h
+  * @author  MCD Application Team
+  * @brief   Header file for usbd_core.c file
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2015 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_CORE_H
+#define __USBD_CORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_conf.h"
+#include "usbd_def.h"
+#include "usbd_ioreq.h"
+#include "usbd_ctlreq.h"
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+  * @{
+  */
+
+/** @defgroup USBD_CORE
+  * @brief This file is the Header file for usbd_core.c file
+  * @{
+  */
+
+
+/** @defgroup USBD_CORE_Exported_Defines
+  * @{
+  */
+#ifndef USBD_DEBUG_LEVEL
+#define USBD_DEBUG_LEVEL           0U
+#endif /* USBD_DEBUG_LEVEL */
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_CORE_Exported_TypesDefinitions
+  * @{
+  */
+
+
+/**
+  * @}
+  */
+
+
+
+/** @defgroup USBD_CORE_Exported_Macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_CORE_Exported_Variables
+  * @{
+  */
+#define USBD_SOF          USBD_LL_SOF
+/**
+  * @}
+  */
+
+/** @defgroup USBD_CORE_Exported_FunctionsPrototype
+  * @{
+  */
+USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id);
+USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass);
+#if (USBD_USER_REGISTER_CALLBACK == 1U)
+USBD_StatusTypeDef USBD_RegisterDevStateCallback(USBD_HandleTypeDef *pdev, USBD_DevStateCallbackTypeDef pUserCallback);
+#endif /* USBD_USER_REGISTER_CALLBACK */
+
+#ifdef USE_USBD_COMPOSITE
+USBD_StatusTypeDef  USBD_RegisterClassComposite(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass,
+                                                USBD_CompositeClassTypeDef classtype, uint8_t *EpAddr);
+
+USBD_StatusTypeDef  USBD_UnRegisterClassComposite(USBD_HandleTypeDef *pdev);
+uint8_t USBD_CoreGetEPAdd(USBD_HandleTypeDef *pdev, uint8_t ep_dir, uint8_t ep_type, uint8_t ClassId);
+#endif /* USE_USBD_COMPOSITE */
+
+uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index);
+uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index);
+
+USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+
+USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup);
+USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *pdata);
+USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *pdata);
+
+USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed);
+USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev);
+
+USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef  *pdev);
+USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
+USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
+
+USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev);
+
+/* USBD Low Level Driver */
+USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev);
+
+USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
+                                  uint8_t ep_type, uint16_t ep_mps);
+
+USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr);
+
+USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
+                                    uint8_t *pbuf, uint32_t size);
+
+USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr,
+                                          uint8_t *pbuf, uint32_t size);
+
+#ifdef USBD_HS_TESTMODE_ENABLE
+USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode);
+#endif /* USBD_HS_TESTMODE_ENABLE */
+
+uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t  ep_addr);
+
+void  USBD_LL_Delay(uint32_t Delay);
+
+void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr);
+USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr);
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_CORE_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+

+ 101 - 0
Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h

@@ -0,0 +1,101 @@
+/**
+  ******************************************************************************
+  * @file    usbd_req.h
+  * @author  MCD Application Team
+  * @brief   Header file for the usbd_req.c file
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2015 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_REQUEST_H
+#define __USB_REQUEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include  "usbd_def.h"
+
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+  * @{
+  */
+
+/** @defgroup USBD_REQ
+  * @brief header file for the usbd_req.c file
+  * @{
+  */
+
+/** @defgroup USBD_REQ_Exported_Defines
+  * @{
+  */
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_REQ_Exported_Types
+  * @{
+  */
+/**
+  * @}
+  */
+
+
+
+/** @defgroup USBD_REQ_Exported_Macros
+  * @{
+  */
+/**
+  * @}
+  */
+
+/** @defgroup USBD_REQ_Exported_Variables
+  * @{
+  */
+/**
+  * @}
+  */
+
+/** @defgroup USBD_REQ_Exported_FunctionsPrototype
+  * @{
+  */
+
+USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+USBD_StatusTypeDef USBD_StdItfReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+
+void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata);
+void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len);
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USB_REQUEST_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+

+ 523 - 0
Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h

@@ -0,0 +1,523 @@
+/**
+  ******************************************************************************
+  * @file    usbd_def.h
+  * @author  MCD Application Team
+  * @brief   General defines for the usb device library
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2015 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_DEF_H
+#define __USBD_DEF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_conf.h"
+
+/** @addtogroup STM32_USBD_DEVICE_LIBRARY
+  * @{
+  */
+
+/** @defgroup USB_DEF
+  * @brief general defines for the usb device library file
+  * @{
+  */
+
+/** @defgroup USB_DEF_Exported_Defines
+  * @{
+  */
+
+#ifndef NULL
+#define NULL                                            0U
+#endif /* NULL */
+
+#ifndef USBD_MAX_NUM_INTERFACES
+#define USBD_MAX_NUM_INTERFACES                         1U
+#endif /* USBD_MAX_NUM_CONFIGURATION */
+
+#ifndef USBD_MAX_NUM_CONFIGURATION
+#define USBD_MAX_NUM_CONFIGURATION                      1U
+#endif /* USBD_MAX_NUM_CONFIGURATION */
+
+#ifdef USE_USBD_COMPOSITE
+#ifndef USBD_MAX_SUPPORTED_CLASS
+#define USBD_MAX_SUPPORTED_CLASS                       4U
+#endif /* USBD_MAX_SUPPORTED_CLASS */
+#else
+#ifndef USBD_MAX_SUPPORTED_CLASS
+#define USBD_MAX_SUPPORTED_CLASS                       1U
+#endif /* USBD_MAX_SUPPORTED_CLASS */
+#endif /* USE_USBD_COMPOSITE */
+
+#ifndef USBD_MAX_CLASS_ENDPOINTS
+#define USBD_MAX_CLASS_ENDPOINTS                       5U
+#endif /* USBD_MAX_CLASS_ENDPOINTS */
+
+#ifndef USBD_MAX_CLASS_INTERFACES
+#define USBD_MAX_CLASS_INTERFACES                      5U
+#endif /* USBD_MAX_CLASS_INTERFACES */
+
+#ifndef USBD_LPM_ENABLED
+#define USBD_LPM_ENABLED                                0U
+#endif /* USBD_LPM_ENABLED */
+
+#ifndef USBD_SELF_POWERED
+#define USBD_SELF_POWERED                               1U
+#endif /*USBD_SELF_POWERED */
+
+#ifndef USBD_MAX_POWER
+#define USBD_MAX_POWER                                  0x32U /* 100 mA */
+#endif /* USBD_MAX_POWER */
+
+#ifndef USBD_SUPPORT_USER_STRING_DESC
+#define USBD_SUPPORT_USER_STRING_DESC                   0U
+#endif /* USBD_SUPPORT_USER_STRING_DESC */
+
+#ifndef USBD_CLASS_USER_STRING_DESC
+#define USBD_CLASS_USER_STRING_DESC                     0U
+#endif /* USBD_CLASS_USER_STRING_DESC */
+
+#define  USB_LEN_DEV_QUALIFIER_DESC                     0x0AU
+#define  USB_LEN_DEV_DESC                               0x12U
+#define  USB_LEN_CFG_DESC                               0x09U
+#define  USB_LEN_IF_DESC                                0x09U
+#define  USB_LEN_EP_DESC                                0x07U
+#define  USB_LEN_OTG_DESC                               0x03U
+#define  USB_LEN_LANGID_STR_DESC                        0x04U
+#define  USB_LEN_OTHER_SPEED_DESC_SIZ                   0x09U
+
+#define  USBD_IDX_LANGID_STR                            0x00U
+#define  USBD_IDX_MFC_STR                               0x01U
+#define  USBD_IDX_PRODUCT_STR                           0x02U
+#define  USBD_IDX_SERIAL_STR                            0x03U
+#define  USBD_IDX_CONFIG_STR                            0x04U
+#define  USBD_IDX_INTERFACE_STR                         0x05U
+
+#define  USB_REQ_TYPE_STANDARD                          0x00U
+#define  USB_REQ_TYPE_CLASS                             0x20U
+#define  USB_REQ_TYPE_VENDOR                            0x40U
+#define  USB_REQ_TYPE_MASK                              0x60U
+
+#define  USB_REQ_RECIPIENT_DEVICE                       0x00U
+#define  USB_REQ_RECIPIENT_INTERFACE                    0x01U
+#define  USB_REQ_RECIPIENT_ENDPOINT                     0x02U
+#define  USB_REQ_RECIPIENT_MASK                         0x03U
+
+#define  USB_REQ_GET_STATUS                             0x00U
+#define  USB_REQ_CLEAR_FEATURE                          0x01U
+#define  USB_REQ_SET_FEATURE                            0x03U
+#define  USB_REQ_SET_ADDRESS                            0x05U
+#define  USB_REQ_GET_DESCRIPTOR                         0x06U
+#define  USB_REQ_SET_DESCRIPTOR                         0x07U
+#define  USB_REQ_GET_CONFIGURATION                      0x08U
+#define  USB_REQ_SET_CONFIGURATION                      0x09U
+#define  USB_REQ_GET_INTERFACE                          0x0AU
+#define  USB_REQ_SET_INTERFACE                          0x0BU
+#define  USB_REQ_SYNCH_FRAME                            0x0CU
+
+#define  USB_DESC_TYPE_DEVICE                           0x01U
+#define  USB_DESC_TYPE_CONFIGURATION                    0x02U
+#define  USB_DESC_TYPE_STRING                           0x03U
+#define  USB_DESC_TYPE_INTERFACE                        0x04U
+#define  USB_DESC_TYPE_ENDPOINT                         0x05U
+#define  USB_DESC_TYPE_DEVICE_QUALIFIER                 0x06U
+#define  USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION        0x07U
+#define  USB_DESC_TYPE_IAD                              0x0BU
+#define  USB_DESC_TYPE_BOS                              0x0FU
+
+#define USB_CONFIG_REMOTE_WAKEUP                        0x02U
+#define USB_CONFIG_SELF_POWERED                         0x01U
+
+#define USB_FEATURE_EP_HALT                             0x00U
+#define USB_FEATURE_REMOTE_WAKEUP                       0x01U
+#define USB_FEATURE_TEST_MODE                           0x02U
+
+#define USB_DEVICE_CAPABITY_TYPE                        0x10U
+
+#define USB_CONF_DESC_SIZE                              0x09U
+#define USB_IF_DESC_SIZE                                0x09U
+#define USB_EP_DESC_SIZE                                0x07U
+#define USB_IAD_DESC_SIZE                               0x08U
+
+#define USB_HS_MAX_PACKET_SIZE                          512U
+#define USB_FS_MAX_PACKET_SIZE                          64U
+#define USB_MAX_EP0_SIZE                                64U
+
+/*  Device Status */
+#define USBD_STATE_DEFAULT                              0x01U
+#define USBD_STATE_ADDRESSED                            0x02U
+#define USBD_STATE_CONFIGURED                           0x03U
+#define USBD_STATE_SUSPENDED                            0x04U
+
+
+/*  EP0 State */
+#define USBD_EP0_IDLE                                   0x00U
+#define USBD_EP0_SETUP                                  0x01U
+#define USBD_EP0_DATA_IN                                0x02U
+#define USBD_EP0_DATA_OUT                               0x03U
+#define USBD_EP0_STATUS_IN                              0x04U
+#define USBD_EP0_STATUS_OUT                             0x05U
+#define USBD_EP0_STALL                                  0x06U
+
+#define USBD_EP_TYPE_CTRL                               0x00U
+#define USBD_EP_TYPE_ISOC                               0x01U
+#define USBD_EP_TYPE_BULK                               0x02U
+#define USBD_EP_TYPE_INTR                               0x03U
+
+#ifdef USE_USBD_COMPOSITE
+#define USBD_EP_IN                                      0x80U
+#define USBD_EP_OUT                                     0x00U
+#define USBD_FUNC_DESCRIPTOR_TYPE                       0x24U
+#define USBD_DESC_SUBTYPE_ACM                           0x0FU
+#define USBD_DESC_ECM_BCD_LOW                           0x00U
+#define USBD_DESC_ECM_BCD_HIGH                          0x10U
+#endif /* USE_USBD_COMPOSITE */
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_DEF_Exported_TypesDefinitions
+  * @{
+  */
+
+typedef  struct  usb_setup_req
+{
+  uint8_t   bmRequest;
+  uint8_t   bRequest;
+  uint16_t  wValue;
+  uint16_t  wIndex;
+  uint16_t  wLength;
+} USBD_SetupReqTypedef;
+
+typedef struct
+{
+  uint8_t   bLength;
+  uint8_t   bDescriptorType;
+  uint16_t  wTotalLength;
+  uint8_t   bNumInterfaces;
+  uint8_t   bConfigurationValue;
+  uint8_t   iConfiguration;
+  uint8_t   bmAttributes;
+  uint8_t   bMaxPower;
+} __PACKED USBD_ConfigDescTypeDef;
+
+typedef struct
+{
+  uint8_t   bLength;
+  uint8_t   bDescriptorType;
+  uint16_t  wTotalLength;
+  uint8_t   bNumDeviceCaps;
+} USBD_BosDescTypeDef;
+
+typedef struct
+{
+  uint8_t   bLength;
+  uint8_t   bDescriptorType;
+  uint8_t   bEndpointAddress;
+  uint8_t   bmAttributes;
+  uint16_t  wMaxPacketSize;
+  uint8_t   bInterval;
+} __PACKED USBD_EpDescTypeDef;
+
+typedef  struct
+{
+  uint8_t  bLength;
+  uint8_t  bDescriptorType;
+  uint8_t  bDescriptorSubType;
+} USBD_DescHeaderTypeDef;
+
+struct _USBD_HandleTypeDef;
+
+typedef struct _Device_cb
+{
+  uint8_t (*Init)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+  uint8_t (*DeInit)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+  /* Control Endpoints*/
+  uint8_t (*Setup)(struct _USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef  *req);
+  uint8_t (*EP0_TxSent)(struct _USBD_HandleTypeDef *pdev);
+  uint8_t (*EP0_RxReady)(struct _USBD_HandleTypeDef *pdev);
+  /* Class Specific Endpoints*/
+  uint8_t (*DataIn)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
+  uint8_t (*DataOut)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
+  uint8_t (*SOF)(struct _USBD_HandleTypeDef *pdev);
+  uint8_t (*IsoINIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
+  uint8_t (*IsoOUTIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
+
+  uint8_t  *(*GetHSConfigDescriptor)(uint16_t *length);
+  uint8_t  *(*GetFSConfigDescriptor)(uint16_t *length);
+  uint8_t  *(*GetOtherSpeedConfigDescriptor)(uint16_t *length);
+  uint8_t  *(*GetDeviceQualifierDescriptor)(uint16_t *length);
+#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
+  uint8_t  *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev, uint8_t index,  uint16_t *length);
+#endif /* USBD_SUPPORT_USER_STRING_DESC  */
+
+} USBD_ClassTypeDef;
+
+/* Following USB Device Speed */
+typedef enum
+{
+  USBD_SPEED_HIGH  = 0U,
+  USBD_SPEED_FULL  = 1U,
+  USBD_SPEED_LOW   = 2U,
+} USBD_SpeedTypeDef;
+
+/* Following USB Device status */
+typedef enum
+{
+  USBD_OK = 0U,
+  USBD_BUSY,
+  USBD_EMEM,
+  USBD_FAIL,
+} USBD_StatusTypeDef;
+
+/* USB Device descriptors structure */
+typedef struct
+{
+  uint8_t *(*GetDeviceDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+  uint8_t *(*GetLangIDStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+  uint8_t *(*GetManufacturerStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+  uint8_t *(*GetProductStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+  uint8_t *(*GetSerialStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+  uint8_t *(*GetConfigurationStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+  uint8_t *(*GetInterfaceStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+#if (USBD_CLASS_USER_STRING_DESC == 1)
+  uint8_t *(*GetUserStrDescriptor)(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
+#endif /* USBD_CLASS_USER_STRING_DESC */
+#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1))
+  uint8_t *(*GetBOSDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length);
+#endif /* (USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1) */
+} USBD_DescriptorsTypeDef;
+
+/* USB Device handle structure */
+typedef struct
+{
+  uint32_t status;
+  uint32_t total_length;
+  uint32_t rem_length;
+  uint32_t maxpacket;
+  uint16_t is_used;
+  uint16_t bInterval;
+} USBD_EndpointTypeDef;
+
+#ifdef USE_USBD_COMPOSITE
+typedef enum
+{
+  CLASS_TYPE_NONE    = 0,
+  CLASS_TYPE_HID     = 1,
+  CLASS_TYPE_CDC     = 2,
+  CLASS_TYPE_MSC     = 3,
+  CLASS_TYPE_DFU     = 4,
+  CLASS_TYPE_CHID    = 5,
+  CLASS_TYPE_AUDIO   = 6,
+  CLASS_TYPE_ECM     = 7,
+  CLASS_TYPE_RNDIS   = 8,
+  CLASS_TYPE_MTP     = 9,
+  CLASS_TYPE_VIDEO   = 10,
+  CLASS_TYPE_PRINTER = 11,
+  CLASS_TYPE_CCID    = 12,
+} USBD_CompositeClassTypeDef;
+
+
+/* USB Device handle structure */
+typedef struct
+{
+  uint8_t                     add;
+  uint8_t                     type;
+  uint8_t                     size;
+  uint8_t                     is_used;
+} USBD_EPTypeDef;
+
+/* USB Device handle structure */
+typedef struct
+{
+  USBD_CompositeClassTypeDef   ClassType;
+  uint32_t                     ClassId;
+  uint32_t                     Active;
+  uint32_t                     NumEps;
+  USBD_EPTypeDef               Eps[USBD_MAX_CLASS_ENDPOINTS];
+  uint8_t                      *EpAdd;
+  uint32_t                     NumIf;
+  uint8_t                      Ifs[USBD_MAX_CLASS_INTERFACES];
+  uint32_t                     CurrPcktSze;
+} USBD_CompositeElementTypeDef;
+#endif /* USE_USBD_COMPOSITE */
+
+/* USB Device handle structure */
+typedef struct _USBD_HandleTypeDef
+{
+  uint8_t                 id;
+  uint32_t                dev_config;
+  uint32_t                dev_default_config;
+  uint32_t                dev_config_status;
+  USBD_SpeedTypeDef       dev_speed;
+  USBD_EndpointTypeDef    ep_in[16];
+  USBD_EndpointTypeDef    ep_out[16];
+  __IO uint32_t           ep0_state;
+  uint32_t                ep0_data_len;
+  __IO uint8_t            dev_state;
+  __IO uint8_t            dev_old_state;
+  uint8_t                 dev_address;
+  uint8_t                 dev_connection_status;
+  uint8_t                 dev_test_mode;
+  uint32_t                dev_remote_wakeup;
+  uint8_t                 ConfIdx;
+
+  USBD_SetupReqTypedef    request;
+  USBD_DescriptorsTypeDef *pDesc;
+  USBD_ClassTypeDef       *pClass[USBD_MAX_SUPPORTED_CLASS];
+  void                    *pClassData;
+  void                    *pClassDataCmsit[USBD_MAX_SUPPORTED_CLASS];
+  void                    *pUserData[USBD_MAX_SUPPORTED_CLASS];
+  void                    *pData;
+  void                    *pBosDesc;
+  void                    *pConfDesc;
+  uint32_t                classId;
+  uint32_t                NumClasses;
+#ifdef USE_USBD_COMPOSITE
+  USBD_CompositeElementTypeDef tclasslist[USBD_MAX_SUPPORTED_CLASS];
+#endif /* USE_USBD_COMPOSITE */
+#if (USBD_USER_REGISTER_CALLBACK == 1U)
+  void (* DevStateCallback)(uint8_t dev_state, uint8_t cfgidx);                    /*!< User Notification callback      */
+#endif /* USBD_USER_REGISTER_CALLBACK */
+} USBD_HandleTypeDef;
+
+#if (USBD_USER_REGISTER_CALLBACK == 1U)
+typedef void (*USBD_DevStateCallbackTypeDef)(uint8_t dev_state, uint8_t cfgidx);   /*!< pointer to User callback function  */
+#endif /* USBD_USER_REGISTER_CALLBACK */
+
+/* USB Device endpoint direction */
+typedef enum
+{
+  OUT   = 0x00,
+  IN    = 0x80,
+} USBD_EPDirectionTypeDef;
+
+typedef enum
+{
+  NETWORK_CONNECTION = 0x00,
+  RESPONSE_AVAILABLE = 0x01,
+  CONNECTION_SPEED_CHANGE = 0x2A
+} USBD_CDC_NotifCodeTypeDef;
+/**
+  * @}
+  */
+
+
+
+/** @defgroup USBD_DEF_Exported_Macros
+  * @{
+  */
+__STATIC_INLINE uint16_t SWAPBYTE(uint8_t *addr)
+{
+  uint16_t _SwapVal;
+  uint16_t _Byte1;
+  uint16_t _Byte2;
+  uint8_t *_pbuff = addr;
+
+  _Byte1 = *(uint8_t *)_pbuff;
+  _pbuff++;
+  _Byte2 = *(uint8_t *)_pbuff;
+
+  _SwapVal = (_Byte2 << 8) | _Byte1;
+
+  return _SwapVal;
+}
+
+#ifndef LOBYTE
+#define LOBYTE(x)  ((uint8_t)((x) & 0x00FFU))
+#endif /* LOBYTE */
+
+#ifndef HIBYTE
+#define HIBYTE(x)  ((uint8_t)(((x) & 0xFF00U) >> 8U))
+#endif /* HIBYTE */
+
+#ifndef MIN
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+#ifndef MAX
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+#if  defined ( __GNUC__ )
+#ifndef __weak
+#define __weak   __attribute__((weak))
+#endif /* __weak */
+#ifndef __packed
+#define __packed __attribute__((__packed__))
+#endif /* __packed */
+#endif /* __GNUC__ */
+
+
+/* In HS mode and when the DMA is used, all variables and data structures dealing
+   with the DMA during the transaction process should be 4-bytes aligned */
+
+#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */
+#ifndef __ALIGN_END
+#define __ALIGN_END    __attribute__ ((aligned (4U)))
+#endif /* __ALIGN_END */
+#ifndef __ALIGN_BEGIN
+#define __ALIGN_BEGIN
+#endif /* __ALIGN_BEGIN */
+#else
+#ifndef __ALIGN_END
+#define __ALIGN_END
+#endif /* __ALIGN_END */
+#ifndef __ALIGN_BEGIN
+#if defined   (__CC_ARM)      /* ARM Compiler */
+#define __ALIGN_BEGIN    __align(4U)
+#elif defined (__ICCARM__)    /* IAR Compiler */
+#define __ALIGN_BEGIN
+#endif /* __CC_ARM */
+#endif /* __ALIGN_BEGIN */
+#endif /* __GNUC__ */
+
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DEF_Exported_Variables
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DEF_Exported_FunctionsPrototype
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_DEF_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 113 - 0
Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h

@@ -0,0 +1,113 @@
+/**
+  ******************************************************************************
+  * @file    usbd_ioreq.h
+  * @author  MCD Application Team
+  * @brief   Header file for the usbd_ioreq.c file
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2015 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_IOREQ_H
+#define __USBD_IOREQ_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include  "usbd_def.h"
+#include  "usbd_core.h"
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+  * @{
+  */
+
+/** @defgroup USBD_IOREQ
+  * @brief header file for the usbd_ioreq.c file
+  * @{
+  */
+
+/** @defgroup USBD_IOREQ_Exported_Defines
+  * @{
+  */
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_IOREQ_Exported_Types
+  * @{
+  */
+
+
+/**
+  * @}
+  */
+
+
+
+/** @defgroup USBD_IOREQ_Exported_Macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_IOREQ_Exported_Variables
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype
+  * @{
+  */
+
+USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev,
+                                    uint8_t *pbuf, uint32_t len);
+
+USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev,
+                                            uint8_t *pbuf, uint32_t len);
+
+USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev,
+                                     uint8_t *pbuf, uint32_t len);
+
+USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev,
+                                      uint8_t *pbuf, uint32_t len);
+
+USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev);
+
+uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_IOREQ_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 1214 - 0
Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c

@@ -0,0 +1,1214 @@
+/**
+  ******************************************************************************
+  * @file    usbd_core.c
+  * @author  MCD Application Team
+  * @brief   This file provides all the USBD core functions.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2015 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_core.h"
+
+#ifdef USE_USBD_COMPOSITE
+#include "usbd_composite_builder.h"
+#endif /* USE_USBD_COMPOSITE */
+
+/** @addtogroup STM32_USBD_DEVICE_LIBRARY
+  * @{
+  */
+
+
+/** @defgroup USBD_CORE
+  * @brief usbd core module
+  * @{
+  */
+
+/** @defgroup USBD_CORE_Private_TypesDefinitions
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_CORE_Private_Defines
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_CORE_Private_Macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_CORE_Private_FunctionPrototypes
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_CORE_Private_Variables
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_CORE_Private_Functions
+  * @{
+  */
+
+/**
+  * @brief  USBD_Init
+  *         Initializes the device stack and load the class driver
+  * @param  pdev: device instance
+  * @param  pdesc: Descriptor structure address
+  * @param  id: Low level core index
+  * @retval None
+  */
+USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev,
+                             USBD_DescriptorsTypeDef *pdesc, uint8_t id)
+{
+  USBD_StatusTypeDef ret;
+
+  /* Check whether the USB Host handle is valid */
+  if (pdev == NULL)
+  {
+#if (USBD_DEBUG_LEVEL > 1U)
+    USBD_ErrLog("Invalid Device handle");
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
+    return USBD_FAIL;
+  }
+
+#ifdef USE_USBD_COMPOSITE
+  /* Parse the table of classes in use */
+  for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
+  {
+    /* Unlink previous class*/
+    pdev->pClass[i] = NULL;
+    pdev->pUserData[i] = NULL;
+
+    /* Set class as inactive */
+    pdev->tclasslist[i].Active = 0;
+    pdev->NumClasses = 0;
+    pdev->classId = 0;
+  }
+#else
+  /* Unlink previous class*/
+  pdev->pClass[0] = NULL;
+  pdev->pUserData[0] = NULL;
+#endif /* USE_USBD_COMPOSITE */
+
+  pdev->pConfDesc = NULL;
+
+  /* Assign USBD Descriptors */
+  if (pdesc != NULL)
+  {
+    pdev->pDesc = pdesc;
+  }
+
+  /* Set Device initial State */
+  pdev->dev_state = USBD_STATE_DEFAULT;
+  pdev->id = id;
+
+  /* Initialize low level driver */
+  ret = USBD_LL_Init(pdev);
+
+  return ret;
+}
+
+/**
+  * @brief  USBD_DeInit
+  *         Re-Initialize the device library
+  * @param  pdev: device instance
+  * @retval status: status
+  */
+USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
+{
+  USBD_StatusTypeDef ret;
+
+  /* Disconnect the USB Device */
+  (void)USBD_LL_Stop(pdev);
+
+  /* Set Default State */
+  pdev->dev_state = USBD_STATE_DEFAULT;
+
+#ifdef USE_USBD_COMPOSITE
+  /* Parse the table of classes in use */
+  for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
+  {
+    /* Check if current class is in use */
+    if ((pdev->tclasslist[i].Active) == 1U)
+    {
+      if (pdev->pClass[i] != NULL)
+      {
+        pdev->classId = i;
+        /* Free Class Resources */
+        pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config);
+      }
+    }
+  }
+#else
+  /* Free Class Resources */
+  if (pdev->pClass[0] != NULL)
+  {
+    pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config);
+  }
+
+  pdev->pUserData[0] = NULL;
+
+#endif /* USE_USBD_COMPOSITE */
+
+  /* Free Device descriptors resources */
+  pdev->pDesc = NULL;
+  pdev->pConfDesc = NULL;
+
+  /* DeInitialize low level driver */
+  ret = USBD_LL_DeInit(pdev);
+
+  return ret;
+}
+
+/**
+  * @brief  USBD_RegisterClass
+  *         Link class driver to Device Core.
+  * @param  pDevice : Device Handle
+  * @param  pclass: Class handle
+  * @retval USBD Status
+  */
+USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass)
+{
+  uint16_t len = 0U;
+
+  if (pclass == NULL)
+  {
+#if (USBD_DEBUG_LEVEL > 1U)
+    USBD_ErrLog("Invalid Class handle");
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
+    return USBD_FAIL;
+  }
+
+  /* link the class to the USB Device handle */
+  pdev->pClass[0] = pclass;
+
+  /* Get Device Configuration Descriptor */
+#ifdef USE_USB_HS
+  if (pdev->pClass[pdev->classId]->GetHSConfigDescriptor != NULL)
+  {
+    pdev->pConfDesc = (void *)pdev->pClass[pdev->classId]->GetHSConfigDescriptor(&len);
+  }
+#else /* Default USE_USB_FS */
+  if (pdev->pClass[pdev->classId]->GetFSConfigDescriptor != NULL)
+  {
+    pdev->pConfDesc = (void *)pdev->pClass[pdev->classId]->GetFSConfigDescriptor(&len);
+  }
+#endif /* USE_USB_FS */
+
+  /* Increment the NumClasses */
+  pdev->NumClasses ++;
+
+  return USBD_OK;
+}
+
+#ifdef USE_USBD_COMPOSITE
+/**
+  * @brief  USBD_RegisterClassComposite
+  *         Link class driver to Device Core.
+  * @param  pdev : Device Handle
+  * @param  pclass: Class handle
+  * @param  classtype: Class type
+  * @param  EpAddr: Endpoint Address handle
+  * @retval USBD Status
+  */
+USBD_StatusTypeDef  USBD_RegisterClassComposite(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass,
+                                                USBD_CompositeClassTypeDef classtype, uint8_t *EpAddr)
+{
+  USBD_StatusTypeDef   ret = USBD_OK;
+  uint16_t len = 0U;
+
+  if ((pdev->classId < USBD_MAX_SUPPORTED_CLASS) && (pdev->NumClasses < USBD_MAX_SUPPORTED_CLASS))
+  {
+    if ((uint32_t)pclass != 0U)
+    {
+      /* Link the class to the USB Device handle */
+      pdev->pClass[pdev->classId] = pclass;
+      ret = USBD_OK;
+
+      pdev->tclasslist[pdev->classId].EpAdd = EpAddr;
+
+      /* Call the composite class builder */
+      (void)USBD_CMPSIT_AddClass(pdev, pclass, classtype, 0);
+
+      /* Increment the ClassId for the next occurrence */
+      pdev->classId ++;
+      pdev->NumClasses ++;
+    }
+    else
+    {
+#if (USBD_DEBUG_LEVEL > 1U)
+      USBD_ErrLog("Invalid Class handle");
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
+      ret = USBD_FAIL;
+    }
+  }
+
+  if (ret == USBD_OK)
+  {
+    /* Get Device Configuration Descriptor */
+#ifdef USE_USB_HS
+    pdev->pConfDesc = USBD_CMPSIT.GetHSConfigDescriptor(&len);
+#else /* Default USE_USB_FS */
+    pdev->pConfDesc = USBD_CMPSIT.GetFSConfigDescriptor(&len);
+#endif /* USE_USB_FS */
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  USBD_UnRegisterClassComposite
+  *         UnLink all composite class drivers from Device Core.
+  * @param  pDevice : Device Handle
+  * @retval USBD Status
+  */
+USBD_StatusTypeDef  USBD_UnRegisterClassComposite(USBD_HandleTypeDef *pdev)
+{
+  USBD_StatusTypeDef   ret = USBD_FAIL;
+  uint8_t idx1;
+  uint8_t idx2;
+
+  /* Unroll all activated classes */
+  for (idx1 = 0; idx1 < pdev->NumClasses; idx1++)
+  {
+    /* Check if the class correspond to the requested type and if it is active */
+    if (pdev->tclasslist[idx1].Active == 1U)
+    {
+      /* Set the new class ID */
+      pdev->classId = idx1;
+
+      /* Free resources used by the selected class */
+      if (pdev->pClass[pdev->classId] != NULL)
+      {
+        /* Free Class Resources */
+        if (pdev->pClass[pdev->classId]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
+        {
+#if (USBD_DEBUG_LEVEL > 1U)
+          USBD_ErrLog("Class DeInit didn't succeed!, can't unregister selected class");
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
+
+          ret = USBD_FAIL;
+        }
+      }
+
+      /* Free the class pointer */
+      pdev->pClass[pdev->classId] = NULL;
+
+      /* Free the class location in classes table and reset its parameters to zero */
+      pdev->tclasslist[pdev->classId].ClassType = CLASS_TYPE_NONE;
+      pdev->tclasslist[pdev->classId].ClassId = 0U;
+      pdev->tclasslist[pdev->classId].Active = 0U;
+      pdev->tclasslist[pdev->classId].NumEps = 0U;
+      pdev->tclasslist[pdev->classId].NumIf = 0U;
+      pdev->tclasslist[pdev->classId].CurrPcktSze = 0U;
+
+      for (idx2 = 0U; idx2 < USBD_MAX_CLASS_ENDPOINTS; idx2++)
+      {
+        pdev->tclasslist[pdev->classId].Eps[idx2].add = 0U;
+        pdev->tclasslist[pdev->classId].Eps[idx2].type = 0U;
+        pdev->tclasslist[pdev->classId].Eps[idx2].size = 0U;
+        pdev->tclasslist[pdev->classId].Eps[idx2].is_used = 0U;
+      }
+
+      for (idx2 = 0U; idx2 < USBD_MAX_CLASS_INTERFACES; idx2++)
+      {
+        pdev->tclasslist[pdev->classId].Ifs[idx2] = 0U;
+      }
+    }
+  }
+
+  /* Reset the configuration descriptor */
+  (void)USBD_CMPST_ClearConfDesc(pdev);
+
+  /* Reset the class ID and number of classes */
+  pdev->classId = 0U;
+  pdev->NumClasses = 0U;
+
+  return ret;
+}
+#endif /* USE_USBD_COMPOSITE */
+
+#if (USBD_USER_REGISTER_CALLBACK == 1U)
+/**
+  * @brief  USBD_RegisterDevStateCallback
+  * @param  pdev : Device Handle
+  * @param  pUserCallback: User Callback
+  * @retval USBD Status
+  */
+USBD_StatusTypeDef USBD_RegisterDevStateCallback(USBD_HandleTypeDef *pdev, USBD_DevStateCallbackTypeDef pUserCallback)
+{
+  pdev->DevStateCallback = pUserCallback;
+
+  return USBD_OK;
+}
+#endif /* USBD_USER_REGISTER_CALLBACK */
+/**
+  * @brief  USBD_Start
+  *         Start the USB Device Core.
+  * @param  pdev: Device Handle
+  * @retval USBD Status
+  */
+USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev)
+{
+#ifdef USE_USBD_COMPOSITE
+  pdev->classId = 0U;
+#endif /* USE_USBD_COMPOSITE */
+
+  /* Start the low level driver  */
+  return USBD_LL_Start(pdev);
+}
+
+/**
+  * @brief  USBD_Stop
+  *         Stop the USB Device Core.
+  * @param  pdev: Device Handle
+  * @retval USBD Status
+  */
+USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev)
+{
+  /* Disconnect USB Device */
+  (void)USBD_LL_Stop(pdev);
+
+  /* Free Class Resources */
+#ifdef USE_USBD_COMPOSITE
+  /* Parse the table of classes in use */
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+  {
+    /* Check if current class is in use */
+    if ((pdev->tclasslist[i].Active) == 1U)
+    {
+      if (pdev->pClass[i] != NULL)
+      {
+        pdev->classId = i;
+        /* Free Class Resources */
+        (void)pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config);
+      }
+    }
+  }
+
+  /* Reset the class ID */
+  pdev->classId = 0U;
+#else
+  if (pdev->pClass[0] != NULL)
+  {
+    (void)pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config);
+  }
+#endif /* USE_USBD_COMPOSITE */
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_RunTestMode
+  *         Launch test mode process
+  * @param  pdev: device instance
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev)
+{
+#ifdef USBD_HS_TESTMODE_ENABLE
+  USBD_StatusTypeDef ret;
+
+  /* Run USB HS test mode */
+  ret = USBD_LL_SetTestMode(pdev, pdev->dev_test_mode);
+
+  return ret;
+#else
+  /* Prevent unused argument compilation warning */
+  UNUSED(pdev);
+
+  return USBD_OK;
+#endif /* USBD_HS_TESTMODE_ENABLE */
+}
+
+/**
+  * @brief  USBD_SetClassConfig
+  *        Configure device and start the interface
+  * @param  pdev: device instance
+  * @param  cfgidx: configuration index
+  * @retval status
+  */
+
+USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+  USBD_StatusTypeDef ret = USBD_OK;
+
+#ifdef USE_USBD_COMPOSITE
+  /* Parse the table of classes in use */
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+  {
+    /* Check if current class is in use */
+    if ((pdev->tclasslist[i].Active) == 1U)
+    {
+      if (pdev->pClass[i] != NULL)
+      {
+        pdev->classId = i;
+        /* Set configuration  and Start the Class*/
+        if (pdev->pClass[i]->Init(pdev, cfgidx) != 0U)
+        {
+          ret = USBD_FAIL;
+        }
+      }
+    }
+  }
+#else
+  if (pdev->pClass[0] != NULL)
+  {
+    /* Set configuration and Start the Class */
+    ret = (USBD_StatusTypeDef)pdev->pClass[0]->Init(pdev, cfgidx);
+  }
+#endif /* USE_USBD_COMPOSITE */
+
+  return ret;
+}
+
+/**
+  * @brief  USBD_ClrClassConfig
+  *         Clear current configuration
+  * @param  pdev: device instance
+  * @param  cfgidx: configuration index
+  * @retval status: USBD_StatusTypeDef
+  */
+USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+  USBD_StatusTypeDef ret = USBD_OK;
+
+#ifdef USE_USBD_COMPOSITE
+  /* Parse the table of classes in use */
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+  {
+    /* Check if current class is in use */
+    if ((pdev->tclasslist[i].Active) == 1U)
+    {
+      if (pdev->pClass[i] != NULL)
+      {
+        pdev->classId = i;
+        /* Clear configuration  and De-initialize the Class process */
+        if (pdev->pClass[i]->DeInit(pdev, cfgidx) != 0U)
+        {
+          ret = USBD_FAIL;
+        }
+      }
+    }
+  }
+#else
+  /* Clear configuration  and De-initialize the Class process */
+  if (pdev->pClass[0]->DeInit(pdev, cfgidx) != 0U)
+  {
+    ret = USBD_FAIL;
+  }
+#endif /* USE_USBD_COMPOSITE */
+
+  return ret;
+}
+
+
+/**
+  * @brief  USBD_LL_SetupStage
+  *         Handle the setup stage
+  * @param  pdev: device instance
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
+{
+  USBD_StatusTypeDef ret;
+
+  USBD_ParseSetupRequest(&pdev->request, psetup);
+
+  pdev->ep0_state = USBD_EP0_SETUP;
+
+  pdev->ep0_data_len = pdev->request.wLength;
+
+  switch (pdev->request.bmRequest & 0x1FU)
+  {
+    case USB_REQ_RECIPIENT_DEVICE:
+      ret = USBD_StdDevReq(pdev, &pdev->request);
+      break;
+
+    case USB_REQ_RECIPIENT_INTERFACE:
+      ret = USBD_StdItfReq(pdev, &pdev->request);
+      break;
+
+    case USB_REQ_RECIPIENT_ENDPOINT:
+      ret = USBD_StdEPReq(pdev, &pdev->request);
+      break;
+
+    default:
+      ret = USBD_LL_StallEP(pdev, (pdev->request.bmRequest & 0x80U));
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  USBD_LL_DataOutStage
+  *         Handle data OUT stage
+  * @param  pdev: device instance
+  * @param  epnum: endpoint index
+  * @param  pdata: data pointer
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev,
+                                        uint8_t epnum, uint8_t *pdata)
+{
+  USBD_EndpointTypeDef *pep;
+  USBD_StatusTypeDef ret = USBD_OK;
+  uint8_t idx;
+
+  if (epnum == 0U)
+  {
+    pep = &pdev->ep_out[0];
+
+    if (pdev->ep0_state == USBD_EP0_DATA_OUT)
+    {
+      if (pep->rem_length > pep->maxpacket)
+      {
+        pep->rem_length -= pep->maxpacket;
+
+        (void)USBD_CtlContinueRx(pdev, pdata, MIN(pep->rem_length, pep->maxpacket));
+      }
+      else
+      {
+        /* Find the class ID relative to the current request */
+        switch (pdev->request.bmRequest & 0x1FU)
+        {
+          case USB_REQ_RECIPIENT_DEVICE:
+            /* Device requests must be managed by the first instantiated class
+               (or duplicated by all classes for simplicity) */
+            idx = 0U;
+            break;
+
+          case USB_REQ_RECIPIENT_INTERFACE:
+            idx = USBD_CoreFindIF(pdev, LOBYTE(pdev->request.wIndex));
+            break;
+
+          case USB_REQ_RECIPIENT_ENDPOINT:
+            idx = USBD_CoreFindEP(pdev, LOBYTE(pdev->request.wIndex));
+            break;
+
+          default:
+            /* Back to the first class in case of doubt */
+            idx = 0U;
+            break;
+        }
+
+        if (idx < USBD_MAX_SUPPORTED_CLASS)
+        {
+          /* Setup the class ID and route the request to the relative class function */
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
+          {
+            if (pdev->pClass[idx]->EP0_RxReady != NULL)
+            {
+              pdev->classId = idx;
+              pdev->pClass[idx]->EP0_RxReady(pdev);
+            }
+          }
+        }
+
+        (void)USBD_CtlSendStatus(pdev);
+      }
+    }
+  }
+  else
+  {
+    /* Get the class index relative to this interface */
+    idx = USBD_CoreFindEP(pdev, (epnum & 0x7FU));
+
+    if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
+    {
+      /* Call the class data out function to manage the request */
+      if (pdev->dev_state == USBD_STATE_CONFIGURED)
+      {
+        if (pdev->pClass[idx]->DataOut != NULL)
+        {
+          pdev->classId = idx;
+          ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataOut(pdev, epnum);
+        }
+      }
+      if (ret != USBD_OK)
+      {
+        return ret;
+      }
+    }
+  }
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_LL_DataInStage
+  *         Handle data in stage
+  * @param  pdev: device instance
+  * @param  epnum: endpoint index
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev,
+                                       uint8_t epnum, uint8_t *pdata)
+{
+  USBD_EndpointTypeDef *pep;
+  USBD_StatusTypeDef ret;
+  uint8_t idx;
+
+  if (epnum == 0U)
+  {
+    pep = &pdev->ep_in[0];
+
+    if (pdev->ep0_state == USBD_EP0_DATA_IN)
+    {
+      if (pep->rem_length > pep->maxpacket)
+      {
+        pep->rem_length -= pep->maxpacket;
+
+        (void)USBD_CtlContinueSendData(pdev, pdata, pep->rem_length);
+
+        /* Prepare endpoint for premature end of transfer */
+        (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
+      }
+      else
+      {
+        /* last packet is MPS multiple, so send ZLP packet */
+        if ((pep->maxpacket == pep->rem_length) &&
+            (pep->total_length >= pep->maxpacket) &&
+            (pep->total_length < pdev->ep0_data_len))
+        {
+          (void)USBD_CtlContinueSendData(pdev, NULL, 0U);
+          pdev->ep0_data_len = 0U;
+
+          /* Prepare endpoint for premature end of transfer */
+          (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
+        }
+        else
+        {
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
+          {
+            if (pdev->pClass[0]->EP0_TxSent != NULL)
+            {
+              pdev->classId = 0U;
+              pdev->pClass[0]->EP0_TxSent(pdev);
+            }
+          }
+          (void)USBD_LL_StallEP(pdev, 0x80U);
+          (void)USBD_CtlReceiveStatus(pdev);
+        }
+      }
+    }
+
+    if (pdev->dev_test_mode != 0U)
+    {
+      (void)USBD_RunTestMode(pdev);
+      pdev->dev_test_mode = 0U;
+    }
+  }
+  else
+  {
+    /* Get the class index relative to this interface */
+    idx = USBD_CoreFindEP(pdev, ((uint8_t)epnum | 0x80U));
+
+    if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
+    {
+      /* Call the class data out function to manage the request */
+      if (pdev->dev_state == USBD_STATE_CONFIGURED)
+      {
+        if (pdev->pClass[idx]->DataIn != NULL)
+        {
+          pdev->classId = idx;
+          ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataIn(pdev, epnum);
+
+          if (ret != USBD_OK)
+          {
+            return ret;
+          }
+        }
+      }
+    }
+  }
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_LL_Reset
+  *         Handle Reset event
+  * @param  pdev: device instance
+  * @retval status
+  */
+
+USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev)
+{
+  USBD_StatusTypeDef ret = USBD_OK;
+
+  /* Upon Reset call user call back */
+  pdev->dev_state = USBD_STATE_DEFAULT;
+  pdev->ep0_state = USBD_EP0_IDLE;
+  pdev->dev_config = 0U;
+  pdev->dev_remote_wakeup = 0U;
+  pdev->dev_test_mode = 0U;
+
+#ifdef USE_USBD_COMPOSITE
+  /* Parse the table of classes in use */
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+  {
+    /* Check if current class is in use */
+    if ((pdev->tclasslist[i].Active) == 1U)
+    {
+      if (pdev->pClass[i] != NULL)
+      {
+        pdev->classId = i;
+        /* Clear configuration  and De-initialize the Class process*/
+
+        if (pdev->pClass[i]->DeInit != NULL)
+        {
+          if (pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config) != USBD_OK)
+          {
+            ret = USBD_FAIL;
+          }
+        }
+      }
+    }
+  }
+#else
+
+  if (pdev->pClass[0] != NULL)
+  {
+    if (pdev->pClass[0]->DeInit != NULL)
+    {
+      if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != USBD_OK)
+      {
+        ret = USBD_FAIL;
+      }
+    }
+  }
+#endif /* USE_USBD_COMPOSITE */
+
+  /* Open EP0 OUT */
+  (void)USBD_LL_OpenEP(pdev, 0x00U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
+  pdev->ep_out[0x00U & 0xFU].is_used = 1U;
+
+  pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
+
+  /* Open EP0 IN */
+  (void)USBD_LL_OpenEP(pdev, 0x80U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
+  pdev->ep_in[0x80U & 0xFU].is_used = 1U;
+
+  pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
+
+  return ret;
+}
+
+/**
+  * @brief  USBD_LL_SetSpeed
+  *         Handle Reset event
+  * @param  pdev: device instance
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev,
+                                    USBD_SpeedTypeDef speed)
+{
+  pdev->dev_speed = speed;
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_LL_Suspend
+  *         Handle Suspend event
+  * @param  pdev: device instance
+  * @retval status
+  */
+
+USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev)
+{
+  if (pdev->dev_state != USBD_STATE_SUSPENDED)
+  {
+    pdev->dev_old_state = pdev->dev_state;
+  }
+
+  pdev->dev_state = USBD_STATE_SUSPENDED;
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_LL_Resume
+  *         Handle Resume event
+  * @param  pdev: device instance
+  * @retval status
+  */
+
+USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev)
+{
+  if (pdev->dev_state == USBD_STATE_SUSPENDED)
+  {
+    pdev->dev_state = pdev->dev_old_state;
+  }
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_LL_SOF
+  *         Handle SOF event
+  * @param  pdev: device instance
+  * @retval status
+  */
+
+USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev)
+{
+  /* The SOF event can be distributed for all classes that support it */
+  if (pdev->dev_state == USBD_STATE_CONFIGURED)
+  {
+#ifdef USE_USBD_COMPOSITE
+    /* Parse the table of classes in use */
+    for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
+    {
+      /* Check if current class is in use */
+      if ((pdev->tclasslist[i].Active) == 1U)
+      {
+        if (pdev->pClass[i] != NULL)
+        {
+          if (pdev->pClass[i]->SOF != NULL)
+          {
+            pdev->classId = i;
+            (void)pdev->pClass[i]->SOF(pdev);
+          }
+        }
+      }
+    }
+#else
+    if (pdev->pClass[0] != NULL)
+    {
+      if (pdev->pClass[0]->SOF != NULL)
+      {
+        (void)pdev->pClass[0]->SOF(pdev);
+      }
+    }
+#endif /* USE_USBD_COMPOSITE */
+  }
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_LL_IsoINIncomplete
+  *         Handle iso in incomplete event
+  * @param  pdev: device instance
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev,
+                                           uint8_t epnum)
+{
+  if (pdev->pClass[pdev->classId] == NULL)
+  {
+    return USBD_FAIL;
+  }
+
+  if (pdev->dev_state == USBD_STATE_CONFIGURED)
+  {
+    if (pdev->pClass[pdev->classId]->IsoINIncomplete != NULL)
+    {
+      (void)pdev->pClass[pdev->classId]->IsoINIncomplete(pdev, epnum);
+    }
+  }
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_LL_IsoOUTIncomplete
+  *         Handle iso out incomplete event
+  * @param  pdev: device instance
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev,
+                                            uint8_t epnum)
+{
+  if (pdev->pClass[pdev->classId] == NULL)
+  {
+    return USBD_FAIL;
+  }
+
+  if (pdev->dev_state == USBD_STATE_CONFIGURED)
+  {
+    if (pdev->pClass[pdev->classId]->IsoOUTIncomplete != NULL)
+    {
+      (void)pdev->pClass[pdev->classId]->IsoOUTIncomplete(pdev, epnum);
+    }
+  }
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_LL_DevConnected
+  *         Handle device connection event
+  * @param  pdev: device instance
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev)
+{
+  /* Prevent unused argument compilation warning */
+  UNUSED(pdev);
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_LL_DevDisconnected
+  *         Handle device disconnection event
+  * @param  pdev: device instance
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev)
+{
+  USBD_StatusTypeDef   ret = USBD_OK;
+
+  /* Free Class Resources */
+  pdev->dev_state = USBD_STATE_DEFAULT;
+
+#ifdef USE_USBD_COMPOSITE
+  /* Parse the table of classes in use */
+  for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
+  {
+    /* Check if current class is in use */
+    if ((pdev->tclasslist[i].Active) == 1U)
+    {
+      if (pdev->pClass[i] != NULL)
+      {
+        pdev->classId = i;
+        /* Clear configuration  and De-initialize the Class process*/
+        if (pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
+        {
+          ret = USBD_FAIL;
+        }
+      }
+    }
+  }
+#else
+  if (pdev->pClass[0] != NULL)
+  {
+    if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
+    {
+      ret = USBD_FAIL;
+    }
+  }
+#endif /* USE_USBD_COMPOSITE */
+
+  return ret;
+}
+
+/**
+  * @brief  USBD_CoreFindIF
+  *         return the class index relative to the selected interface
+  * @param  pdev: device instance
+  * @param  index : selected interface number
+  * @retval index of the class using the selected interface number. OxFF if no class found.
+  */
+uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index)
+{
+#ifdef USE_USBD_COMPOSITE
+  /* Parse the table of classes in use */
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+  {
+    /* Check if current class is in use */
+    if ((pdev->tclasslist[i].Active) == 1U)
+    {
+      /* Parse all interfaces listed in the current class */
+      for (uint32_t j = 0U; j < pdev->tclasslist[i].NumIf; j++)
+      {
+        /* Check if requested Interface matches the current class interface */
+        if (pdev->tclasslist[i].Ifs[j] == index)
+        {
+          if (pdev->pClass[i]->Setup != NULL)
+          {
+            return (uint8_t)i;
+          }
+        }
+      }
+    }
+  }
+
+  return 0xFFU;
+#else
+  UNUSED(pdev);
+  UNUSED(index);
+
+  return 0x00U;
+#endif /* USE_USBD_COMPOSITE */
+}
+
+/**
+  * @brief  USBD_CoreFindEP
+  *         return the class index relative to the selected endpoint
+  * @param  pdev: device instance
+  * @param  index : selected endpoint number
+  * @retval index of the class using the selected endpoint number. 0xFF if no class found.
+  */
+uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index)
+{
+#ifdef USE_USBD_COMPOSITE
+  /* Parse the table of classes in use */
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
+  {
+    /* Check if current class is in use */
+    if ((pdev->tclasslist[i].Active) == 1U)
+    {
+      /* Parse all endpoints listed in the current class */
+      for (uint32_t j = 0U; j < pdev->tclasslist[i].NumEps; j++)
+      {
+        /* Check if requested endpoint matches the current class endpoint */
+        if (pdev->tclasslist[i].Eps[j].add == index)
+        {
+          if (pdev->pClass[i]->Setup != NULL)
+          {
+            return (uint8_t)i;
+          }
+        }
+      }
+    }
+  }
+
+  return 0xFFU;
+#else
+  UNUSED(pdev);
+  UNUSED(index);
+
+  return 0x00U;
+#endif /* USE_USBD_COMPOSITE */
+}
+
+#ifdef USE_USBD_COMPOSITE
+/**
+  * @brief  USBD_CoreGetEPAdd
+  *         Get the endpoint address relative to a selected class
+  * @param  pdev: device instance
+  * @param  ep_dir: USBD_EP_IN or USBD_EP_OUT
+  * @param  ep_type: USBD_EP_TYPE_CTRL, USBD_EP_TYPE_ISOC, USBD_EP_TYPE_BULK or USBD_EP_TYPE_INTR
+  * @param  ClassId: The Class ID
+  * @retval Address of the selected endpoint or 0xFFU if no endpoint found.
+  */
+uint8_t USBD_CoreGetEPAdd(USBD_HandleTypeDef *pdev, uint8_t ep_dir, uint8_t ep_type, uint8_t ClassId)
+{
+  uint8_t idx;
+
+  /* Find the EP address in the selected class table */
+  for (idx = 0; idx < pdev->tclasslist[ClassId].NumEps; idx++)
+  {
+    if (((pdev->tclasslist[ClassId].Eps[idx].add & USBD_EP_IN) == ep_dir) && \
+        (pdev->tclasslist[ClassId].Eps[idx].type == ep_type) && \
+        (pdev->tclasslist[ClassId].Eps[idx].is_used != 0U))
+    {
+      return (pdev->tclasslist[ClassId].Eps[idx].add);
+    }
+  }
+
+  /* If reaching this point, then no endpoint was found */
+  return 0xFFU;
+}
+#endif /* USE_USBD_COMPOSITE */
+
+/**
+  * @brief  USBD_GetEpDesc
+  *         This function return the Endpoint descriptor
+  * @param  pdev: device instance
+  * @param  pConfDesc:  pointer to Bos descriptor
+  * @param  EpAddr:  endpoint address
+  * @retval pointer to video endpoint descriptor
+  */
+void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr)
+{
+  USBD_DescHeaderTypeDef *pdesc = (USBD_DescHeaderTypeDef *)(void *)pConfDesc;
+  USBD_ConfigDescTypeDef *desc = (USBD_ConfigDescTypeDef *)(void *)pConfDesc;
+  USBD_EpDescTypeDef *pEpDesc = NULL;
+  uint16_t ptr;
+
+  if (desc->wTotalLength > desc->bLength)
+  {
+    ptr = desc->bLength;
+
+    while (ptr < desc->wTotalLength)
+    {
+      pdesc = USBD_GetNextDesc((uint8_t *)pdesc, &ptr);
+
+      if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT)
+      {
+        pEpDesc = (USBD_EpDescTypeDef *)(void *)pdesc;
+
+        if (pEpDesc->bEndpointAddress == EpAddr)
+        {
+          break;
+        }
+        else
+        {
+          pEpDesc = NULL;
+        }
+      }
+    }
+  }
+
+  return (void *)pEpDesc;
+}
+
+/**
+  * @brief  USBD_GetNextDesc
+  *         This function return the next descriptor header
+  * @param  buf: Buffer where the descriptor is available
+  * @param  ptr: data pointer inside the descriptor
+  * @retval next header
+  */
+USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr)
+{
+  USBD_DescHeaderTypeDef *pnext = (USBD_DescHeaderTypeDef *)(void *)pbuf;
+
+  *ptr += pnext->bLength;
+  pnext = (USBD_DescHeaderTypeDef *)(void *)(pbuf + pnext->bLength);
+
+  return (pnext);
+}
+
+/**
+  * @}
+  */
+
+
+/**
+  * @}
+  */
+
+
+/**
+  * @}
+  */
+

+ 1056 - 0
Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c

@@ -0,0 +1,1056 @@
+/**
+  ******************************************************************************
+  * @file    usbd_req.c
+  * @author  MCD Application Team
+  * @brief   This file provides the standard USB requests following chapter 9.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2015 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_ctlreq.h"
+#include "usbd_ioreq.h"
+
+#ifdef USE_USBD_COMPOSITE
+#include "usbd_composite_builder.h"
+#endif /* USE_USBD_COMPOSITE */
+
+/** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY
+  * @{
+  */
+
+
+/** @defgroup USBD_REQ
+  * @brief USB standard requests module
+  * @{
+  */
+
+/** @defgroup USBD_REQ_Private_TypesDefinitions
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_REQ_Private_Defines
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_REQ_Private_Macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_REQ_Private_Variables
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_REQ_Private_FunctionPrototypes
+  * @{
+  */
+static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void USBD_SetAddress(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static USBD_StatusTypeDef USBD_SetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void USBD_SetFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static void USBD_ClrFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static uint8_t USBD_GetLen(uint8_t *buf);
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_REQ_Private_Functions
+  * @{
+  */
+
+
+/**
+  * @brief  USBD_StdDevReq
+  *         Handle standard usb device requests
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  USBD_StatusTypeDef ret = USBD_OK;
+
+  switch (req->bmRequest & USB_REQ_TYPE_MASK)
+  {
+    case USB_REQ_TYPE_CLASS:
+    case USB_REQ_TYPE_VENDOR:
+      ret = (USBD_StatusTypeDef)pdev->pClass[pdev->classId]->Setup(pdev, req);
+      break;
+
+    case USB_REQ_TYPE_STANDARD:
+      switch (req->bRequest)
+      {
+        case USB_REQ_GET_DESCRIPTOR:
+          USBD_GetDescriptor(pdev, req);
+          break;
+
+        case USB_REQ_SET_ADDRESS:
+          USBD_SetAddress(pdev, req);
+          break;
+
+        case USB_REQ_SET_CONFIGURATION:
+          ret = USBD_SetConfig(pdev, req);
+          break;
+
+        case USB_REQ_GET_CONFIGURATION:
+          USBD_GetConfig(pdev, req);
+          break;
+
+        case USB_REQ_GET_STATUS:
+          USBD_GetStatus(pdev, req);
+          break;
+
+        case USB_REQ_SET_FEATURE:
+          USBD_SetFeature(pdev, req);
+          break;
+
+        case USB_REQ_CLEAR_FEATURE:
+          USBD_ClrFeature(pdev, req);
+          break;
+
+        default:
+          USBD_CtlError(pdev, req);
+          break;
+      }
+      break;
+
+    default:
+      USBD_CtlError(pdev, req);
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  USBD_StdItfReq
+  *         Handle standard usb interface requests
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_StdItfReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  USBD_StatusTypeDef ret = USBD_OK;
+  uint8_t idx;
+
+  switch (req->bmRequest & USB_REQ_TYPE_MASK)
+  {
+    case USB_REQ_TYPE_CLASS:
+    case USB_REQ_TYPE_VENDOR:
+    case USB_REQ_TYPE_STANDARD:
+      switch (pdev->dev_state)
+      {
+        case USBD_STATE_DEFAULT:
+        case USBD_STATE_ADDRESSED:
+        case USBD_STATE_CONFIGURED:
+
+          if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES)
+          {
+            /* Get the class index relative to this interface */
+            idx = USBD_CoreFindIF(pdev, LOBYTE(req->wIndex));
+            if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
+            {
+              /* Call the class data out function to manage the request */
+              if (pdev->pClass[idx]->Setup != NULL)
+              {
+                pdev->classId = idx;
+                ret = (USBD_StatusTypeDef)(pdev->pClass[idx]->Setup(pdev, req));
+              }
+              else
+              {
+                /* should never reach this condition */
+                ret = USBD_FAIL;
+              }
+            }
+            else
+            {
+              /* No relative interface found */
+              ret = USBD_FAIL;
+            }
+
+            if ((req->wLength == 0U) && (ret == USBD_OK))
+            {
+              (void)USBD_CtlSendStatus(pdev);
+            }
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+          }
+          break;
+
+        default:
+          USBD_CtlError(pdev, req);
+          break;
+      }
+      break;
+
+    default:
+      USBD_CtlError(pdev, req);
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  USBD_StdEPReq
+  *         Handle standard usb endpoint requests
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  USBD_EndpointTypeDef *pep;
+  uint8_t ep_addr;
+  uint8_t idx;
+  USBD_StatusTypeDef ret = USBD_OK;
+
+  ep_addr = LOBYTE(req->wIndex);
+
+  switch (req->bmRequest & USB_REQ_TYPE_MASK)
+  {
+    case USB_REQ_TYPE_CLASS:
+    case USB_REQ_TYPE_VENDOR:
+      /* Get the class index relative to this endpoint */
+      idx = USBD_CoreFindEP(pdev, ep_addr);
+      if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
+      {
+        pdev->classId = idx;
+        /* Call the class data out function to manage the request */
+        if (pdev->pClass[idx]->Setup != NULL)
+        {
+          ret = (USBD_StatusTypeDef)pdev->pClass[idx]->Setup(pdev, req);
+        }
+      }
+      break;
+
+    case USB_REQ_TYPE_STANDARD:
+      switch (req->bRequest)
+      {
+        case USB_REQ_SET_FEATURE:
+          switch (pdev->dev_state)
+          {
+            case USBD_STATE_ADDRESSED:
+              if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
+              {
+                (void)USBD_LL_StallEP(pdev, ep_addr);
+                (void)USBD_LL_StallEP(pdev, 0x80U);
+              }
+              else
+              {
+                USBD_CtlError(pdev, req);
+              }
+              break;
+
+            case USBD_STATE_CONFIGURED:
+              if (req->wValue == USB_FEATURE_EP_HALT)
+              {
+                if ((ep_addr != 0x00U) && (ep_addr != 0x80U) && (req->wLength == 0x00U))
+                {
+                  (void)USBD_LL_StallEP(pdev, ep_addr);
+                }
+              }
+              (void)USBD_CtlSendStatus(pdev);
+
+              break;
+
+            default:
+              USBD_CtlError(pdev, req);
+              break;
+          }
+          break;
+
+        case USB_REQ_CLEAR_FEATURE:
+
+          switch (pdev->dev_state)
+          {
+            case USBD_STATE_ADDRESSED:
+              if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
+              {
+                (void)USBD_LL_StallEP(pdev, ep_addr);
+                (void)USBD_LL_StallEP(pdev, 0x80U);
+              }
+              else
+              {
+                USBD_CtlError(pdev, req);
+              }
+              break;
+
+            case USBD_STATE_CONFIGURED:
+              if (req->wValue == USB_FEATURE_EP_HALT)
+              {
+                if ((ep_addr & 0x7FU) != 0x00U)
+                {
+                  (void)USBD_LL_ClearStallEP(pdev, ep_addr);
+                }
+                (void)USBD_CtlSendStatus(pdev);
+
+                /* Get the class index relative to this interface */
+                idx = USBD_CoreFindEP(pdev, ep_addr);
+                if (((uint8_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
+                {
+                  pdev->classId = idx;
+                  /* Call the class data out function to manage the request */
+                  if (pdev->pClass[idx]->Setup != NULL)
+                  {
+                    ret = (USBD_StatusTypeDef)(pdev->pClass[idx]->Setup(pdev, req));
+                  }
+                }
+              }
+              break;
+
+            default:
+              USBD_CtlError(pdev, req);
+              break;
+          }
+          break;
+
+        case USB_REQ_GET_STATUS:
+          switch (pdev->dev_state)
+          {
+            case USBD_STATE_ADDRESSED:
+              if ((ep_addr != 0x00U) && (ep_addr != 0x80U))
+              {
+                USBD_CtlError(pdev, req);
+                break;
+              }
+              pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU] : \
+                    &pdev->ep_out[ep_addr & 0x7FU];
+
+              pep->status = 0x0000U;
+
+              (void)USBD_CtlSendData(pdev, (uint8_t *)&pep->status, 2U);
+              break;
+
+            case USBD_STATE_CONFIGURED:
+              if ((ep_addr & 0x80U) == 0x80U)
+              {
+                if (pdev->ep_in[ep_addr & 0xFU].is_used == 0U)
+                {
+                  USBD_CtlError(pdev, req);
+                  break;
+                }
+              }
+              else
+              {
+                if (pdev->ep_out[ep_addr & 0xFU].is_used == 0U)
+                {
+                  USBD_CtlError(pdev, req);
+                  break;
+                }
+              }
+
+              pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU] : \
+                    &pdev->ep_out[ep_addr & 0x7FU];
+
+              if ((ep_addr == 0x00U) || (ep_addr == 0x80U))
+              {
+                pep->status = 0x0000U;
+              }
+              else if (USBD_LL_IsStallEP(pdev, ep_addr) != 0U)
+              {
+                pep->status = 0x0001U;
+              }
+              else
+              {
+                pep->status = 0x0000U;
+              }
+
+              (void)USBD_CtlSendData(pdev, (uint8_t *)&pep->status, 2U);
+              break;
+
+            default:
+              USBD_CtlError(pdev, req);
+              break;
+          }
+          break;
+
+        default:
+          USBD_CtlError(pdev, req);
+          break;
+      }
+      break;
+
+    default:
+      USBD_CtlError(pdev, req);
+      break;
+  }
+
+  return ret;
+}
+
+
+/**
+  * @brief  USBD_GetDescriptor
+  *         Handle Get Descriptor requests
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval status
+  */
+static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  uint16_t len = 0U;
+  uint8_t *pbuf = NULL;
+  uint8_t err = 0U;
+
+  switch (req->wValue >> 8)
+  {
+#if ((USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1U))
+    case USB_DESC_TYPE_BOS:
+      if (pdev->pDesc->GetBOSDescriptor != NULL)
+      {
+        pbuf = pdev->pDesc->GetBOSDescriptor(pdev->dev_speed, &len);
+      }
+      else
+      {
+        USBD_CtlError(pdev, req);
+        err++;
+      }
+      break;
+#endif /* (USBD_LPM_ENABLED == 1U) || (USBD_CLASS_BOS_ENABLED == 1U) */
+    case USB_DESC_TYPE_DEVICE:
+      pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len);
+      break;
+
+    case USB_DESC_TYPE_CONFIGURATION:
+      if (pdev->dev_speed == USBD_SPEED_HIGH)
+      {
+#ifdef USE_USBD_COMPOSITE
+        if ((uint8_t)(pdev->NumClasses) > 0U)
+        {
+          pbuf = (uint8_t *)USBD_CMPSIT.GetHSConfigDescriptor(&len);
+        }
+        else
+#endif /* USE_USBD_COMPOSITE */
+        {
+          pbuf = (uint8_t *)pdev->pClass[0]->GetHSConfigDescriptor(&len);
+        }
+        pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
+      }
+      else
+      {
+#ifdef USE_USBD_COMPOSITE
+        if ((uint8_t)(pdev->NumClasses) > 0U)
+        {
+          pbuf = (uint8_t *)USBD_CMPSIT.GetFSConfigDescriptor(&len);
+        }
+        else
+#endif /* USE_USBD_COMPOSITE */
+        {
+          pbuf = (uint8_t *)pdev->pClass[0]->GetFSConfigDescriptor(&len);
+        }
+        pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
+      }
+      break;
+
+    case USB_DESC_TYPE_STRING:
+      switch ((uint8_t)(req->wValue))
+      {
+        case USBD_IDX_LANGID_STR:
+          if (pdev->pDesc->GetLangIDStrDescriptor != NULL)
+          {
+            pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len);
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+            err++;
+          }
+          break;
+
+        case USBD_IDX_MFC_STR:
+          if (pdev->pDesc->GetManufacturerStrDescriptor != NULL)
+          {
+            pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len);
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+            err++;
+          }
+          break;
+
+        case USBD_IDX_PRODUCT_STR:
+          if (pdev->pDesc->GetProductStrDescriptor != NULL)
+          {
+            pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len);
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+            err++;
+          }
+          break;
+
+        case USBD_IDX_SERIAL_STR:
+          if (pdev->pDesc->GetSerialStrDescriptor != NULL)
+          {
+            pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len);
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+            err++;
+          }
+          break;
+
+        case USBD_IDX_CONFIG_STR:
+          if (pdev->pDesc->GetConfigurationStrDescriptor != NULL)
+          {
+            pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len);
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+            err++;
+          }
+          break;
+
+        case USBD_IDX_INTERFACE_STR:
+          if (pdev->pDesc->GetInterfaceStrDescriptor != NULL)
+          {
+            pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len);
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+            err++;
+          }
+          break;
+
+        default:
+#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
+          pbuf = NULL;
+
+          for (uint32_t idx = 0U; (idx < pdev->NumClasses); idx++)
+          {
+            if (pdev->pClass[idx]->GetUsrStrDescriptor != NULL)
+            {
+              pdev->classId = idx;
+              pbuf = pdev->pClass[idx]->GetUsrStrDescriptor(pdev, LOBYTE(req->wValue), &len);
+
+              if (pbuf == NULL) /* This means that no class recognized the string index */
+              {
+                continue;
+              }
+              else
+              {
+                break;
+              }
+            }
+          }
+#endif /* USBD_SUPPORT_USER_STRING_DESC  */
+
+#if (USBD_CLASS_USER_STRING_DESC == 1U)
+          if (pdev->pDesc->GetUserStrDescriptor != NULL)
+          {
+            pbuf = pdev->pDesc->GetUserStrDescriptor(pdev->dev_speed, LOBYTE(req->wValue), &len);
+          }
+          else
+          {
+            USBD_CtlError(pdev, req);
+            err++;
+          }
+#endif /* USBD_SUPPORT_USER_STRING_DESC  */
+
+#if ((USBD_CLASS_USER_STRING_DESC == 0U) && (USBD_SUPPORT_USER_STRING_DESC == 0U))
+          USBD_CtlError(pdev, req);
+          err++;
+#endif /* (USBD_CLASS_USER_STRING_DESC == 0U) && (USBD_SUPPORT_USER_STRING_DESC == 0U) */
+          break;
+      }
+      break;
+
+    case USB_DESC_TYPE_DEVICE_QUALIFIER:
+      if (pdev->dev_speed == USBD_SPEED_HIGH)
+      {
+#ifdef USE_USBD_COMPOSITE
+        if ((uint8_t)(pdev->NumClasses) > 0U)
+        {
+          pbuf = (uint8_t *)USBD_CMPSIT.GetDeviceQualifierDescriptor(&len);
+        }
+        else
+#endif /* USE_USBD_COMPOSITE */
+        {
+          pbuf = (uint8_t *)pdev->pClass[0]->GetDeviceQualifierDescriptor(&len);
+        }
+      }
+      else
+      {
+        USBD_CtlError(pdev, req);
+        err++;
+      }
+      break;
+
+    case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
+      if (pdev->dev_speed == USBD_SPEED_HIGH)
+      {
+#ifdef USE_USBD_COMPOSITE
+        if ((uint8_t)(pdev->NumClasses) > 0U)
+        {
+          pbuf = (uint8_t *)USBD_CMPSIT.GetOtherSpeedConfigDescriptor(&len);
+        }
+        else
+#endif /* USE_USBD_COMPOSITE */
+        {
+          pbuf = (uint8_t *)pdev->pClass[0]->GetOtherSpeedConfigDescriptor(&len);
+        }
+        pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION;
+      }
+      else
+      {
+        USBD_CtlError(pdev, req);
+        err++;
+      }
+      break;
+
+    default:
+      USBD_CtlError(pdev, req);
+      err++;
+      break;
+  }
+
+  if (err != 0U)
+  {
+    return;
+  }
+
+  if (req->wLength != 0U)
+  {
+    if (len != 0U)
+    {
+      len = MIN(len, req->wLength);
+      (void)USBD_CtlSendData(pdev, pbuf, len);
+    }
+    else
+    {
+      USBD_CtlError(pdev, req);
+    }
+  }
+  else
+  {
+    (void)USBD_CtlSendStatus(pdev);
+  }
+}
+
+
+/**
+  * @brief  USBD_SetAddress
+  *         Set device address
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval status
+  */
+static void USBD_SetAddress(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  uint8_t  dev_addr;
+
+  if ((req->wIndex == 0U) && (req->wLength == 0U) && (req->wValue < 128U))
+  {
+    dev_addr = (uint8_t)(req->wValue) & 0x7FU;
+
+    if (pdev->dev_state == USBD_STATE_CONFIGURED)
+    {
+      USBD_CtlError(pdev, req);
+    }
+    else
+    {
+      pdev->dev_address = dev_addr;
+      (void)USBD_LL_SetUSBAddress(pdev, dev_addr);
+      (void)USBD_CtlSendStatus(pdev);
+
+      if (dev_addr != 0U)
+      {
+        pdev->dev_state = USBD_STATE_ADDRESSED;
+      }
+      else
+      {
+        pdev->dev_state = USBD_STATE_DEFAULT;
+      }
+    }
+  }
+  else
+  {
+    USBD_CtlError(pdev, req);
+  }
+}
+
+/**
+  * @brief  USBD_SetConfig
+  *         Handle Set device configuration request
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval status
+  */
+static USBD_StatusTypeDef USBD_SetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  USBD_StatusTypeDef ret = USBD_OK;
+  static uint8_t cfgidx;
+
+  cfgidx = (uint8_t)(req->wValue);
+
+  if (cfgidx > USBD_MAX_NUM_CONFIGURATION)
+  {
+    USBD_CtlError(pdev, req);
+    return USBD_FAIL;
+  }
+
+  switch (pdev->dev_state)
+  {
+    case USBD_STATE_ADDRESSED:
+      if (cfgidx != 0U)
+      {
+        pdev->dev_config = cfgidx;
+
+        ret = USBD_SetClassConfig(pdev, cfgidx);
+
+        if (ret != USBD_OK)
+        {
+          USBD_CtlError(pdev, req);
+          pdev->dev_state = USBD_STATE_ADDRESSED;
+        }
+        else
+        {
+          (void)USBD_CtlSendStatus(pdev);
+          pdev->dev_state = USBD_STATE_CONFIGURED;
+
+#if (USBD_USER_REGISTER_CALLBACK == 1U)
+          if (pdev->DevStateCallback != NULL)
+          {
+            pdev->DevStateCallback(USBD_STATE_CONFIGURED, cfgidx);
+          }
+#endif /* USBD_USER_REGISTER_CALLBACK */
+        }
+      }
+      else
+      {
+        (void)USBD_CtlSendStatus(pdev);
+      }
+      break;
+
+    case USBD_STATE_CONFIGURED:
+      if (cfgidx == 0U)
+      {
+        pdev->dev_state = USBD_STATE_ADDRESSED;
+        pdev->dev_config = cfgidx;
+        (void)USBD_ClrClassConfig(pdev, cfgidx);
+        (void)USBD_CtlSendStatus(pdev);
+      }
+      else if (cfgidx != pdev->dev_config)
+      {
+        /* Clear old configuration */
+        (void)USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config);
+
+        /* set new configuration */
+        pdev->dev_config = cfgidx;
+
+        ret = USBD_SetClassConfig(pdev, cfgidx);
+
+        if (ret != USBD_OK)
+        {
+          USBD_CtlError(pdev, req);
+          (void)USBD_ClrClassConfig(pdev, (uint8_t)pdev->dev_config);
+          pdev->dev_state = USBD_STATE_ADDRESSED;
+        }
+        else
+        {
+          (void)USBD_CtlSendStatus(pdev);
+        }
+      }
+      else
+      {
+        (void)USBD_CtlSendStatus(pdev);
+      }
+      break;
+
+    default:
+      USBD_CtlError(pdev, req);
+      (void)USBD_ClrClassConfig(pdev, cfgidx);
+      ret = USBD_FAIL;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  USBD_GetConfig
+  *         Handle Get device configuration request
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval status
+  */
+static void USBD_GetConfig(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  if (req->wLength != 1U)
+  {
+    USBD_CtlError(pdev, req);
+  }
+  else
+  {
+    switch (pdev->dev_state)
+    {
+      case USBD_STATE_DEFAULT:
+      case USBD_STATE_ADDRESSED:
+        pdev->dev_default_config = 0U;
+        (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_default_config, 1U);
+        break;
+
+      case USBD_STATE_CONFIGURED:
+        (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_config, 1U);
+        break;
+
+      default:
+        USBD_CtlError(pdev, req);
+        break;
+    }
+  }
+}
+
+/**
+  * @brief  USBD_GetStatus
+  *         Handle Get Status request
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval status
+  */
+static void USBD_GetStatus(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  switch (pdev->dev_state)
+  {
+    case USBD_STATE_DEFAULT:
+    case USBD_STATE_ADDRESSED:
+    case USBD_STATE_CONFIGURED:
+      if (req->wLength != 0x2U)
+      {
+        USBD_CtlError(pdev, req);
+        break;
+      }
+
+#if (USBD_SELF_POWERED == 1U)
+      pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
+#else
+      pdev->dev_config_status = 0U;
+#endif /* USBD_SELF_POWERED */
+
+      if (pdev->dev_remote_wakeup != 0U)
+      {
+        pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
+      }
+
+      (void)USBD_CtlSendData(pdev, (uint8_t *)&pdev->dev_config_status, 2U);
+      break;
+
+    default:
+      USBD_CtlError(pdev, req);
+      break;
+  }
+}
+
+
+/**
+  * @brief  USBD_SetFeature
+  *         Handle Set device feature request
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval status
+  */
+static void USBD_SetFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
+  {
+    pdev->dev_remote_wakeup = 1U;
+    (void)USBD_CtlSendStatus(pdev);
+  }
+  else if (req->wValue == USB_FEATURE_TEST_MODE)
+  {
+    pdev->dev_test_mode = (uint8_t)(req->wIndex >> 8);
+    (void)USBD_CtlSendStatus(pdev);
+  }
+  else
+  {
+    USBD_CtlError(pdev, req);
+  }
+}
+
+
+/**
+  * @brief  USBD_ClrFeature
+  *         Handle clear device feature request
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval status
+  */
+static void USBD_ClrFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  switch (pdev->dev_state)
+  {
+    case USBD_STATE_DEFAULT:
+    case USBD_STATE_ADDRESSED:
+    case USBD_STATE_CONFIGURED:
+      if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
+      {
+        pdev->dev_remote_wakeup = 0U;
+        (void)USBD_CtlSendStatus(pdev);
+      }
+      break;
+
+    default:
+      USBD_CtlError(pdev, req);
+      break;
+  }
+}
+
+
+/**
+  * @brief  USBD_ParseSetupRequest
+  *         Copy buffer into setup structure
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval None
+  */
+void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata)
+{
+  uint8_t *pbuff = pdata;
+
+  req->bmRequest = *(uint8_t *)(pbuff);
+
+  pbuff++;
+  req->bRequest = *(uint8_t *)(pbuff);
+
+  pbuff++;
+  req->wValue = SWAPBYTE(pbuff);
+
+  pbuff++;
+  pbuff++;
+  req->wIndex = SWAPBYTE(pbuff);
+
+  pbuff++;
+  pbuff++;
+  req->wLength = SWAPBYTE(pbuff);
+}
+
+
+/**
+  * @brief  USBD_CtlError
+  *         Handle USB low level Error
+  * @param  pdev: device instance
+  * @param  req: usb request
+  * @retval None
+  */
+void USBD_CtlError(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+  UNUSED(req);
+
+  (void)USBD_LL_StallEP(pdev, 0x80U);
+  (void)USBD_LL_StallEP(pdev, 0U);
+}
+
+
+/**
+  * @brief  USBD_GetString
+  *         Convert Ascii string into unicode one
+  * @param  desc : descriptor buffer
+  * @param  unicode : Formatted string buffer (unicode)
+  * @param  len : descriptor length
+  * @retval None
+  */
+void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len)
+{
+  uint8_t idx = 0U;
+  uint8_t *pdesc;
+
+  if (desc == NULL)
+  {
+    return;
+  }
+
+  pdesc = desc;
+  *len = ((uint16_t)USBD_GetLen(pdesc) * 2U) + 2U;
+
+  unicode[idx] = *(uint8_t *)len;
+  idx++;
+  unicode[idx] = USB_DESC_TYPE_STRING;
+  idx++;
+
+  while (*pdesc != (uint8_t)'\0')
+  {
+    unicode[idx] = *pdesc;
+    pdesc++;
+    idx++;
+
+    unicode[idx] = 0U;
+    idx++;
+  }
+}
+
+
+/**
+  * @brief  USBD_GetLen
+  *         return the string length
+   * @param  buf : pointer to the ascii string buffer
+  * @retval string length
+  */
+static uint8_t USBD_GetLen(uint8_t *buf)
+{
+  uint8_t  len = 0U;
+  uint8_t *pbuff = buf;
+
+  while (*pbuff != (uint8_t)'\0')
+  {
+    len++;
+    pbuff++;
+  }
+
+  return len;
+}
+/**
+  * @}
+  */
+
+
+/**
+  * @}
+  */
+
+
+/**
+  * @}
+  */
+

+ 224 - 0
Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c

@@ -0,0 +1,224 @@
+/**
+  ******************************************************************************
+  * @file    usbd_ioreq.c
+  * @author  MCD Application Team
+  * @brief   This file provides the IO requests APIs for control endpoints.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2015 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_ioreq.h"
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+  * @{
+  */
+
+
+/** @defgroup USBD_IOREQ
+  * @brief control I/O requests module
+  * @{
+  */
+
+/** @defgroup USBD_IOREQ_Private_TypesDefinitions
+  * @{
+  */
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_IOREQ_Private_Defines
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_IOREQ_Private_Macros
+  * @{
+  */
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_IOREQ_Private_Variables
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_IOREQ_Private_FunctionPrototypes
+  * @{
+  */
+/**
+  * @}
+  */
+
+
+/** @defgroup USBD_IOREQ_Private_Functions
+  * @{
+  */
+
+/**
+  * @brief  USBD_CtlSendData
+  *         send data on the ctl pipe
+  * @param  pdev: device instance
+  * @param  buff: pointer to data buffer
+  * @param  len: length of data to be sent
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev,
+                                    uint8_t *pbuf, uint32_t len)
+{
+  /* Set EP0 State */
+  pdev->ep0_state = USBD_EP0_DATA_IN;
+  pdev->ep_in[0].total_length = len;
+
+#ifdef USBD_AVOID_PACKET_SPLIT_MPS
+  pdev->ep_in[0].rem_length = 0U;
+#else
+  pdev->ep_in[0].rem_length = len;
+#endif /* USBD_AVOID_PACKET_SPLIT_MPS */
+
+  /* Start the transfer */
+  (void)USBD_LL_Transmit(pdev, 0x00U, pbuf, len);
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_CtlContinueSendData
+  *         continue sending data on the ctl pipe
+  * @param  pdev: device instance
+  * @param  buff: pointer to data buffer
+  * @param  len: length of data to be sent
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev,
+                                            uint8_t *pbuf, uint32_t len)
+{
+  /* Start the next transfer */
+  (void)USBD_LL_Transmit(pdev, 0x00U, pbuf, len);
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_CtlPrepareRx
+  *         receive data on the ctl pipe
+  * @param  pdev: device instance
+  * @param  buff: pointer to data buffer
+  * @param  len: length of data to be received
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev,
+                                     uint8_t *pbuf, uint32_t len)
+{
+  /* Set EP0 State */
+  pdev->ep0_state = USBD_EP0_DATA_OUT;
+  pdev->ep_out[0].total_length = len;
+
+#ifdef USBD_AVOID_PACKET_SPLIT_MPS
+  pdev->ep_out[0].rem_length = 0U;
+#else
+  pdev->ep_out[0].rem_length = len;
+#endif /* USBD_AVOID_PACKET_SPLIT_MPS */
+
+  /* Start the transfer */
+  (void)USBD_LL_PrepareReceive(pdev, 0U, pbuf, len);
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_CtlContinueRx
+  *         continue receive data on the ctl pipe
+  * @param  pdev: device instance
+  * @param  buff: pointer to data buffer
+  * @param  len: length of data to be received
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev,
+                                      uint8_t *pbuf, uint32_t len)
+{
+  (void)USBD_LL_PrepareReceive(pdev, 0U, pbuf, len);
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_CtlSendStatus
+  *         send zero lzngth packet on the ctl pipe
+  * @param  pdev: device instance
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev)
+{
+  /* Set EP0 State */
+  pdev->ep0_state = USBD_EP0_STATUS_IN;
+
+  /* Start the transfer */
+  (void)USBD_LL_Transmit(pdev, 0x00U, NULL, 0U);
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_CtlReceiveStatus
+  *         receive zero lzngth packet on the ctl pipe
+  * @param  pdev: device instance
+  * @retval status
+  */
+USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev)
+{
+  /* Set EP0 State */
+  pdev->ep0_state = USBD_EP0_STATUS_OUT;
+
+  /* Start the transfer */
+  (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
+
+  return USBD_OK;
+}
+
+/**
+  * @brief  USBD_GetRxCount
+  *         returns the received data length
+  * @param  pdev: device instance
+  * @param  ep_addr: endpoint address
+  * @retval Rx Data blength
+  */
+uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+  return USBD_LL_GetRxDataSize(pdev, ep_addr);
+}
+
+/**
+  * @}
+  */
+
+
+/**
+  * @}
+  */
+
+
+/**
+  * @}
+  */
+

+ 86 - 0
Middlewares/ST/STM32_USB_Device_Library/LICENSE.txt

@@ -0,0 +1,86 @@
+This software component is provided to you as part of a software package and
+applicable license terms are in the Package_license file. If you received this
+software component outside of a package or without applicable license terms,
+the terms of the SLA0044 license shall apply and are fully reproduced below:
+
+SLA0044 Rev5/February 2018
+
+Software license agreement
+
+ULTIMATE LIBERTY SOFTWARE LICENSE AGREEMENT
+
+BY INSTALLING, COPYING, DOWNLOADING, ACCESSING OR OTHERWISE USING THIS SOFTWARE
+OR ANY PART THEREOF (AND THE RELATED DOCUMENTATION) FROM STMICROELECTRONICS
+INTERNATIONAL N.V, SWISS BRANCH AND/OR ITS AFFILIATED COMPANIES
+(STMICROELECTRONICS), THE RECIPIENT, ON BEHALF OF HIMSELF OR HERSELF, OR ON
+BEHALF OF ANY ENTITY BY WHICH SUCH RECIPIENT IS EMPLOYED AND/OR ENGAGED AGREES
+TO BE BOUND BY THIS SOFTWARE LICENSE AGREEMENT.
+
+Under STMicroelectronics’ intellectual property rights, the redistribution,
+reproduction and use in source and binary forms of the software or any part
+thereof, with or without modification, are permitted provided that the following
+conditions are met:
+
+1. Redistribution of source code (modified or not) must retain any copyright
+notice, this list of conditions and the disclaimer set forth below as items 10
+and 11.
+
+2. Redistributions in binary form, except as embedded into microcontroller or
+microprocessor device manufactured by or for STMicroelectronics or a software
+update for such device, must reproduce any copyright notice provided with the
+binary code, this list of conditions, and the disclaimer set forth below as
+items 10 and 11, in documentation and/or other materials provided with the
+distribution.
+
+3. Neither the name of STMicroelectronics nor the names of other contributors to
+this software may be used to endorse or promote products derived from this
+software or part thereof without specific written permission.
+
+4. This software or any part thereof, including modifications and/or derivative
+works of this software, must be used and execute solely and exclusively on or in
+combination with a microcontroller or microprocessor device manufactured by or
+for STMicroelectronics.
+
+5. No use, reproduction or redistribution of this software partially or totally
+may be done in any manner that would subject this software to any Open Source
+Terms. “Open Source Terms” shall mean any open source license which requires as
+part of distribution of software that the source code of such software is
+distributed therewith or otherwise made available, or open source license that
+substantially complies with the Open Source definition specified at
+www.opensource.org and any other comparable open source license such as for
+example GNU General Public License (GPL), Eclipse Public License (EPL), Apache
+Software License, BSD license or MIT license.
+
+6. STMicroelectronics has no obligation to provide any maintenance, support or
+updates for the software.
+
+7. The software is and will remain the exclusive property of STMicroelectronics
+and its licensors. The recipient will not take any action that jeopardizes
+STMicroelectronics and its licensors' proprietary rights or acquire any rights
+in the software, except the limited rights specified hereunder.
+
+8. The recipient shall comply with all applicable laws and regulations affecting
+the use of the software or any part thereof including any applicable export
+control law or regulation.
+
+9. Redistribution and use of this software or any part thereof other than as
+permitted under this license is void and will automatically terminate your
+rights under this license.
+
+10. THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY RIGHTS, WHICH ARE
+DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT SHALL
+STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+11. EXCEPT AS EXPRESSLY PERMITTED HEREUNDER, NO LICENSE OR OTHER RIGHTS, WHETHER
+EXPRESS OR IMPLIED, ARE GRANTED UNDER ANY PATENT OR OTHER INTELLECTUAL PROPERTY
+RIGHTS OF STMICROELECTRONICS OR ANY THIRD PARTY.
+

+ 100 - 0
USB_DEVICE/App/usb_device.c

@@ -0,0 +1,100 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file           : usb_device.c
+  * @version        : v1.0_Cube
+  * @brief          : This file implements the USB Device
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "usb_device.h"
+#include "usbd_core.h"
+#include "usbd_desc.h"
+#include "usbd_audio.h"
+#include "usbd_audio_if.h"
+
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+/* USER CODE BEGIN PV */
+/* Private variables ---------------------------------------------------------*/
+
+/* USER CODE END PV */
+
+/* USER CODE BEGIN PFP */
+/* Private function prototypes -----------------------------------------------*/
+
+/* USER CODE END PFP */
+
+/* USB Device Core handle declaration. */
+USBD_HandleTypeDef hUsbDeviceFS;
+
+/*
+ * -- Insert your variables declaration here --
+ */
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/*
+ * -- Insert your external function declaration here --
+ */
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
+
+/**
+  * Init USB device Library, add supported class and start the library
+  * @retval None
+  */
+void MX_USB_DEVICE_Init(void)
+{
+  /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
+
+  /* USER CODE END USB_DEVICE_Init_PreTreatment */
+
+  /* Init Device Library, add supported class and start the library. */
+  if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
+  {
+    Error_Handler();
+  }
+  if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_AUDIO) != USBD_OK)
+  {
+    Error_Handler();
+  }
+  if (USBD_AUDIO_RegisterInterface(&hUsbDeviceFS, &USBD_AUDIO_fops_FS) != USBD_OK)
+  {
+    Error_Handler();
+  }
+  if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
+  {
+    Error_Handler();
+  }
+
+  /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */
+
+  /* USER CODE END USB_DEVICE_Init_PostTreatment */
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 102 - 0
USB_DEVICE/App/usb_device.h

@@ -0,0 +1,102 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file           : usb_device.h
+  * @version        : v1.0_Cube
+  * @brief          : Header for usb_device.c file.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_DEVICE__H__
+#define __USB_DEVICE__H__
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx.h"
+#include "stm32f4xx_hal.h"
+#include "usbd_def.h"
+
+/* USER CODE BEGIN INCLUDE */
+
+/* USER CODE END INCLUDE */
+
+/** @addtogroup USBD_OTG_DRIVER
+  * @{
+  */
+
+/** @defgroup USBD_DEVICE USBD_DEVICE
+  * @brief Device file for Usb otg low level driver.
+  * @{
+  */
+
+/** @defgroup USBD_DEVICE_Exported_Variables USBD_DEVICE_Exported_Variables
+  * @brief Public variables.
+  * @{
+  */
+
+/* Private variables ---------------------------------------------------------*/
+/* USER CODE BEGIN PV */
+
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+/* USER CODE BEGIN PFP */
+
+/* USER CODE END PFP */
+
+/*
+ * -- Insert your variables declaration here --
+ */
+/* USER CODE BEGIN VARIABLES */
+
+/* USER CODE END VARIABLES */
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DEVICE_Exported_FunctionsPrototype USBD_DEVICE_Exported_FunctionsPrototype
+  * @brief Declaration of public functions for Usb device.
+  * @{
+  */
+
+/** USB Device initialization function. */
+void MX_USB_DEVICE_Init(void);
+
+/*
+ * -- Insert functions declaration here --
+ */
+/* USER CODE BEGIN FD */
+
+/* USER CODE END FD */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USB_DEVICE__H__ */

+ 285 - 0
USB_DEVICE/App/usbd_audio_if.c

@@ -0,0 +1,285 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file           : usbd_audio_if.c
+  * @version        : v1.0_Cube
+  * @brief          : Generic media access layer.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+ /* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_audio_if.h"
+
+/* USER CODE BEGIN INCLUDE */
+
+/* USER CODE END INCLUDE */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+
+/* USER CODE BEGIN PV */
+/* Private variables ---------------------------------------------------------*/
+
+/* USER CODE END PV */
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+  * @brief Usb device library.
+  * @{
+  */
+
+/** @addtogroup USBD_AUDIO_IF
+  * @{
+  */
+
+/** @defgroup USBD_AUDIO_IF_Private_TypesDefinitions USBD_AUDIO_IF_Private_TypesDefinitions
+  * @brief Private types.
+  * @{
+  */
+
+/* USER CODE BEGIN PRIVATE_TYPES */
+
+/* USER CODE END PRIVATE_TYPES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_IF_Private_Defines USBD_AUDIO_IF_Private_Defines
+  * @brief Private defines.
+  * @{
+  */
+
+/* USER CODE BEGIN PRIVATE_DEFINES */
+
+/* USER CODE END PRIVATE_DEFINES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_IF_Private_Macros USBD_AUDIO_IF_Private_Macros
+  * @brief Private macros.
+  * @{
+  */
+
+/* USER CODE BEGIN PRIVATE_MACRO */
+
+/* USER CODE END PRIVATE_MACRO */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_IF_Private_Variables USBD_AUDIO_IF_Private_Variables
+  * @brief Private variables.
+  * @{
+  */
+
+/* USER CODE BEGIN PRIVATE_VARIABLES */
+
+/* USER CODE END PRIVATE_VARIABLES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_IF_Exported_Variables USBD_AUDIO_IF_Exported_Variables
+  * @brief Public variables.
+  * @{
+  */
+
+extern USBD_HandleTypeDef hUsbDeviceFS;
+
+/* USER CODE BEGIN EXPORTED_VARIABLES */
+
+/* USER CODE END EXPORTED_VARIABLES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_IF_Private_FunctionPrototypes USBD_AUDIO_IF_Private_FunctionPrototypes
+  * @brief Private functions declaration.
+  * @{
+  */
+
+static int8_t AUDIO_Init_FS(uint32_t AudioFreq, uint32_t Volume, uint32_t options);
+static int8_t AUDIO_DeInit_FS(uint32_t options);
+static int8_t AUDIO_AudioCmd_FS(uint8_t* pbuf, uint32_t size, uint8_t cmd);
+static int8_t AUDIO_VolumeCtl_FS(uint8_t vol);
+static int8_t AUDIO_MuteCtl_FS(uint8_t cmd);
+static int8_t AUDIO_PeriodicTC_FS(uint8_t *pbuf, uint32_t size, uint8_t cmd);
+static int8_t AUDIO_GetState_FS(void);
+
+/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
+
+/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
+
+/**
+  * @}
+  */
+
+USBD_AUDIO_ItfTypeDef USBD_AUDIO_fops_FS =
+{
+  AUDIO_Init_FS,
+  AUDIO_DeInit_FS,
+  AUDIO_AudioCmd_FS,
+  AUDIO_VolumeCtl_FS,
+  AUDIO_MuteCtl_FS,
+  AUDIO_PeriodicTC_FS,
+  AUDIO_GetState_FS,
+};
+
+/* Private functions ---------------------------------------------------------*/
+/**
+  * @brief  Initializes the AUDIO media low layer over USB FS IP
+  * @param  AudioFreq: Audio frequency used to play the audio stream.
+  * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
+  * @param  options: Reserved for future use
+  * @retval USBD_OK if all operations are OK else USBD_FAIL
+  */
+static int8_t AUDIO_Init_FS(uint32_t AudioFreq, uint32_t Volume, uint32_t options)
+{
+  /* USER CODE BEGIN 0 */
+  UNUSED(AudioFreq);
+  UNUSED(Volume);
+  UNUSED(options);
+  return (USBD_OK);
+  /* USER CODE END 0 */
+}
+
+/**
+  * @brief  De-Initializes the AUDIO media low layer
+  * @param  options: Reserved for future use
+  * @retval USBD_OK if all operations are OK else USBD_FAIL
+  */
+static int8_t AUDIO_DeInit_FS(uint32_t options)
+{
+  /* USER CODE BEGIN 1 */
+  UNUSED(options);
+  return (USBD_OK);
+  /* USER CODE END 1 */
+}
+
+/**
+  * @brief  Handles AUDIO command.
+  * @param  pbuf: Pointer to buffer of data to be sent
+  * @param  size: Number of data to be sent (in bytes)
+  * @param  cmd: Command opcode
+  * @retval USBD_OK if all operations are OK else USBD_FAIL
+  */
+static int8_t AUDIO_AudioCmd_FS(uint8_t* pbuf, uint32_t size, uint8_t cmd)
+{
+  /* USER CODE BEGIN 2 */
+  switch(cmd)
+  {
+    case AUDIO_CMD_START:
+    break;
+
+    case AUDIO_CMD_PLAY:
+    break;
+  }
+  UNUSED(pbuf);
+  UNUSED(size);
+  UNUSED(cmd);
+  return (USBD_OK);
+  /* USER CODE END 2 */
+}
+
+/**
+  * @brief  Controls AUDIO Volume.
+  * @param  vol: volume level (0..100)
+  * @retval USBD_OK if all operations are OK else USBD_FAIL
+  */
+static int8_t AUDIO_VolumeCtl_FS(uint8_t vol)
+{
+  /* USER CODE BEGIN 3 */
+  UNUSED(vol);
+  return (USBD_OK);
+  /* USER CODE END 3 */
+}
+
+/**
+  * @brief  Controls AUDIO Mute.
+  * @param  cmd: command opcode
+  * @retval USBD_OK if all operations are OK else USBD_FAIL
+  */
+static int8_t AUDIO_MuteCtl_FS(uint8_t cmd)
+{
+  /* USER CODE BEGIN 4 */
+  UNUSED(cmd);
+  return (USBD_OK);
+  /* USER CODE END 4 */
+}
+
+/**
+  * @brief  AUDIO_PeriodicT_FS
+  * @param  cmd: Command opcode
+  * @retval USBD_OK if all operations are OK else USBD_FAIL
+  */
+static int8_t AUDIO_PeriodicTC_FS(uint8_t *pbuf, uint32_t size, uint8_t cmd)
+{
+  /* USER CODE BEGIN 5 */
+  UNUSED(pbuf);
+  UNUSED(size);
+  UNUSED(cmd);
+  return (USBD_OK);
+  /* USER CODE END 5 */
+}
+
+/**
+  * @brief  Gets AUDIO State.
+  * @retval USBD_OK if all operations are OK else USBD_FAIL
+  */
+static int8_t AUDIO_GetState_FS(void)
+{
+  /* USER CODE BEGIN 6 */
+  return (USBD_OK);
+  /* USER CODE END 6 */
+}
+
+/**
+  * @brief  Manages the DMA full transfer complete event.
+  * @retval None
+  */
+void TransferComplete_CallBack_FS(void)
+{
+  /* USER CODE BEGIN 7 */
+  USBD_AUDIO_Sync(&hUsbDeviceFS, AUDIO_OFFSET_FULL);
+  /* USER CODE END 7 */
+}
+
+/**
+  * @brief  Manages the DMA Half transfer complete event.
+  * @retval None
+  */
+void HalfTransfer_CallBack_FS(void)
+{
+  /* USER CODE BEGIN 8 */
+  USBD_AUDIO_Sync(&hUsbDeviceFS, AUDIO_OFFSET_HALF);
+  /* USER CODE END 8 */
+}
+
+/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
+
+/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 137 - 0
USB_DEVICE/App/usbd_audio_if.h

@@ -0,0 +1,137 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file           : usbd_audio_if.h
+  * @version        : v1.0_Cube
+  * @brief          : Header for usbd_audio_if.c file.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_AUDIO_IF_H__
+#define __USBD_AUDIO_IF_H__
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_audio.h"
+
+/* USER CODE BEGIN INCLUDE */
+
+/* USER CODE END INCLUDE */
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+  * @brief For Usb device.
+  * @{
+  */
+
+/** @defgroup USBD_AUDIO_IF USBD_AUDIO_IF
+  * @brief Usb audio interface device module.
+  * @{
+  */
+
+/** @defgroup USBD_AUDIO_IF_Exported_Defines USBD_AUDIO_IF_Exported_Defines
+  * @brief Defines.
+  * @{
+  */
+
+/* USER CODE BEGIN EXPORTED_DEFINES */
+
+/* USER CODE END EXPORTED_DEFINES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_IF_Exported_Types USBD_AUDIO_IF_Exported_Types
+  * @brief Types.
+  * @{
+  */
+
+/* USER CODE BEGIN EXPORTED_TYPES */
+
+/* USER CODE END EXPORTED_TYPES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_IF_Exported_Macros USBD_AUDIO_IF_Exported_Macros
+  * @brief Aliases.
+  * @{
+  */
+
+/* USER CODE BEGIN EXPORTED_MACRO */
+
+/* USER CODE END EXPORTED_MACRO */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_IF_Exported_Variables USBD_AUDIO_IF_Exported_Variables
+  * @brief Public variables.
+  * @{
+  */
+
+/** AUDIO_IF Interface callback. */
+extern USBD_AUDIO_ItfTypeDef USBD_AUDIO_fops_FS;
+
+/* USER CODE BEGIN EXPORTED_VARIABLES */
+
+/* USER CODE END EXPORTED_VARIABLES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_AUDIO_IF_Exported_FunctionsPrototype USBD_AUDIO_IF_Exported_FunctionsPrototype
+  * @brief Public functions declaration.
+  * @{
+  */
+
+/**
+  * @brief  Manages the DMA full transfer complete event.
+  * @retval None
+  */
+void TransferComplete_CallBack_FS(void);
+
+/**
+  * @brief  Manages the DMA half transfer complete event.
+  * @retval None
+  */
+void HalfTransfer_CallBack_FS(void);
+
+/* USER CODE BEGIN EXPORTED_FUNCTIONS */
+
+/* USER CODE END EXPORTED_FUNCTIONS */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_AUDIO_IF_H__ */

+ 445 - 0
USB_DEVICE/App/usbd_desc.c

@@ -0,0 +1,445 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file           : App/usbd_desc.c
+  * @version        : v1.0_Cube
+  * @brief          : This file implements the USB device descriptors.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_core.h"
+#include "usbd_desc.h"
+#include "usbd_conf.h"
+
+/* USER CODE BEGIN INCLUDE */
+
+/* USER CODE END INCLUDE */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+
+/* USER CODE BEGIN PV */
+/* Private variables ---------------------------------------------------------*/
+
+/* USER CODE END PV */
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+  * @{
+  */
+
+/** @addtogroup USBD_DESC
+  * @{
+  */
+
+/** @defgroup USBD_DESC_Private_TypesDefinitions USBD_DESC_Private_TypesDefinitions
+  * @brief Private types.
+  * @{
+  */
+
+/* USER CODE BEGIN PRIVATE_TYPES */
+
+/* USER CODE END PRIVATE_TYPES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
+  * @brief Private defines.
+  * @{
+  */
+
+#define USBD_VID     1155
+#define USBD_LANGID_STRING     1033
+#define USBD_MANUFACTURER_STRING     "STMicroelectronics"
+#define USBD_PID_FS     22336
+#define USBD_PRODUCT_STRING_FS     "STM32 Audio Class"
+#define USBD_CONFIGURATION_STRING_FS     "AUDIO Config"
+#define USBD_INTERFACE_STRING_FS     "AUDIO Interface"
+
+#define USB_SIZ_BOS_DESC            0x0C
+
+/* USER CODE BEGIN PRIVATE_DEFINES */
+
+/* USER CODE END PRIVATE_DEFINES */
+
+/**
+  * @}
+  */
+
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/** @defgroup USBD_DESC_Private_Macros USBD_DESC_Private_Macros
+  * @brief Private macros.
+  * @{
+  */
+
+/* USER CODE BEGIN PRIVATE_MACRO */
+
+/* USER CODE END PRIVATE_MACRO */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Private_FunctionPrototypes USBD_DESC_Private_FunctionPrototypes
+  * @brief Private functions declaration.
+  * @{
+  */
+
+static void Get_SerialNum(void);
+static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len);
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Private_FunctionPrototypes USBD_DESC_Private_FunctionPrototypes
+  * @brief Private functions declaration for FS.
+  * @{
+  */
+
+uint8_t * USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t * USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t * USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t * USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+#if (USBD_LPM_ENABLED == 1)
+uint8_t * USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+#endif /* (USBD_LPM_ENABLED == 1) */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
+  * @brief Private variables.
+  * @{
+  */
+
+USBD_DescriptorsTypeDef FS_Desc =
+{
+  USBD_FS_DeviceDescriptor
+, USBD_FS_LangIDStrDescriptor
+, USBD_FS_ManufacturerStrDescriptor
+, USBD_FS_ProductStrDescriptor
+, USBD_FS_SerialStrDescriptor
+, USBD_FS_ConfigStrDescriptor
+, USBD_FS_InterfaceStrDescriptor
+#if (USBD_LPM_ENABLED == 1)
+, USBD_FS_USR_BOSDescriptor
+#endif /* (USBD_LPM_ENABLED == 1) */
+};
+
+#if defined ( __ICCARM__ ) /* IAR Compiler */
+  #pragma data_alignment=4
+#endif /* defined ( __ICCARM__ ) */
+/** USB standard device descriptor. */
+__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
+{
+  0x12,                       /*bLength */
+  USB_DESC_TYPE_DEVICE,       /*bDescriptorType*/
+#if (USBD_LPM_ENABLED == 1)
+  0x01,                       /*bcdUSB */ /* changed to USB version 2.01
+                                             in order to support LPM L1 suspend
+                                             resume test of USBCV3.0*/
+#else
+  0x00,                       /*bcdUSB */
+#endif /* (USBD_LPM_ENABLED == 1) */
+  0x02,
+  0x00,                       /*bDeviceClass*/
+  0x00,                       /*bDeviceSubClass*/
+  0x00,                       /*bDeviceProtocol*/
+  USB_MAX_EP0_SIZE,           /*bMaxPacketSize*/
+  LOBYTE(USBD_VID),           /*idVendor*/
+  HIBYTE(USBD_VID),           /*idVendor*/
+  LOBYTE(USBD_PID_FS),        /*idProduct*/
+  HIBYTE(USBD_PID_FS),        /*idProduct*/
+  0x00,                       /*bcdDevice rel. 2.00*/
+  0x02,
+  USBD_IDX_MFC_STR,           /*Index of manufacturer  string*/
+  USBD_IDX_PRODUCT_STR,       /*Index of product string*/
+  USBD_IDX_SERIAL_STR,        /*Index of serial number string*/
+  USBD_MAX_NUM_CONFIGURATION  /*bNumConfigurations*/
+};
+
+/* USB_DeviceDescriptor */
+/** BOS descriptor. */
+#if (USBD_LPM_ENABLED == 1)
+#if defined ( __ICCARM__ ) /* IAR Compiler */
+  #pragma data_alignment=4
+#endif /* defined ( __ICCARM__ ) */
+__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END =
+{
+  0x5,
+  USB_DESC_TYPE_BOS,
+  0xC,
+  0x0,
+  0x1,  /* 1 device capability*/
+        /* device capability*/
+  0x7,
+  USB_DEVICE_CAPABITY_TYPE,
+  0x2,
+  0x2,  /* LPM capability bit set*/
+  0x0,
+  0x0,
+  0x0
+};
+#endif /* (USBD_LPM_ENABLED == 1) */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
+  * @brief Private variables.
+  * @{
+  */
+
+#if defined ( __ICCARM__ ) /* IAR Compiler */
+  #pragma data_alignment=4
+#endif /* defined ( __ICCARM__ ) */
+
+/** USB lang identifier descriptor. */
+__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END =
+{
+     USB_LEN_LANGID_STR_DESC,
+     USB_DESC_TYPE_STRING,
+     LOBYTE(USBD_LANGID_STRING),
+     HIBYTE(USBD_LANGID_STRING)
+};
+
+#if defined ( __ICCARM__ ) /* IAR Compiler */
+  #pragma data_alignment=4
+#endif /* defined ( __ICCARM__ ) */
+/* Internal string descriptor. */
+__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
+
+#if defined ( __ICCARM__ ) /*!< IAR Compiler */
+  #pragma data_alignment=4
+#endif
+__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
+  USB_SIZ_STRING_SERIAL,
+  USB_DESC_TYPE_STRING,
+};
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Private_Functions USBD_DESC_Private_Functions
+  * @brief Private functions.
+  * @{
+  */
+
+/**
+  * @brief  Return the device descriptor
+  * @param  speed : Current device speed
+  * @param  length : Pointer to data length variable
+  * @retval Pointer to descriptor buffer
+  */
+uint8_t * USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+  UNUSED(speed);
+  *length = sizeof(USBD_FS_DeviceDesc);
+  return USBD_FS_DeviceDesc;
+}
+
+/**
+  * @brief  Return the LangID string descriptor
+  * @param  speed : Current device speed
+  * @param  length : Pointer to data length variable
+  * @retval Pointer to descriptor buffer
+  */
+uint8_t * USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+  UNUSED(speed);
+  *length = sizeof(USBD_LangIDDesc);
+  return USBD_LangIDDesc;
+}
+
+/**
+  * @brief  Return the product string descriptor
+  * @param  speed : Current device speed
+  * @param  length : Pointer to data length variable
+  * @retval Pointer to descriptor buffer
+  */
+uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+  if(speed == 0)
+  {
+    USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
+  }
+  else
+  {
+    USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
+  }
+  return USBD_StrDesc;
+}
+
+/**
+  * @brief  Return the manufacturer string descriptor
+  * @param  speed : Current device speed
+  * @param  length : Pointer to data length variable
+  * @retval Pointer to descriptor buffer
+  */
+uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+  UNUSED(speed);
+  USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
+  return USBD_StrDesc;
+}
+
+/**
+  * @brief  Return the serial number string descriptor
+  * @param  speed : Current device speed
+  * @param  length : Pointer to data length variable
+  * @retval Pointer to descriptor buffer
+  */
+uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+  UNUSED(speed);
+  *length = USB_SIZ_STRING_SERIAL;
+
+  /* Update the serial number string descriptor with the data from the unique
+   * ID */
+  Get_SerialNum();
+  /* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
+
+  /* USER CODE END USBD_FS_SerialStrDescriptor */
+  return (uint8_t *) USBD_StringSerial;
+}
+
+/**
+  * @brief  Return the configuration string descriptor
+  * @param  speed : Current device speed
+  * @param  length : Pointer to data length variable
+  * @retval Pointer to descriptor buffer
+  */
+uint8_t * USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+  if(speed == USBD_SPEED_HIGH)
+  {
+    USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
+  }
+  else
+  {
+    USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
+  }
+  return USBD_StrDesc;
+}
+
+/**
+  * @brief  Return the interface string descriptor
+  * @param  speed : Current device speed
+  * @param  length : Pointer to data length variable
+  * @retval Pointer to descriptor buffer
+  */
+uint8_t * USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+  if(speed == 0)
+  {
+    USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length);
+  }
+  else
+  {
+    USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length);
+  }
+  return USBD_StrDesc;
+}
+
+#if (USBD_LPM_ENABLED == 1)
+/**
+  * @brief  Return the BOS descriptor
+  * @param  speed : Current device speed
+  * @param  length : Pointer to data length variable
+  * @retval Pointer to descriptor buffer
+  */
+uint8_t * USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+  UNUSED(speed);
+  *length = sizeof(USBD_FS_BOSDesc);
+  return (uint8_t*)USBD_FS_BOSDesc;
+}
+#endif /* (USBD_LPM_ENABLED == 1) */
+
+/**
+  * @brief  Create the serial number string descriptor
+  * @param  None
+  * @retval None
+  */
+static void Get_SerialNum(void)
+{
+  uint32_t deviceserial0;
+  uint32_t deviceserial1;
+  uint32_t deviceserial2;
+
+  deviceserial0 = *(uint32_t *) DEVICE_ID1;
+  deviceserial1 = *(uint32_t *) DEVICE_ID2;
+  deviceserial2 = *(uint32_t *) DEVICE_ID3;
+
+  deviceserial0 += deviceserial2;
+
+  if (deviceserial0 != 0)
+  {
+    IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8);
+    IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4);
+  }
+}
+
+/**
+  * @brief  Convert Hex 32Bits value into char
+  * @param  value: value to convert
+  * @param  pbuf: pointer to the buffer
+  * @param  len: buffer length
+  * @retval None
+  */
+static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len)
+{
+  uint8_t idx = 0;
+
+  for (idx = 0; idx < len; idx++)
+  {
+    if (((value >> 28)) < 0xA)
+    {
+      pbuf[2 * idx] = (value >> 28) + '0';
+    }
+    else
+    {
+      pbuf[2 * idx] = (value >> 28) + 'A' - 10;
+    }
+
+    value = value << 4;
+
+    pbuf[2 * idx + 1] = 0;
+  }
+}
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 143 - 0
USB_DEVICE/App/usbd_desc.h

@@ -0,0 +1,143 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file           : usbd_desc.c
+  * @version        : v1.0_Cube
+  * @brief          : Header for usbd_conf.c file.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_DESC__C__
+#define __USBD_DESC__C__
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_def.h"
+
+/* USER CODE BEGIN INCLUDE */
+
+/* USER CODE END INCLUDE */
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+  * @{
+  */
+
+/** @defgroup USBD_DESC USBD_DESC
+  * @brief Usb device descriptors module.
+  * @{
+  */
+
+/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants
+  * @brief Constants.
+  * @{
+  */
+#define         DEVICE_ID1          (UID_BASE)
+#define         DEVICE_ID2          (UID_BASE + 0x4)
+#define         DEVICE_ID3          (UID_BASE + 0x8)
+
+#define  USB_SIZ_STRING_SERIAL       0x1A
+
+/* USER CODE BEGIN EXPORTED_CONSTANTS */
+
+/* USER CODE END EXPORTED_CONSTANTS */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Exported_Defines USBD_DESC_Exported_Defines
+  * @brief Defines.
+  * @{
+  */
+
+/* USER CODE BEGIN EXPORTED_DEFINES */
+
+/* USER CODE END EXPORTED_DEFINES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Exported_TypesDefinitions USBD_DESC_Exported_TypesDefinitions
+  * @brief Types.
+  * @{
+  */
+
+/* USER CODE BEGIN EXPORTED_TYPES */
+
+/* USER CODE END EXPORTED_TYPES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Exported_Macros USBD_DESC_Exported_Macros
+  * @brief Aliases.
+  * @{
+  */
+
+/* USER CODE BEGIN EXPORTED_MACRO */
+
+/* USER CODE END EXPORTED_MACRO */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Exported_Variables USBD_DESC_Exported_Variables
+  * @brief Public variables.
+  * @{
+  */
+
+/** Descriptor for the Usb device. */
+extern USBD_DescriptorsTypeDef FS_Desc;
+
+/* USER CODE BEGIN EXPORTED_VARIABLES */
+
+/* USER CODE END EXPORTED_VARIABLES */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_DESC_Exported_FunctionsPrototype USBD_DESC_Exported_FunctionsPrototype
+  * @brief Public functions declaration.
+  * @{
+  */
+
+/* USER CODE BEGIN EXPORTED_FUNCTIONS */
+
+/* USER CODE END EXPORTED_FUNCTIONS */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_DESC__C__ */
+

+ 671 - 0
USB_DEVICE/Target/usbd_conf.c

@@ -0,0 +1,671 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file           : Target/usbd_conf.c
+  * @version        : v1.0_Cube
+  * @brief          : This file implements the board support package for the USB device library
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx.h"
+#include "stm32f4xx_hal.h"
+#include "usbd_def.h"
+#include "usbd_core.h"
+
+#include "usbd_audio.h"
+
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+
+/* USER CODE BEGIN PV */
+/* Private variables ---------------------------------------------------------*/
+
+/* USER CODE END PV */
+
+PCD_HandleTypeDef hpcd_USB_OTG_FS;
+void Error_Handler(void);
+
+/* External functions --------------------------------------------------------*/
+void SystemClock_Config(void);
+
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/* USER CODE BEGIN PFP */
+/* Private function prototypes -----------------------------------------------*/
+USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status);
+
+/* USER CODE END PFP */
+
+/* Private functions ---------------------------------------------------------*/
+
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
+
+/*******************************************************************************
+                       LL Driver Callbacks (PCD -> USB Device Library)
+*******************************************************************************/
+/* MSP Init */
+
+void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
+{
+  GPIO_InitTypeDef GPIO_InitStruct = {0};
+  if(pcdHandle->Instance==USB_OTG_FS)
+  {
+  /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */
+
+  /* USER CODE END USB_OTG_FS_MspInit 0 */
+
+    __HAL_RCC_GPIOA_CLK_ENABLE();
+    /**USB_OTG_FS GPIO Configuration
+    PA11     ------> USB_OTG_FS_DM
+    PA12     ------> USB_OTG_FS_DP
+    */
+    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    /* Peripheral clock enable */
+    __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
+
+    /* Peripheral interrupt init */
+    HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0);
+    HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
+  /* USER CODE BEGIN USB_OTG_FS_MspInit 1 */
+
+  /* USER CODE END USB_OTG_FS_MspInit 1 */
+  }
+}
+
+void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle)
+{
+  if(pcdHandle->Instance==USB_OTG_FS)
+  {
+  /* USER CODE BEGIN USB_OTG_FS_MspDeInit 0 */
+
+  /* USER CODE END USB_OTG_FS_MspDeInit 0 */
+    /* Peripheral clock disable */
+    __HAL_RCC_USB_OTG_FS_CLK_DISABLE();
+
+    /**USB_OTG_FS GPIO Configuration
+    PA11     ------> USB_OTG_FS_DM
+    PA12     ------> USB_OTG_FS_DP
+    */
+    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);
+
+    /* Peripheral interrupt Deinit*/
+    HAL_NVIC_DisableIRQ(OTG_FS_IRQn);
+
+  /* USER CODE BEGIN USB_OTG_FS_MspDeInit 1 */
+
+  /* USER CODE END USB_OTG_FS_MspDeInit 1 */
+  }
+}
+
+/**
+  * @brief  Setup stage callback
+  * @param  hpcd: PCD handle
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
+#else
+void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);
+}
+
+/**
+  * @brief  Data Out stage callback.
+  * @param  hpcd: PCD handle
+  * @param  epnum: Endpoint number
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+#else
+void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
+}
+
+/**
+  * @brief  Data In stage callback.
+  * @param  hpcd: PCD handle
+  * @param  epnum: Endpoint number
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+#else
+void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
+}
+
+/**
+  * @brief  SOF callback.
+  * @param  hpcd: PCD handle
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
+#else
+void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);
+}
+
+/**
+  * @brief  Reset callback.
+  * @param  hpcd: PCD handle
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
+#else
+void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+   USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
+
+  if ( hpcd->Init.speed != PCD_SPEED_FULL)
+  {
+    Error_Handler();
+  }
+    /* Set Speed. */
+  USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);
+
+  /* Reset Device. */
+  USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
+}
+
+/**
+  * @brief  Suspend callback.
+  * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
+  * @param  hpcd: PCD handle
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
+#else
+void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  /* Inform USB library that core enters in suspend Mode. */
+  USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
+  __HAL_PCD_GATE_PHYCLOCK(hpcd);
+  /* Enter in STOP mode. */
+  /* USER CODE BEGIN 2 */
+  if (hpcd->Init.low_power_enable)
+  {
+    /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */
+    SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
+  }
+  /* USER CODE END 2 */
+}
+
+/**
+  * @brief  Resume callback.
+  * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
+  * @param  hpcd: PCD handle
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
+#else
+void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  /* USER CODE BEGIN 3 */
+
+  /* USER CODE END 3 */
+  USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);
+}
+
+/**
+  * @brief  ISOOUTIncomplete callback.
+  * @param  hpcd: PCD handle
+  * @param  epnum: Endpoint number
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+#else
+void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
+}
+
+/**
+  * @brief  ISOINIncomplete callback.
+  * @param  hpcd: PCD handle
+  * @param  epnum: Endpoint number
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+#else
+void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
+}
+
+/**
+  * @brief  Connect callback.
+  * @param  hpcd: PCD handle
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
+#else
+void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);
+}
+
+/**
+  * @brief  Disconnect callback.
+  * @param  hpcd: PCD handle
+  * @retval None
+  */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+static void PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
+#else
+void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+{
+  USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
+}
+
+/*******************************************************************************
+                       LL Driver Interface (USB Device Library --> PCD)
+*******************************************************************************/
+
+/**
+  * @brief  Initializes the low level portion of the device driver.
+  * @param  pdev: Device handle
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
+{
+  /* Init USB Ip. */
+  if (pdev->id == DEVICE_FS) {
+  /* Link the driver to the stack. */
+  hpcd_USB_OTG_FS.pData = pdev;
+  pdev->pData = &hpcd_USB_OTG_FS;
+
+  hpcd_USB_OTG_FS.Instance = USB_OTG_FS;
+  hpcd_USB_OTG_FS.Init.dev_endpoints = 4;
+  hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
+  hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
+  hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
+  hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
+  hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
+  hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
+  hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
+  hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
+  if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
+  {
+    Error_Handler( );
+  }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+  /* Register USB PCD CallBacks */
+  HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
+  HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
+  HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
+  HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
+  HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
+  HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
+  HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
+
+  HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
+  HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
+  HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
+  HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+  HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80);
+  HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40);
+  HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x80);
+  }
+  return USBD_OK;
+}
+
+/**
+  * @brief  De-Initializes the low level portion of the device driver.
+  * @param  pdev: Device handle
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_DeInit(pdev->pData);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Starts the low level portion of the device driver.
+  * @param  pdev: Device handle
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_Start(pdev->pData);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Stops the low level portion of the device driver.
+  * @param  pdev: Device handle
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_Stop(pdev->pData);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Opens an endpoint of the low level driver.
+  * @param  pdev: Device handle
+  * @param  ep_addr: Endpoint number
+  * @param  ep_type: Endpoint type
+  * @param  ep_mps: Endpoint max packet size
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Closes an endpoint of the low level driver.
+  * @param  pdev: Device handle
+  * @param  ep_addr: Endpoint number
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Flushes an endpoint of the Low Level Driver.
+  * @param  pdev: Device handle
+  * @param  ep_addr: Endpoint number
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Sets a Stall condition on an endpoint of the Low Level Driver.
+  * @param  pdev: Device handle
+  * @param  ep_addr: Endpoint number
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Clears a Stall condition on an endpoint of the Low Level Driver.
+  * @param  pdev: Device handle
+  * @param  ep_addr: Endpoint number
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Returns Stall condition.
+  * @param  pdev: Device handle
+  * @param  ep_addr: Endpoint number
+  * @retval Stall (1: Yes, 0: No)
+  */
+uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+  PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData;
+
+  if((ep_addr & 0x80) == 0x80)
+  {
+    return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
+  }
+  else
+  {
+    return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
+  }
+}
+
+/**
+  * @brief  Assigns a USB address to the device.
+  * @param  pdev: Device handle
+  * @param  dev_addr: Device address
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Transmits data over an endpoint.
+  * @param  pdev: Device handle
+  * @param  ep_addr: Endpoint number
+  * @param  pbuf: Pointer to data to be sent
+  * @param  size: Data size
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Prepares an endpoint for reception.
+  * @param  pdev: Device handle
+  * @param  ep_addr: Endpoint number
+  * @param  pbuf: Pointer to data to be received
+  * @param  size: Data size
+  * @retval USBD status
+  */
+USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size)
+{
+  HAL_StatusTypeDef hal_status = HAL_OK;
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
+
+  usb_status =  USBD_Get_USB_Status(hal_status);
+
+  return usb_status;
+}
+
+/**
+  * @brief  Returns the last transferred packet size.
+  * @param  pdev: Device handle
+  * @param  ep_addr: Endpoint number
+  * @retval Received Data Size
+  */
+uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+  return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr);
+}
+
+#ifdef USBD_HS_TESTMODE_ENABLE
+/**
+  * @brief  Set High speed Test mode.
+  * @param  pdev: Device handle
+  * @param  testmode: test mode
+  * @retval USBD Status
+  */
+USBD_StatusTypeDef USBD_LL_SetTestMode(USBD_HandleTypeDef *pdev, uint8_t testmode)
+{
+  UNUSED(pdev);
+  UNUSED(testmode);
+
+  return USBD_OK;
+}
+#endif /* USBD_HS_TESTMODE_ENABLE */
+
+/**
+  * @brief  Static single allocation.
+  * @param  size: Size of allocated memory
+  * @retval None
+  */
+void *USBD_static_malloc(uint32_t size)
+{
+  static uint32_t mem[(sizeof(USBD_AUDIO_HandleTypeDef)/4)+1];/* On 32-bit boundary */
+  return mem;
+}
+
+/**
+  * @brief  Dummy memory free
+  * @param  p: Pointer to allocated  memory address
+  * @retval None
+  */
+void USBD_static_free(void *p)
+{
+
+}
+
+/**
+  * @brief  Delays routine for the USB Device Library.
+  * @param  Delay: Delay in ms
+  * @retval None
+  */
+void USBD_LL_Delay(uint32_t Delay)
+{
+  HAL_Delay(Delay);
+}
+
+/**
+  * @brief  Returns the USB status depending on the HAL status:
+  * @param  hal_status: HAL status
+  * @retval USB status
+  */
+USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status)
+{
+  USBD_StatusTypeDef usb_status = USBD_OK;
+
+  switch (hal_status)
+  {
+    case HAL_OK :
+      usb_status = USBD_OK;
+    break;
+    case HAL_ERROR :
+      usb_status = USBD_FAIL;
+    break;
+    case HAL_BUSY :
+      usb_status = USBD_BUSY;
+    break;
+    case HAL_TIMEOUT :
+      usb_status = USBD_FAIL;
+    break;
+    default :
+      usb_status = USBD_FAIL;
+    break;
+  }
+  return usb_status;
+}

+ 175 - 0
USB_DEVICE/Target/usbd_conf.h

@@ -0,0 +1,175 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file           : usbd_conf.h
+  * @version        : v1.0_Cube
+  * @brief          : Header for usbd_conf.c file.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2024 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_CONF__H__
+#define __USBD_CONF__H__
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "main.h"
+#include "stm32f4xx.h"
+#include "stm32f4xx_hal.h"
+
+/* USER CODE BEGIN INCLUDE */
+
+/* USER CODE END INCLUDE */
+
+/** @addtogroup USBD_OTG_DRIVER
+  * @brief Driver for Usb device.
+  * @{
+  */
+
+/** @defgroup USBD_CONF USBD_CONF
+  * @brief Configuration file for Usb otg low level driver.
+  * @{
+  */
+
+/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables
+  * @brief Public variables.
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
+  * @brief Defines for configuration of the Usb device.
+  * @{
+  */
+
+/*---------- -----------*/
+#define USBD_MAX_NUM_INTERFACES     1U
+/*---------- -----------*/
+#define USBD_MAX_NUM_CONFIGURATION     1U
+/*---------- -----------*/
+#define USBD_MAX_STR_DESC_SIZ     512U
+/*---------- -----------*/
+#define USBD_DEBUG_LEVEL     0U
+/*---------- -----------*/
+#define USBD_LPM_ENABLED     0U
+/*---------- -----------*/
+#define USBD_SELF_POWERED     1U
+/*---------- -----------*/
+#define USBD_AUDIO_FREQ     22100U
+
+/****************************************/
+/* #define for FS and HS identification */
+#define DEVICE_FS 		0
+#define DEVICE_HS 		1
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros
+  * @brief Aliases.
+  * @{
+  */
+/* Memory management macros make sure to use static memory allocation */
+/** Alias for memory allocation. */
+
+#define USBD_malloc         (void *)USBD_static_malloc
+
+/** Alias for memory release. */
+#define USBD_free           USBD_static_free
+
+/** Alias for memory set. */
+#define USBD_memset         memset
+
+/** Alias for memory copy. */
+#define USBD_memcpy         memcpy
+
+/** Alias for delay. */
+#define USBD_Delay          HAL_Delay
+
+/* DEBUG macros */
+
+#if (USBD_DEBUG_LEVEL > 0)
+#define USBD_UsrLog(...)    printf(__VA_ARGS__);\
+                            printf("\n");
+#else
+#define USBD_UsrLog(...)
+#endif /* (USBD_DEBUG_LEVEL > 0U) */
+
+#if (USBD_DEBUG_LEVEL > 1)
+
+#define USBD_ErrLog(...)    printf("ERROR: ");\
+                            printf(__VA_ARGS__);\
+                            printf("\n");
+#else
+#define USBD_ErrLog(...)
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
+
+#if (USBD_DEBUG_LEVEL > 2)
+#define USBD_DbgLog(...)    printf("DEBUG : ");\
+                            printf(__VA_ARGS__);\
+                            printf("\n");
+#else
+#define USBD_DbgLog(...)
+#endif /* (USBD_DEBUG_LEVEL > 2U) */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_CONF_Exported_Types USBD_CONF_Exported_Types
+  * @brief Types.
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_CONF_Exported_FunctionsPrototype USBD_CONF_Exported_FunctionsPrototype
+  * @brief Declaration of public functions for Usb device.
+  * @{
+  */
+
+/* Exported functions -------------------------------------------------------*/
+void *USBD_static_malloc(uint32_t size);
+void USBD_static_free(void *p);
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_CONF__H__ */
+

+ 48 - 11
usb_mic.ioc

@@ -8,10 +8,21 @@ Mcu.CPN=STM32F411CEU6
 Mcu.Family=STM32F4
 Mcu.IP0=NVIC
 Mcu.IP1=RCC
-Mcu.IPNb=2
+Mcu.IP2=SYS
+Mcu.IP3=USB_DEVICE
+Mcu.IP4=USB_OTG_FS
+Mcu.IPNb=5
 Mcu.Name=STM32F411C(C-E)Ux
 Mcu.Package=UFQFPN48
-Mcu.PinsNb=0
+Mcu.Pin0=PC14-OSC32_IN
+Mcu.Pin1=PC15-OSC32_OUT
+Mcu.Pin2=PH0 - OSC_IN
+Mcu.Pin3=PH1 - OSC_OUT
+Mcu.Pin4=PA11
+Mcu.Pin5=PA12
+Mcu.Pin6=VP_SYS_VS_Systick
+Mcu.Pin7=VP_USB_DEVICE_VS_USB_DEVICE_AUDIO_FS
+Mcu.PinsNb=8
 Mcu.ThirdPartyNb=0
 Mcu.UserConstants=
 Mcu.UserName=STM32F411CEUx
@@ -23,11 +34,24 @@ NVIC.ForceEnableDMAVector=true
 NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
 NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
 NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
+NVIC.OTG_FS_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
 NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
 NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
 NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false
 NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
+PA11.Mode=Device_Only
+PA11.Signal=USB_OTG_FS_DM
+PA12.Mode=Device_Only
+PA12.Signal=USB_OTG_FS_DP
+PC14-OSC32_IN.Mode=LSE-External-Oscillator
+PC14-OSC32_IN.Signal=RCC_OSC32_IN
+PC15-OSC32_OUT.Mode=LSE-External-Oscillator
+PC15-OSC32_OUT.Signal=RCC_OSC32_OUT
+PH0\ -\ OSC_IN.Mode=HSE-External-Oscillator
+PH0\ -\ OSC_IN.Signal=RCC_OSC_IN
+PH1\ -\ OSC_OUT.Mode=HSE-External-Oscillator
+PH1\ -\ OSC_OUT.Signal=RCC_OSC_OUT
 PinOutPanel.RotationAngle=0
 ProjectManager.AskForMigrate=true
 ProjectManager.BackupPrevious=false
@@ -60,6 +84,7 @@ ProjectManager.UAScriptAfterPath=
 ProjectManager.UAScriptBeforePath=
 ProjectManager.UnderRoot=true
 ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false
+RCC.48MHZClocksFreq_Value=48000000
 RCC.AHBFreq_Value=16000000
 RCC.APB1Freq_Value=16000000
 RCC.APB2Freq_Value=16000000
@@ -67,19 +92,31 @@ RCC.CortexFreq_Value=16000000
 RCC.FamilyName=M
 RCC.HSE_VALUE=25000000
 RCC.HSI_VALUE=16000000
-RCC.I2SClocksFreq_Value=96000000
-RCC.IPParameters=AHBFreq_Value,APB1Freq_Value,APB2Freq_Value,CortexFreq_Value,FamilyName,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSE_VALUE,LSI_VALUE,PLLCLKFreq_Value,PLLQCLKFreq_Value,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOInputMFreq_Value,VCOOutputFreq_Value,VcooutputI2S
-RCC.LSE_VALUE=32768
+RCC.I2SClocksFreq_Value=150000000
+RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1Freq_Value,APB2Freq_Value,CortexFreq_Value,FamilyName,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSI_VALUE,PLLCLKFreq_Value,PLLM,PLLN,PLLQ,PLLQCLKFreq_Value,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOInputMFreq_Value,VCOOutputFreq_Value,VcooutputI2S
 RCC.LSI_VALUE=32000
-RCC.PLLCLKFreq_Value=96000000
+RCC.PLLCLKFreq_Value=120000000
+RCC.PLLM=15
+RCC.PLLN=144
+RCC.PLLQ=5
 RCC.PLLQCLKFreq_Value=48000000
 RCC.RTCFreq_Value=32000
 RCC.RTCHSEDivFreq_Value=12500000
 RCC.SYSCLKFreq_VALUE=16000000
-RCC.VCOI2SOutputFreq_Value=192000000
-RCC.VCOInputFreq_Value=1000000
-RCC.VCOInputMFreq_Value=1000000
-RCC.VCOOutputFreq_Value=192000000
-RCC.VcooutputI2S=96000000
+RCC.VCOI2SOutputFreq_Value=300000000
+RCC.VCOInputFreq_Value=1666666.6666666667
+RCC.VCOInputMFreq_Value=1562500
+RCC.VCOOutputFreq_Value=240000000
+RCC.VcooutputI2S=150000000
+USB_DEVICE.CLASS_NAME_FS=AUDIO
+USB_DEVICE.IPParameters=VirtualMode,VirtualModeFS,CLASS_NAME_FS
+USB_DEVICE.VirtualMode=Audio
+USB_DEVICE.VirtualModeFS=Audio_FS
+USB_OTG_FS.IPParameters=VirtualMode
+USB_OTG_FS.VirtualMode=Device_Only
+VP_SYS_VS_Systick.Mode=SysTick
+VP_SYS_VS_Systick.Signal=SYS_VS_Systick
+VP_USB_DEVICE_VS_USB_DEVICE_AUDIO_FS.Mode=AUDIO_FS
+VP_USB_DEVICE_VS_USB_DEVICE_AUDIO_FS.Signal=USB_DEVICE_VS_USB_DEVICE_AUDIO_FS
 board=custom
 isbadioc=false

+ 82 - 0
usb_mic.launch

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="com.st.stm32cube.ide.mcu.debug.launch.launchConfigurationType">
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.access_port_id" value="0"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.cubeprog_external_loaders" value="[]"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.debug_auth_certif_path" value=""/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.debug_auth_check_enable" value="false"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.debug_auth_key_path" value=""/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.debug_auth_permission" value="debug_non_secure_L3"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.enable_live_expr" value="true"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.enable_swv" value="false"/>
+    <intAttribute key="com.st.stm32cube.ide.mcu.debug.launch.formatVersion" value="2"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.ip_address_local" value="localhost"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.limit_swo_clock.enabled" value="false"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.limit_swo_clock.value" value=""/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.loadList" value="{&quot;fItems&quot;:[{&quot;fIsFromMainTab&quot;:true,&quot;fPath&quot;:&quot;Debug/usb_mic.elf&quot;,&quot;fProjectName&quot;:&quot;usb_mic&quot;,&quot;fPerformBuild&quot;:true,&quot;fDownload&quot;:true,&quot;fLoadSymbols&quot;:true}]}"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.override_start_address_mode" value="default"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.remoteCommand" value="target remote"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.startServer" value="true"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.startuptab.exception.divby0" value="true"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.startuptab.exception.unaligned" value="false"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.startuptab.haltonexception" value="true"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.swd_mode" value="true"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.swv_port" value="61235"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.swv_trace_hclk" value="16000000"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.useRemoteTarget" value="true"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.launch.vector_table" value=""/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.launch.verify_flash_download" value="true"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.cti_allow_halt" value="false"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.cti_signal_halt" value="false"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.enable_logging" value="false"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.enable_max_halt_delay" value="false"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.enable_shared_stlink" value="false"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.frequency" value="0"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.halt_all_on_reset" value="false"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.log_file" value="/Users/muradjabir/STM32CubeIDE/workspace_1.14.0/usb_mic/Debug/st-link_gdbserver_log.txt"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.low_power_debug" value="enable"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.max_halt_delay" value="2"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.reset_strategy" value="connect_under_reset"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.stlink_check_serial_number" value="false"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.stlink_txt_serial_number" value=""/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.stlink.watchdog_config" value="none"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.debug.stlinkenable_rtos" value="false"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.debug.stlinkrestart_configurations" value="{&quot;fVersion&quot;:1,&quot;fItems&quot;:[{&quot;fDisplayName&quot;:&quot;Reset&quot;,&quot;fIsSuppressible&quot;:false,&quot;fResetAttribute&quot;:&quot;Software system reset&quot;,&quot;fResetStrategies&quot;:[{&quot;fDisplayName&quot;:&quot;Software system reset&quot;,&quot;fLaunchAttribute&quot;:&quot;system_reset&quot;,&quot;fGdbCommands&quot;:[&quot;monitor reset\n&quot;],&quot;fCmdOptions&quot;:[&quot;-g&quot;]},{&quot;fDisplayName&quot;:&quot;Hardware reset&quot;,&quot;fLaunchAttribute&quot;:&quot;hardware_reset&quot;,&quot;fGdbCommands&quot;:[&quot;monitor reset hardware\n&quot;],&quot;fCmdOptions&quot;:[&quot;-g&quot;]},{&quot;fDisplayName&quot;:&quot;Core reset&quot;,&quot;fLaunchAttribute&quot;:&quot;core_reset&quot;,&quot;fGdbCommands&quot;:[&quot;monitor reset core\n&quot;],&quot;fCmdOptions&quot;:[&quot;-g&quot;]},{&quot;fDisplayName&quot;:&quot;None&quot;,&quot;fLaunchAttribute&quot;:&quot;no_reset&quot;,&quot;fGdbCommands&quot;:[],&quot;fCmdOptions&quot;:[&quot;-g&quot;]}],&quot;fGdbCommandGroup&quot;:{&quot;name&quot;:&quot;Additional commands&quot;,&quot;commands&quot;:[]},&quot;fStartApplication&quot;:true}]}"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.rtosproxy.enableRtosProxy" value="false"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.rtosproxy.rtosProxyCustomProperties" value=""/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.rtosproxy.rtosProxyDriver" value="threadx"/>
+    <booleanAttribute key="com.st.stm32cube.ide.mcu.rtosproxy.rtosProxyDriverAuto" value="false"/>
+    <stringAttribute key="com.st.stm32cube.ide.mcu.rtosproxy.rtosProxyDriverPort" value="cortex_m0"/>
+    <intAttribute key="com.st.stm32cube.ide.mcu.rtosproxy.rtosProxyPort" value="60000"/>
+    <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doHalt" value="false"/>
+    <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doReset" value="false"/>
+    <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.initCommands" value=""/>
+    <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/>
+    <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDeviceId" value="com.st.stm32cube.ide.mcu.debug.stlink"/>
+    <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/>
+    <intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.portNumber" value="61234"/>
+    <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.runCommands" value=""/>
+    <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="false"/>
+    <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="true"/>
+    <booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/>
+    <stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="main"/>
+    <stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="arm-none-eabi-gdb"/>
+    <booleanAttribute key="org.eclipse.cdt.dsf.gdb.NON_STOP" value="false"/>
+    <booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/>
+    <intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
+    <stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
+    <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="remote"/>
+    <booleanAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN" value="true"/>
+    <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN_SYMBOL" value="main"/>
+    <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="Debug/usb_mic.elf"/>
+    <stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="usb_mic"/>
+    <booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/>
+    <stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.1498544152"/>
+    <booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
+    <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+        <listEntry value="/usb_mic"/>
+    </listAttribute>
+    <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+        <listEntry value="4"/>
+    </listAttribute>
+    <stringAttribute key="process_factory_id" value="com.st.stm32cube.ide.mcu.debug.launch.HardwareDebugProcessFactory"/>
+</launchConfiguration>

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików