Browse Source

[bsp][stm32] add sdio, hw_timer and pwm drivers

SummerGift 6 years ago
parent
commit
71751eb6f1

+ 11 - 5
bsp/stm32/libraries/HAL_Drivers/SConscript

@@ -13,7 +13,13 @@ if GetDepend(['RT_USING_PIN']):
     
     
 if GetDepend(['RT_USING_SERIAL']):
 if GetDepend(['RT_USING_SERIAL']):
     src += ['drv_usart.c']
     src += ['drv_usart.c']
-    
+
+if GetDepend(['RT_USING_HWTIMER']):
+    src += ['drv_hwtimer.c']
+
+if GetDepend(['RT_USING_PWM']):
+    src += ['drv_pwm.c']
+
 if GetDepend(['RT_USING_SPI']):
 if GetDepend(['RT_USING_SPI']):
     src += ['drv_spi.c']
     src += ['drv_spi.c']
 
 
@@ -22,10 +28,7 @@ if GetDepend(['RT_USING_QSPI']):
 
 
 if GetDepend(['RT_USING_USB_DEVICE']):
 if GetDepend(['RT_USING_USB_DEVICE']):
     src += ['drv_usb.c']
     src += ['drv_usb.c']
-    
-if GetDepend(['RT_USING_SDCARD']):
-    src += ['drv_sdcard.c']
-    
+
 if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']):
 if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']):
     src += ['drv_soft_i2c.c']
     src += ['drv_soft_i2c.c']
 
 
@@ -53,6 +56,9 @@ if GetDepend(['BSP_USING_ON_CHIP_FLASH', 'SOC_SERIES_STM32L4']):
 if GetDepend(['BSP_USING_WDT']):
 if GetDepend(['BSP_USING_WDT']):
     src += ['drv_wdt.c']
     src += ['drv_wdt.c']
 
 
+if GetDepend(['BSP_USING_SDIO']):
+    src += ['drv_sdio.c']
+
 src += ['drv_common.c']
 src += ['drv_common.c']
 
 
 path =  [cwd]
 path =  [cwd]

+ 60 - 0
bsp/stm32/libraries/HAL_Drivers/config/f1/pwm_config.h

@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-13     zylx         first version
+ */
+
+#ifndef __PWM_CONFIG_H__
+#define __PWM_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef BSP_USING_PWM2
+#ifndef PWM2_CONFIG
+#define PWM2_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM2,         \
+       .name                    = "pwm2",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM2_CONFIG */
+#endif /* BSP_USING_PWM2 */
+
+#ifdef BSP_USING_PWM3
+#ifndef PWM3_CONFIG
+#define PWM3_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM3,         \
+       .name                    = "pwm3",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM3_CONFIG */
+#endif /* BSP_USING_PWM3 */
+
+#ifdef BSP_USING_PWM4
+#ifndef PWM4_CONFIG
+#define PWM4_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM4,         \
+       .name                    = "pwm4",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM4_CONFIG */
+#endif /* BSP_USING_PWM4 */
+
+#ifdef BSP_USING_PWM5
+#ifndef PWM5_CONFIG
+#define PWM5_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM5,         \
+       .name                    = "pwm5",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM5_CONFIG */
+#endif /* BSP_USING_PWM5 */
+
+#endif /* __PWM_CONFIG_H__ */

+ 36 - 0
bsp/stm32/libraries/HAL_Drivers/config/f1/sdio_config.h

@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-13     BalanceTWK   first version
+ */
+
+#ifndef __SDIO_CONFIG_H__
+#define __SDIO_CONFIG_H__
+
+#include <rtthread.h>
+#include "stm32f1xx_hal.h"
+
+#ifdef BSP_USING_SDIO
+#define SDIO_BUS_CONFIG                                  \
+    {                                                    \
+        .Instance = SDIO,                                \
+        .dma_rx.dma_rcc = RCC_AHBENR_DMA2EN,             \
+        .dma_tx.dma_rcc = RCC_AHBENR_DMA2EN,             \
+        .dma_rx.Instance = DMA2_Channel4,                \
+        .dma_rx.dma_irq = DMA2_Channel4_IRQn,            \
+        .dma_tx.Instance = DMA2_Channel4,                \
+        .dma_tx.dma_irq = DMA2_Channel4_IRQn,            \
+    }
+
+#define SPI1_DMA_RX_IRQHandler           DMA2_Channel4_IRQHandler    
+#define SPI1_DMA_TX_IRQHandler           DMA2_Channel4_IRQHandler
+#endif
+
+#endif /*__SDIO_CONFIG_H__ */
+
+
+

+ 70 - 0
bsp/stm32/libraries/HAL_Drivers/config/f1/tim_config.h

@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-11     zylx         first version
+ */
+
+#ifndef __TIM_CONFIG_H__
+#define __TIM_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifndef TIM_DEV_INFO_CONFIG
+#define TIM_DEV_INFO_CONFIG                     \
+    {                                           \
+        .maxfreq = 1000000,                     \
+        .minfreq = 2000,                        \
+        .maxcnt  = 0xFFFF,                      \
+        .cntmode = HWTIMER_CNTMODE_UP,          \
+    }
+#endif /* TIM_DEV_INFO_CONFIG */
+
+#ifdef BSP_USING_TIM2
+#ifndef TIM2_CONFIG
+#define TIM2_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM2,         \
+       .tim_irqn                = TIM2_IRQn,    \
+       .name                    = "timer2",     \
+    }
+#endif /* TIM2_CONFIG */
+#endif /* BSP_USING_TIM2 */
+
+#ifdef BSP_USING_TIM3
+#ifndef TIM3_CONFIG
+#define TIM3_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM3,         \
+       .tim_irqn                = TIM3_IRQn,    \
+       .name                    = "timer3",     \
+    }
+#endif /* TIM3_CONFIG */
+#endif /* BSP_USING_TIM3 */
+
+#ifdef BSP_USING_TIM4
+#ifndef TIM4_CONFIG
+#define TIM4_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM4,         \
+       .tim_irqn                = TIM4_IRQn,    \
+       .name                    = "timer4",     \
+    }
+#endif /* TIM4_CONFIG */
+#endif /* BSP_USING_TIM4 */
+
+#ifdef BSP_USING_TIM5
+#ifndef TIM5_CONFIG
+#define TIM5_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM5,         \
+       .tim_irqn                = TIM5_IRQn,    \
+       .name                    = "timer5",     \
+    }
+#endif /* TIM5_CONFIG */
+#endif /* BSP_USING_TIM5 */
+
+#endif /* __TIM_CONFIG_H__ */

+ 60 - 0
bsp/stm32/libraries/HAL_Drivers/config/f4/pwm_config.h

@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-13     zylx         first version
+ */
+
+#ifndef __PWM_CONFIG_H__
+#define __PWM_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef BSP_USING_PWM2
+#ifndef PWM2_CONFIG
+#define PWM2_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM2,         \
+       .name                    = "pwm2",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM2_CONFIG */
+#endif /* BSP_USING_PWM2 */
+
+#ifdef BSP_USING_PWM3
+#ifndef PWM3_CONFIG
+#define PWM3_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM3,         \
+       .name                    = "pwm3",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM3_CONFIG */
+#endif /* BSP_USING_PWM3 */
+
+#ifdef BSP_USING_PWM4
+#ifndef PWM4_CONFIG
+#define PWM4_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM4,         \
+       .name                    = "pwm4",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM4_CONFIG */
+#endif /* BSP_USING_PWM4 */
+
+#ifdef BSP_USING_PWM5
+#ifndef PWM5_CONFIG
+#define PWM5_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM5,         \
+       .name                    = "pwm5",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM5_CONFIG */
+#endif /* BSP_USING_PWM5 */
+
+#endif /* __PWM_CONFIG_H__ */

+ 38 - 0
bsp/stm32/libraries/HAL_Drivers/config/f4/sdio_config.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-13     BalanceTWK   first version
+ */
+
+#ifndef __SDIO_CONFIG_H__
+#define __SDIO_CONFIG_H__
+
+#include <rtthread.h>
+#include "stm32f4xx_hal.h"
+
+#ifdef BSP_USING_SDIO
+#define SDIO_BUS_CONFIG                                  \
+    {                                                    \
+        .Instance = SDIO,                                \
+        .dma_rx.dma_rcc = RCC_AHB1ENR_DMA2EN,            \
+        .dma_tx.dma_rcc = RCC_AHB1ENR_DMA2EN,            \
+        .dma_rx.Instance = DMA2_Stream3,                 \
+        .dma_rx.channel = DMA_CHANNEL_4,                 \
+        .dma_rx.dma_irq = DMA2_Stream3_IRQn,             \
+        .dma_tx.Instance = DMA2_Stream6,                 \
+        .dma_tx.channel = DMA_CHANNEL_4,                 \
+        .dma_tx.dma_irq = DMA2_Stream6_IRQn,             \
+    }
+
+#define SPI1_DMA_RX_IRQHandler           DMA2_Stream3_IRQHandler
+#define SPI1_DMA_TX_IRQHandler           DMA2_Stream6_IRQHandler
+#endif
+
+#endif /*__SDIO_CONFIG_H__ */
+
+
+

+ 59 - 0
bsp/stm32/libraries/HAL_Drivers/config/f4/tim_config.h

@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-11     zylx         first version
+ */
+
+#ifndef __TIM_CONFIG_H__
+#define __TIM_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifndef TIM_DEV_INFO_CONFIG
+#define TIM_DEV_INFO_CONFIG                     \
+    {                                           \
+        .maxfreq = 1000000,                     \
+        .minfreq = 3000,                        \
+        .maxcnt  = 0xFFFF,                      \
+        .cntmode = HWTIMER_CNTMODE_UP,          \
+    }
+#endif /* TIM_DEV_INFO_CONFIG */
+
+#ifdef BSP_USING_TIM11
+#ifndef TIM11_CONFIG
+#define TIM11_CONFIG                                        \
+    {                                                       \
+       .tim_handle.Instance     = TIM11,                    \
+       .tim_irqn                = TIM1_TRG_COM_TIM11_IRQn,  \
+       .name                    = "timer11",                \
+    }
+#endif /* TIM11_CONFIG */
+#endif /* BSP_USING_TIM11 */
+
+#ifdef BSP_USING_TIM13
+#ifndef TIM13_CONFIG
+#define TIM13_CONFIG                                        \
+    {                                                       \
+       .tim_handle.Instance     = TIM13,                    \
+       .tim_irqn                = TIM8_UP_TIM13_IRQn,       \
+       .name                    = "timer13",                \
+    }
+#endif /* TIM13_CONFIG */
+#endif /* BSP_USING_TIM13 */
+
+#ifdef BSP_USING_TIM14
+#ifndef TIM14_CONFIG
+#define TIM14_CONFIG                                        \
+    {                                                       \
+       .tim_handle.Instance     = TIM14,                    \
+       .tim_irqn                = TIM8_TRG_COM_TIM14_IRQn,  \
+       .name                    = "timer14",                \
+    }
+#endif /* TIM14_CONFIG */
+#endif /* BSP_USING_TIM14 */
+
+#endif /* __TIM_CONFIG_H__ */

+ 60 - 0
bsp/stm32/libraries/HAL_Drivers/config/l4/pwm_config.h

@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-13     zylx         first version
+ */
+
+#ifndef __PWM_CONFIG_H__
+#define __PWM_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef BSP_USING_PWM2
+#ifndef PWM2_CONFIG
+#define PWM2_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM2,         \
+       .name                    = "pwm2",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM2_CONFIG */
+#endif /* BSP_USING_PWM2 */
+
+#ifdef BSP_USING_PWM3
+#ifndef PWM3_CONFIG
+#define PWM3_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM3,         \
+       .name                    = "pwm3",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM3_CONFIG */
+#endif /* BSP_USING_PWM3 */
+
+#ifdef BSP_USING_PWM4
+#ifndef PWM4_CONFIG
+#define PWM4_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM4,         \
+       .name                    = "pwm4",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM4_CONFIG */
+#endif /* BSP_USING_PWM4 */
+
+#ifdef BSP_USING_PWM5
+#ifndef PWM5_CONFIG
+#define PWM5_CONFIG                             \
+    {                                           \
+       .tim_handle.Instance     = TIM5,         \
+       .name                    = "pwm5",       \
+       .channel                 = 0             \
+    }
+#endif /* PWM5_CONFIG */
+#endif /* BSP_USING_PWM5 */
+
+#endif /* __PWM_CONFIG_H__ */

+ 59 - 0
bsp/stm32/libraries/HAL_Drivers/config/l4/tim_config.h

@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-12     zylx         first version
+ */
+
+#ifndef __TIM_CONFIG_H__
+#define __TIM_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifndef TIM_DEV_INFO_CONFIG
+#define TIM_DEV_INFO_CONFIG                     \
+    {                                           \
+        .maxfreq = 1000000,                     \
+        .minfreq = 2000,                        \
+        .maxcnt  = 0xFFFF,                      \
+        .cntmode = HWTIMER_CNTMODE_UP,          \
+    }
+#endif /* TIM_DEV_INFO_CONFIG */
+
+#ifdef BSP_USING_TIM15
+#ifndef TIM15_CONFIG
+#define TIM15_CONFIG                                        \
+    {                                                       \
+       .tim_handle.Instance     = TIM15,                    \
+       .tim_irqn                = TIM1_BRK_TIM15_IRQn,      \
+       .name                    = "timer15",                \
+    }
+#endif /* TIM15_CONFIG */
+#endif /* BSP_USING_TIM15 */
+
+#ifdef BSP_USING_TIM16
+#ifndef TIM16_CONFIG
+#define TIM16_CONFIG                                        \
+    {                                                       \
+       .tim_handle.Instance     = TIM16,                    \
+       .tim_irqn                = TIM1_UP_TIM16_IRQn,       \
+       .name                    = "timer16",                \
+    }
+#endif /* TIM16_CONFIG */
+#endif /* BSP_USING_TIM16 */
+
+#ifdef BSP_USING_TIM17
+#ifndef TIM17_CONFIG
+#define TIM17_CONFIG                                        \
+    {                                                       \
+       .tim_handle.Instance     = TIM17,                    \
+       .tim_irqn                = TIM1_TRG_COM_TIM17_IRQn,  \
+       .name                    = "timer17",                \
+    }
+#endif /* TIM17_CONFIG */
+#endif /* BSP_USING_TIM17 */
+
+#endif /* __TIM_CONFIG_H__ */

+ 8 - 0
bsp/stm32/libraries/HAL_Drivers/drv_config.h

@@ -18,14 +18,22 @@
 #include "f1/uart_config.h"
 #include "f1/uart_config.h"
 #include "f1/spi_config.h"
 #include "f1/spi_config.h"
 #include "f1/adc_config.h"
 #include "f1/adc_config.h"
+#include "f1/tim_config.h"
+#include "f1/sdio_config.h"
+#include "f1/pwm_config.h"
 #elif  defined(SOC_SERIES_STM32F4)
 #elif  defined(SOC_SERIES_STM32F4)
 #include "f4/uart_config.h"
 #include "f4/uart_config.h"
 #include "f4/spi_config.h"
 #include "f4/spi_config.h"
 #include "f4/adc_config.h"
 #include "f4/adc_config.h"
+#include "f4/tim_config.h"
+#include "f4/sdio_config.h"
+#include "f4/pwm_config.h"
 #elif  defined(SOC_SERIES_STM32L4)
 #elif  defined(SOC_SERIES_STM32L4)
 #include "l4/uart_config.h"
 #include "l4/uart_config.h"
 #include "l4/spi_config.h"
 #include "l4/spi_config.h"
 #include "l4/adc_config.h"
 #include "l4/adc_config.h"
+#include "l4/tim_config.h"
+#include "l4/pwm_config.h"
 #endif
 #endif
 
 
 #endif
 #endif

+ 525 - 0
bsp/stm32/libraries/HAL_Drivers/drv_hwtimer.c

@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-10     zylx         first version
+ */
+
+#include <board.h>
+#ifdef BSP_USING_TIM
+#include "drv_config.h"
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.hwtimer"
+#include <drv_log.h>
+
+#ifdef RT_USING_HWTIMER
+enum
+{
+#ifdef BSP_USING_TIM1
+    TIM1_INDEX,
+#endif
+#ifdef BSP_USING_TIM2
+    TIM2_INDEX,
+#endif
+#ifdef BSP_USING_TIM3
+    TIM3_INDEX,
+#endif
+#ifdef BSP_USING_TIM4
+    TIM4_INDEX,
+#endif
+#ifdef BSP_USING_TIM5
+    TIM5_INDEX,
+#endif
+#ifdef BSP_USING_TIM6
+    TIM6_INDEX,
+#endif
+#ifdef BSP_USING_TIM7
+    TIM7_INDEX,
+#endif
+#ifdef BSP_USING_TIM8
+    TIM8_INDEX,
+#endif
+#ifdef BSP_USING_TIM9
+    TIM9_INDEX,
+#endif
+#ifdef BSP_USING_TIM10
+    TIM10_INDEX,
+#endif
+#ifdef BSP_USING_TIM11
+    TIM11_INDEX,
+#endif
+#ifdef BSP_USING_TIM12
+    TIM12_INDEX,
+#endif
+#ifdef BSP_USING_TIM13
+    TIM13_INDEX,
+#endif
+#ifdef BSP_USING_TIM14
+    TIM14_INDEX,
+#endif
+#ifdef BSP_USING_TIM15
+    TIM15_INDEX,
+#endif
+#ifdef BSP_USING_TIM16
+    TIM16_INDEX,
+#endif
+#ifdef BSP_USING_TIM17
+    TIM17_INDEX,
+#endif
+};
+
+struct stm32_hwtimer
+{
+    rt_hwtimer_t time_device;
+    TIM_HandleTypeDef    tim_handle;
+    IRQn_Type tim_irqn;
+    char *name;
+};
+
+static struct stm32_hwtimer stm32_hwtimer_obj[] =
+{
+#ifdef BSP_USING_TIM1
+    TIM1_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM2
+    TIM2_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM3
+    TIM3_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM4
+    TIM4_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM5
+    TIM5_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM6
+    TIM6_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM7
+    TIM7_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM8
+    TIM8_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM9
+    TIM9_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM10
+    TIM10_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM11
+    TIM11_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM12
+    TIM12_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM13
+    TIM13_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM14
+    TIM14_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM15
+    TIM15_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM16
+    TIM16_CONFIG,
+#endif
+
+#ifdef BSP_USING_TIM17
+    TIM17_CONFIG,
+#endif
+};
+
+static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
+{
+    uint32_t prescaler_value = 0;
+    TIM_HandleTypeDef *tim = RT_NULL;
+    struct stm32_hwtimer *tim_device = RT_NULL;
+
+    RT_ASSERT(timer != RT_NULL);
+    if (state)
+    {
+        tim = (TIM_HandleTypeDef *)timer->parent.user_data;
+        tim_device = (struct stm32_hwtimer *)timer;
+
+        /* time init */
+#if defined(SOC_SERIES_STM32F4)
+        if (tim->Instance == TIM9 || tim->Instance == TIM10 || tim->Instance == TIM11)
+#elif defined(SOC_SERIES_STM32L4)
+        if (tim->Instance == TIM15 || tim->Instance == TIM16 || tim->Instance == TIM17)
+#elif defined(SOC_SERIES_STM32F1)
+        if (0)
+#endif
+        {
+            prescaler_value = (uint32_t)(HAL_RCC_GetPCLK2Freq() * 2 / 10000) - 1;
+        }
+        else
+        {
+            prescaler_value = (uint32_t)(HAL_RCC_GetPCLK1Freq() * 2 / 10000) - 1;
+        }
+        tim->Init.Period            = 10000 - 1;
+        tim->Init.Prescaler         = prescaler_value;
+        tim->Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;
+        if (timer->info->cntmode == HWTIMER_CNTMODE_UP)
+        {
+            tim->Init.CounterMode   = TIM_COUNTERMODE_UP;
+        }
+        else
+        {
+            tim->Init.CounterMode   = TIM_COUNTERMODE_DOWN;
+        }
+        tim->Init.RepetitionCounter = 0;
+#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32L4)
+        tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+#endif
+        if (HAL_TIM_Base_Init(tim) != HAL_OK)
+        {
+            LOG_E("%s init failed", tim_device->name);
+            return;
+        }
+        else
+        {
+            /* set the TIMx priority */
+            HAL_NVIC_SetPriority(tim_device->tim_irqn, 3, 0);
+
+            /* enable the TIMx global Interrupt */
+            HAL_NVIC_EnableIRQ(tim_device->tim_irqn);
+
+            /* clear update flag */
+            __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE);
+            /* enable update request source */
+            __HAL_TIM_URS_ENABLE(tim);
+
+            LOG_D("%s init success", tim_device->name);
+        }
+    }
+}
+
+static rt_err_t timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode)
+{
+    rt_err_t result = RT_EOK;
+    TIM_HandleTypeDef *tim = RT_NULL;
+
+    RT_ASSERT(timer != RT_NULL);
+
+    tim = (TIM_HandleTypeDef *)timer->parent.user_data;
+
+    /* set tim cnt */
+    __HAL_TIM_SET_AUTORELOAD(tim, t);
+
+    if (opmode == HWTIMER_MODE_ONESHOT)
+    {
+        /* set timer to single mode */
+        tim->Instance->CR1 |= TIM_OPMODE_SINGLE;
+    }
+
+    /* start timer */
+    if (HAL_TIM_Base_Start_IT(tim) != HAL_OK)
+    {
+        LOG_E("TIM2 start failed");
+        result = -RT_ERROR;
+    }
+
+    return result;
+}
+
+static void timer_stop(rt_hwtimer_t *timer)
+{
+    TIM_HandleTypeDef *tim = RT_NULL;
+
+    RT_ASSERT(timer != RT_NULL);
+
+    tim = (TIM_HandleTypeDef *)timer->parent.user_data;
+
+    /* stop timer */
+    HAL_TIM_Base_Stop_IT(tim);
+}
+
+static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
+{
+    TIM_HandleTypeDef *tim = RT_NULL;
+    rt_err_t result = RT_EOK;
+
+    RT_ASSERT(timer != RT_NULL);
+    RT_ASSERT(arg != RT_NULL);
+
+    tim = (TIM_HandleTypeDef *)timer->parent.user_data;
+
+    switch (cmd)
+    {
+    case HWTIMER_CTRL_FREQ_SET:
+    {
+        rt_uint32_t freq;
+        rt_uint16_t val;
+
+        /* set timer frequence */
+        freq = *((rt_uint32_t *)arg);
+
+#if defined(SOC_SERIES_STM32F4)
+        if (tim->Instance == TIM9 || tim->Instance == TIM10 || tim->Instance == TIM11)
+#elif defined(SOC_SERIES_STM32L4)
+        if (tim->Instance == TIM15 || tim->Instance == TIM16 || tim->Instance == TIM17)
+#elif defined(SOC_SERIES_STM32F1)
+        if (0)
+#endif
+        {
+#if defined(SOC_SERIES_STM32L4)
+            val = HAL_RCC_GetPCLK2Freq() / freq;
+#else
+            val = HAL_RCC_GetPCLK2Freq() * 2 / freq;
+#endif
+        }
+        else
+        {
+            val = HAL_RCC_GetPCLK1Freq() * 2 / freq;
+        }
+        __HAL_TIM_SET_PRESCALER(tim, val - 1);
+
+        /* Update frequency value */
+        tim->Instance->EGR |= TIM_EVENTSOURCE_UPDATE;
+    }
+    break;
+    default:
+    {
+        result = -RT_ENOSYS;
+    }
+    break;
+    }
+
+    return result;
+}
+
+static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer)
+{
+    TIM_HandleTypeDef *tim = RT_NULL;
+
+    RT_ASSERT(timer != RT_NULL);
+
+    tim = (TIM_HandleTypeDef *)timer->parent.user_data;
+
+    return tim->Instance->CNT;
+}
+
+static const struct rt_hwtimer_info _info = TIM_DEV_INFO_CONFIG;
+
+static const struct rt_hwtimer_ops _ops =
+{
+    .init = timer_init,
+    .start = timer_start,
+    .stop = timer_stop,
+    .count_get = timer_counter_get,
+    .control = timer_ctrl,
+};
+
+#ifdef BSP_USING_TIM2
+void TIM2_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM2_INDEX].tim_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#ifdef BSP_USING_TIM3
+void TIM3_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM3_INDEX].tim_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#ifdef BSP_USING_TIM4
+void TIM4_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM4_INDEX].tim_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#ifdef BSP_USING_TIM5
+void TIM5_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM5_INDEX].tim_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#ifdef BSP_USING_TIM11
+void TIM1_TRG_COM_TIM11_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM11_INDEX].tim_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#ifdef BSP_USING_TIM13
+void TIM8_UP_TIM13_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM13_INDEX].tim_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#ifdef BSP_USING_TIM14
+void TIM8_TRG_COM_TIM14_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM14_INDEX].tim_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#ifdef BSP_USING_TIM15
+void TIM1_BRK_TIM15_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM15_INDEX].tim_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#ifdef BSP_USING_TIM16
+void TIM1_UP_TIM16_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM16_INDEX].tim_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#ifdef BSP_USING_TIM17
+void TIM1_TRG_COM_TIM17_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM17_INDEX].tim_handle);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+
+void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
+{
+#ifdef BSP_USING_TIM2
+    if (htim->Instance == TIM2)
+    {
+        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM2_INDEX].time_device);
+    }
+#endif
+#ifdef BSP_USING_TIM3
+    if (htim->Instance == TIM3)
+    {
+        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM3_INDEX].time_device);
+    }
+#endif
+#ifdef BSP_USING_TIM4
+    if (htim->Instance == TIM4)
+    {
+        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM4_INDEX].time_device);
+    }
+#endif
+#ifdef BSP_USING_TIM5
+    if (htim->Instance == TIM5)
+    {
+        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM5_INDEX].time_device);
+    }
+#endif
+#ifdef BSP_USING_TIM11
+    if (htim->Instance == TIM11)
+    {
+        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM11_INDEX].time_device);
+    }
+#endif
+#ifdef BSP_USING_TIM13
+    if (htim->Instance == TIM13)
+    {
+        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM13_INDEX].time_device);
+    }
+#endif
+#ifdef BSP_USING_TIM14
+    if (htim->Instance == TIM14)
+    {
+        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM14_INDEX].time_device);
+    }
+#endif
+#ifdef BSP_USING_TIM15
+    if (htim->Instance == TIM15)
+    {
+        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM15_INDEX].time_device);
+    }
+#endif
+#ifdef BSP_USING_TIM16
+    if (htim->Instance == TIM16)
+    {
+        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM16_INDEX].time_device);
+    }
+#endif
+#ifdef BSP_USING_TIM17
+    if (htim->Instance == TIM17)
+    {
+        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM17_INDEX].time_device);
+    }
+#endif
+}
+
+static int stm32_hwtimer_init(void)
+{
+    int i = 0;
+    int result = RT_EOK;
+
+    for (i = 0; i < sizeof(stm32_hwtimer_obj) / sizeof(stm32_hwtimer_obj[0]); i++)
+    {
+        stm32_hwtimer_obj[i].time_device.info = &_info;
+        stm32_hwtimer_obj[i].time_device.ops  = &_ops;
+        if (rt_device_hwtimer_register(&stm32_hwtimer_obj[i].time_device, stm32_hwtimer_obj[i].name, &stm32_hwtimer_obj[i].tim_handle) == RT_EOK)
+        {
+            LOG_D("%s register success", stm32_hwtimer_obj[i].name);
+        }
+        else
+        {
+            LOG_E("%s register failed", stm32_hwtimer_obj[i].name);
+            result = -RT_ERROR;
+        }
+    }
+
+    return result;
+}
+INIT_BOARD_EXPORT(stm32_hwtimer_init);
+
+#endif /* RT_USING_HWTIMER */
+#endif /* BSP_USING_TIM */

+ 480 - 0
bsp/stm32/libraries/HAL_Drivers/drv_pwm.c

@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-13     zylx         first version
+ */
+
+#include <board.h>
+#ifdef RT_USING_PWM
+#include "drv_config.h"
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.pwm"
+#include <drv_log.h>
+
+#define MAX_PERIOD 65535
+#define MIN_PERIOD 3
+#define MIN_PULSE 2
+
+extern void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
+
+enum
+{
+#ifdef BSP_USING_PWM1
+    PWM1_INDEX,
+#endif
+#ifdef BSP_USING_PWM2
+    PWM2_INDEX,
+#endif
+#ifdef BSP_USING_PWM3
+    PWM3_INDEX,
+#endif
+#ifdef BSP_USING_PWM4
+    PWM4_INDEX,
+#endif
+#ifdef BSP_USING_PWM5
+    PWM5_INDEX,
+#endif
+#ifdef BSP_USING_PWM6
+    PWM6_INDEX,
+#endif
+#ifdef BSP_USING_PWM7
+    PWM7_INDEX,
+#endif
+#ifdef BSP_USING_PWM8
+    PWM8_INDEX,
+#endif
+#ifdef BSP_USING_PWM9
+    PWM9_INDEX,
+#endif
+#ifdef BSP_USING_PWM10
+    PWM10_INDEX,
+#endif
+#ifdef BSP_USING_PWM11
+    PWM11_INDEX,
+#endif
+#ifdef BSP_USING_PWM12
+    PWM12_INDEX,
+#endif
+#ifdef BSP_USING_PWM13
+    PWM13_INDEX,
+#endif
+#ifdef BSP_USING_PWM14
+    PWM14_INDEX,
+#endif
+#ifdef BSP_USING_PWM15
+    PWM15_INDEX,
+#endif
+#ifdef BSP_USING_PWM16
+    PWM16_INDEX,
+#endif
+#ifdef BSP_USING_PWM17
+    PWM17_INDEX,
+#endif
+};
+
+struct stm32_pwm
+{
+    struct rt_device_pwm pwm_device;
+    TIM_HandleTypeDef    tim_handle;
+    rt_uint8_t channel;
+    char *name;
+};
+
+static struct stm32_pwm stm32_pwm_obj[] =
+{
+#ifdef BSP_USING_PWM1
+    PWM1_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM2
+    PWM2_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM3
+    PWM3_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM4
+    PWM4_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM5
+    PWM5_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM6
+    PWM6_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM7
+    PWM7_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM8
+    PWM8_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM9
+    PWM9_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM10
+    PWM10_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM11
+    PWM11_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM12
+    PWM12_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM13
+    PWM13_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM14
+    PWM14_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM15
+    PWM15_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM16
+    PWM16_CONFIG,
+#endif
+
+#ifdef BSP_USING_PWM17
+    PWM17_CONFIG,
+#endif
+};
+
+static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg);
+static struct rt_pwm_ops drv_ops =
+{
+    drv_pwm_control
+};
+
+static rt_err_t drv_pwm_enable(TIM_HandleTypeDef *htim, struct rt_pwm_configuration *configuration, rt_bool_t enable)
+{
+    /* Converts the channel number to the channel number of Hal library */
+    rt_uint32_t channel = 0x04 * (configuration->channel - 1);
+
+    if (!enable)
+    {
+        HAL_TIM_PWM_Stop(htim, channel);
+    }
+    else
+    {
+        HAL_TIM_PWM_Start(htim, channel);
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t drv_pwm_get(TIM_HandleTypeDef *htim, struct rt_pwm_configuration *configuration)
+{
+    /* Converts the channel number to the channel number of Hal library */
+    rt_uint32_t channel = 0x04 * (configuration->channel - 1);
+    rt_uint64_t tim_clock;
+
+#if defined(SOC_SERIES_STM32F4)
+    if (htim->Instance == TIM9 || htim->Instance == TIM10 || htim->Instance == TIM11)
+#elif defined(SOC_SERIES_STM32L4)
+    if (htim->Instance == TIM15 || htim->Instance == TIM16 || htim->Instance == TIM17)
+#elif defined(SOC_SERIES_STM32F1)
+    if (0)
+#endif
+    {
+        tim_clock = HAL_RCC_GetPCLK2Freq() * 2;
+    }
+    else
+    {
+#if defined(SOC_SERIES_STM32L4)
+        tim_clock = HAL_RCC_GetPCLK1Freq();
+#else
+        tim_clock = HAL_RCC_GetPCLK1Freq() * 2;
+#endif
+    }
+    
+    if (__HAL_TIM_GET_CLOCKDIVISION(htim) == TIM_CLOCKDIVISION_DIV2)
+    {
+        tim_clock = tim_clock / 2;
+    }
+    else if (__HAL_TIM_GET_CLOCKDIVISION(htim) == TIM_CLOCKDIVISION_DIV4)
+    {
+        tim_clock = tim_clock / 4;
+    }
+
+    /* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */
+    tim_clock /= 1000000UL;
+    configuration->period = (__HAL_TIM_GET_AUTORELOAD(htim) + 1) * (htim->Instance->PSC + 1) * 1000UL / tim_clock;
+    configuration->pulse = (__HAL_TIM_GET_COMPARE(htim, channel) + 1) * (htim->Instance->PSC + 1) * 1000UL / tim_clock;
+
+    return RT_EOK;
+}
+
+static rt_err_t drv_pwm_set(TIM_HandleTypeDef *htim, struct rt_pwm_configuration *configuration)
+{
+    rt_uint32_t period, pulse;
+    rt_uint64_t tim_clock, psc;
+    /* Converts the channel number to the channel number of Hal library */
+    rt_uint32_t channel = 0x04 * (configuration->channel - 1);
+
+#if defined(SOC_SERIES_STM32F4)
+    if (htim->Instance == TIM9 || htim->Instance == TIM10 || htim->Instance == TIM11)
+#elif defined(SOC_SERIES_STM32L4)
+    if (htim->Instance == TIM15 || htim->Instance == TIM16 || htim->Instance == TIM17)
+#elif defined(SOC_SERIES_STM32F1)
+    if (0)
+#endif
+    {
+        tim_clock = HAL_RCC_GetPCLK2Freq() * 2;
+    }
+    else
+    {
+#if defined(SOC_SERIES_STM32L4)
+        tim_clock = HAL_RCC_GetPCLK1Freq();
+#else
+        tim_clock = HAL_RCC_GetPCLK1Freq() * 2;
+#endif
+    }
+
+    /* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */
+    tim_clock /= 1000000UL;
+    period = (unsigned long long)configuration->period * tim_clock / 1000ULL ;
+    psc = period / MAX_PERIOD + 1;
+    period = period / psc;
+    __HAL_TIM_SET_PRESCALER(htim, psc - 1);
+
+    if (period < MIN_PERIOD)
+    {
+        period = MIN_PERIOD;
+    }
+    __HAL_TIM_SET_AUTORELOAD(htim, period - 1);
+
+    pulse = (unsigned long long)configuration->pulse * tim_clock / psc / 1000ULL;
+    if (pulse < MIN_PULSE)
+    {
+        pulse = MIN_PULSE;
+    }
+    else if (pulse > period)
+    {
+        pulse = period;
+    }
+    __HAL_TIM_SET_COMPARE(htim, channel, pulse - 1);
+    __HAL_TIM_SET_COUNTER(htim, 0);
+
+    /* Update frequency value */
+    HAL_TIM_GenerateEvent(htim, TIM_EVENTSOURCE_UPDATE);
+
+    return RT_EOK;
+}
+
+static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
+{
+    struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
+    TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)device->parent.user_data;
+
+    switch (cmd)
+    {
+    case PWM_CMD_ENABLE:
+        return drv_pwm_enable(htim, configuration, RT_TRUE);
+    case PWM_CMD_DISABLE:
+        return drv_pwm_enable(htim, configuration, RT_FALSE);
+    case PWM_CMD_SET:
+        return drv_pwm_set(htim, configuration);
+    case PWM_CMD_GET:
+        return drv_pwm_get(htim, configuration);
+    default:
+        return RT_EINVAL;
+    }
+}
+
+static rt_err_t stm32_hw_pwm_init(struct stm32_pwm *device)
+{
+    rt_err_t result = RT_EOK;
+    TIM_HandleTypeDef *tim = RT_NULL;
+    TIM_OC_InitTypeDef oc_config = {0};
+    TIM_MasterConfigTypeDef master_config = {0};
+    TIM_ClockConfigTypeDef clock_config = {0};
+
+    RT_ASSERT(device != RT_NULL);
+
+    tim = (TIM_HandleTypeDef *)&device->tim_handle;
+
+    /* configure the timer to pwm mode */
+    tim->Init.Prescaler = 0;
+    tim->Init.CounterMode = TIM_COUNTERMODE_UP;
+    tim->Init.Period = 0;
+    tim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32L4)
+    tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+#endif
+    if (HAL_TIM_Base_Init(tim) != HAL_OK)
+    {
+        LOG_E("%s time base init failed", device->name);
+        result = -RT_ERROR;
+        goto __exit;
+    }
+
+    clock_config.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
+    if (HAL_TIM_ConfigClockSource(tim, &clock_config) != HAL_OK)
+    {
+        LOG_E("%s clock init failed", device->name);
+        result = -RT_ERROR;
+        goto __exit;
+    }
+
+    if (HAL_TIM_PWM_Init(tim) != HAL_OK)
+    {
+        LOG_E("%s pwm init failed", device->name);
+        result = -RT_ERROR;
+        goto __exit;
+    }
+
+    master_config.MasterOutputTrigger = TIM_TRGO_RESET;
+    master_config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+    if (HAL_TIMEx_MasterConfigSynchronization(tim, &master_config) != HAL_OK)
+    {
+        LOG_E("%s master config failed", device->name);
+        result = -RT_ERROR;
+        goto __exit;
+    }
+
+    oc_config.OCMode = TIM_OCMODE_PWM1;
+    oc_config.Pulse = 0;
+    oc_config.OCPolarity = TIM_OCPOLARITY_HIGH;
+    oc_config.OCFastMode = TIM_OCFAST_DISABLE;
+
+    /* config pwm channel */
+    if (device->channel & 0x01)
+    {
+        if (HAL_TIM_PWM_ConfigChannel(tim, &oc_config, TIM_CHANNEL_1) != HAL_OK)
+        {
+            LOG_E("%s channel1 config failed", device->name);
+            result = -RT_ERROR;
+            goto __exit;
+        }
+    }
+
+    if (device->channel & 0x02)
+    {
+        if (HAL_TIM_PWM_ConfigChannel(tim, &oc_config, TIM_CHANNEL_2) != HAL_OK)
+        {
+            LOG_E("%s channel2 config failed", device->name);
+            result = -RT_ERROR;
+            goto __exit;
+        }
+    }
+
+    if (device->channel & 0x04)
+    {
+        if (HAL_TIM_PWM_ConfigChannel(tim, &oc_config, TIM_CHANNEL_3) != HAL_OK)
+        {
+            LOG_E("%s channel3 config failed", device->name);
+            result = -RT_ERROR;
+            goto __exit;
+        }
+    }
+
+    if (device->channel & 0x08)
+    {
+        if (HAL_TIM_PWM_ConfigChannel(tim, &oc_config, TIM_CHANNEL_4) != HAL_OK)
+        {
+            LOG_E("%s channel4 config failed", device->name);
+            result = -RT_ERROR;
+            goto __exit;
+        }
+    }
+
+    /* pwm pin configuration */
+    HAL_TIM_MspPostInit(tim);
+
+    /* enable update request source */
+    __HAL_TIM_URS_ENABLE(tim);
+
+__exit:
+    return result;
+}
+
+static void pwm_get_channel(void)
+{
+#ifdef BSP_USING_PWM2_CH4
+    stm32_pwm_obj[PWM2_INDEX].channel |= 1 << 3;
+#endif
+#ifdef BSP_USING_PWM3_CH1
+    stm32_pwm_obj[PWM3_INDEX].channel |= 1 << 0;
+#endif
+#ifdef BSP_USING_PWM3_CH2
+    stm32_pwm_obj[PWM3_INDEX].channel |= 1 << 1;
+#endif
+#ifdef BSP_USING_PWM3_CH3
+    stm32_pwm_obj[PWM3_INDEX].channel |= 1 << 2;
+#endif
+#ifdef BSP_USING_PWM3_CH4
+    stm32_pwm_obj[PWM3_INDEX].channel |= 1 << 3;
+#endif
+#ifdef BSP_USING_PWM4_CH2
+    stm32_pwm_obj[PWM4_INDEX].channel |= 1 << 1;
+#endif
+#ifdef BSP_USING_PWM4_CH3
+    stm32_pwm_obj[PWM4_INDEX].channel |= 1 << 2;
+#endif
+#ifdef BSP_USING_PWM5_CH1
+    stm32_pwm_obj[PWM5_INDEX].channel |= 1 << 1;
+#endif
+#ifdef BSP_USING_PWM5_CH2
+    stm32_pwm_obj[PWM5_INDEX].channel |= 1 << 2;
+#endif
+#ifdef BSP_USING_PWM5_CH3
+    stm32_pwm_obj[PWM5_INDEX].channel |= 1 << 3;
+#endif
+}
+
+static int stm32_pwm_init(void)
+{
+    int i = 0;
+    int result = RT_EOK;
+
+    pwm_get_channel();
+
+    for (i = 0; i < sizeof(stm32_pwm_obj) / sizeof(stm32_pwm_obj[0]); i++)
+    {
+        /* pwm init */
+        if (stm32_hw_pwm_init(&stm32_pwm_obj[i]) != RT_EOK)
+        {
+            LOG_E("%s init failed", stm32_pwm_obj[i].name);
+            result = -RT_ERROR;
+            goto __exit;
+        }
+        else
+        {
+            LOG_D("%s init success", stm32_pwm_obj[i].name);
+
+            /* register pwm device */
+            if (rt_device_pwm_register(rt_calloc(1, sizeof(struct rt_device_pwm)), stm32_pwm_obj[i].name, &drv_ops, &stm32_pwm_obj[i].tim_handle) == RT_EOK)
+            {
+
+                LOG_D("%s register success", stm32_pwm_obj[i].name);
+            }
+            else
+            {
+                LOG_E("%s register failed", stm32_pwm_obj[i].name);
+                result = -RT_ERROR;
+            }
+        }
+    }
+
+__exit:
+    return result;
+}
+INIT_DEVICE_EXPORT(stm32_pwm_init);
+#endif /* RT_USING_PWM */

+ 846 - 0
bsp/stm32/libraries/HAL_Drivers/drv_sdio.c

@@ -0,0 +1,846 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-06-22     tyx          first
+ * 2018-12-12     balanceTWK   change to new framework
+ */
+
+#include "board.h"
+#include "drv_sdio.h"
+#include "drv_config.h"
+
+#ifdef BSP_USING_SDIO
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.sdio"
+#include <drv_log.h>
+
+static struct stm32_sdio_config sdio_config = SDIO_BUS_CONFIG;
+static struct stm32_sdio_class sdio_obj;
+static struct rt_mmcsd_host *host;
+
+#define SDIO_TX_RX_COMPLETE_TIMEOUT_LOOPS    (100000)
+
+#define RTHW_SDIO_LOCK(_sdio)   rt_mutex_take(&_sdio->mutex, RT_WAITING_FOREVER)
+#define RTHW_SDIO_UNLOCK(_sdio) rt_mutex_release(&_sdio->mutex);
+
+struct sdio_pkg
+{
+    struct rt_mmcsd_cmd *cmd;
+    void *buff;
+    rt_uint32_t flag;
+};
+
+struct rthw_sdio
+{
+    struct rt_mmcsd_host *host;
+    struct stm32_sdio_des sdio_des;
+    struct rt_event event;
+    struct rt_mutex mutex;
+    struct sdio_pkg *pkg;
+};
+
+ALIGN(SDIO_ALIGN_LEN)
+static rt_uint8_t cache_buf[SDIO_BUFF_SIZE];
+
+static rt_uint32_t stm32_sdio_clk_get(struct stm32_sdio *hw_sdio)
+{
+    return SDIO_CLOCK_FREQ;
+}
+
+/**
+  * @brief  This function get order from sdio.
+  * @param  data
+  * @retval sdio  order
+  */
+static int get_order(rt_uint32_t data)
+{
+    int order = 0;
+
+    switch (data)
+    {
+    case 1:
+        order = 0;
+        break;
+    case 2:
+        order = 1;
+        break;
+    case 4:
+        order = 2;
+        break;
+    case 8:
+        order = 3;
+        break;
+    case 16:
+        order = 4;
+        break;
+    case 32:
+        order = 5;
+        break;
+    case 64:
+        order = 6;
+        break;
+    case 128:
+        order = 7;
+        break;
+    case 256:
+        order = 8;
+        break;
+    case 512:
+        order = 9;
+        break;
+    case 1024:
+        order = 10;
+        break;
+    case 2048:
+        order = 11;
+        break;
+    case 4096:
+        order = 12;
+        break;
+    case 8192:
+        order = 13;
+        break;
+    case 16384:
+        order = 14;
+        break;
+    default :
+        order = 0;
+        break;
+    }
+
+    return order;
+}
+
+/**
+  * @brief  This function wait sdio completed.
+  * @param  sdio  rthw_sdio
+  * @retval None
+  */
+static void rthw_sdio_wait_completed(struct rthw_sdio *sdio)
+{
+    rt_uint32_t status;
+    struct rt_mmcsd_cmd *cmd = sdio->pkg->cmd;
+    struct rt_mmcsd_data *data = cmd->data;
+    struct stm32_sdio *hw_sdio = sdio->sdio_des.hw_sdio;
+
+    if (rt_event_recv(&sdio->event, 0xffffffff, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
+                      rt_tick_from_millisecond(5000), &status) != RT_EOK)
+    {
+        LOG_E("wait completed timeout");
+        cmd->err = -RT_ETIMEOUT;
+        return;
+    }
+
+    if (sdio->pkg == RT_NULL)
+    {
+        return;
+    }
+
+    cmd->resp[0] = hw_sdio->resp1;
+    cmd->resp[1] = hw_sdio->resp2;
+    cmd->resp[2] = hw_sdio->resp3;
+    cmd->resp[3] = hw_sdio->resp4;
+
+    if (status & HW_SDIO_ERRORS)
+    {
+        if ((status & HW_SDIO_IT_CCRCFAIL) && (resp_type(cmd) & (RESP_R3 | RESP_R4)))
+        {
+            cmd->err = RT_EOK;
+        }
+        else
+        {
+            cmd->err = -RT_ERROR;
+        }
+
+        if (status & HW_SDIO_IT_CTIMEOUT)
+        {
+            cmd->err = -RT_ETIMEOUT;
+        }
+
+        if (status & HW_SDIO_IT_DCRCFAIL)
+        {
+            data->err = -RT_ERROR;
+        }
+
+        if (status & HW_SDIO_IT_DTIMEOUT)
+        {
+            data->err = -RT_ETIMEOUT;
+        }
+
+        if (cmd->err == RT_EOK)
+        {
+            LOG_D("sta:0x%08X [%08X %08X %08X %08X]", status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+        }
+        else
+        {
+            LOG_D("err:0x%08x, %s%s%s%s%s%s%s cmd:%d arg:0x%08x rw:%c len:%d blksize:%d",
+                  status,
+                  status & HW_SDIO_IT_CCRCFAIL  ? "CCRCFAIL "    : "",
+                  status & HW_SDIO_IT_DCRCFAIL  ? "DCRCFAIL "    : "",
+                  status & HW_SDIO_IT_CTIMEOUT  ? "CTIMEOUT "    : "",
+                  status & HW_SDIO_IT_DTIMEOUT  ? "DTIMEOUT "    : "",
+                  status & HW_SDIO_IT_TXUNDERR  ? "TXUNDERR "    : "",
+                  status & HW_SDIO_IT_RXOVERR   ? "RXOVERR "     : "",
+                  status == 0                   ? "NULL"         : "",
+                  cmd->cmd_code,
+                  cmd->arg,
+                  data ? (data->flags & DATA_DIR_WRITE ?  'w' : 'r') : '-',
+                      data ? data->blks * data->blksize : 0,
+                      data ? data->blksize : 0
+                     );
+        }
+    }
+    else
+{
+        cmd->err = RT_EOK;
+        LOG_D("sta:0x%08X [%08X %08X %08X %08X]", status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+    }
+}
+
+/**
+  * @brief  This function transfer data by dma.
+  * @param  sdio  rthw_sdio
+  * @param  pkg   sdio package
+  * @retval None
+  */
+static void rthw_sdio_transfer_by_dma(struct rthw_sdio *sdio, struct sdio_pkg *pkg)
+{
+    struct rt_mmcsd_data *data;
+    int size;
+    void *buff;
+    struct stm32_sdio *hw_sdio;
+
+    if ((RT_NULL == pkg) || (RT_NULL == sdio))
+    {
+        LOG_E("rthw_sdio_transfer_by_dma invalid args");
+        return;
+    }
+
+    data = pkg->cmd->data;
+    if (RT_NULL == data)
+    {
+        LOG_E("rthw_sdio_transfer_by_dma invalid args");
+        return;
+    }
+
+    buff = pkg->buff;
+    if (RT_NULL == buff)
+    {
+        LOG_E("rthw_sdio_transfer_by_dma invalid args");
+        return;
+    }
+    hw_sdio = sdio->sdio_des.hw_sdio;
+    size = data->blks * data->blksize;
+
+    if (data->flags & DATA_DIR_WRITE)
+    {
+        sdio->sdio_des.txconfig((rt_uint32_t *)buff, (rt_uint32_t *)&hw_sdio->fifo, size);
+        hw_sdio->dctrl |= HW_SDIO_DMA_ENABLE;
+    }
+    else if (data->flags & DATA_DIR_READ)
+    {
+        sdio->sdio_des.rxconfig((rt_uint32_t *)&hw_sdio->fifo, (rt_uint32_t *)buff, size);
+        hw_sdio->dctrl |= HW_SDIO_DMA_ENABLE | HW_SDIO_DPSM_ENABLE;
+    }
+}
+
+/**
+  * @brief  This function send command.
+  * @param  sdio  rthw_sdio
+  * @param  pkg   sdio package
+  * @retval None
+  */
+static void rthw_sdio_send_command(struct rthw_sdio *sdio, struct sdio_pkg *pkg)
+{
+    struct rt_mmcsd_cmd *cmd = pkg->cmd;
+    struct rt_mmcsd_data *data = cmd->data;
+    struct stm32_sdio *hw_sdio = sdio->sdio_des.hw_sdio;
+    rt_uint32_t reg_cmd;
+
+    /* save pkg */
+    sdio->pkg = pkg;
+
+    LOG_D("CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d",
+          cmd->cmd_code,
+          cmd->arg,
+          resp_type(cmd) == RESP_NONE ? "NONE"  : "",
+          resp_type(cmd) == RESP_R1  ? "R1"  : "",
+          resp_type(cmd) == RESP_R1B ? "R1B"  : "",
+          resp_type(cmd) == RESP_R2  ? "R2"  : "",
+          resp_type(cmd) == RESP_R3  ? "R3"  : "",
+          resp_type(cmd) == RESP_R4  ? "R4"  : "",
+          resp_type(cmd) == RESP_R5  ? "R5"  : "",
+          resp_type(cmd) == RESP_R6  ? "R6"  : "",
+          resp_type(cmd) == RESP_R7  ? "R7"  : "",
+          data ? (data->flags & DATA_DIR_WRITE ?  'w' : 'r') : '-',
+              data ? data->blks * data->blksize : 0,
+              data ? data->blksize : 0
+             );
+
+    /* config cmd reg */
+    reg_cmd = cmd->cmd_code | HW_SDIO_CPSM_ENABLE;
+    if (resp_type(cmd) == RESP_NONE)
+        reg_cmd |= HW_SDIO_RESPONSE_NO;
+    else if (resp_type(cmd) == RESP_R2)
+        reg_cmd |= HW_SDIO_RESPONSE_LONG;
+    else
+        reg_cmd |= HW_SDIO_RESPONSE_SHORT;
+
+    /* config data reg */
+    if (data != RT_NULL)
+{
+        rt_uint32_t dir = 0;
+        rt_uint32_t size = data->blks * data->blksize;
+        int order;
+
+        hw_sdio->dctrl = 0;
+        hw_sdio->dtimer = HW_SDIO_DATATIMEOUT;
+        hw_sdio->dlen = size;
+        order = get_order(data->blksize);
+        dir = (data->flags & DATA_DIR_READ) ? HW_SDIO_TO_HOST : 0;
+        hw_sdio->dctrl = HW_SDIO_IO_ENABLE | (order << 4) | dir;
+    }
+
+    /* transfer config */
+    if (data != RT_NULL)
+    {
+        rthw_sdio_transfer_by_dma(sdio, pkg);
+    }
+
+    /* open irq */
+    hw_sdio->mask |= HW_SDIO_IT_CMDSENT | HW_SDIO_IT_CMDREND | HW_SDIO_ERRORS;
+    if (data != RT_NULL)
+    {
+        hw_sdio->mask |= HW_SDIO_IT_DATAEND;
+    }
+
+    /* send cmd */
+    hw_sdio->arg = cmd->arg;
+    hw_sdio->cmd = reg_cmd;
+
+    /* wait completed */
+    rthw_sdio_wait_completed(sdio);
+
+    /* Waiting for data to be sent to completion */
+    if (data != RT_NULL)
+    {
+        volatile rt_uint32_t count = SDIO_TX_RX_COMPLETE_TIMEOUT_LOOPS;
+
+        while (count && (hw_sdio->sta & (HW_SDIO_IT_TXACT | HW_SDIO_IT_RXACT)))
+        {
+            count--;
+        }
+
+        if ((count == 0) || (hw_sdio->sta & HW_SDIO_ERRORS))
+        {
+            cmd->err = -RT_ERROR;
+        }
+    }
+
+    /* close irq, keep sdio irq */
+    hw_sdio->mask = hw_sdio->mask & HW_SDIO_IT_SDIOIT ? HW_SDIO_IT_SDIOIT : 0x00;
+
+    /* clear pkg */
+    sdio->pkg = RT_NULL;
+}
+
+/**
+  * @brief  This function send sdio request.
+  * @param  sdio  rthw_sdio
+  * @param  req   request
+  * @retval None
+  */
+static void rthw_sdio_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
+{
+    struct sdio_pkg pkg;
+    struct rthw_sdio *sdio = host->private_data;
+    struct rt_mmcsd_data *data;
+
+    RTHW_SDIO_LOCK(sdio);
+
+    if (req->cmd != RT_NULL)
+    {
+        memset(&pkg, 0, sizeof(pkg));
+        data = req->cmd->data;
+        pkg.cmd = req->cmd;
+
+        if (data != RT_NULL)
+        {
+            rt_uint32_t size = data->blks * data->blksize;
+
+            RT_ASSERT(size <= SDIO_BUFF_SIZE);
+
+            pkg.buff = data->buf;
+            if ((rt_uint32_t)data->buf & (SDIO_ALIGN_LEN - 1))
+            {
+                pkg.buff = cache_buf;
+                if (data->flags & DATA_DIR_WRITE)
+                {
+                    memcpy(cache_buf, data->buf, size);
+                }
+            }
+        }
+
+        rthw_sdio_send_command(sdio, &pkg);
+
+        if ((data != RT_NULL) && (data->flags & DATA_DIR_READ) && ((rt_uint32_t)data->buf & (SDIO_ALIGN_LEN - 1)))
+        {
+            memcpy(data->buf, cache_buf, data->blksize * data->blks);
+        }
+    }
+
+    if (req->stop != RT_NULL)
+    {
+        memset(&pkg, 0, sizeof(pkg));
+        pkg.cmd = req->stop;
+        rthw_sdio_send_command(sdio, &pkg);
+    }
+
+    RTHW_SDIO_UNLOCK(sdio);
+
+    mmcsd_req_complete(sdio->host);
+}
+
+/**
+  * @brief  This function config sdio.
+  * @param  host    rt_mmcsd_host
+  * @param  io_cfg  rt_mmcsd_io_cfg
+  * @retval None
+  */
+static void rthw_sdio_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
+{
+    rt_uint32_t clkcr, div, clk_src;
+    rt_uint32_t clk = io_cfg->clock;
+    struct rthw_sdio *sdio = host->private_data;
+    struct stm32_sdio *hw_sdio = sdio->sdio_des.hw_sdio;
+
+    clk_src = sdio->sdio_des.clk_get(sdio->sdio_des.hw_sdio);
+    if (clk_src < 400 * 1000)
+    {
+        LOG_E("The clock rate is too low! rata:%d", clk_src);
+        return;
+    }
+
+    if (clk > host->freq_max) clk = host->freq_max;
+
+    if (clk > clk_src)
+    {
+        LOG_W("Setting rate is greater than clock source rate.");
+        clk = clk_src;
+    }
+
+    LOG_D("clk:%d width:%s%s%s power:%s%s%s",
+          clk,
+          io_cfg->bus_width == MMCSD_BUS_WIDTH_8 ? "8" : "",
+          io_cfg->bus_width == MMCSD_BUS_WIDTH_4 ? "4" : "",
+          io_cfg->bus_width == MMCSD_BUS_WIDTH_1 ? "1" : "",
+          io_cfg->power_mode == MMCSD_POWER_OFF ? "OFF" : "",
+          io_cfg->power_mode == MMCSD_POWER_UP ? "UP" : "",
+          io_cfg->power_mode == MMCSD_POWER_ON ? "ON" : ""
+         );
+
+    RTHW_SDIO_LOCK(sdio);
+
+    div = clk_src / clk;
+    if ((clk == 0) || (div == 0))
+    {
+        clkcr = 0;
+    }
+    else
+    {
+        if (div < 2)
+        {
+            div = 2;
+        }
+        else if (div > 0xFF)
+        {
+            div = 0xFF;
+        }
+        div -= 2;
+        clkcr = div | HW_SDIO_CLK_ENABLE;
+    }
+
+    if (io_cfg->bus_width == MMCSD_BUS_WIDTH_8)
+    {
+        clkcr |= HW_SDIO_BUSWIDE_8B;
+    }
+    else if (io_cfg->bus_width == MMCSD_BUS_WIDTH_4)
+    {
+        clkcr |= HW_SDIO_BUSWIDE_4B;
+    }
+    else
+    {
+        clkcr |= HW_SDIO_BUSWIDE_1B;
+    }
+
+    hw_sdio->clkcr = clkcr;
+
+    switch (io_cfg->power_mode)
+    {
+    case MMCSD_POWER_OFF:
+        hw_sdio->power = HW_SDIO_POWER_OFF;
+        break;
+    case MMCSD_POWER_UP:
+        hw_sdio->power = HW_SDIO_POWER_UP;
+        break;
+    case MMCSD_POWER_ON:
+        hw_sdio->power = HW_SDIO_POWER_ON;
+        break;
+    default:
+        LOG_W("unknown power_mode %d", io_cfg->power_mode);
+        break;
+    }
+
+    RTHW_SDIO_UNLOCK(sdio);
+}
+
+/**
+  * @brief  This function update sdio interrupt.
+  * @param  host    rt_mmcsd_host
+  * @param  enable
+  * @retval None
+  */
+void rthw_sdio_irq_update(struct rt_mmcsd_host *host, rt_int32_t enable)
+{
+    struct rthw_sdio *sdio = host->private_data;
+    struct stm32_sdio *hw_sdio = sdio->sdio_des.hw_sdio;
+
+    if (enable)
+    {
+        LOG_D("enable sdio irq");
+        hw_sdio->mask |= HW_SDIO_IT_SDIOIT;
+    }
+    else
+    {
+        LOG_D("disable sdio irq");
+        hw_sdio->mask &= ~HW_SDIO_IT_SDIOIT;
+    }
+}
+
+/**
+  * @brief  This function delect sdcard.
+  * @param  host    rt_mmcsd_host
+  * @retval 0x01
+  */
+static rt_int32_t rthw_sd_delect(struct rt_mmcsd_host *host)
+{
+    LOG_D("try to detect device");
+    return 0x01;
+}
+
+/**
+  * @brief  This function interrupt process function.
+  * @param  host  rt_mmcsd_host
+  * @retval None
+  */
+void rthw_sdio_irq_process(struct rt_mmcsd_host *host)
+{
+    int complete = 0;
+    struct rthw_sdio *sdio = host->private_data;
+    struct stm32_sdio *hw_sdio = sdio->sdio_des.hw_sdio;
+    rt_uint32_t intstatus = hw_sdio->sta;
+
+    if (intstatus & HW_SDIO_ERRORS)
+    {
+        hw_sdio->icr = HW_SDIO_ERRORS;
+        complete = 1;
+    }
+    else
+    {
+        if (intstatus & HW_SDIO_IT_CMDREND)
+        {
+            hw_sdio->icr = HW_SDIO_IT_CMDREND;
+
+            if (sdio->pkg != RT_NULL)
+            {
+                if (!sdio->pkg->cmd->data)
+                {
+                    complete = 1;
+                }
+                else if ((sdio->pkg->cmd->data->flags & DATA_DIR_WRITE))
+                {
+                    hw_sdio->dctrl |= HW_SDIO_DPSM_ENABLE;
+                }
+            }
+        }
+
+        if (intstatus & HW_SDIO_IT_CMDSENT)
+        {
+            hw_sdio->icr = HW_SDIO_IT_CMDSENT;
+
+            if (resp_type(sdio->pkg->cmd) == RESP_NONE)
+            {
+                complete = 1;
+            }
+        }
+
+        if (intstatus & HW_SDIO_IT_DATAEND)
+        {
+            hw_sdio->icr = HW_SDIO_IT_DATAEND;
+            complete = 1;
+        }
+    }
+
+    if ((intstatus & HW_SDIO_IT_SDIOIT) && (hw_sdio->mask & HW_SDIO_IT_SDIOIT))
+    {
+        hw_sdio->icr = HW_SDIO_IT_SDIOIT;
+        sdio_irq_wakeup(host);
+    }
+
+    if (complete)
+    {
+        hw_sdio->mask &= ~HW_SDIO_ERRORS;
+        rt_event_send(&sdio->event, intstatus);
+    }
+}
+
+static const struct rt_mmcsd_host_ops ops =
+{
+    rthw_sdio_request,
+    rthw_sdio_iocfg,
+    rthw_sd_delect,
+    rthw_sdio_irq_update,
+};
+
+/**
+  * @brief  This function create mmcsd host.
+  * @param  sdio_des  stm32_sdio_des
+  * @retval rt_mmcsd_host
+  */
+struct rt_mmcsd_host *sdio_host_create(struct stm32_sdio_des *sdio_des)
+{
+    struct rt_mmcsd_host *host;
+    struct rthw_sdio *sdio = RT_NULL;
+
+    if ((sdio_des == RT_NULL) || (sdio_des->txconfig == RT_NULL) || (sdio_des->rxconfig == RT_NULL))
+    {
+        LOG_E("L:%d F:%s %s %s %s",
+              (sdio_des == RT_NULL ? "sdio_des is NULL" : ""),
+              (sdio_des ? (sdio_des->txconfig ? "txconfig is NULL" : "") : ""),
+              (sdio_des ? (sdio_des->rxconfig ? "rxconfig is NULL" : "") : "")
+             );
+        return RT_NULL;
+    }
+
+    sdio = rt_malloc(sizeof(struct rthw_sdio));
+    if (sdio == RT_NULL)
+    {
+        LOG_E("L:%d F:%s malloc rthw_sdio fail");
+        return RT_NULL;
+    }
+    rt_memset(sdio, 0, sizeof(struct rthw_sdio));
+
+    host = mmcsd_alloc_host();
+    if (host == RT_NULL)
+    {
+        LOG_E("L:%d F:%s mmcsd alloc host fail");
+        rt_free(sdio);
+        return RT_NULL;
+    }
+
+    rt_memcpy(&sdio->sdio_des, sdio_des, sizeof(struct stm32_sdio_des));
+    sdio->sdio_des.hw_sdio = (sdio_des->hw_sdio == RT_NULL ? (struct stm32_sdio *)SDIO_BASE_ADDRESS : sdio_des->hw_sdio);
+    sdio->sdio_des.clk_get = (sdio_des->clk_get == RT_NULL ? stm32_sdio_clk_get : sdio_des->clk_get);
+
+    rt_event_init(&sdio->event, "sdio", RT_IPC_FLAG_FIFO);
+    rt_mutex_init(&sdio->mutex, "sdio", RT_IPC_FLAG_FIFO);
+
+    /* set host defautl attributes */
+    host->ops = &ops;
+    host->freq_min = 400 * 1000;
+    host->freq_max = SDIO_MAX_FREQ;
+    host->valid_ocr = 0X00FFFF80;/* The voltage range supported is 1.65v-3.6v */
+#ifndef SDIO_USING_1_BIT
+    host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ;
+#else
+    host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ;
+#endif
+    host->max_seg_size = SDIO_BUFF_SIZE;
+    host->max_dma_segs = 1;
+    host->max_blk_size = 512;
+    host->max_blk_count = 512;
+
+    /* link up host and sdio */
+    sdio->host = host;
+    host->private_data = sdio;
+
+    rthw_sdio_irq_update(host, 1);
+
+    /* ready to change */
+    mmcsd_change(host);
+
+    return host;
+}
+
+/**
+  * @brief  This function configures the DMATX.
+  * @param  BufferSRC: pointer to the source buffer
+  * @param  BufferSize: buffer size
+  * @retval None
+  */
+void SD_LowLevel_DMA_TxConfig(uint32_t *src, uint32_t *dst, uint32_t BufferSize)
+{
+#if defined(SOC_SERIES_STM32F1)
+    static uint32_t size = 0;
+    size += BufferSize * 4;
+    sdio_obj.cfg = &sdio_config;
+    sdio_obj.dma.handle_tx.Instance = sdio_config.dma_tx.Instance;
+    sdio_obj.dma.handle_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
+    sdio_obj.dma.handle_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
+    sdio_obj.dma.handle_tx.Init.MemInc              = DMA_MINC_ENABLE;
+    sdio_obj.dma.handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+    sdio_obj.dma.handle_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
+    sdio_obj.dma.handle_tx.Init.Priority            = DMA_PRIORITY_MEDIUM;
+    /* DMA_PFCTRL */
+    HAL_DMA_DeInit(&sdio_obj.dma.handle_tx);
+    HAL_DMA_Init(&sdio_obj.dma.handle_tx);
+
+    HAL_DMA_Start(&sdio_obj.dma.handle_tx, (uint32_t)src, (uint32_t)dst, BufferSize);
+#else
+    static uint32_t size = 0;
+    size += BufferSize * 4;
+    sdio_obj.cfg = &sdio_config;
+    sdio_obj.dma.handle_tx.Instance = sdio_config.dma_tx.Instance;
+    sdio_obj.dma.handle_tx.Init.Channel = sdio_config.dma_tx.channel;
+    sdio_obj.dma.handle_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
+    sdio_obj.dma.handle_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
+    sdio_obj.dma.handle_tx.Init.MemInc              = DMA_MINC_ENABLE;
+    sdio_obj.dma.handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+    sdio_obj.dma.handle_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
+    sdio_obj.dma.handle_tx.Init.Mode                = DMA_PFCTRL;
+    sdio_obj.dma.handle_tx.Init.Priority            = DMA_PRIORITY_MEDIUM;
+    sdio_obj.dma.handle_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
+    sdio_obj.dma.handle_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
+    sdio_obj.dma.handle_tx.Init.MemBurst            = DMA_MBURST_INC4;
+    sdio_obj.dma.handle_tx.Init.PeriphBurst         = DMA_PBURST_INC4;
+    /* DMA_PFCTRL */
+    HAL_DMA_DeInit(&sdio_obj.dma.handle_tx);
+    HAL_DMA_Init(&sdio_obj.dma.handle_tx);
+
+    HAL_DMA_Start(&sdio_obj.dma.handle_tx, (uint32_t)src, (uint32_t)dst, BufferSize);
+#endif
+}
+
+/**
+  * @brief  This function configures the DMARX.
+  * @param  BufferDST: pointer to the destination buffer
+  * @param  BufferSize: buffer size
+  * @retval None
+  */
+void SD_LowLevel_DMA_RxConfig(uint32_t *src, uint32_t *dst, uint32_t BufferSize)
+{
+#if defined(SOC_SERIES_STM32F1)
+    sdio_obj.cfg = &sdio_config;
+    sdio_obj.dma.handle_tx.Instance = sdio_config.dma_tx.Instance;
+    sdio_obj.dma.handle_tx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+    sdio_obj.dma.handle_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
+    sdio_obj.dma.handle_tx.Init.MemInc              = DMA_MINC_ENABLE;
+    sdio_obj.dma.handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+    sdio_obj.dma.handle_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
+    sdio_obj.dma.handle_tx.Init.Priority            = DMA_PRIORITY_MEDIUM;
+
+    HAL_DMA_DeInit(&sdio_obj.dma.handle_tx);
+    HAL_DMA_Init(&sdio_obj.dma.handle_tx);
+
+    HAL_DMA_Start(&sdio_obj.dma.handle_tx, (uint32_t)src, (uint32_t)dst, BufferSize);
+#else
+    sdio_obj.cfg = &sdio_config;
+    sdio_obj.dma.handle_tx.Instance = sdio_config.dma_tx.Instance;
+    sdio_obj.dma.handle_tx.Init.Channel = sdio_config.dma_tx.channel;
+    sdio_obj.dma.handle_tx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+    sdio_obj.dma.handle_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
+    sdio_obj.dma.handle_tx.Init.MemInc              = DMA_MINC_ENABLE;
+    sdio_obj.dma.handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+    sdio_obj.dma.handle_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
+    sdio_obj.dma.handle_tx.Init.Mode                = DMA_PFCTRL;
+    sdio_obj.dma.handle_tx.Init.Priority            = DMA_PRIORITY_MEDIUM;
+    sdio_obj.dma.handle_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
+    sdio_obj.dma.handle_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
+    sdio_obj.dma.handle_tx.Init.MemBurst            = DMA_MBURST_INC4;
+    sdio_obj.dma.handle_tx.Init.PeriphBurst         = DMA_PBURST_INC4;
+
+    HAL_DMA_DeInit(&sdio_obj.dma.handle_tx);
+    HAL_DMA_Init(&sdio_obj.dma.handle_tx);
+
+    HAL_DMA_Start(&sdio_obj.dma.handle_tx, (uint32_t)src, (uint32_t)dst, BufferSize);
+#endif
+
+}
+
+/**
+  * @brief  This function get stm32 sdio clock.
+  * @param  hw_sdio: stm32_sdio
+  * @retval PCLK2Freq
+  */
+static rt_uint32_t stm32_sdio_clock_get(struct stm32_sdio *hw_sdio)
+{
+    return HAL_RCC_GetPCLK2Freq();
+}
+
+static rt_err_t DMA_TxConfig(rt_uint32_t *src, rt_uint32_t *dst, int Size)
+{
+    SD_LowLevel_DMA_TxConfig((uint32_t *)src, (uint32_t *)dst, Size / 4);
+    return RT_EOK;
+}
+
+static rt_err_t DMA_RxConfig(rt_uint32_t *src, rt_uint32_t *dst, int Size)
+{
+    SD_LowLevel_DMA_RxConfig((uint32_t *)src, (uint32_t *)dst, Size / 4);
+    return RT_EOK;
+}
+
+void SDIO_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    /* Process All SDIO Interrupt Sources */
+    rthw_sdio_irq_process(host);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+int rt_hw_sdio_init(void)
+{
+    struct stm32_sdio_des sdio_des;
+    SD_HandleTypeDef hsd;
+    hsd.Instance = SDIO;
+    {
+        rt_uint32_t tmpreg = 0x00U;
+#if defined(SOC_SERIES_STM32F1)
+        /* enable DMA clock && Delay after an RCC peripheral clock enabling*/
+        SET_BIT(RCC->AHBENR, sdio_config.dma_rx.dma_rcc);
+        tmpreg = READ_BIT(RCC->AHBENR, sdio_config.dma_rx.dma_rcc);
+#elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32L4)
+        SET_BIT(RCC->AHB1ENR, sdio_config.dma_rx.dma_rcc);
+        /* Delay after an RCC peripheral clock enabling */
+        tmpreg = READ_BIT(RCC->AHB1ENR, sdio_config.dma_rx.dma_rcc);
+#endif
+        UNUSED(tmpreg); /* To avoid compiler warnings */
+    }
+    HAL_NVIC_SetPriority(SDIO_IRQn, 2, 0);
+    HAL_NVIC_EnableIRQ(SDIO_IRQn);
+    HAL_SD_MspInit(&hsd);
+
+    sdio_des.clk_get = stm32_sdio_clock_get;
+    sdio_des.hw_sdio = (struct stm32_sdio *)SDIO;
+    sdio_des.rxconfig = DMA_RxConfig;
+    sdio_des.txconfig = DMA_TxConfig;
+
+    host = sdio_host_create(&sdio_des);
+    if (host == RT_NULL)
+    {
+        LOG_E("host create fail");
+        return -1;
+    }
+
+    return 0;
+}
+INIT_DEVICE_EXPORT(rt_hw_sdio_init);
+
+#endif

+ 178 - 0
bsp/stm32/libraries/HAL_Drivers/drv_sdio.h

@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-13     BalanceTWK   first version
+ */
+
+#ifndef _DRV_SDIO_H
+#define _DRV_SDIO_H
+#include <rtthread.h>
+#include "rtdevice.h"
+#include <rthw.h>
+#include <drv_common.h>
+#include "drv_dma.h"
+#include <string.h>
+#include <drivers/mmcsd_core.h>
+#include <drivers/sdio.h>
+
+#define SDIO_BUFF_SIZE       4096
+#define SDIO_MAX_FREQ        2000000
+#define SDIO_ALIGN_LEN       32
+
+#ifndef SDIO_BASE_ADDRESS
+#define SDIO_BASE_ADDRESS    (0x40012800U)
+#endif
+
+#ifndef SDIO_CLOCK_FREQ
+#define SDIO_CLOCK_FREQ      (48U * 1000 * 1000)
+#endif
+
+#ifndef SDIO_BUFF_SIZE
+#define SDIO_BUFF_SIZE       (4096)
+#endif
+
+#ifndef SDIO_ALIGN_LEN
+#define SDIO_ALIGN_LEN       (32)
+#endif
+
+#ifndef SDIO_MAX_FREQ
+#define SDIO_MAX_FREQ        (24 * 1000 * 1000)
+#endif
+
+#define HW_SDIO_IT_CCRCFAIL                    (0x01U << 0)
+#define HW_SDIO_IT_DCRCFAIL                    (0x01U << 1)
+#define HW_SDIO_IT_CTIMEOUT                    (0x01U << 2)
+#define HW_SDIO_IT_DTIMEOUT                    (0x01U << 3)
+#define HW_SDIO_IT_TXUNDERR                    (0x01U << 4)
+#define HW_SDIO_IT_RXOVERR                     (0x01U << 5)
+#define HW_SDIO_IT_CMDREND                     (0x01U << 6)
+#define HW_SDIO_IT_CMDSENT                     (0x01U << 7)
+#define HW_SDIO_IT_DATAEND                     (0x01U << 8)
+#define HW_SDIO_IT_STBITERR                    (0x01U << 9)
+#define HW_SDIO_IT_DBCKEND                     (0x01U << 10)
+#define HW_SDIO_IT_CMDACT                      (0x01U << 11)
+#define HW_SDIO_IT_TXACT                       (0x01U << 12)
+#define HW_SDIO_IT_RXACT                       (0x01U << 13)
+#define HW_SDIO_IT_TXFIFOHE                    (0x01U << 14)
+#define HW_SDIO_IT_RXFIFOHF                    (0x01U << 15)
+#define HW_SDIO_IT_TXFIFOF                     (0x01U << 16)
+#define HW_SDIO_IT_RXFIFOF                     (0x01U << 17)
+#define HW_SDIO_IT_TXFIFOE                     (0x01U << 18)
+#define HW_SDIO_IT_RXFIFOE                     (0x01U << 19)
+#define HW_SDIO_IT_TXDAVL                      (0x01U << 20)
+#define HW_SDIO_IT_RXDAVL                      (0x01U << 21)
+#define HW_SDIO_IT_SDIOIT                      (0x01U << 22)
+
+#define HW_SDIO_ERRORS \
+    (HW_SDIO_IT_CCRCFAIL | HW_SDIO_IT_CTIMEOUT | \
+     HW_SDIO_IT_DCRCFAIL | HW_SDIO_IT_DTIMEOUT | \
+     HW_SDIO_IT_RXOVERR  | HW_SDIO_IT_TXUNDERR)
+
+#define HW_SDIO_POWER_OFF                      (0x00U)
+#define HW_SDIO_POWER_UP                       (0x02U)
+#define HW_SDIO_POWER_ON                       (0x03U)
+
+#define HW_SDIO_FLOW_ENABLE                    (0x01U << 14)
+#define HW_SDIO_BUSWIDE_1B                     (0x00U << 11)
+#define HW_SDIO_BUSWIDE_4B                     (0x01U << 11)
+#define HW_SDIO_BUSWIDE_8B                     (0x02U << 11)
+#define HW_SDIO_BYPASS_ENABLE                  (0x01U << 10)
+#define HW_SDIO_IDLE_ENABLE                    (0x01U << 9)
+#define HW_SDIO_CLK_ENABLE                     (0x01U << 8)
+
+#define HW_SDIO_SUSPEND_CMD                    (0x01U << 11)
+#define HW_SDIO_CPSM_ENABLE                    (0x01U << 10)
+#define HW_SDIO_WAIT_END                       (0x01U << 9)
+#define HW_SDIO_WAIT_INT                       (0x01U << 8)
+#define HW_SDIO_RESPONSE_NO                    (0x00U << 6)
+#define HW_SDIO_RESPONSE_SHORT                 (0x01U << 6)
+#define HW_SDIO_RESPONSE_LONG                  (0x03U << 6)
+
+#define HW_SDIO_DATA_LEN_MASK                  (0x01FFFFFFU)
+
+#define HW_SDIO_IO_ENABLE                      (0x01U << 11)
+#define HW_SDIO_RWMOD_CK                       (0x01U << 10)
+#define HW_SDIO_RWSTOP_ENABLE                  (0x01U << 9)
+#define HW_SDIO_RWSTART_ENABLE                 (0x01U << 8)
+#define HW_SDIO_DBLOCKSIZE_1                   (0x00U << 4)
+#define HW_SDIO_DBLOCKSIZE_2                   (0x01U << 4)
+#define HW_SDIO_DBLOCKSIZE_4                   (0x02U << 4)
+#define HW_SDIO_DBLOCKSIZE_8                   (0x03U << 4)
+#define HW_SDIO_DBLOCKSIZE_16                  (0x04U << 4)
+#define HW_SDIO_DBLOCKSIZE_32                  (0x05U << 4)
+#define HW_SDIO_DBLOCKSIZE_64                  (0x06U << 4)
+#define HW_SDIO_DBLOCKSIZE_128                 (0x07U << 4)
+#define HW_SDIO_DBLOCKSIZE_256                 (0x08U << 4)
+#define HW_SDIO_DBLOCKSIZE_512                 (0x09U << 4)
+#define HW_SDIO_DBLOCKSIZE_1024                (0x0AU << 4)
+#define HW_SDIO_DBLOCKSIZE_2048                (0x0BU << 4)
+#define HW_SDIO_DBLOCKSIZE_4096                (0x0CU << 4)
+#define HW_SDIO_DBLOCKSIZE_8192                (0x0DU << 4)
+#define HW_SDIO_DBLOCKSIZE_16384               (0x0EU << 4)
+#define HW_SDIO_DMA_ENABLE                     (0x01U << 3)
+#define HW_SDIO_STREAM_ENABLE                  (0x01U << 2)
+#define HW_SDIO_TO_HOST                        (0x01U << 1)
+#define HW_SDIO_DPSM_ENABLE                    (0x01U << 0)
+
+#define HW_SDIO_DATATIMEOUT                    (0xF0000000U)
+
+struct stm32_sdio
+{
+    volatile rt_uint32_t power;
+    volatile rt_uint32_t clkcr;
+    volatile rt_uint32_t arg;
+    volatile rt_uint32_t cmd;
+    volatile rt_uint32_t respcmd;
+    volatile rt_uint32_t resp1;
+    volatile rt_uint32_t resp2;
+    volatile rt_uint32_t resp3;
+    volatile rt_uint32_t resp4;
+    volatile rt_uint32_t dtimer;
+    volatile rt_uint32_t dlen;
+    volatile rt_uint32_t dctrl;
+    volatile rt_uint32_t dcount;
+    volatile rt_uint32_t sta;
+    volatile rt_uint32_t icr;
+    volatile rt_uint32_t mask;
+    volatile rt_uint32_t reserved0[2];
+    volatile rt_uint32_t fifocnt;
+    volatile rt_uint32_t reserved1[13];
+    volatile rt_uint32_t fifo;
+};
+
+typedef rt_err_t (*dma_txconfig)(rt_uint32_t *src, rt_uint32_t *dst, int size);
+typedef rt_err_t (*dma_rxconfig)(rt_uint32_t *src, rt_uint32_t *dst, int size);
+typedef rt_uint32_t (*sdio_clk_get)(struct stm32_sdio *hw_sdio);
+
+struct stm32_sdio_des
+{
+    struct stm32_sdio *hw_sdio;
+    dma_txconfig txconfig;
+    dma_rxconfig rxconfig;
+    sdio_clk_get clk_get;
+};
+
+struct stm32_sdio_config
+{
+    SDIO_TypeDef *Instance;
+    struct dma_config dma_rx, dma_tx;
+};
+
+/* stm32 sdio dirver class */
+struct stm32_sdio_class
+{
+    struct stm32_sdio_des *des;
+    const struct stm32_sdio_config *cfg;
+    struct rt_mmcsd_host host;
+    struct
+    {
+        DMA_HandleTypeDef handle_rx;
+        DMA_HandleTypeDef handle_tx;
+    } dma;
+};
+
+#endif