Browse Source

Merge pull request #4116 from thread-liu/step4-ev1

[add] drivers for stm32mp157a-ev1
Bernard Xiong 4 years ago
parent
commit
286d4f657e
37 changed files with 7757 additions and 87 deletions
  1. 56 0
      bsp/stm32/libraries/HAL_Drivers/config/mp1/qspi_config.h
  2. 0 4
      bsp/stm32/libraries/HAL_Drivers/config/mp1/spi_config.h
  3. 1 0
      bsp/stm32/libraries/HAL_Drivers/drv_config.h
  4. 1 1
      bsp/stm32/libraries/HAL_Drivers/drv_crypto.c
  5. 5 1
      bsp/stm32/libraries/HAL_Drivers/drv_qspi.c
  6. 16 1
      bsp/stm32/libraries/STM32MPxx_HAL/SConscript
  7. 9 9
      bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/stm32mp1xx_hal_conf.h
  8. 685 14
      bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c
  9. 98 19
      bsp/stm32/stm32mp157a-st-ev1/board/Kconfig
  10. 44 0
      bsp/stm32/stm32mp157a-st-ev1/board/SConscript
  11. 1 6
      bsp/stm32/stm32mp157a-st-ev1/board/board.h
  12. 365 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/crypto_sample.c
  13. 203 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_dcmi.c
  14. 22 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_dcmi.h
  15. 385 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_dfsdm.c
  16. 26 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_dfsdm.h
  17. 36 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_exti.c
  18. 290 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_fdcan.c
  19. 22 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_fdcan.h
  20. 163 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_lptim.c
  21. 297 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_mfx.c
  22. 45 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_mfx.h
  23. 666 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_ov5640.c
  24. 653 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_ov5640.h
  25. 31 31
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_pmic.c
  26. 202 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_pwr.c
  27. 180 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_qspi_flash.c
  28. 111 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_rs485.c
  29. 25 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_rs485.h
  30. 303 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_spdifrx.c
  31. 0 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_spdifrx.h
  32. 115 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_wwdg.c
  33. 1602 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/mfxstm32l152.c
  34. 853 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/mfxstm32l152.h
  35. 85 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/spi_sample.c
  36. 160 0
      bsp/stm32/stm32mp157a-st-ev1/board/ports/timer_sample.c
  37. 1 1
      bsp/stm32/stm32mp157a-st-ev1/rtconfig.py

+ 56 - 0
bsp/stm32/libraries/HAL_Drivers/config/mp1/qspi_config.h

@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-12-22     zylx         first version 
+ */
+
+#ifndef __QSPI_CONFIG_H__
+#define __QSPI_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef BSP_USING_QSPI
+#ifndef QSPI_BUS_CONFIG
+#define QSPI_BUS_CONFIG                                        \
+    {                                                          \
+        .Instance = QUADSPI,                                   \
+        .Init.FifoThreshold = 4,                               \
+        .Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE, \
+        .Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE,  \
+    }
+#endif /* QSPI_BUS_CONFIG */
+#endif /* BSP_USING_QSPI */
+
+#ifdef BSP_QSPI_USING_DMA
+#ifndef QSPI_DMA_CONFIG
+#define QSPI_DMA_CONFIG                                        \
+    {                                                          \
+        .Instance = QSPI_DMA_INSTANCE,                         \
+        .Init.Channel  = QSPI_DMA_CHANNEL,                     \
+        .Init.Direction = DMA_PERIPH_TO_MEMORY,                \
+        .Init.PeriphInc = DMA_PINC_DISABLE,                    \
+        .Init.MemInc = DMA_MINC_ENABLE,                        \
+        .Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE,       \
+        .Init.MemDataAlignment = DMA_MDATAALIGN_BYTE,          \
+        .Init.Mode = DMA_NORMAL,                               \
+        .Init.Priority = DMA_PRIORITY_LOW                      \
+    }
+#endif /* QSPI_DMA_CONFIG */
+#endif /* BSP_QSPI_USING_DMA */
+
+#define QSPI_IRQn                   QUADSPI_IRQn
+#define QSPI_IRQHandler             QUADSPI_IRQHandler
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __QSPI_CONFIG_H__ */

+ 0 - 4
bsp/stm32/libraries/HAL_Drivers/config/mp1/spi_config.h

@@ -23,7 +23,6 @@ extern "C" {
     {                                               \
         .Instance = SPI1,                           \
         .bus_name = "spi1",                         \
-        .irq_type = SPI1_IRQn,                      \
     }
 #endif /* SPI1_BUS_CONFIG */
 #endif /* BSP_USING_SPI1 */
@@ -58,7 +57,6 @@ extern "C" {
     {                                               \
         .Instance = SPI2,                           \
         .bus_name = "spi2",                         \
-        .irq_type = SPI2_IRQn,                      \
     }
 #endif /* SPI2_BUS_CONFIG */
 #endif /* BSP_USING_SPI2 */
@@ -93,7 +91,6 @@ extern "C" {
     {                                               \
         .Instance = SPI3,                           \
         .bus_name = "spi3",                         \
-        .irq_type = SPI3_IRQn,                      \
     }
 #endif /* SPI3_BUS_CONFIG */
 #endif /* BSP_USING_SPI3 */
@@ -128,7 +125,6 @@ extern "C" {
     {                                               \
         .Instance = SPI4,                           \
         .bus_name = "spi4",                         \
-        .irq_type = SPI4_IRQn,                      \
     }
 #endif /* SPI4_BUS_CONFIG */
 #endif /* BSP_USING_SPI4 */

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

@@ -110,6 +110,7 @@ extern "C" {
 #elif  defined(SOC_SERIES_STM32MP1)
 #include "mp1/dma_config.h"
 #include "mp1/uart_config.h"
+#include "mp1/qspi_config.h"
 #include "mp1/spi_config.h"
 #include "mp1/adc_config.h"
 #include "mp1/dac_config.h"    

+ 1 - 1
bsp/stm32/libraries/HAL_Drivers/drv_crypto.c

@@ -147,7 +147,7 @@ static rt_uint32_t _rng_rand(struct hwcrypto_rng *ctx)
     {
         return gen_random ;
     }
-
+    
     return 0;
 }
 

+ 5 - 1
bsp/stm32/libraries/HAL_Drivers/drv_qspi.c

@@ -52,8 +52,12 @@ static int stm32_qspi_init(struct rt_qspi_device *device, struct rt_qspi_configu
     QSPI_HandleTypeDef QSPI_Handler_config = QSPI_BUS_CONFIG;
     qspi_bus->QSPI_Handler = QSPI_Handler_config;
 
+#if defined(SOC_SERIES_STM32MP1)
+    while (cfg->max_hz < HAL_RCC_GetACLKFreq() / (i + 1))
+#else
     while (cfg->max_hz < HAL_RCC_GetHCLKFreq() / (i + 1))
-    {
+#endif
+   {
         i++;
         if (i == 255)
         {

+ 16 - 1
bsp/stm32/libraries/STM32MPxx_HAL/SConscript

@@ -66,7 +66,9 @@ if GetDepend(['RT_USING_SDIO']):
 if GetDepend(['RT_USING_AUDIO']):
     src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sai.c']
     src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sai_ex.c']
-
+if GetDepend(['BSP_USING_DCMI']):
+    src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dcmi.c']
+    
 if GetDepend(['BSP_USING_FMC']):
     src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_fmc.c']
     src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_fsmc.c']
@@ -89,6 +91,19 @@ if GetDepend(['BSP_USING_LTDC']):
     src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_dma2d.c']
     src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dsi.c']
 
+if GetDepend(['BSP_USING_FDCAN']):
+    src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_fdcan.c']
+
+if GetDepend(['BSP_USING_QSPI']):
+    src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_qspi.c']
+
+if GetDepend(['BSP_USING_SPDIFRX']):
+    src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_spdifrx.c']
+
+if GetDepend(['BSP_USING_DFSDM']):
+    src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dfsdm.c']
+    src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dfsdm_ex.c']
+
 if GetDepend(['BSP_USING_SDMMC']):
     src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_sdmmc.c']
     src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd.c']

+ 9 - 9
bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/stm32mp1xx_hal_conf.h

@@ -34,16 +34,16 @@
 #define HAL_MODULE_ENABLED  
 #define HAL_ADC_MODULE_ENABLED
 /*#define HAL_CEC_MODULE_ENABLED   */
-/*#define HAL_CRC_MODULE_ENABLED   */
-/*#define HAL_CRYP_MODULE_ENABLED   */
+#define HAL_CRC_MODULE_ENABLED
+#define HAL_CRYP_MODULE_ENABLED
 #define HAL_DAC_MODULE_ENABLED
-/*#define HAL_DCMI_MODULE_ENABLED   */
+#define HAL_DCMI_MODULE_ENABLED
 /*#define HAL_DSI_MODULE_ENABLED   */
-/*#define HAL_DFSDM_MODULE_ENABLED   */
+#define HAL_DFSDM_MODULE_ENABLED
 /*#define HAL_DTS_MODULE_ENABLED   */
 /*#define HAL_ETH_MODULE_ENABLED   */
-/*#define HAL_FDCAN_MODULE_ENABLED   */
-/*#define HAL_HASH_MODULE_ENABLED   */
+#define HAL_FDCAN_MODULE_ENABLED
+#define HAL_HASH_MODULE_ENABLED
 /*#define HAL_HCD_MODULE_ENABLED   */
 #define HAL_HSEM_MODULE_ENABLED
 #define HAL_I2C_MODULE_ENABLED
@@ -55,14 +55,14 @@
 /*#define HAL_NAND_MODULE_ENABLED   */
 /*#define HAL_NOR_MODULE_ENABLED   */
 /*#define HAL_PCD_MODULE_ENABLED   */
-/*#define HAL_QSPI_MODULE_ENABLED   */
-/*#define HAL_RNG_MODULE_ENABLED   */
+#define HAL_QSPI_MODULE_ENABLED
+#define HAL_RNG_MODULE_ENABLED
 #define HAL_SAI_MODULE_ENABLED
 #define HAL_SD_MODULE_ENABLED
 /*#define HAL_MMC_MODULE_ENABLED   */
 /*#define HAL_RTC_MODULE_ENABLED   */
 /*#define HAL_SMBUS_MODULE_ENABLED   */
-/*#define HAL_SPDIFRX_MODULE_ENABLED   */
+#define HAL_SPDIFRX_MODULE_ENABLED
 #define HAL_SPI_MODULE_ENABLED
 /*#define HAL_SRAM_MODULE_ENABLED   */
 /*#define HAL_TAMP_MODULE_ENABLED   */

+ 685 - 14
bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c

@@ -26,9 +26,15 @@
 
 /* Private typedef -----------------------------------------------------------*/
 /* USER CODE BEGIN TD */
+DMA_HandleTypeDef hdma_hash_in    = {0};
+DMA_HandleTypeDef hdma_cryp_in    = {0};
+DMA_HandleTypeDef hdma_cryp_out   = {0};
 DMA_HandleTypeDef hdma_sai2_a     = {0};
 DMA_HandleTypeDef hdma_sai2_b     = {0};
 DMA_HandleTypeDef hdma_sai4_a     = {0};
+DMA_HandleTypeDef hdma_spdifrx_rx = {0};
+DMA_HandleTypeDef hdma_dfsdm1_flt0 = {0};
+DMA_HandleTypeDef hdma_dfsdm1_flt1 = {0};
 /* USER CODE END TD */
 
 /* Private define ------------------------------------------------------------*/
@@ -291,7 +297,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim)
   /** Initializes the peripherals clock 
   */
     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
-    PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_PCLK1;
+    PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE;
     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
     {
       Error_Handler();
@@ -514,17 +520,17 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
 {
   GPIO_InitTypeDef GPIO_InitStruct = {0};
   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
-  if(hspi->Instance==SPI5)
+  if(hspi->Instance==SPI1)
   {
-  /* USER CODE BEGIN SPI5_MspInit 0 */
+  /* USER CODE BEGIN SPI1_MspInit 0 */
 
-  /* USER CODE END SPI5_MspInit 0 */
+  /* USER CODE END SPI1_MspInit 0 */
   if(IS_ENGINEERING_BOOT_MODE())
   {
   /** Initializes the peripherals clock 
   */
-    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI45;
-    PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PCLK2;
+    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI1;
+    PeriphClkInit.Spi1ClockSelection = RCC_SPI1CLKSOURCE_PLL4;
     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
     {
       Error_Handler();
@@ -533,19 +539,20 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
   }
 
     /* Peripheral clock enable */
-    __HAL_RCC_SPI5_CLK_ENABLE();
+    __HAL_RCC_SPI1_CLK_ENABLE();
   
-    __HAL_RCC_GPIOF_CLK_ENABLE();
-    /**SPI5 GPIO Configuration    
-    PF9     ------> SPI5_MOSI
-    PF7     ------> SPI5_SCK 
+    __HAL_RCC_GPIOZ_CLK_ENABLE();
+    /**SPI1 GPIO Configuration    
+    PZ2      ------> SPI1_MOSI
+    PZ1      ------> SPI1_MISO
+    PZ0      ------> SPI1_SCK
     */
-    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_7;
+    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
-    GPIO_InitStruct.Alternate = GPIO_AF5_SPI5;
-    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
+    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
+    HAL_GPIO_Init(GPIOZ, &GPIO_InitStruct);
 
   /* USER CODE BEGIN SPI5_MspInit 1 */
 
@@ -1397,6 +1404,670 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
     }
 }
 
+/**
+* @brief DCMI MSP Initialization
+* This function configures the hardware resources used in this example
+* @param hdcmi: DCMI handle pointer
+* @retval None
+*/
+void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi)
+{
+  GPIO_InitTypeDef GPIO_InitStruct = {0};
+  if(hdcmi->Instance==DCMI)
+  {
+  /* USER CODE BEGIN DCMI_MspInit 0 */
+
+  /* USER CODE END DCMI_MspInit 0 */
+    /* Peripheral clock enable */
+    __HAL_RCC_DCMI_CLK_ENABLE();
+  
+    __HAL_RCC_GPIOH_CLK_ENABLE();
+    __HAL_RCC_GPIOE_CLK_ENABLE();
+    __HAL_RCC_GPIOB_CLK_ENABLE();
+    __HAL_RCC_GPIOI_CLK_ENABLE();
+    __HAL_RCC_GPIOA_CLK_ENABLE();
+    
+    /**DCMI GPIO Configuration
+    PH9     ------> DCMI_D0      
+    PH10    ------> DCMI_D1
+    PH11    ------> DCMI_D2
+    PH12    ------> DCMI_D3
+    PH14    ------> DCMI_D4
+    PI4     ------> DCMI_D5  
+    PB8     ------> DCMI_D6  
+    PE6     ------> DCMI_D7      
+    PH8     ------> DCMI_HSYNC
+    PB7     ------> DCMI_VSYNC
+    PA6     ------> DCMI_PIXCLK
+    */
+    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_8 
+                          |GPIO_PIN_9|GPIO_PIN_12;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
+    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
+
+    GPIO_InitStruct.Pin = GPIO_PIN_6;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
+    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
+
+    GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    GPIO_InitStruct.Pin = GPIO_PIN_4;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
+    HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
+
+    GPIO_InitStruct.Pin = GPIO_PIN_6;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    
+    HAL_NVIC_SetPriority(DCMI_IRQn, 0x03, 0x00);        
+    HAL_NVIC_EnableIRQ(DCMI_IRQn);     
+    
+  /* USER CODE BEGIN DCMI_MspInit 1 */
+  /* USER CODE END DCMI_MspInit 1 */
+  }
+
+}
+
+/**
+* @brief DCMI MSP De-Initialization
+* This function freeze the hardware resources used in this example
+* @param hdcmi: DCMI handle pointer
+* @retval None
+*/
+void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* hdcmi)
+{
+  if(hdcmi->Instance==DCMI)
+  {
+  /* USER CODE BEGIN DCMI_MspDeInit 0 */
+
+  /* USER CODE END DCMI_MspDeInit 0 */
+    /* Peripheral clock disable */
+    __HAL_RCC_DCMI_CLK_DISABLE();
+  
+    /**DCMI GPIO Configuration    
+    PH10     ------> DCMI_D1
+    PH11     ------> DCMI_D2
+    PH14     ------> DCMI_D4
+    PH8     ------> DCMI_HSYNC
+    PH9     ------> DCMI_D0
+    PE6     ------> DCMI_D7
+    PH12     ------> DCMI_D3
+    PB7     ------> DCMI_VSYNC
+    PI4     ------> DCMI_D5
+    PA6     ------> DCMI_PIXCLK
+    PB8     ------> DCMI_D6 
+    */
+    HAL_GPIO_DeInit(GPIOH, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_8 
+                          |GPIO_PIN_9|GPIO_PIN_12);
+
+    HAL_GPIO_DeInit(GPIOE, GPIO_PIN_6);
+
+    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7|GPIO_PIN_8);
+
+    HAL_GPIO_DeInit(GPIOI, GPIO_PIN_4);
+
+    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_6);
+
+  /* USER CODE BEGIN DCMI_MspDeInit 1 */
+    HAL_DMA_DeInit(hdcmi->DMA_Handle);
+  /* USER CODE END DCMI_MspDeInit 1 */
+  }
+
+}
+
+/**
+* @brief FDCAN MSP Initialization
+* This function configures the hardware resources used in this example
+* @param hfdcan: FDCAN handle pointer
+* @retval None
+*/
+void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan)
+{
+  GPIO_InitTypeDef GPIO_InitStruct = {0};
+  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+  if(hfdcan->Instance==FDCAN1)
+  {
+  /* USER CODE BEGIN FDCAN1_MspInit 0 */
+
+  /* USER CODE END FDCAN1_MspInit 0 */
+  if(IS_ENGINEERING_BOOT_MODE())
+  {
+  /** Initializes the peripherals clock 
+  */
+    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
+    PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_HSE;
+    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
+    {
+      Error_Handler();
+    }
+
+  }
+
+    /* Peripheral clock enable */
+    __HAL_RCC_FDCAN_CLK_ENABLE();
+  
+    __HAL_RCC_GPIOH_CLK_ENABLE();
+    __HAL_RCC_GPIOI_CLK_ENABLE();
+    /**FDCAN1 GPIO Configuration    
+    PH13     ------> FDCAN1_TX
+    PI9     ------> FDCAN1_RX 
+    */
+    GPIO_InitStruct.Pin = GPIO_PIN_13;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+    GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
+    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
+
+    GPIO_InitStruct.Pin = GPIO_PIN_9;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
+    HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
+
+    /* FDCAN1 interrupt Init */
+    HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 0x02, 0);
+    HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
+    HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 0x02, 0);
+    HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
+    HAL_NVIC_SetPriority(FDCAN_CAL_IRQn, 0x02, 0);
+    HAL_NVIC_EnableIRQ(FDCAN_CAL_IRQn);
+  /* USER CODE BEGIN FDCAN1_MspInit 1 */
+  /* USER CODE END FDCAN1_MspInit 1 */
+  }
+
+}
+
+/**
+* @brief FDCAN MSP De-Initialization
+* This function freeze the hardware resources used in this example
+* @param hfdcan: FDCAN handle pointer
+* @retval None
+*/
+void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* hfdcan)
+{
+  if(hfdcan->Instance==FDCAN1)
+  {
+  /* USER CODE BEGIN FDCAN1_MspDeInit 0 */
+
+  /* USER CODE END FDCAN1_MspDeInit 0 */
+    /* Peripheral clock disable */
+    __HAL_RCC_FDCAN_CLK_DISABLE();
+  
+    /**FDCAN1 GPIO Configuration    
+    PH13     ------> FDCAN1_TX
+    PI9     ------> FDCAN1_RX 
+    */
+    HAL_GPIO_DeInit(GPIOH, GPIO_PIN_13);
+
+    HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9);
+
+    /* FDCAN1 interrupt DeInit */
+    HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn);
+    HAL_NVIC_DisableIRQ(FDCAN1_IT1_IRQn);
+    HAL_NVIC_DisableIRQ(FDCAN_CAL_IRQn);
+  /* USER CODE BEGIN FDCAN1_MspDeInit 1 */
+
+  /* USER CODE END FDCAN1_MspDeInit 1 */
+  }
+
+}
+
+void HAL_SPDIFRX_MspInit(SPDIFRX_HandleTypeDef* hspdifrx)
+{
+    GPIO_InitTypeDef GPIO_InitStruct = {0};
+    RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+
+    if(hspdifrx->Instance==SPDIFRX)
+    {
+        if(IS_ENGINEERING_BOOT_MODE())
+        {
+
+            PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPDIFRX;
+            PeriphClkInit.SpdifrxClockSelection = RCC_SPDIFRXCLKSOURCE_PLL4;
+            if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
+            {
+                Error_Handler();
+            }
+        }
+        /* Peripheral clock enable */
+        __HAL_RCC_SPDIFRX_CLK_ENABLE();
+
+        __HAL_RCC_GPIOG_CLK_ENABLE();
+
+        GPIO_InitStruct.Pin = GPIO_PIN_12;
+        GPIO_InitStruct.Mode = GPIO_MODE_AF;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        GPIO_InitStruct.Alternate = GPIO_AF8_SPDIF;
+        HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
+
+        __HAL_RCC_DMAMUX_CLK_ENABLE();
+        __HAL_RCC_DMA1_CLK_ENABLE();
+            
+        hdma_spdifrx_rx.Instance                  = DMA1_Stream7;
+        hdma_spdifrx_rx.Init.Request              = DMA_REQUEST_SPDIF_RX_DT;
+        hdma_spdifrx_rx.Init.Direction            = DMA_PERIPH_TO_MEMORY;
+        hdma_spdifrx_rx.Init.PeriphInc            = DMA_PINC_DISABLE;
+        hdma_spdifrx_rx.Init.MemInc               = DMA_MINC_ENABLE;
+        hdma_spdifrx_rx.Init.PeriphDataAlignment  = DMA_PDATAALIGN_WORD;
+        hdma_spdifrx_rx.Init.MemDataAlignment     = DMA_MDATAALIGN_WORD;
+        hdma_spdifrx_rx.Init.Mode                 = DMA_CIRCULAR;
+        hdma_spdifrx_rx.Init.Priority             = DMA_PRIORITY_HIGH;
+        hdma_spdifrx_rx.Init.FIFOMode             = DMA_FIFOMODE_ENABLE;
+        hdma_spdifrx_rx.Init.FIFOThreshold        = DMA_FIFO_THRESHOLD_FULL;
+        hdma_spdifrx_rx.Init.MemBurst             = DMA_MBURST_SINGLE;
+        hdma_spdifrx_rx.Init.PeriphBurst          = DMA_MBURST_SINGLE; 
+  
+        HAL_DMA_DeInit(&hdma_spdifrx_rx);
+        if (HAL_DMA_Init(&hdma_spdifrx_rx) != HAL_OK)
+        {
+            Error_Handler();
+        }
+
+        __HAL_LINKDMA(hspdifrx, hdmaDrRx, hdma_spdifrx_rx);
+        
+        HAL_NVIC_SetPriority(DMA1_Stream7_IRQn, 0x02, 0);
+        HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn);
+    }
+}
+
+void HAL_SPDIFRX_MspDeInit(SPDIFRX_HandleTypeDef* hspdifrx)
+{
+    if(hspdifrx->Instance==SPDIFRX)
+    {
+        __HAL_RCC_SPDIFRX_CLK_DISABLE();
+
+        HAL_GPIO_DeInit(GPIOG, GPIO_PIN_12);
+        HAL_DMA_DeInit(hspdifrx->hdmaDrRx);
+    }
+}
+
+void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef* hdfsdm_channel)
+{
+    GPIO_InitTypeDef GPIO_InitStruct = {0};
+    RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+
+    if(IS_ENGINEERING_BOOT_MODE())
+    {
+        PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_DFSDM1;
+        if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
+        {
+          Error_Handler();
+        }
+    }
+    /* Peripheral clock enable */
+    __HAL_RCC_DFSDM1_CLK_ENABLE();
+
+    __HAL_RCC_GPIOC_CLK_ENABLE();
+    __HAL_RCC_GPIOB_CLK_ENABLE();
+    __HAL_RCC_GPIOF_CLK_ENABLE();
+    /**DFSDM1 GPIO Configuration    
+    PC3     ------> DFSDM1_DATIN1
+    PB13     ------> DFSDM1_CKOUT
+    PF13     ------> DFSDM1_DATIN3 
+    */
+    GPIO_InitStruct.Pin         = GPIO_PIN_13;
+    GPIO_InitStruct.Mode        = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull        = GPIO_PULLDOWN;
+    GPIO_InitStruct.Speed       = GPIO_SPEED_FREQ_HIGH;
+    GPIO_InitStruct.Alternate   = GPIO_AF3_DFSDM1;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+    
+    GPIO_InitStruct.Pin         = GPIO_PIN_3;
+    GPIO_InitStruct.Alternate   = GPIO_AF3_DFSDM1;
+    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+    GPIO_InitStruct.Pin = GPIO_PIN_13;
+    GPIO_InitStruct.Alternate = GPIO_AF6_DFSDM1;
+    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
+}
+
+void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef* hdfsdm_filter)
+{
+    RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+    
+    if(IS_ENGINEERING_BOOT_MODE())
+    {
+        /** Initializes the peripherals clock 
+        */
+        PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_DFSDM1;
+        if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
+        {
+          Error_Handler();
+        }
+    }
+      
+    __HAL_RCC_DFSDM1_CLK_ENABLE();
+      /* DMA controller clock enable */
+    __HAL_RCC_DMAMUX_CLK_ENABLE();
+    __HAL_RCC_DMA2_CLK_ENABLE();
+  
+    if(hdfsdm_filter->Instance == DFSDM1_Filter0)
+    {
+        hdma_dfsdm1_flt0.Instance                   = DMA2_Stream2;
+        hdma_dfsdm1_flt0.Init.Request               = DMA_REQUEST_DFSDM1_FLT0;
+        hdma_dfsdm1_flt0.Init.Direction             = DMA_PERIPH_TO_MEMORY;
+        hdma_dfsdm1_flt0.Init.PeriphInc             = DMA_PINC_DISABLE;
+        hdma_dfsdm1_flt0.Init.MemInc                = DMA_MINC_ENABLE;
+        hdma_dfsdm1_flt0.Init.PeriphDataAlignment   = DMA_PDATAALIGN_WORD;
+        hdma_dfsdm1_flt0.Init.MemDataAlignment      = DMA_MDATAALIGN_WORD;
+        hdma_dfsdm1_flt0.Init.Mode                  = DMA_CIRCULAR;
+        hdma_dfsdm1_flt0.Init.Priority              = DMA_PRIORITY_HIGH;
+        hdma_dfsdm1_flt0.Init.FIFOMode              = DMA_FIFOMODE_ENABLE;
+        hdma_dfsdm1_flt0.Init.FIFOThreshold         = DMA_FIFO_THRESHOLD_FULL;
+        hdma_dfsdm1_flt0.Init.MemBurst              = DMA_MBURST_SINGLE;
+        hdma_dfsdm1_flt0.Init.PeriphBurst           = DMA_PBURST_SINGLE;
+        if (HAL_DMA_Init(&hdma_dfsdm1_flt0) != HAL_OK)
+        {
+          Error_Handler();
+        }
+
+        /* Several peripheral DMA handle pointers point to the same DMA handle.
+         Be aware that there is only one channel to perform all the requested DMAs. */
+        __HAL_LINKDMA(hdfsdm_filter,hdmaReg,hdma_dfsdm1_flt0);
+        
+        HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 2, 0);
+        HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
+    }
+
+    if(hdfsdm_filter->Instance == DFSDM1_Filter1)
+    {
+        hdma_dfsdm1_flt1.Instance                   = DMA2_Stream1;
+        hdma_dfsdm1_flt1.Init.Request               = DMA_REQUEST_DFSDM1_FLT1;
+        hdma_dfsdm1_flt1.Init.Direction             = DMA_PERIPH_TO_MEMORY;
+        hdma_dfsdm1_flt1.Init.PeriphInc             = DMA_PINC_DISABLE;
+        hdma_dfsdm1_flt1.Init.MemInc                = DMA_MINC_ENABLE;
+        hdma_dfsdm1_flt1.Init.PeriphDataAlignment   = DMA_PDATAALIGN_WORD;
+        hdma_dfsdm1_flt1.Init.MemDataAlignment      = DMA_MDATAALIGN_WORD;
+        hdma_dfsdm1_flt1.Init.Mode                  = DMA_CIRCULAR;
+        hdma_dfsdm1_flt1.Init.Priority              = DMA_PRIORITY_HIGH;
+        hdma_dfsdm1_flt1.Init.FIFOMode              = DMA_FIFOMODE_ENABLE;
+        hdma_dfsdm1_flt1.Init.FIFOThreshold         = DMA_FIFO_THRESHOLD_FULL;
+        hdma_dfsdm1_flt1.Init.MemBurst              = DMA_MBURST_SINGLE;
+        hdma_dfsdm1_flt1.Init.PeriphBurst           = DMA_PBURST_SINGLE;
+        
+        if (HAL_DMA_Init(&hdma_dfsdm1_flt1) != HAL_OK)
+        {
+          Error_Handler();
+        }
+        
+        __HAL_LINKDMA(hdfsdm_filter,hdmaReg,hdma_dfsdm1_flt1);
+        
+        HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 2, 0);
+        HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
+    }
+}
+
+void HAL_DFSDM_FilterMspDeInit(DFSDM_Filter_HandleTypeDef* hdfsdm_filter)
+{
+    HAL_DMA_DeInit(hdfsdm_filter->hdmaReg);
+}
+
+void HAL_DFSDM_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef* hdfsdm_channel)
+{
+    __HAL_RCC_DFSDM1_CLK_DISABLE();
+    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_3);
+    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13);
+    HAL_GPIO_DeInit(GPIOF, GPIO_PIN_13);
+}
+
+/**
+* @brief HASH MSP Initialization
+* This function configures the hardware resources used in this example
+* @param hhash: HASH handle pointer
+* @retval None
+*/
+void HAL_HASH_MspInit(HASH_HandleTypeDef* hhash)
+{
+  /* USER CODE BEGIN HASH2_MspInit 0 */
+  /* USER CODE END HASH2_MspInit 0 */
+    /* Peripheral clock enable */
+    __HAL_RCC_HASH2_CLK_ENABLE();
+  /* USER CODE BEGIN HASH2_MspInit 1 */
+    __HAL_RCC_DMAMUX_CLK_ENABLE();
+    
+    /* Peripheral DMA init*/
+    hdma_hash_in.Instance = DMA2_Stream7;
+    hdma_hash_in.Init.Request = DMA_REQUEST_HASH2_IN;
+    hdma_hash_in.Init.Direction = DMA_MEMORY_TO_PERIPH;
+    hdma_hash_in.Init.PeriphInc = DMA_PINC_DISABLE;
+    hdma_hash_in.Init.MemInc = DMA_MINC_ENABLE;
+    hdma_hash_in.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+    hdma_hash_in.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
+    hdma_hash_in.Init.Mode = DMA_NORMAL;
+    hdma_hash_in.Init.Priority = DMA_PRIORITY_HIGH;
+    hdma_hash_in.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
+    hdma_hash_in.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
+    hdma_hash_in.Init.MemBurst = DMA_MBURST_SINGLE;
+    hdma_hash_in.Init.PeriphBurst = DMA_PBURST_SINGLE;
+
+    if (HAL_DMA_DeInit(&hdma_hash_in) != HAL_OK)
+    {
+      Error_Handler();
+    }
+    if (HAL_DMA_Init(&hdma_hash_in) != HAL_OK)
+    {
+      Error_Handler();
+    }
+
+    __HAL_LINKDMA(hhash,hdmain,hdma_hash_in);
+  /* USER CODE END HASH2_MspInit 1 */
+
+}
+
+/**
+* @brief HASH MSP De-Initialization
+* This function freeze the hardware resources used in this example
+* @param hhash: HASH handle pointer
+* @retval None
+*/
+void HAL_HASH_MspDeInit(HASH_HandleTypeDef* hhash)
+{
+  /* USER CODE BEGIN HASH2_MspDeInit 0 */
+
+  /* USER CODE END HASH2_MspDeInit 0 */
+    /* Peripheral clock disable */
+    __HAL_RCC_HASH2_CLK_DISABLE();
+  /* USER CODE BEGIN HASH2_MspDeInit 1 */
+
+  /* USER CODE END HASH2_MspDeInit 1 */
+
+}
+
+/**
+* @brief CRC MSP Initialization
+* This function configures the hardware resources used in this example
+* @param hcrc: CRC handle pointer
+* @retval None
+*/
+void HAL_CRC_MspInit(CRC_HandleTypeDef* hcrc)
+{
+  if(hcrc->Instance==CRC2)
+  {
+  /* USER CODE BEGIN CRC2_MspInit 0 */
+
+  /* USER CODE END CRC2_MspInit 0 */
+    /* Peripheral clock enable */
+    __HAL_RCC_CRC2_CLK_ENABLE();
+  /* USER CODE BEGIN CRC2_MspInit 1 */
+
+  /* USER CODE END CRC2_MspInit 1 */
+  }
+
+}
+
+/**
+* @brief CRC MSP De-Initialization
+* This function freeze the hardware resources used in this example
+* @param hcrc: CRC handle pointer
+* @retval None
+*/
+void HAL_CRC_MspDeInit(CRC_HandleTypeDef* hcrc)
+{
+  if(hcrc->Instance==CRC2)
+  {
+  /* USER CODE BEGIN CRC2_MspDeInit 0 */
+
+  /* USER CODE END CRC2_MspDeInit 0 */
+    /* Peripheral clock disable */
+    __HAL_RCC_CRC2_CLK_DISABLE();
+  /* USER CODE BEGIN CRC2_MspDeInit 1 */
+
+  /* USER CODE END CRC2_MspDeInit 1 */
+  }
+
+}
+
+/**
+* @brief RNG MSP Initialization
+* This function configures the hardware resources used in this example
+* @param hrng: RNG handle pointer
+* @retval None
+*/
+void HAL_RNG_MspInit(RNG_HandleTypeDef* hrng)
+{
+  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+  if(hrng->Instance==RNG2)
+  {
+  /* USER CODE BEGIN RNG2_MspInit 0 */
+
+  /* USER CODE END RNG2_MspInit 0 */
+  if(IS_ENGINEERING_BOOT_MODE())
+  {
+  /** Initializes the peripherals clock 
+  */
+    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG2;
+    PeriphClkInit.Rng2ClockSelection = RCC_RNG2CLKSOURCE_LSE;
+    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
+    {
+      Error_Handler();
+    }
+
+  }
+
+    /* Peripheral clock enable */
+    __HAL_RCC_RNG2_CLK_ENABLE();
+  /* USER CODE BEGIN RNG2_MspInit 1 */
+
+  /* USER CODE END RNG2_MspInit 1 */
+  }
+
+}
+
+/**
+* @brief RNG MSP De-Initialization
+* This function freeze the hardware resources used in this example
+* @param hrng: RNG handle pointer
+* @retval None
+*/
+void HAL_RNG_MspDeInit(RNG_HandleTypeDef* hrng)
+{
+  if(hrng->Instance==RNG2)
+  {
+  /* USER CODE BEGIN RNG2_MspDeInit 0 */
+
+  /* USER CODE END RNG2_MspDeInit 0 */
+    /* Peripheral clock disable */
+    __HAL_RCC_RNG2_CLK_DISABLE();
+  /* USER CODE BEGIN RNG2_MspDeInit 1 */
+
+  /* USER CODE END RNG2_MspDeInit 1 */
+  }
+
+}
+
+#if defined (CRYP1) || defined (CRYP2)
+void HAL_CRYP_MspInit(CRYP_HandleTypeDef* hcryp)
+{
+    if(hcryp->Instance==CRYP2)
+    {
+        /* Peripheral clock enable */
+        __HAL_RCC_CRYP2_CLK_ENABLE();
+        __HAL_RCC_DMAMUX_CLK_ENABLE();
+
+       /* Peripheral DMA init*/
+        hdma_cryp_in.Instance = DMA2_Stream6;
+        hdma_cryp_in.Init.Request = DMA_REQUEST_CRYP2_IN;
+        hdma_cryp_in.Init.Direction = DMA_MEMORY_TO_PERIPH;
+        hdma_cryp_in.Init.PeriphInc = DMA_PINC_DISABLE;
+        hdma_cryp_in.Init.MemInc = DMA_MINC_ENABLE;
+        hdma_cryp_in.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+        hdma_cryp_in.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
+        hdma_cryp_in.Init.Mode = DMA_NORMAL;
+        hdma_cryp_in.Init.Priority = DMA_PRIORITY_HIGH;
+        hdma_cryp_in.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+        if (HAL_DMA_DeInit(&hdma_cryp_in) != HAL_OK)
+        {
+            Error_Handler();
+        }
+        if (HAL_DMA_Init(&hdma_cryp_in) != HAL_OK)
+        {
+            Error_Handler();
+        }
+
+        __HAL_LINKDMA(hcryp,hdmain,hdma_cryp_in);
+
+        hdma_cryp_out.Instance = DMA2_Stream5;
+        hdma_cryp_out.Init.Request = DMA_REQUEST_CRYP2_OUT;
+        hdma_cryp_out.Init.Direction = DMA_PERIPH_TO_MEMORY;
+        hdma_cryp_out.Init.PeriphInc = DMA_PINC_DISABLE;
+        hdma_cryp_out.Init.MemInc = DMA_MINC_ENABLE;
+        hdma_cryp_out.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+        hdma_cryp_out.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
+        hdma_cryp_out.Init.Mode = DMA_NORMAL;
+        hdma_cryp_out.Init.Priority = DMA_PRIORITY_VERY_HIGH;
+        hdma_cryp_out.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+        if (HAL_DMA_DeInit(&hdma_cryp_out) != HAL_OK)
+        {
+            Error_Handler();
+        }
+        if (HAL_DMA_Init(&hdma_cryp_out) != HAL_OK)
+        {
+            Error_Handler();
+        }
+
+        __HAL_LINKDMA(hcryp,hdmaout,hdma_cryp_out);
+
+      /* USER CODE BEGIN CRYP_MspInit 1 */
+
+      /* USER CODE END CRYP_MspInit 1 */
+    }
+}
+
+void HAL_CRYP_MspDeInit(CRYP_HandleTypeDef* hcryp)
+{
+
+  if(hcryp->Instance==CRYP2)
+  {
+  /* USER CODE BEGIN CRYP_MspDeInit 0 */
+
+  /* USER CODE END CRYP_MspDeInit 0 */
+    /* Peripheral clock disable */
+    __HAL_RCC_CRYP2_CLK_DISABLE();
+
+    /* Peripheral DMA DeInit*/
+    HAL_DMA_DeInit(hcryp->hdmain);
+    HAL_DMA_DeInit(hcryp->hdmaout);
+  }
+  /* USER CODE BEGIN CRYP_MspDeInit 1 */
+
+  /* USER CODE END CRYP_MspDeInit 1 */
+
+}
+#endif
+
 /**
   * @brief  This function is executed in case of error occurrence.
   * @retval None

+ 98 - 19
bsp/stm32/stm32mp157a-st-ev1/board/Kconfig

@@ -14,6 +14,10 @@ menu "Onboard Peripheral Drivers"
         select BSP_USING_UART
         select BSP_USING_UART4
         default y
+        
+    config BSP_USING_EXTI
+        bool "Enable exti sample"
+        default n
 
     config BSP_USING_PMIC
         bool "Enable PMIC"
@@ -21,6 +25,12 @@ menu "Onboard Peripheral Drivers"
         select BSP_USING_I2C3
         default y
 
+    config BSP_USING_PWR
+        bool "Enable PM (power control)"
+        select BSP_USING_LPTIM
+        select BSP_USING_LPTIM1
+        default n
+
     config BSP_USING_NAND
         bool "Enable FMC (MT29F8G08ABACAH4)"
         select RT_USING_FMC
@@ -28,6 +38,13 @@ menu "Onboard Peripheral Drivers"
         select RT_MTD_NAND_DEBUG
         default n
 
+    config BSP_USING_QSPI_FLASH
+        bool "Enable QSPI FLASH (MX25L51245G)"
+        select BSP_USING_QSPI
+        select RT_USING_SFUD
+        select RT_SFUD_USING_QSPI
+        default n
+
     config BSP_USING_OPENAMP
         bool "Enable OpenAMP"
         select RT_USING_OPENAMP
@@ -51,7 +68,7 @@ menu "Onboard Peripheral Drivers"
                 if BSP_USING_SD_CARD
                     config SD_USING_DFS
                         bool "sd card fatfs"
-                        default n
+                        default y
                 endif
 
             menuconfig BSP_USING_EMMC
@@ -65,12 +82,43 @@ menu "Onboard Peripheral Drivers"
         endif
 
     config BSP_USING_AUDIO
-    bool "Enable Audio Device (WM8994)"
-    select RT_USING_AUDIO
-    select BSP_USING_PMIC
-    select BSP_USING_I2C
-    select BSP_USING_I2C2
-    default n
+        bool "Enable Audio Device (WM8994)"
+        select RT_USING_AUDIO
+        select BSP_USING_PMIC
+        select BSP_USING_SDMMC
+        select BSP_USING_SD_CARD
+        select SD_USING_DFS
+        select BSP_USING_I2C
+        select BSP_USING_I2C2
+        default n
+
+    config BSP_USING_DCMI
+        bool "Enable CAMERA (ov5640)"
+        select BSP_USING_MFX
+        select BSP_USING_PMIC
+        select BSP_USING_I2C
+        select BSP_USING_I2C2
+        default n
+
+    config BSP_USING_MFX
+        bool "Enable Multi Function eXpander"
+        default n
+
+    menuconfig BSP_USING_RS485
+        bool "Enable RS485 "
+        default n
+        if BSP_USING_RS485
+            comment "set rts pin number "
+            config BSP_RS485_RTS_PIN
+                int "RS485 rts pin number"
+                range 1 176
+                default 5
+
+            config RS485_UART_DEVICE_NAME
+            string "the uart name for rs485"
+            default "uart3"
+
+        endif
 
 endmenu
 
@@ -80,6 +128,28 @@ menu "On-chip Peripheral Drivers"
         select RT_USING_PIN
         default y
 
+    config BSP_USING_WWDG
+        bool "Enable WWDG"
+        select RT_USING_WWDG
+        select RT_USING_WDT
+        default n
+
+    config BSP_USING_QSPI
+        bool "Enable QSPI BUS"
+        select RT_USING_QSPI
+        select RT_USING_SPI
+        default n
+    
+    config BSP_USING_SPDIFRX
+        bool "Enable spdifrx"
+        select BSP_USING_AUDIO
+        default n
+
+    config BSP_USING_DFSDM
+        bool "Enable dfsdm"
+        select BSP_USING_AUDIO
+        default n
+
     menuconfig BSP_USING_UART
         bool "Enable UART"
         select RT_USING_SERIAL
@@ -133,6 +203,16 @@ menu "On-chip Peripheral Drivers"
                 default n
         endif
 
+    menuconfig BSP_USING_LPTIM
+        bool "Enable lptimer"
+        default n
+        select RT_USING_LPTIMER
+        if BSP_USING_LPTIM
+            config BSP_USING_LPTIM1
+                bool "Enable LPTIM1"
+                default n
+        endif
+
     menuconfig BSP_USING_PWM
         bool "Enable pwm"
         default n
@@ -224,22 +304,21 @@ menu "On-chip Peripheral Drivers"
         select RT_USING_SPI
         default n
         if BSP_USING_SPI
-            config BSP_USING_SPI5
-                bool "Enable SPI5 BUS"
-                default n
-
-            config BSP_SPI5_TX_USING_DMA
-                bool "Enable SPI5 TX DMA"
-                depends on BSP_USING_SPI5
+            config BSP_USING_SPI1
+                bool "Enable SPI1 BUS"
                 default n
 
-            config BSP_SPI5_RX_USING_DMA
-                bool "Enable SPI5 RX DMA"
-                depends on BSP_USING_SPI5
-                select BSP_SPI5_TX_USING_DMA
-                default n
         endif
 
+    menuconfig BSP_USING_FDCAN
+    bool "Enable FDCAN"
+    default n
+    if BSP_USING_FDCAN
+        config BSP_USING_FDCAN1
+            bool "Enable FDCAN1"
+            default n
+    endif
+
  source "../libraries/HAL_Drivers/Kconfig"
 
 endmenu

+ 44 - 0
bsp/stm32/stm32mp157a-st-ev1/board/SConscript

@@ -13,6 +13,9 @@ CubeMX_Config/Common/System/system_stm32mp1xx.c
 CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c
 ''')
 
+if GetDepend(['BSP_USING_SPI1']):
+    src += Glob('ports/spi_sample.c')
+
 if GetDepend(['BSP_USING_PMIC']):
     src += Glob('ports/drv_pmic.c')
 
@@ -32,6 +35,47 @@ if GetDepend(['BSP_USING_AUDIO']):
     src += Glob('ports/drv_wm8994.c')
     src += Glob('ports/drv_sound.c')
 
+if GetDepend(['BSP_USING_DCMI']):
+    src += Glob('ports/drv_dcmi.c')
+    src += Glob('ports/drv_ov5640.c')
+
+if GetDepend(['BSP_USING_MFX']):
+    src += Glob('ports/drv_mfx.c')
+    src += Glob('ports/mfxstm32l152.c')
+
+if GetDepend(['BSP_USING_FDCAN']):
+    src += Glob('ports/drv_fdcan.c')
+
+if GetDepend(['BSP_USING_QSPI']):
+    src += Glob('ports/drv_qspi_flash.c')
+
+if GetDepend(['BSP_USING_SPDIFRX']):
+    src += Glob('ports/drv_spdifrx.c')
+
+if GetDepend(['BSP_USING_DFSDM']):
+    src += Glob('ports/drv_dfsdm.c')
+
+if GetDepend(['BSP_USING_WWDG']):
+    src += Glob('ports/drv_wwdg.c')
+
+if GetDepend(['BSP_USING_EXTI']):
+    src += Glob('ports/drv_exti.c')
+
+if GetDepend(['BSP_USING_RNG']) or GetDepend(['BSP_USING_HASH']) or GetDepend(['BSP_USING_CRC']) or GetDepend(['BSP_USING_CRYP']):
+    src += Glob('ports/crypto_sample.c')
+
+if GetDepend(['BSP_USING_PWR']):
+    src += Glob('ports/drv_pwr.c')
+
+if GetDepend(['BSP_USING_LPTIM1']):
+    src += Glob('ports/drv_lptim.c')
+
+if GetDepend(['BSP_USING_RS485']):
+    src += Glob('ports/drv_rs485.c')
+
+if GetDepend(['BSP_USING_TIM14']):
+    src += Glob('ports/timer_sample.c')
+
 if GetDepend(['BSP_USING_OPENAMP']):
     src +=  Glob('CubeMX_Config/CM4/Src/ipcc.c')
     src +=  Glob('CubeMX_Config/CM4/Src/openamp.c')

+ 1 - 6
bsp/stm32/stm32mp157a-st-ev1/board/board.h

@@ -23,14 +23,9 @@ extern "C" {
 #endif
 
 #define STM32_FLASH_START_ADRESS     ((uint32_t)0x10000000)  
-#if defined(BSP_USING_OPENAMP)
-#define STM32_FLASH_SIZE             (64 * 1024)
-#else
-#define STM32_FLASH_SIZE             (256 * 1024)    
-#endif
+#define STM32_FLASH_SIZE             (191 * 1024)
 #define STM32_FLASH_END_ADDRESS      ((uint32_t)(STM32_FLASH_START_ADRESS + STM32_FLASH_SIZE))
 
-    
 #if defined(BSP_USING_OPENAMP)    
 #define STM32_SRAM_BEGIN             (uint32_t)0x10030000 
 #else

+ 365 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/crypto_sample.c

@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-06-27     thread-liu   first version
+ */
+
+#include <board.h>
+
+#include "drv_crypto.h"
+#include <hwcrypto.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(BSP_USING_RNG)
+static rt_err_t hw_rng_sample(int random_num)
+{
+    rt_err_t result = RT_EOK;
+    int i = 0, num0 = 0, num1 = 0;
+
+    if (random_num == 0)
+    {
+        return RT_ERROR;
+    }
+
+    for (i = 0; i< random_num; i++)
+    {
+        result = rt_hwcrypto_rng_update();
+        rt_kprintf("%d ", result);
+        result%2 ? num1++ : num0++;
+    }
+    rt_kprintf("\neven numbers : %d, odd numbers: %d\n",num1, num0);
+
+    return RT_EOK;
+}
+#endif
+
+#if defined(BSP_USING_CRC)
+static void hw_crc_sample(uint8_t *temp, int size)
+{
+    struct rt_hwcrypto_ctx *ctx;
+    rt_uint32_t result = 0;
+    
+    struct hwcrypto_crc_cfg cfg =
+    {
+        .last_val = 0xFFFFFFFF,
+        .poly     = 0x04C11DB7,
+        .width    = 32,
+        .xorout   = 0x00000000,
+        .flags    = 0,
+    };
+
+    ctx = rt_hwcrypto_crc_create(rt_hwcrypto_dev_default(), HWCRYPTO_CRC_CRC32);
+    rt_hwcrypto_crc_cfg(ctx, &cfg);
+
+    result = rt_hwcrypto_crc_update(ctx, temp, size);
+
+    rt_kprintf("crc result: %x \n", result);                
+
+    rt_hwcrypto_crc_destroy(ctx);  
+}
+#endif
+
+#if defined(BSP_USING_HASH)
+static void hw_hash_sample()
+{
+    int i = 0;
+    struct rt_hwcrypto_ctx *ctx = RT_NULL;
+    const uint8_t hash_input[] = "RT-Thread was born in 2006, it is an open source, neutral, and community-based real-time operating system (RTOS).";
+    
+    static uint8_t sha1_output[20];
+    static uint8_t sha1_except[20] = {0xff, 0x3c, 0x95, 0x54, 0x95, 0xf0, 0xad, 
+                                    0x02, 0x1b, 0xa8, 0xbc, 0xa2, 0x2e, 0xa5,
+                                    0xb0, 0x62, 0x1b, 0xdf, 0x7f, 0xec};
+    
+    static uint8_t md5_output[16];
+    static uint8_t md5_except[16] = {0x40, 0x86, 0x03, 0x80, 0x0d, 0x8c, 0xb9, 
+                                   0x4c, 0xd6, 0x7d, 0x28, 0xfc, 0xf6, 0xc3,
+                                   0xac, 0x8b};
+    
+    static uint8_t sha224_output[28];
+    static uint8_t sha224_except[28] = {0x6f, 0x62, 0x52, 0x7d, 0x80, 0xe6, 
+                                        0x9f, 0x82, 0x78, 0x7a, 0x46, 0x91,
+                                        0xb0, 0xe9, 0x64, 0x89, 0xe6, 0xc3,
+                                        0x6b, 0x7e, 0xcf, 0xca, 0x11, 0x42,
+                                        0xc8, 0x77, 0x13, 0x79};
+    static uint8_t sha256_output[32];
+    static uint8_t sha256_except[32] = {0x74, 0x19, 0xb9, 0x0e, 0xd1, 0x46,
+                                        0x37, 0x0a, 0x55, 0x18, 0x26, 0x6c,
+                                        0x50, 0xd8, 0x71, 0x34, 0xfa, 0x1f,
+                                        0x5f, 0x5f, 0xe4, 0x9a, 0xe9, 0x40,
+                                        0x0a, 0x7d, 0xa0, 0x26, 0x1b, 0x86,
+                                        0x67, 0x45};
+    rt_kprintf("Hash Test start: \n");
+    rt_kprintf("Hash Test string: \n");
+    for (i = 0; i < sizeof(hash_input); i++)
+    {
+        rt_kprintf("%c", hash_input[i]);
+    }
+    rt_kprintf("\n");
+    
+    /* sh1 test*/
+    ctx = rt_hwcrypto_hash_create(rt_hwcrypto_dev_default(), HWCRYPTO_TYPE_SHA1);
+    if (ctx == RT_NULL)
+    {
+        rt_kprintf("create hash[%08x] context err!\n", HWCRYPTO_TYPE_SHA1);
+        return ;
+    }
+    rt_kprintf("Create sha1 type success!\n");
+    rt_kprintf("Except sha1 result: \n");
+    for (i = 0; i < sizeof(sha1_except); i++)
+    {
+        rt_kprintf("%x ", sha1_except[i]);
+    } 
+    rt_kprintf("\n");
+    /* start sha1 */
+    rt_hwcrypto_hash_update(ctx, hash_input, rt_strlen((char const *)hash_input));
+    /* get sha1 result */
+    rt_hwcrypto_hash_finish(ctx, sha1_output, rt_strlen((char const *)sha1_output));
+    
+    rt_kprintf("Actual sha1 result: \n");
+    for (i = 0; i < sizeof(sha1_output); i++)
+    {
+        rt_kprintf("%x ", sha1_output[i]);
+    }
+    rt_kprintf("\n");
+    if(rt_memcmp(sha1_output, sha1_except, sizeof(sha1_except)/sizeof(sha1_except[0])) != 0)
+    {
+        rt_kprintf("Hash type sha1 Test error, The actual result is not equal to the except result\n");
+    }
+    else
+    {
+        rt_kprintf("Hash type sha1 Test success, The actual result is equal to the except result\n");
+    }
+    /* deinit hash*/
+    rt_hwcrypto_hash_destroy(ctx);
+    
+    /* md5 test*/
+    ctx = rt_hwcrypto_hash_create(rt_hwcrypto_dev_default(), HWCRYPTO_TYPE_MD5);
+    if (ctx == RT_NULL)
+    {
+        rt_kprintf("create hash[%08x] context err!\n", HWCRYPTO_TYPE_MD5);
+        return ;
+    }
+    rt_kprintf("Create md5 type success!\n");
+    rt_kprintf("Except md5 result: \n");
+    for (i = 0; i < sizeof(md5_except); i++)
+    {
+        rt_kprintf("%x ", md5_except[i]);
+    } 
+    rt_kprintf("\n");
+    /* start md5 */
+    rt_hwcrypto_hash_update(ctx, hash_input, rt_strlen((char const *)hash_input));
+    /* get md5 result */
+    rt_hwcrypto_hash_finish(ctx, md5_output, rt_strlen((char const *)md5_output));
+    
+    rt_kprintf("Actual md5 result: \n");
+    for (i = 0; i < sizeof(md5_output); i++)
+    {
+        rt_kprintf("%x ", md5_output[i]);
+    }
+    rt_kprintf("\n");
+    if(rt_memcmp(md5_output, md5_except, sizeof(md5_except)/sizeof(md5_except[0])) != 0)
+    {
+        rt_kprintf("Hash type md5 Test error, The actual result is not equal to the except result\n");
+    }
+    else
+    {
+        rt_kprintf("Hash type md5 Test success, The actual result is equal to the except result\n");
+    }
+    /* deinit hash*/
+    rt_hwcrypto_hash_destroy(ctx);
+    
+    /* sha224 test */
+    ctx = rt_hwcrypto_hash_create(rt_hwcrypto_dev_default(), HWCRYPTO_TYPE_SHA224);
+    if (ctx == RT_NULL)
+    {
+        rt_kprintf("create hash[%08x] context err!\n", HWCRYPTO_TYPE_SHA224);
+        return ;
+    }
+    rt_kprintf("Create sha224 type success!\n");
+    rt_kprintf("Except sha224 result: \n");
+    for (i = 0; i < sizeof(sha224_except); i++)
+    {
+        rt_kprintf("%x ", sha224_except[i]);
+    } 
+    rt_kprintf("\n");
+    /* start sha224 */
+    rt_hwcrypto_hash_update(ctx, hash_input, rt_strlen((char const *)hash_input));
+    /* get sha224 result */
+    rt_hwcrypto_hash_finish(ctx, sha224_output, rt_strlen((char const *)sha224_output));
+    
+    rt_kprintf("Actual sha224 result: \n");
+    for (i = 0; i < sizeof(sha224_output); i++)
+    {
+        rt_kprintf("%x ", sha224_output[i]);
+    }
+    rt_kprintf("\n");
+    if(rt_memcmp(sha224_output, sha224_except, sizeof(sha224_except)/sizeof(sha224_except[0])) != 0)
+    {
+        rt_kprintf("Hash type sha224 Test error, The actual result is not equal to the except result\n");
+    }
+    else
+    {
+        rt_kprintf("Hash type sha224 Test success, The actual result is equal to the except result\n");
+    }
+    rt_hwcrypto_hash_destroy(ctx);
+
+    /* sha256 test*/
+    ctx = rt_hwcrypto_hash_create(rt_hwcrypto_dev_default(), HWCRYPTO_TYPE_SHA256);
+    if (ctx == RT_NULL)
+    {
+        rt_kprintf("create hash[%08x] context err!\n", HWCRYPTO_TYPE_SHA256);
+        return ;
+    }
+    
+    rt_kprintf("Create sha256 type success!\n");
+    rt_kprintf("Except sha256 result: \n");
+    for (i = 0; i < sizeof(sha256_except); i++)
+    {
+        rt_kprintf("%x ", sha256_except[i]);
+    } 
+    rt_kprintf("\n");
+    /* start sha256 */
+    rt_hwcrypto_hash_update(ctx, hash_input, rt_strlen((char const *)hash_input));
+    /* get sha256 result */
+    rt_hwcrypto_hash_finish(ctx, sha256_output, rt_strlen((char const *)sha256_output));
+
+    rt_kprintf("Actual sha256 result: \n");
+    for (i = 0; i < sizeof(sha256_output); i++)
+    {
+        rt_kprintf("%x ", sha256_output[i]);
+    }
+    rt_kprintf("\n");
+    
+    if(rt_memcmp(sha256_output, sha256_except, sizeof(sha256_except)/sizeof(sha256_except[0])) != 0)
+    {
+        rt_kprintf("Hash type sha256 Test error, The actual result is not equal to the except result\n");
+    }
+    else
+    {
+        rt_kprintf("Hash type sha256 Test success, The actual result is equal to the except result\n");
+    }
+    rt_hwcrypto_hash_destroy(ctx);
+    rt_kprintf("Hash Test over!\n");    
+}
+#endif
+
+static int crypto(int argc, char **argv)
+{
+    int result = RT_EOK;
+    static rt_device_t device = RT_NULL;
+    char *result_str;
+    
+    if (argc > 1)
+    {
+        if (!strcmp(argv[1], "probe"))
+        {
+            if (argc == 3)
+            {
+                char *dev_name = argv[2];
+                device = rt_device_find(dev_name);
+                result_str = (device == RT_NULL) ? "failure" : "success";
+                rt_kprintf("probe %s %s \n", argv[2], result_str);
+            }
+            else
+            {
+                rt_kprintf("crypto probe <crypto_name>   - probe crypto by name\n");
+            }
+        }
+        else
+        {
+            if (device == RT_NULL)
+            {
+                rt_kprintf("Please using 'crypto probe <crypto_name>' first\n");
+                return -RT_ERROR;
+            }
+            if (!strcmp(argv[1], "rng"))
+            {
+#if defined (BSP_USING_RNG)
+                if (argc == 3)
+                {
+                    result = hw_rng_sample(atoi(argv[2]));
+                    if(result != RT_EOK)
+                    {
+                        rt_kprintf("please input a  legal number, not <%d>\n", atoi(argv[2]));
+                    }
+                }
+                else
+                {
+                    rt_kprintf("rng <number>        - generate <number> digital\n");
+                }
+                
+#else
+                rt_kprintf("please enable RNG first!\n");
+#endif
+            }
+            else if (!strcmp(argv[1], "crc"))
+            {
+#if defined (BSP_USING_CRC)
+                int size = 0, i = 0; 
+                if (argc > 3)
+                {
+                    size = argc - 2;
+                    uint8_t *data = rt_malloc(size);
+                    if (data)
+                    {
+                        for (i = 0; i < size; i++)
+                        {
+                            data[i] = strtol(argv[2 + i], NULL, 0);
+                        }
+                        hw_crc_sample(data, size);  
+                        rt_free(data);
+                    }
+                    else
+                    {
+                        rt_kprintf("Low memory!\n");
+                    }
+                }
+                else
+                {
+                    rt_kprintf("crypto crc data1 ... dataN          - calculate data1 ... dataN crc\n");
+                }
+#else
+                rt_kprintf("please enable CRC first!\n");
+#endif
+            }
+            else if (!strcmp(argv[1], "hash"))
+            {
+#if defined (BSP_USING_HASH)
+                if (argc == 3)
+                {
+                    hw_hash_sample(); 
+                }
+                else
+                {
+                    rt_kprintf("crypto hash sample          - hash use sample\n");    
+                }
+#else
+         rt_kprintf("please enable CRC first!\n");       
+#endif
+                
+            }
+            else
+            {
+                rt_kprintf("Unknown command. Please enter 'crypto' for help\n");
+            }
+        }
+    }
+    else
+    {
+        rt_kprintf("Usage: \n");
+        rt_kprintf("crypto probe <crypto_name>                  - probe crypto by name\n");
+        rt_kprintf("crypto rng number                           - generate numbers digital\n");
+        rt_kprintf("crypto crc data1 ... dataN                  - calculate data1 ... dataN crc\n");
+        rt_kprintf("crypto hash sample                          - hash use sample\n");
+        result = -RT_ERROR;
+    }
+    
+    return result;
+}
+MSH_CMD_EXPORT(crypto, crypto function);

+ 203 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_dcmi.c

@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-07-27     thread-liu        the first version
+ */
+
+#include "board.h"
+
+#if defined(BSP_USING_DCMI)
+#include "drv_dcmi.h"
+
+#define DRV_DEBUG
+#define LOG_TAG             "drv.dcmi"
+#include <drv_log.h>
+
+struct stm32_dcmi
+{
+    struct rt_device dev;
+};
+static struct stm32_dcmi rt_dcmi = {0};
+DCMI_HandleTypeDef dcmi    = {0};
+DMA_HandleTypeDef hdma_dcmi = {0};
+
+extern void jpeg_data_process(void);
+
+static void rt_hw_dmci_dma_init(void)
+{
+    __HAL_RCC_DMAMUX_CLK_ENABLE();
+    __HAL_RCC_DMA1_CLK_ENABLE();
+
+    hdma_dcmi.Instance                 = DMA1_Stream3;
+    hdma_dcmi.Init.Request             = DMA_REQUEST_DCMI;
+    hdma_dcmi.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+    hdma_dcmi.Init.PeriphInc           = DMA_PINC_DISABLE;
+    hdma_dcmi.Init.MemInc              = DMA_MINC_ENABLE;
+    hdma_dcmi.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+    hdma_dcmi.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
+    hdma_dcmi.Init.Mode                = DMA_CIRCULAR;
+    hdma_dcmi.Init.Priority            = DMA_PRIORITY_HIGH;
+    hdma_dcmi.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
+    hdma_dcmi.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
+    hdma_dcmi.Init.MemBurst            = DMA_MBURST_SINGLE;
+    hdma_dcmi.Init.PeriphBurst         = DMA_PBURST_SINGLE;
+
+    HAL_DMA_Init(&hdma_dcmi);
+
+    __HAL_LINKDMA(&dcmi, DMA_Handle, hdma_dcmi);
+
+    HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0x02, 0);
+    HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
+}
+
+void rt_hw_dcmi_dma_config(rt_uint32_t dst_addr1, rt_uint32_t dst_addr2, rt_uint16_t len)
+{
+    HAL_DMAEx_MultiBufferStart(&hdma_dcmi, (rt_uint32_t)&DCMI->DR, dst_addr1, dst_addr2, len);
+    __HAL_DMA_ENABLE_IT(&hdma_dcmi, DMA_IT_TC);
+}
+
+static rt_err_t rt_hw_dcmi_init(DCMI_HandleTypeDef *device)
+{
+    RT_ASSERT(device != RT_NULL);
+
+    device->Instance               = DCMI;
+    device->Init.SynchroMode       = DCMI_SYNCHRO_HARDWARE;
+    device->Init.PCKPolarity       = DCMI_PCKPOLARITY_RISING;
+    device->Init.VSPolarity        = DCMI_VSPOLARITY_LOW;
+    device->Init.HSPolarity        = DCMI_HSPOLARITY_LOW;
+    device->Init.CaptureRate       = DCMI_CR_ALL_FRAME;
+    device->Init.ExtendedDataMode  = DCMI_EXTEND_DATA_8B;
+    device->Init.JPEGMode          = DCMI_JPEG_DISABLE;
+    device->Init.ByteSelectMode    = DCMI_BSM_ALL;
+    device->Init.ByteSelectStart   = DCMI_OEBS_ODD;
+    device->Init.LineSelectMode    = DCMI_LSM_ALL;
+    device->Init.LineSelectStart   = DCMI_OELS_ODD;
+
+    if (HAL_DCMI_Init(device) != HAL_OK)
+    {
+        LOG_E("dcmi init error!");
+        return RT_ERROR;
+    }
+
+    DCMI->IER = 0x0;
+
+    __HAL_DCMI_ENABLE_IT(device, DCMI_IT_FRAME);
+    __HAL_DCMI_ENABLE(device);
+
+    rt_hw_dmci_dma_init();
+
+    return RT_EOK;
+}
+
+void DCMI_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    HAL_DCMI_IRQHandler(&dcmi);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+/* Capture a frame of the image */
+void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+	jpeg_data_process();
+    __HAL_DCMI_ENABLE_IT(&dcmi,DCMI_IT_FRAME);
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+void DMA1_Stream3_IRQHandler(void)
+{
+    extern void rt_hw_camera_rx_callback(void);
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    if(__HAL_DMA_GET_FLAG(&hdma_dcmi, DMA_FLAG_TCIF3_7)!=RESET)
+    {
+        __HAL_DMA_CLEAR_FLAG(&hdma_dcmi, DMA_FLAG_TCIF3_7);
+        rt_hw_camera_rx_callback();
+    }
+    
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+static rt_err_t rt_dcmi_init(rt_device_t dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+    rt_err_t result = RT_EOK;
+
+    result = rt_hw_dcmi_init(&dcmi);
+    if (result != RT_EOK)
+    {
+        return result;
+    }
+
+    return result;
+}
+
+static rt_err_t rt_dcmi_open(rt_device_t dev, rt_uint16_t oflag)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_dcmi_close(rt_device_t dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_dcmi_control(rt_device_t dev, int cmd, void *args)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    return RT_EOK;
+}
+
+static rt_size_t rt_dcmi_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    return RT_EOK;
+}
+
+static rt_size_t rt_dcmi_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    return RT_EOK;
+}
+
+int dcmi_init(void)
+{
+    rt_dcmi.dev.type      = RT_Device_Class_Miscellaneous;
+    rt_dcmi.dev.init      = rt_dcmi_init;
+    rt_dcmi.dev.open      = rt_dcmi_open;
+    rt_dcmi.dev.close     = rt_dcmi_close;
+    rt_dcmi.dev.read      = rt_dcmi_read;
+    rt_dcmi.dev.write     = rt_dcmi_write;
+    rt_dcmi.dev.control   = rt_dcmi_control;
+    rt_dcmi.dev.user_data = RT_NULL;
+
+    rt_device_register(&rt_dcmi.dev, "dcmi", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
+
+    LOG_I("dcmi init success!");
+
+    return RT_EOK;
+}
+INIT_BOARD_EXPORT(dcmi_init);
+
+#endif

+ 22 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_dcmi.h

@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-07-27     thread-liu   first version
+ */
+
+#ifndef __DRV_DCMI_H__
+#define __DRV_DCMI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 385 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_dfsdm.c

@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-07-07     thread-liu   first version
+ */
+
+#include "board.h"
+
+#if defined(BSP_USING_DFSDM)
+#include "drv_wm8994.h"
+#include "drv_dfsdm.h"
+
+#define DRV_DEBUG
+#define LOG_TAG             "drv.dfsdm"
+#include <drv_log.h>
+
+#define          FILTER_FIFO_SIZE         (1024)
+#if defined(__CC_ARM) || defined(__CLANG_ARM)
+__attribute__((at(0x2FFC8000)))
+#elif defined ( __GNUC__ )
+__attribute__((at(0x2FFC8000)))
+#elif defined(__ICCARM__)
+#pragma location = 0x2FFC8000
+#endif
+rt_int32_t FILTER0_FIFO[FILTER_FIFO_SIZE];
+
+#define PALY_SIZE 2048
+#if defined(__CC_ARM) || defined(__CLANG_ARM)
+__attribute__((at(0x2FFCA000)))
+#elif defined ( __GNUC__ )
+__attribute__((at(0x2FFCA000)))
+#elif defined(__ICCARM__)
+#pragma location = 0x2FFCA000
+#endif
+static rt_int16_t PLAY_BUF[PALY_SIZE];
+    
+#if defined(__CC_ARM) || defined(__CLANG_ARM)
+__attribute__((at(0x2FFC9000)))
+#elif defined ( __GNUC__ )
+__attribute__((at(0x2FFC9000)))
+#elif defined(__ICCARM__)
+#pragma location = 0x2FFC9000
+#endif
+rt_int32_t FILTER1_FIFO[FILTER_FIFO_SIZE];
+
+static volatile rt_uint8_t DmaLeftRecBuffCplt  = 0;
+static volatile rt_uint8_t DmaRightRecBuffCplt = 0;
+static volatile rt_uint8_t DmaLeftRecHalfBuffCplt = 0;
+static volatile rt_uint8_t DmaRightRecHalfBuffCplt = 0;
+
+static DFSDM_Channel_HandleTypeDef hdfsdm1_channel0 = {0}; /* data_in1_right */
+static DFSDM_Channel_HandleTypeDef hdfsdm1_channel1 = {0}; /* data_in1_left */
+
+static DFSDM_Filter_HandleTypeDef hdfsdm1_filter0 = {0}; /* data_in1_right */
+static DFSDM_Filter_HandleTypeDef hdfsdm1_filter1 = {0}; /* data_in1_left */
+
+extern DMA_HandleTypeDef hdma_dfsdm1_flt0;
+extern DMA_HandleTypeDef hdma_dfsdm1_flt1;
+
+static struct rt_device dfsdm_dev =  {0};
+
+void DMA2_Stream2_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    
+    HAL_DMA_IRQHandler(&hdma_dfsdm1_flt1);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+void DMA2_Stream1_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    
+    HAL_DMA_IRQHandler(&hdma_dfsdm1_flt0);
+    
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+    if(hdfsdm_filter == &hdfsdm1_filter1)
+    {
+        DmaLeftRecHalfBuffCplt = 1;
+    }
+    else
+    {
+        DmaRightRecHalfBuffCplt = 1;
+    }
+}
+
+void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+    if (hdfsdm_filter == &hdfsdm1_filter1)
+    {
+        DmaLeftRecBuffCplt = 1;
+    }
+    else
+    {
+        DmaRightRecBuffCplt = 1;
+    }
+}
+
+static int rt_hw_dfsdm_init(void)
+{
+    /* DATAIN1_LEFT */
+    __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hdfsdm1_channel1);
+    hdfsdm1_channel1.Instance                      = DFSDM1_Channel1;
+    hdfsdm1_channel1.Init.OutputClock.Activation   = ENABLE;
+    hdfsdm1_channel1.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_SYSTEM; /* 209MHZ */
+    hdfsdm1_channel1.Init.OutputClock.Divider      = 74; /* 209/74 = 2.82MHZ*/
+    hdfsdm1_channel1.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
+    hdfsdm1_channel1.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
+    hdfsdm1_channel1.Init.Input.Pins               = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
+    hdfsdm1_channel1.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_RISING ;   /* left */
+    hdfsdm1_channel1.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
+    hdfsdm1_channel1.Init.Awd.FilterOrder          = DFSDM_CHANNEL_FASTSINC_ORDER; 
+    hdfsdm1_channel1.Init.Awd.Oversampling         = 10; 
+    hdfsdm1_channel1.Init.Offset                   = 0;
+    hdfsdm1_channel1.Init.RightBitShift            = 2;
+    if(HAL_OK != HAL_DFSDM_ChannelInit(&hdfsdm1_channel1))
+    {
+        return RT_ERROR;
+    }
+    
+    /* DATAIN1_RIGHT */
+    __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hdfsdm1_channel0);
+    hdfsdm1_channel0.Instance                      = DFSDM1_Channel0;
+    hdfsdm1_channel0.Init.OutputClock.Activation   = ENABLE;
+    hdfsdm1_channel0.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_SYSTEM;
+    hdfsdm1_channel0.Init.OutputClock.Divider      = 74;  /* 209/74 = 2.82MHZ*/
+    hdfsdm1_channel0.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
+    hdfsdm1_channel0.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE; 
+    hdfsdm1_channel0.Init.Input.Pins               = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
+    hdfsdm1_channel0.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_FALLING;   /* right */
+    hdfsdm1_channel0.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
+    hdfsdm1_channel0.Init.Awd.FilterOrder          = DFSDM_CHANNEL_FASTSINC_ORDER;
+    hdfsdm1_channel0.Init.Awd.Oversampling         = 10;
+    hdfsdm1_channel0.Init.Offset                   = 0;
+    hdfsdm1_channel0.Init.RightBitShift            = 2;
+    if(HAL_OK != HAL_DFSDM_ChannelInit(&hdfsdm1_channel0))
+    {
+        return RT_ERROR;
+    }
+
+    /* Initialize filter 0 (data_in1 right channel) */
+    __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hdfsdm1_filter0);
+    hdfsdm1_filter0.Instance                          = DFSDM1_Filter0;
+    hdfsdm1_filter0.Init.RegularParam.Trigger         = DFSDM_FILTER_SW_TRIGGER;
+    hdfsdm1_filter0.Init.RegularParam.FastMode        = ENABLE;
+    hdfsdm1_filter0.Init.RegularParam.DmaMode         = ENABLE;
+    hdfsdm1_filter0.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
+    hdfsdm1_filter0.Init.InjectedParam.ScanMode       = DISABLE;
+    hdfsdm1_filter0.Init.InjectedParam.DmaMode        = DISABLE; 
+    hdfsdm1_filter0.Init.FilterParam.SincOrder        = DFSDM_FILTER_SINC3_ORDER;
+    hdfsdm1_filter0.Init.FilterParam.Oversampling     = 64; /* 209 / ( 74 * 64) = 44.1KHZ*/
+    hdfsdm1_filter0.Init.FilterParam.IntOversampling  = 1;
+    if (HAL_OK != HAL_DFSDM_FilterInit(&hdfsdm1_filter0))
+    {
+        return RT_ERROR;
+    }
+
+    /* Initialize filter 1 (data_in1 left channel) */
+    __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hdfsdm1_filter1);
+    hdfsdm1_filter1.Instance                          = DFSDM1_Filter1;
+    hdfsdm1_filter1.Init.RegularParam.Trigger         = DFSDM_FILTER_SW_TRIGGER;
+    hdfsdm1_filter1.Init.RegularParam.FastMode        = ENABLE;
+    hdfsdm1_filter1.Init.RegularParam.DmaMode         = ENABLE;
+    hdfsdm1_filter1.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER; 
+    hdfsdm1_filter1.Init.InjectedParam.ScanMode       = DISABLE; 
+    hdfsdm1_filter1.Init.InjectedParam.DmaMode        = DISABLE; 
+    hdfsdm1_filter1.Init.FilterParam.SincOrder        = DFSDM_FILTER_SINC3_ORDER;
+    hdfsdm1_filter1.Init.FilterParam.Oversampling     = 64; /* 209 / ( 74 * 64) = 44.1KHZ*/
+    hdfsdm1_filter1.Init.FilterParam.IntOversampling  = 1;
+    if (HAL_OK != HAL_DFSDM_FilterInit(&hdfsdm1_filter1))
+    {
+        return RT_ERROR;
+    }
+
+    /* Configure regular channel and continuous mode for filter 0 (data_in1 left channel) */
+    if (HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hdfsdm1_filter1, DFSDM_CHANNEL_1, DFSDM_CONTINUOUS_CONV_ON))
+    {
+        return RT_ERROR;
+    }
+
+    /* Configure regular channel and continuous mode for filter 1 (data_in1 right channel) */
+    if (HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hdfsdm1_filter0, DFSDM_CHANNEL_0, DFSDM_CONTINUOUS_CONV_ON))
+    {
+        return RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+/* dfsdm start coversions */
+static rt_err_t rt_hw_dfsdm_open(void)
+{
+    if (HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hdfsdm1_filter0, FILTER0_FIFO, FILTER_FIFO_SIZE))
+    {
+        LOG_E("DFSDM DATA_IN1 rifht channel start conversions failed!");
+        return RT_ERROR;
+    }
+
+    if (HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hdfsdm1_filter1, FILTER1_FIFO, FILTER_FIFO_SIZE))
+    {
+        LOG_E("DFSDM DATA_IN1 left channel start conversions failed!");
+        return RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t _init(rt_device_t dev)
+{
+   RT_ASSERT(dev != RT_NULL);
+   
+   rt_hw_dfsdm_init();
+
+   return RT_EOK;
+}
+
+static rt_err_t _open(rt_device_t dev, rt_uint16_t oflag)
+{
+   RT_ASSERT(dev != RT_NULL);
+   
+   rt_hw_dfsdm_open();
+
+   return RT_EOK;
+}
+
+static rt_err_t _close(rt_device_t dev)
+{
+   RT_ASSERT(dev != RT_NULL);
+   
+   HAL_DFSDM_FilterRegularStop_DMA(&hdfsdm1_filter0);
+   HAL_DFSDM_FilterRegularStop_DMA(&hdfsdm1_filter1);
+    
+   return RT_EOK;
+}
+
+static rt_size_t _read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+    RT_ASSERT(dev != RT_NULL);
+    rt_uint32_t i = 0;
+    rt_int16_t *p = RT_NULL;
+    p = (rt_int16_t *)buffer;
+    
+    if (!pos)
+    {
+        for (i = 0; i < 512; i++)
+        {
+            p[2*i]     = (int16_t)SaturaLH((FILTER0_FIFO[i] >> 8), -32768, 32767);
+            p[(2*i)+1] = (int16_t)SaturaLH((FILTER1_FIFO[i] >> 8), -32768, 32767);
+        }
+    }
+    else
+    {
+        for (i = 512; i < 1024; i++)
+        {
+            p[2*i]     = (int16_t)SaturaLH((FILTER0_FIFO[i] >> 8), -32768, 32767);
+            p[(2*i)+1] = (int16_t)SaturaLH((FILTER1_FIFO[i] >> 8), -32768, 32767);
+        } 
+    }
+
+    return size;
+}
+
+static rt_size_t _write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+   RT_ASSERT(dev != RT_NULL);
+   
+   return RT_EOK;
+}
+
+static rt_err_t _control(rt_device_t dev, int cmd, void *args)
+{
+   RT_ASSERT(dev != RT_NULL);
+
+   return RT_EOK;
+}
+
+int dfsdm_init(void)
+{
+    dfsdm_dev.type      = RT_Device_Class_Miscellaneous;
+    dfsdm_dev.init      = _init;
+    dfsdm_dev.open      = _open;
+    dfsdm_dev.close     = _close;
+    dfsdm_dev.read      = _read;
+    dfsdm_dev.write     = _write;
+    dfsdm_dev.control   = _control;
+    dfsdm_dev.user_data = RT_NULL;
+
+    rt_device_register(&dfsdm_dev, "dfsdm1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
+    
+    LOG_I("dfsdm1 init success!");
+    
+    return RT_EOK;
+}
+INIT_DEVICE_EXPORT(dfsdm_init);
+
+static int dfsdm_sample(int argc, char **argv)
+{
+    if (argc != 1)
+    {
+        rt_kprintf("Usage:\n");
+        rt_kprintf("dfsdm_sample\n");
+        return -1;
+    }
+    
+    static struct rt_device *dfsdm_dev = RT_NULL;  
+    static struct rt_device *sound_dev = RT_NULL; 
+    rt_uint16_t play_type = OUTPUT_DEVICE_HEADPHONE;
+    rt_uint16_t tickstart = 0;
+    
+    extern SAI_HandleTypeDef hsai_BlockA2;
+    
+    dfsdm_dev = rt_device_find("dfsdm1");
+    if (dfsdm_dev == RT_NULL)
+    {
+        rt_kprintf("no dfsdm device!");
+        return RT_ERROR;
+    }
+    
+    sound_dev = rt_device_find("decoder");
+    if (sound_dev == RT_NULL)
+    {
+        rt_kprintf("no decoder device!");
+        return RT_ERROR;    
+    }
+
+    /* open dfsdm device */
+    rt_device_open(dfsdm_dev, RT_DEVICE_OFLAG_RDWR);
+    /* open sound device */
+    rt_device_open(sound_dev, RT_DEVICE_OFLAG_WRONLY);
+    
+    rt_device_control(sound_dev, SET_PLAY_TYPE, &play_type);
+    rt_device_control(sound_dev, START_PLAY, RT_NULL);
+    
+    rt_memset(PLAY_BUF, 0, PALY_SIZE);
+    
+    tickstart = rt_tick_get();
+    if (HAL_SAI_Transmit_DMA(&hsai_BlockA2, (uint8_t *)PLAY_BUF, PALY_SIZE) != HAL_OK)
+    {
+        rt_kprintf("sai transmit dma failed!\n");
+        return RT_ERROR;
+    }
+    rt_kprintf("dfsdm audio record test begin!\n");
+    
+    while (1)
+    {
+        if ((rt_tick_get() - tickstart) > 0x1000)
+        {
+            HAL_SAI_DMAStop(&hsai_BlockA2);
+            rt_device_close(dfsdm_dev);
+            break;
+        }
+        if (DmaLeftRecHalfBuffCplt && DmaRightRecHalfBuffCplt)
+        {
+            rt_device_read(dfsdm_dev, 0, PLAY_BUF, 512);
+            DmaLeftRecHalfBuffCplt  = 0;
+            DmaRightRecHalfBuffCplt = 0;
+        }
+        else if (DmaLeftRecBuffCplt && DmaRightRecBuffCplt)
+        {
+            rt_device_read(dfsdm_dev, 1, PLAY_BUF, 512);
+            DmaLeftRecBuffCplt  = 0;
+            DmaRightRecBuffCplt = 0;
+        }
+    }
+    
+    rt_kprintf("dfsdm audio record test end!\n");
+    
+    return RT_EOK;
+}
+MSH_CMD_EXPORT(dfsdm_sample, dfsdm audiorecord test);
+
+#endif

+ 26 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_dfsdm.h

@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-07-07     thread-liu   first version
+ */
+
+#ifndef __DRV_DFSDM_H__
+#define __DRV_DFSDM_H__
+
+#include "board.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 36 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_exti.c

@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-07-27     thread-liu        first version
+ */
+
+#include "board.h"
+#ifdef BSP_USING_EXTI
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.exti"
+#include <drv_log.h>
+
+/* defined the KEY2 pin: */
+#define KEY2_PIN    GET_PIN(A, 13)
+
+void key2_on(void *args)
+{
+    rt_kprintf("press key2!\n");
+}
+
+static int exti_sample(void)
+{
+    rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLUP);
+    rt_pin_attach_irq(KEY2_PIN, PIN_IRQ_MODE_FALLING, key2_on, RT_NULL);
+    rt_pin_irq_enable(KEY2_PIN, PIN_IRQ_ENABLE);
+    
+    return RT_EOK;
+}
+INIT_DEVICE_EXPORT(exti_sample);
+
+#endif

+ 290 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_fdcan.c

@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-07-06     thread-liu   first version
+ */
+
+#include "board.h"
+
+#if defined(BSP_USING_FDCAN1) || defined(BSP_USING_FDCAN2)
+
+#include "drv_fdcan.h"
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.fdcan"
+#include <drv_log.h>
+
+struct stm32_fdcan
+{
+    struct rt_device dev;
+    FDCAN_HandleTypeDef fdcan;
+    FDCAN_FilterTypeDef filter;
+    FDCAN_TxHeaderTypeDef tx_config;
+    FDCAN_RxHeaderTypeDef rx_config;
+    volatile rt_uint8_t fifo0;
+    volatile rt_uint8_t fifo1;
+};
+static struct stm32_fdcan rt_fdcan = {0};
+
+static rt_err_t rt_fdcan_init(rt_device_t dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+    struct stm32_fdcan *device = (struct stm32_fdcan *)dev;
+
+    device->fdcan.Instance                  = FDCAN1;
+    device->fdcan.Init.FrameFormat          = FDCAN_FRAME_CLASSIC;
+    device->fdcan.Init.Mode                 = FDCAN_MODE_INTERNAL_LOOPBACK;
+    device->fdcan.Init.AutoRetransmission   = ENABLE;
+    device->fdcan.Init.TransmitPause        = DISABLE;
+    device->fdcan.Init.ProtocolException    = ENABLE;
+    device->fdcan.Init.NominalPrescaler     = 0x01; /* tq = NominalPrescaler x (1/fdcan_ker_ck) */
+    device->fdcan.Init.NominalSyncJumpWidth = 0x08;
+    device->fdcan.Init.DataPrescaler        = 0x01;
+    device->fdcan.Init.DataSyncJumpWidth    = 0x04;
+    device->fdcan.Init.DataTimeSeg1         = 0x05; /* DataTimeSeg1 = Propagation_segment + Phase_segment_1 */
+    device->fdcan.Init.DataTimeSeg2         = 0x04;
+    device->fdcan.Init.NominalTimeSeg1      = 0x1F; /* NominalTimeSeg1 = Propagation_segment + Phase_segment_1 */
+    device->fdcan.Init.NominalTimeSeg2      = 0x08;
+    device->fdcan.Init.MessageRAMOffset     = 0x00;
+    device->fdcan.Init.StdFiltersNbr        = 0x01;
+    device->fdcan.Init.ExtFiltersNbr        = 0x01;
+    device->fdcan.Init.RxFifo0ElmtsNbr      = 0x01;
+    device->fdcan.Init.RxFifo0ElmtSize      = FDCAN_DATA_BYTES_8;
+    device->fdcan.Init.RxFifo1ElmtsNbr      = 0x02;
+    device->fdcan.Init.RxFifo1ElmtSize      = FDCAN_DATA_BYTES_8;
+    device->fdcan.Init.RxBuffersNbr         = 0x00;
+    device->fdcan.Init.TxEventsNbr          = 0x00;
+    device->fdcan.Init.TxBuffersNbr         = 0x00;
+    device->fdcan.Init.TxFifoQueueElmtsNbr  = 0x01;
+    device->fdcan.Init.TxFifoQueueMode      = FDCAN_TX_FIFO_OPERATION;
+    device->fdcan.Init.TxElmtSize           = FDCAN_DATA_BYTES_8;
+
+    if (HAL_FDCAN_Init(&device->fdcan) != HAL_OK)
+    {
+        return RT_ERROR;
+    }
+
+    device->filter.IdType             = FDCAN_EXTENDED_ID;
+    device->filter.FilterIndex        = 0;
+    device->filter.FilterType         = FDCAN_FILTER_MASK;
+    device->filter.FilterConfig       = FDCAN_FILTER_TO_RXFIFO0;
+    device->filter.FilterID1          = 0x1111111;
+    device->filter.FilterID2          = 0x2222222;
+
+    if (HAL_FDCAN_ConfigFilter(&device->fdcan, &device->filter)!=HAL_OK)
+    {
+        return RT_ERROR;
+    }
+    HAL_FDCAN_Start(&device->fdcan);
+    HAL_FDCAN_ActivateNotification(&device->fdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); /* open rx fifo0 new message it */
+
+    device->fifo0 = RESET;
+    device->fifo1 = RESET;
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_fdcan_open(rt_device_t dev, rt_uint16_t oflag)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_fdcan_close(rt_device_t dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_fdcan_control(rt_device_t dev, int cmd, void *args)
+{
+    RT_ASSERT(dev != RT_NULL);
+    struct stm32_fdcan *device = (struct stm32_fdcan *)dev;
+
+    switch (cmd)
+    {
+        case FDCAN_MODE_NORMAL:
+            device->fdcan.Init.Mode  = FDCAN_MODE_NORMAL;
+            break;
+        case FDCAN_MODE_INTERNAL_LOOPBACK:
+            device->fdcan.Init.Mode  = FDCAN_MODE_INTERNAL_LOOPBACK;
+            break;
+        default:
+            break;
+    }
+
+    HAL_FDCAN_Init(&device->fdcan);
+
+    return RT_EOK;
+}
+
+static rt_size_t rt_fdcan_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+    RT_ASSERT(dev != RT_NULL);
+    struct stm32_fdcan *device = (struct stm32_fdcan *)dev;
+
+    if (rt_fdcan.fifo0 == SET)
+    {
+        rt_fdcan.fifo0 = RESET;
+        if (HAL_FDCAN_GetRxMessage(&device->fdcan, FDCAN_RX_FIFO0, &device->rx_config, (uint8_t *)buffer) != HAL_OK)
+        {
+            LOG_E("get msg error from fdcan fifo0!");
+            return 0;
+        }
+
+        return device->rx_config.DataLength >> 16;
+    }
+    if (rt_fdcan.fifo1 == SET)
+    {
+        rt_fdcan.fifo0 = RESET;
+        if (HAL_FDCAN_GetRxMessage(&device->fdcan, FDCAN_RX_FIFO1, &device->rx_config, (uint8_t *)buffer) != HAL_OK)
+        {
+            LOG_E("get msg error from fdcan fifo1!");
+            return 0;
+        }
+
+        return device->rx_config.DataLength >> 16;
+    }
+
+    return 0;
+}
+
+static rt_size_t rt_fdcan_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    RT_ASSERT(dev != RT_NULL);
+    struct stm32_fdcan *device = (struct stm32_fdcan *)dev;
+
+    device->tx_config.Identifier          = 0x1111112;
+    device->tx_config.IdType              = FDCAN_EXTENDED_ID;
+    device->tx_config.TxFrameType         = FDCAN_DATA_FRAME;
+    device->tx_config.DataLength          = FDCAN_DLC_BYTES_8;
+    device->tx_config.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
+    device->tx_config.BitRateSwitch       = FDCAN_BRS_OFF;
+    device->tx_config.FDFormat            = FDCAN_CLASSIC_CAN;
+    device->tx_config.TxEventFifoControl  = FDCAN_NO_TX_EVENTS;
+    device->tx_config.MessageMarker       = 0xCC;
+
+    if (HAL_FDCAN_AddMessageToTxFifoQ(&device->fdcan, &device->tx_config, (uint8_t *)buffer) != HAL_OK)
+    {
+        return RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+void FDCAN1_IT0_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    HAL_FDCAN_IRQHandler(&rt_fdcan.fdcan);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+void FDCAN1_IT1_IRQHandler(void)
+{
+   /* enter interrupt */
+   rt_interrupt_enter();
+
+   HAL_FDCAN_IRQHandler(&rt_fdcan.fdcan);
+
+   /* leave interrupt */
+   rt_interrupt_leave();
+}
+
+void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
+{
+    if (hfdcan->Instance == FDCAN1)
+    {
+        if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
+        {
+            rt_fdcan.fifo0 = SET;
+            HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
+        }
+    }
+}
+
+void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs)
+{
+    if ((RxFifo1ITs & FDCAN_IT_RX_FIFO1_NEW_MESSAGE) != RESET)
+    {
+        rt_fdcan.fifo1 = SET;
+        HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
+    }
+}
+
+int fdcan_init(void)
+{
+    rt_fdcan.dev.type      = RT_Device_Class_CAN;
+    rt_fdcan.dev.init      = rt_fdcan_init;
+    rt_fdcan.dev.open      = rt_fdcan_open;
+    rt_fdcan.dev.close     = rt_fdcan_close;
+    rt_fdcan.dev.read      = rt_fdcan_read;
+    rt_fdcan.dev.write     = rt_fdcan_write;
+    rt_fdcan.dev.control   = rt_fdcan_control;
+    rt_fdcan.dev.user_data = RT_NULL;
+
+    rt_device_register(&rt_fdcan.dev, "fdcan1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
+
+    LOG_I("fdcan1 init success!");
+
+    return RT_EOK;
+}
+INIT_DEVICE_EXPORT(fdcan_init);
+
+#ifdef FINSH_USING_MSH
+#include <finsh.h>
+
+int fdcan_sample(int argc, char **argv)
+{
+    rt_err_t result = RT_EOK;
+    rt_uint8_t i, rx_buf[8], tx_buf[8];
+    struct rt_device *dev = RT_NULL;
+
+    if (argc != 9)
+    {
+        rt_kprintf("Usage:\n");
+        rt_kprintf("fdcan_sample 1 2 3 4 5 6 7 8\n");
+        return -1;
+    }
+
+    for (i = 0; i < 8; i++)
+    {
+        tx_buf[i] = atoi(argv[i+1]);
+    }
+
+    dev = rt_device_find("fdcan1");
+    if (dev == RT_NULL)
+    {
+        rt_kprintf("can't find fdcan1 device!\n");
+        return RT_ERROR;
+    }
+    rt_device_open(dev, RT_DEVICE_OFLAG_RDWR);
+
+    rt_device_write(dev, 0, tx_buf, 8);
+    rt_thread_delay(1);
+    rt_device_read(dev, 0, rx_buf, 8);
+
+    rt_kprintf("fdcan1 loopback test over, rbuf = ");
+    for (i = 0; i < 8; i++)
+    {
+        rt_kprintf(" %x ", rx_buf[i]);
+    }
+    rt_kprintf("\n");
+
+    return result;
+}
+
+MSH_CMD_EXPORT(fdcan_sample, fdcan loopback mode test);
+
+#endif
+
+#endif

+ 22 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_fdcan.h

@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-07-06     thread-liu   first version
+ */
+
+#ifndef __DRV_FDCAN_H__
+#define __DRV_FDCAN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 163 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_lptim.c

@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author          Notes
+ * 2020-06-19     thread-liu      first version
+ */
+
+#include <board.h>
+
+#ifdef BSP_USING_LPTIM
+#include "drv_config.h"
+#include <string.h>
+#include <stdlib.h>
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.lptimer"
+#include <drv_log.h>
+
+#define LED5_PIN  GET_PIN(D, 9)
+LPTIM_HandleTypeDef hlptim1;
+
+extern int lptim_stop(void);
+
+void LPTIM1_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    
+    HAL_LPTIM_IRQHandler(&hlptim1);
+    
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim)
+{
+    if(hlptim->Instance == LPTIM1)
+    {
+        HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_9);
+    }
+    
+#if defined(BSP_USING_PWR)
+    /* All level of ITs can interrupt */
+    __set_BASEPRI(0U); 
+
+    lptim_stop();
+    rt_kprintf("system returns to normal!\n");
+#endif
+}
+
+static int lptim_control(uint8_t pre_value)
+{
+    if(pre_value > 7)
+    {
+       pre_value = 7; 
+    }
+    hlptim1.Instance->CFGR &= ~(7 << 9);      /* clear PRESC[2:0] */
+    hlptim1.Instance->CFGR |= pre_value << 9; /* set PRESC[2:0]  */
+    rt_kprintf("set lptim pre value [0x%x] success!\n", pre_value);
+    
+    return RT_EOK;
+}
+
+int lptim_start(void)
+{
+  /* ### Start counting in interrupt mode ############################# */
+    if (HAL_LPTIM_Counter_Start_IT(&hlptim1, 32767) != HAL_OK)
+    {
+        LOG_D("lptim1 start counting failed!\n");
+        return -RT_ERROR;
+    }
+    
+    LOG_D("lptim1 start counting success!\n");
+        
+    return RT_EOK;
+}
+
+int lptim_stop(void)
+{
+   if (HAL_LPTIM_Counter_Stop_IT(&hlptim1) != HAL_OK)
+   {
+        LOG_D("lptim1 stop failed!\n");
+        return -RT_ERROR;
+   }
+   
+   LOG_D("lptim1 stop counting success!\n"); 
+   
+   return RT_EOK;
+}
+
+int lptim_init(void)
+{
+    rt_pin_mode(LED5_PIN, PIN_MODE_OUTPUT);
+        
+    hlptim1.Instance = LPTIM1;
+    hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
+    hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV8;
+    hlptim1.Init.UltraLowPowerClock.Polarity = LPTIM_CLOCKPOLARITY_RISING;
+    hlptim1.Init.UltraLowPowerClock.SampleTime = LPTIM_CLOCKSAMPLETIME_DIRECTTRANSITION;
+    hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
+    hlptim1.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
+    hlptim1.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;
+    hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;
+    hlptim1.Init.Input1Source = LPTIM_INPUT1SOURCE_GPIO;
+    hlptim1.Init.Input2Source = LPTIM_INPUT2SOURCE_GPIO;
+    if (HAL_LPTIM_Init(&hlptim1) != HAL_OK)
+    {
+        LOG_D("lptim init failed!\n");
+        return -RT_ERROR;
+    }
+    LOG_D("lptim init success!\n");
+    
+    return RT_EOK;
+}
+INIT_DEVICE_EXPORT(lptim_init);
+
+static int lptim_sample(int argc, char *argv[])
+{
+    if (argc > 1)
+    {
+        if (!strcmp(argv[1], "start"))
+        { 
+           lptim_start();
+           return RT_EOK;
+        }
+        else if (!strcmp(argv[1], "stop"))
+        {
+            lptim_stop();
+            return RT_EOK;
+        }
+        else if (!strcmp(argv[1], "set"))
+        {
+            if (argc > 2)
+            {
+               lptim_control(atoi(argv[2]));
+               return RT_EOK;
+            }
+            else
+            {
+                goto _exit;
+            }
+        }
+        else
+        {
+            goto _exit;
+        }
+    }
+_exit:
+    {
+        rt_kprintf("Usage:\n");
+        rt_kprintf("lptim_sample start    - start lptim, the LED5 will start blink\n");
+        rt_kprintf("lptim_sample stop     - stop lptim, the LED5 will stop blink\n");
+        rt_kprintf("lptim_sample set      - set the lptim prescaler to change LED5 blink frquency, lptim_sample set [0 - 7]\n");
+    }
+
+    return -RT_ERROR;
+}
+MSH_CMD_EXPORT(lptim_sample, low power timer sample);
+
+#endif

+ 297 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_mfx.c

@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-08-08     thread-liu   first version
+ */
+
+#include "board.h"
+
+#include "mfxstm32l152.h"
+#define DRV_DEBUG
+#define LOG_TAG             "drv.mfx"
+#include <drv_log.h>
+
+#define CHIP_ADDRESS    0x42     /* mfx address */
+#define I2C_NAME       "i2c2"
+
+struct st_mfx
+{
+    struct rt_device dev; 
+    struct rt_i2c_bus_device *i2c_bus;
+    rt_uint8_t id;
+    rt_uint16_t type;
+};
+static struct st_mfx rt_mfx = {0};
+static IO_DrvTypeDef *IoDrv = NULL;
+
+static rt_err_t read_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint16_t len, rt_uint8_t *buf)
+{
+    struct rt_i2c_msg msg[2] = {0, 0};
+    
+    RT_ASSERT(bus != RT_NULL);
+
+    msg[0].addr  = CHIP_ADDRESS;
+    msg[0].flags = RT_I2C_WR;
+    msg[0].buf   = &reg;
+    msg[0].len   = 1;
+
+    msg[1].addr  = CHIP_ADDRESS;
+    msg[1].flags = RT_I2C_RD;
+    msg[1].len   = len;
+    msg[1].buf   = buf;
+
+    if (rt_i2c_transfer(bus, msg, 2) == 2)
+    {
+        return RT_EOK;
+    }
+
+    return RT_ERROR;
+}
+
+/* i2c write reg */
+static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t data)
+{
+    rt_uint8_t buf[2];
+    struct rt_i2c_msg msgs;
+
+    RT_ASSERT(bus != RT_NULL);
+    buf[0] = reg;
+    buf[1] = data;
+
+    msgs.addr  = CHIP_ADDRESS;
+    msgs.flags = RT_I2C_WR;
+    msgs.buf   = buf;
+    msgs.len   = sizeof(buf);
+
+    if (rt_i2c_transfer(bus, &msgs, 1) == 1)
+    {
+        return RT_EOK;
+    }
+
+    return RT_ERROR;
+}
+
+void MFX_IO_Init(void)
+{
+    rt_mfx.i2c_bus = rt_i2c_bus_device_find(I2C_NAME);
+    if (rt_mfx.i2c_bus == RT_NULL)
+    {
+        LOG_E("can't find %c deivce", I2C_NAME);
+    }
+}
+
+void MFX_IO_DeInit(void)
+{
+}
+
+void MFX_IO_ITConfig(void)
+{
+    static rt_uint8_t mfx_io_it_enabled = 0;
+    GPIO_InitTypeDef  gpio_init_structure;
+
+    if(mfx_io_it_enabled == 0)
+    {
+        mfx_io_it_enabled = 1;
+        /* Enable the GPIO EXTI clock */
+        __HAL_RCC_GPIOI_CLK_ENABLE();
+
+        gpio_init_structure.Pin   = GPIO_PIN_8;
+        gpio_init_structure.Pull  = GPIO_NOPULL;
+        gpio_init_structure.Speed = GPIO_SPEED_FREQ_LOW;
+        gpio_init_structure.Mode  = GPIO_MODE_IT_RISING;
+        HAL_GPIO_Init(GPIOI, &gpio_init_structure);
+
+        /* Enable and set GPIO EXTI Interrupt to the lowest priority */
+        HAL_NVIC_SetPriority((IRQn_Type)(EXTI8_IRQn), 0x04, 0x00);
+        HAL_NVIC_EnableIRQ((IRQn_Type)(EXTI8_IRQn));
+    }
+}
+
+void MFX_IO_Write(rt_uint16_t Addr, rt_uint8_t Reg, rt_uint8_t Value)
+{
+    write_reg(rt_mfx.i2c_bus, Reg, Value);
+}
+
+rt_uint8_t MFX_IO_Read(rt_uint16_t Addr, rt_uint8_t Reg)
+{
+    rt_uint8_t value = 0;
+    read_reg(rt_mfx.i2c_bus, Reg, 1, &value);
+
+    return value;
+}
+
+rt_uint16_t MFX_IO_ReadMultiple(rt_uint16_t Addr, rt_uint8_t Reg, rt_uint8_t *Buffer, rt_uint16_t Length)
+{
+    return read_reg(rt_mfx.i2c_bus, Reg, Length, Buffer);
+}
+
+RT_WEAK void MFX_IO_Delay(rt_uint32_t Delay)
+{
+    rt_thread_delay(Delay);
+}
+
+RT_WEAK void MFX_IO_Wakeup(void) 
+{
+}
+
+RT_WEAK void MFX_IO_EnableWakeupPin(void) 
+{
+}
+
+rt_uint8_t BSP_IO_DeInit(void)
+{
+    IoDrv = NULL;
+    return RT_EOK;
+}
+
+rt_uint32_t BSP_IO_ITGetStatus(rt_uint32_t IoPin)
+{
+    /* Return the IO Pin IT status */
+    return (IoDrv->ITStatus(0, IoPin));
+}
+
+/**
+  * @brief  Clears all the IO IT pending bits.
+  * @retval None
+  */
+void BSP_IO_ITClear(void)
+{
+    /* Clear all IO IT pending bits */
+    IoDrv->ClearIT(0, MFXSTM32L152_GPIO_PINS_ALL);
+}
+
+void BSP_IO_ITClearPin(rt_uint32_t IO_Pins_To_Clear)
+{
+    /* Clear only the selected list of IO IT pending bits */
+    IoDrv->ClearIT(0, IO_Pins_To_Clear);
+}
+
+/**
+  * @brief  Configures the IO pin(s) according to IO mode structure value.
+  * @param  IoPin: IO pin(s) to be configured. 
+  *          This parameter can be one of the following values:
+  *            @arg  MFXSTM32L152_GPIO_PIN_x: where x can be from 0 to 23.
+  * @param  IoMode: IO pin mode to configure
+  *          This parameter can be one of the following values:
+  *            @arg  IO_MODE_INPUT
+  *            @arg  IO_MODE_OUTPUT
+  *            @arg  IO_MODE_IT_RISING_EDGE
+  *            @arg  IO_MODE_IT_FALLING_EDGE
+  *            @arg  IO_MODE_IT_LOW_LEVEL
+  *            @arg  IO_MODE_IT_HIGH_LEVEL            
+  *            @arg  IO_MODE_ANALOG
+  *            @arg  IO_MODE_OFF
+  *            @arg  IO_MODE_INPUT_PU,
+  *            @arg  IO_MODE_INPUT_PD,
+  *            @arg  IO_MODE_OUTPUT_OD,
+  *            @arg  IO_MODE_OUTPUT_OD_PU,
+  *            @arg  IO_MODE_OUTPUT_OD_PD,
+  *            @arg  IO_MODE_OUTPUT_PP,
+  *            @arg  IO_MODE_OUTPUT_PP_PU,
+  *            @arg  IO_MODE_OUTPUT_PP_PD,
+  *            @arg  IO_MODE_IT_RISING_EDGE_PU
+  *            @arg  IO_MODE_IT_FALLING_EDGE_PU
+  *            @arg  IO_MODE_IT_LOW_LEVEL_PU
+  *            @arg  IO_MODE_IT_HIGH_LEVEL_PU
+  *            @arg  IO_MODE_IT_RISING_EDGE_PD
+  *            @arg  IO_MODE_IT_FALLING_EDGE_PD
+  *            @arg  IO_MODE_IT_LOW_LEVEL_PD
+  *            @arg  IO_MODE_IT_HIGH_LEVEL_PD
+  * @retval RT_EOK if all initializations are OK. Other value if error.  
+  */
+rt_uint8_t rt_mfx_pin_mode(rt_uint32_t IoPin, IO_ModeTypedef IoMode)
+{
+    /* Configure the selected IO pin(s) mode */
+    IoDrv->Config(0, IoPin, IoMode);
+
+    return RT_EOK;  
+}
+
+/**
+  * @brief  Sets the IRQ_OUT pin polarity and type
+  * @param  IoIrqOutPinPolarity: High/Low
+  * @param  IoIrqOutPinType:     OpenDrain/PushPull 
+  * @retval OK
+  */
+rt_uint8_t rt_mfx_config_irq(rt_uint8_t IoIrqOutPinPolarity, rt_uint8_t IoIrqOutPinType)
+{
+    if((rt_mfx.id == MFXSTM32L152_ID_1) || (rt_mfx.id == MFXSTM32L152_ID_2))
+    {
+        /* Initialize the IO driver structure */
+        mfxstm32l152_SetIrqOutPinPolarity(0, IoIrqOutPinPolarity);
+        mfxstm32l152_SetIrqOutPinType(0, IoIrqOutPinType);
+    }
+
+    return RT_EOK;
+}
+
+/**
+  * @brief  Sets the selected pins state.
+  * @param  IoPin: Selected pins to write. 
+  *          This parameter can be any combination of the IO pins. 
+  * @param  PinState: New pins state to write  
+  * @retval None
+  */
+void rt_mfx_pin_write(rt_uint32_t IoPin, rt_base_t PinState)
+{
+    /* Set the Pin state */
+    IoDrv->WritePin(0, IoPin, PinState);
+}
+
+/**
+  * @brief  Gets the selected pins current state.
+  * @param  IoPin: Selected pins to read. 
+  *          This parameter can be any combination of the IO pins. 
+  * @retval The current pins state 
+  */
+rt_uint32_t rt_mfx_pin_read(rt_uint32_t IoPin)
+{
+    return(IoDrv->ReadPin(0, IoPin));
+}
+
+/**
+  * @brief  Toggles the selected pins state.
+  * @param  IoPin: Selected pins to toggle. 
+  *          This parameter can be any combination of the IO pins.  
+  * @note   This function is only used to toggle one pin in the same time  
+  * @retval None
+  */
+void rt_mfx_pin_toggle(rt_uint32_t IoPin)
+{
+    /* Toggle the current pin state */
+    if(IoDrv->ReadPin(0, IoPin) != 0)
+    {
+        IoDrv->WritePin(0, IoPin, 0); /* Reset */
+    }
+    else
+    {
+        IoDrv->WritePin(0, IoPin, 1); /* Set */
+    } 
+}
+
+int rt_mfx_init(void)
+{
+    /* Read ID and verify the MFX is ready */
+    rt_mfx.id = mfxstm32l152_io_drv.ReadID(0);
+    if((rt_mfx.id == MFXSTM32L152_ID_1) || (rt_mfx.id == MFXSTM32L152_ID_2))
+    {
+        /* Initialize the IO driver structure */
+        IoDrv = &mfxstm32l152_io_drv;
+
+        /* Initialize MFX */
+        IoDrv->Init(0);
+        IoDrv->Start(0, IO_PIN_ALL);
+        
+        LOG_I("mfx init success, id: 0x%x", rt_mfx.id);
+        
+        return RT_EOK;
+    }
+    LOG_I("mfx init error, id: 0x%x", rt_mfx.id);
+    
+    return RT_ERROR;
+}
+INIT_DEVICE_EXPORT(rt_mfx_init);

+ 45 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_mfx.h

@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-08-08     thread-liu   first version
+ */
+
+#ifndef __DRV_MFX_H__
+#define __DRV_MFX_H__
+
+#include "board.h"
+#include "mfxstm32l152.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+  BSP_IO_PIN_RESET = 0,
+  BSP_IO_PIN_SET   = 1
+}BSP_IO_PinStateTypeDef;
+
+#define CAMERA_RST1   MFXSTM32L152_AGPIO_PIN_3
+#define CAMERA_XSDN   MFXSTM32L152_AGPIO_PIN_2
+#define CARMERA_PLUG  MFXSTM32L152_GPIO_PIN_12
+
+void rt_mfx_init(void);
+rt_uint32_t BSP_IO_ITGetStatus(rt_uint32_t IoPin);
+void BSP_IO_ITClear(void);
+void BSP_IO_ITClearPin(rt_uint32_t IO_Pins_To_Clear);
+rt_uint8_t rt_mfx_pin_mode(rt_uint32_t IoPin, IO_ModeTypedef IoMode);
+rt_uint8_t rt_mfx_config_irq(rt_uint8_t IoIrqOutPinPolarity, rt_uint8_t IoIrqOutPinType);
+void rt_mfx_pin_write(rt_uint32_t IoPin, rt_base_t PinState);
+rt_uint32_t rt_mfx_pin_read(rt_uint32_t IoPin);
+void rt_mfx_pin_toggle(rt_uint32_t IoPin);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 666 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_ov5640.c

@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-08-03     thread-liu        the first version
+ */
+
+#include "board.h"
+
+#if defined(BSP_USING_DCMI)
+
+#include "drv_mfx.h"
+#include <dfs_posix.h>
+#include "drv_ov5640.h"
+
+//#define DRV_DEBUG
+//#define CAMERA_DUMP
+#define LOG_TAG     "drv.ov5640"
+#include <drv_log.h>
+
+#define CHIP_ADDRESS    0x3C /* OV5640 address */
+#define I2C_NAME        "i2c2"
+
+#define JPEG_BUF_SIZE   8 * 1024
+#define JPEG_LINE_SIZE  1 * 1024
+
+#if defined(__CC_ARM) || defined(__CLANG_ARM)
+__attribute__((at(0x2FFCC000)))
+#elif defined(__GNUC__)
+__attribute__((at(0x2FFCC000)))
+#elif defined(__ICCARM__)
+#pragma location = 0x2FFCC000
+#endif
+static rt_int32_t JPEG_DATA_BUF[JPEG_BUF_SIZE];
+
+#if defined(__CC_ARM) || defined(__CLANG_ARM)
+__attribute__((at(0x2FFDC000)))
+#elif defined(__GNUC__)
+__attribute__((at(0x2FFDC000)))             
+#elif defined(__ICCARM__)
+#pragma location = 0x2FFDC000
+#endif
+static rt_int32_t JPEG_LINE_BUF[2][JPEG_LINE_SIZE]; 
+
+
+volatile rt_uint32_t jpeg_data_len = 0;
+volatile rt_uint8_t  jpeg_data_ok  = 0;
+struct rt_i2c_bus_device *i2c_bus  = RT_NULL;
+extern DCMI_HandleTypeDef dcmi;
+extern DMA_HandleTypeDef hdma_dcmi;
+
+#if defined(CAMERA_DUMP)
+#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
+static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
+{
+    unsigned char *buf = (unsigned char *)ptr;
+    int i, j;
+
+    for (i = 0; i < buflen; i += 16)
+    {
+        rt_kprintf("%08x:", i);
+
+        for (j = 0; j < 16; j++)
+        {
+            if (i + j < buflen)
+            {
+                rt_kprintf("%02x", buf[i + j]);
+            }
+            else
+            {
+                rt_kprintf(" ");
+            }
+        }
+        rt_kprintf(" ");
+
+        for (j = 0; j < 16; j++)
+        {
+            if (i + j < buflen)
+            {
+                rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
+            }
+        }
+        rt_kprintf("\n");
+    }
+}
+#endif
+
+static rt_err_t read_reg(struct rt_i2c_bus_device *bus, rt_uint16_t reg, rt_uint8_t len, rt_uint8_t *buf)
+{
+    struct rt_i2c_msg msg[2] = {0, 0};
+    static rt_uint8_t i2c_reg[2] = {0, 0};
+
+    RT_ASSERT(bus != RT_NULL);
+
+    i2c_reg[0] = ((uint16_t)(reg >> 8) & 0xFF);
+    i2c_reg[1] = ((uint16_t)(reg & 0xFF));
+
+    msg[0].addr  = CHIP_ADDRESS;
+    msg[0].flags = RT_I2C_WR;
+    msg[0].buf   = i2c_reg;
+    msg[0].len   = 2;
+
+    msg[1].addr  = CHIP_ADDRESS;
+    msg[1].flags = RT_I2C_RD;
+    msg[1].len   = len;
+    msg[1].buf   = buf;
+
+    if (rt_i2c_transfer(bus, msg, 2) == 2)
+    {
+        return RT_EOK;
+    }
+
+    return RT_ERROR;
+}
+
+/* i2c write reg */
+static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint16_t reg, rt_uint8_t data)
+{
+    rt_uint8_t buf[3];
+    struct rt_i2c_msg msgs;
+
+    RT_ASSERT(bus != RT_NULL);
+
+    buf[0] = ((uint16_t)(reg >> 8) & 0xFF);
+    buf[1] = ((uint16_t)(reg)&0xFF);
+
+    buf[2] = data;
+
+    msgs.addr = CHIP_ADDRESS;
+    msgs.flags = RT_I2C_WR;
+    msgs.buf = buf;
+    msgs.len = 3;
+
+    if (rt_i2c_transfer(bus, &msgs, 1) == 1)
+    {
+        return RT_EOK;
+    }
+
+    return RT_ERROR;
+}
+
+static rt_err_t ov5640_read_id(struct rt_i2c_bus_device *bus, rt_uint16_t *id)
+{
+    rt_uint8_t read_value[2];
+
+    read_reg(bus, 0x300A, 1, &read_value[0]);
+    read_reg(bus, 0x300B, 1, &read_value[1]);
+    *id = ((uint16_t)(read_value[0] << 8) & 0xFF00);
+    *id |= ((uint16_t)(read_value[1]) & 0x00FF);
+
+    if (*id != OV5640_ID)
+    {
+        LOG_E("ov5640 init error, id: 0x%04x", *id);
+        return RT_ERROR;
+    }
+
+    LOG_I("ov5640 init success, id: 0x%04x", *id);
+
+    return RT_EOK;
+}
+
+static rt_err_t ov5640_hard_reset(struct rt_i2c_bus_device *bus)
+{
+    /* Camera sensor RESET sequence */
+    rt_mfx_pin_mode(CAMERA_RST1, IO_MODE_OUTPUT);
+    rt_mfx_pin_mode(CAMERA_XSDN, IO_MODE_OUTPUT);
+
+    /* Assert the camera STANDBY pin (active high)  */
+    rt_mfx_pin_write(CAMERA_XSDN, BSP_IO_PIN_SET);
+
+    /* Assert the camera RSTI pin (active low) */
+    rt_mfx_pin_write(CAMERA_RST1, BSP_IO_PIN_RESET);
+
+    rt_thread_delay(100); /* RST and XSDN signals asserted during 100ms */
+
+    /* De-assert the camera STANDBY pin (active high) */
+    rt_mfx_pin_write(CAMERA_XSDN, BSP_IO_PIN_RESET);
+
+    rt_thread_delay(3); /* RST de-asserted and XSDN asserted during 3ms */
+
+    /* De-assert the camera RSTI pin (active low) */
+    rt_mfx_pin_write(CAMERA_RST1, BSP_IO_PIN_SET);
+
+    rt_thread_delay(6); /* RST de-asserted during 3ms */
+
+    return RT_EOK;
+}
+
+void OV5640_Flash_Ctrl(struct rt_i2c_bus_device *bus, rt_uint8_t sw)
+{
+    write_reg(bus, 0x3016, 0X02);
+    write_reg(bus, 0x301C, 0X02);
+    if (sw)
+    {
+        write_reg(bus, 0X3019, 0X02);
+    }
+    else
+    {
+        write_reg(bus, 0X3019, 0X00);
+    }
+}
+
+static rt_err_t ov5640_config(struct rt_i2c_bus_device *bus)
+{
+    rt_uint32_t i = 0;
+    rt_uint8_t value = 0;
+
+    write_reg(bus, 0x3103, 0X11); /* system clock from pad, bit[1] */
+    write_reg(bus, 0X3008, 0X82); /* soft reset */
+
+    rt_thread_delay(10);
+
+    for (i = 0; i < (sizeof(RGB565_Init) / 4); i++)
+    {
+        write_reg(bus, RGB565_Init[i][0], RGB565_Init[i][1]);
+        rt_thread_delay(10);
+        read_reg(bus, RGB565_Init[i][0], 1, &value);
+
+        if (RGB565_Init[i][1] != value)
+        {
+            LOG_D("error reg value[0x%x]:0x%02x - 0x%02x", RGB565_Init[i][0], RGB565_Init[i][1], value);
+        }
+    }
+
+    OV5640_Flash_Ctrl(bus, 1); /* open camera flash*/
+    rt_thread_delay(3);
+    OV5640_Flash_Ctrl(bus, 0); /* close camera flash*/
+
+    return RT_EOK;
+}
+
+/* JPEG */
+void ov5640_jpeg_mode(struct rt_i2c_bus_device *bus)
+{
+    rt_uint16_t i = 0;
+    for (i = 0; i < (sizeof(OV5640_jpeg_reg_tbl) / 4); i++)
+    {
+        write_reg(bus, OV5640_jpeg_reg_tbl[i][0], OV5640_jpeg_reg_tbl[i][1]);
+    }
+}
+
+/* RGB565 */
+void ov5640_rgb565_mode(struct rt_i2c_bus_device *bus)
+{
+    rt_uint16_t i = 0;
+    for (i = 0; i < (sizeof(ov5640_rgb565_reg_tbl) / 4); i++)
+    {
+        write_reg(bus, ov5640_rgb565_reg_tbl[i][0], ov5640_rgb565_reg_tbl[i][1]);
+    }
+
+    write_reg(bus, 0x3821, 0x06);
+}
+
+rt_uint8_t ov5640_focus_init(struct rt_i2c_bus_device *bus)
+{
+    rt_uint16_t tickstart = 0 ,i = 0;
+    rt_uint16_t addr = 0x8000;
+    rt_uint8_t state = 0x8F;
+
+    write_reg(bus, 0x3000, 0x20); //reset MCU
+    for (i = 0; i < sizeof(OV5640_AF_Config); i++)
+    {
+        write_reg(bus, addr, OV5640_AF_Config[i]);
+        addr++;
+    }
+    write_reg(bus, 0x3022, 0x00);
+    write_reg(bus, 0x3023, 0x00);
+    write_reg(bus, 0x3024, 0x00);
+    write_reg(bus, 0x3025, 0x00);
+    write_reg(bus, 0x3026, 0x00);
+    write_reg(bus, 0x3027, 0x00);
+    write_reg(bus, 0x3028, 0x00);
+    write_reg(bus, 0x3029, 0x7f);
+    write_reg(bus, 0x3000, 0x00);
+    i = 0;
+
+    tickstart = rt_tick_get();
+    do
+    {
+        read_reg(bus, 0x3029, 1, &state);
+        if (rt_tick_get() - tickstart > 1000)
+        {
+            return RT_ERROR;
+        }
+    } while (state != 0x70);
+
+    return RT_EOK;
+}
+
+void ov5640_set_light(struct rt_i2c_bus_device *bus, rt_uint8_t mode)
+{
+    rt_uint8_t i = 0;
+    write_reg(bus, 0x3212, 0x03); //start group 3
+
+    for (i = 0; i < 7; i++)
+    {
+        write_reg(bus, 0x3400 + i, OV5640_LIGHTMODE_TBL[mode][i]);
+    }
+
+    write_reg(bus, 0x3212, 0x13); //end group 3
+    write_reg(bus, 0x3212, 0xa3); //launch group 3
+}
+
+/* sat:0~6 */
+void ov5640_color_saturation(struct rt_i2c_bus_device *bus, rt_uint8_t sat)
+{
+    rt_uint8_t i = 0;
+    write_reg(bus, 0x3212, 0x03); //start group 3
+    write_reg(bus, 0x5381, 0x1c);
+    write_reg(bus, 0x5382, 0x5a);
+    write_reg(bus, 0x5383, 0x06);
+    for (i = 0; i < 6; i++)
+    {
+        write_reg(bus, 0x5384 + i, OV5640_SATURATION_TBL[sat][i]);
+    }
+    write_reg(bus, 0x538b, 0x98);
+    write_reg(bus, 0x538a, 0x01);
+    write_reg(bus, 0x3212, 0x13); //end group 3
+    write_reg(bus, 0x3212, 0xa3); //launch group 3
+}
+
+/* bright:0~8 */
+void ov5640_set_brightness(struct rt_i2c_bus_device *bus, rt_uint8_t bright)
+{
+    rt_uint8_t brtval;
+    if (bright < 4)
+    {
+        brtval = 4 - bright;
+    }
+    else
+    {
+        brtval = bright - 4;
+    }
+    write_reg(bus, 0x3212, 0x03); //start group 3
+    write_reg(bus, 0x5587, brtval << 4);
+    if (bright < 4)
+    {
+        write_reg(bus, 0x5588, 0x09);
+    }
+    else
+    {
+        write_reg(bus, 0x5588, 0x01);
+    }
+    write_reg(bus, 0x3212, 0x13); //end group 3
+    write_reg(bus, 0x3212, 0xa3); //launch group 3
+}
+
+/* contrast:0~6 */
+void ov5640_contrast(struct rt_i2c_bus_device *bus, rt_uint8_t contrast)
+{
+    rt_uint8_t reg0val = 0x00;
+    rt_uint8_t reg1val = 0x20;
+    switch (contrast)
+    {
+    case 0:
+        reg1val = reg0val = 0X14;
+        break;
+
+    case 1:
+        reg1val = reg0val = 0X18;
+        break;
+
+    case 2:
+        reg1val = reg0val = 0X1C;
+        break;
+
+    case 4:
+        reg0val = 0X10;
+        reg1val = 0X24;
+        break;
+
+    case 5:
+        reg0val = 0X18;
+        reg1val = 0X28;
+        break;
+
+    case 6:
+        reg0val = 0X1C;
+        reg1val = 0X2C;
+
+        break;
+    }
+    write_reg(bus, 0x3212, 0x03); //start group 3
+    write_reg(bus, 0x5585, reg0val);
+    write_reg(bus, 0x5586, reg1val);
+    write_reg(bus, 0x3212, 0x13); //end group 3
+    write_reg(bus, 0x3212, 0xa3); //launch group 3
+}
+/* sharp:0~33 */
+void ov5640_set_sharpness(struct rt_i2c_bus_device *bus, rt_uint8_t sharp)
+{
+    if (sharp < 33)
+    {
+        write_reg(bus, 0x5308, 0x65);
+        write_reg(bus, 0x5302, sharp);
+    }
+    else
+    {
+        write_reg(bus, 0x5308, 0x25);
+        write_reg(bus, 0x5300, 0x08);
+        write_reg(bus, 0x5301, 0x30);
+        write_reg(bus, 0x5302, 0x10);
+        write_reg(bus, 0x5303, 0x00);
+        write_reg(bus, 0x5309, 0x08);
+        write_reg(bus, 0x530a, 0x30);
+        write_reg(bus, 0x530b, 0x04);
+        write_reg(bus, 0x530c, 0x06);
+    }
+}
+
+rt_uint8_t ov5640_focus_constant(struct rt_i2c_bus_device *bus)
+{
+    rt_uint8_t temp = 0;
+    rt_uint16_t tickstrat = 0;
+
+    write_reg(bus, 0x3023, 0x01);
+    write_reg(bus, 0x3022, 0x08);
+    do
+    {
+        tickstrat = rt_tick_get();
+        read_reg(bus, 0x3023, 1, &temp);
+        if (rt_tick_get() - tickstrat > 1000)
+        {
+            return RT_ERROR;
+        }
+    } while (temp != 0x00);
+
+    write_reg(bus, 0x3023, 0x01);
+    write_reg(bus, 0x3022, 0x04);
+
+    do
+    {
+        tickstrat = rt_tick_get();
+        read_reg(bus, 0x3023, 1, &temp);
+        if (rt_tick_get() - tickstrat > 1000)
+        {
+            return RT_ERROR;
+        }
+    } while (temp != 0x00);
+
+    return 0;
+}
+
+rt_uint8_t ov5640_set_outsize(struct rt_i2c_bus_device *bus, rt_uint16_t offx, rt_uint16_t offy, rt_uint16_t width, rt_uint16_t height)
+{
+    write_reg(bus, 0X3212, 0X03);
+
+    write_reg(bus, 0x3808, width >> 8);
+    write_reg(bus, 0x3809, width & 0xff);
+    write_reg(bus, 0x380a, height >> 8);
+    write_reg(bus, 0x380b, height & 0xff);
+
+    write_reg(bus, 0x3810, offx >> 8);
+    write_reg(bus, 0x3811, offx & 0xff);
+
+    write_reg(bus, 0x3812, offy >> 8);
+    write_reg(bus, 0x3813, offy & 0xff);
+
+    write_reg(bus, 0X3212, 0X13);
+    write_reg(bus, 0X3212, 0Xa3);
+
+    return RT_EOK;
+}
+
+void rt_hw_camera_rx_callback(void)
+{
+    rt_uint16_t i;
+    rt_int32_t *pbuf = RT_NULL;
+    pbuf = JPEG_DATA_BUF + jpeg_data_len;
+
+    if (hdma_dcmi.Instance->CR & (1 << 19))
+    {
+        for (i = 0; i < JPEG_LINE_SIZE; i++)
+        {
+            pbuf[i] = JPEG_LINE_BUF[0][i];
+        }
+        jpeg_data_len += JPEG_LINE_SIZE;
+
+    }
+    else
+    {
+        for (i = 0; i < JPEG_LINE_SIZE; i++)
+        {
+            pbuf[i] = JPEG_LINE_BUF[1][i];
+        }
+        jpeg_data_len += JPEG_LINE_SIZE;
+    }
+}
+
+/* After a frame of JPEG data has been collected. */
+void jpeg_data_process(void)
+{
+    rt_uint16_t i, rlen;
+    int *pbuf = RT_NULL;
+
+    if (!jpeg_data_ok)
+    {
+        __HAL_DMA_DISABLE(&hdma_dcmi);
+        rlen = JPEG_LINE_SIZE - __HAL_DMA_GET_COUNTER(&hdma_dcmi);
+        pbuf = JPEG_DATA_BUF + jpeg_data_len;
+        if (hdma_dcmi.Instance->CR & (1 << 19))
+        {
+            for (i = 0; i < rlen; i++)
+            {
+                pbuf[i] = JPEG_LINE_BUF[1][i];
+            }
+        }
+        else
+        {
+            for (i = 0; i < rlen; i++)
+            {
+                pbuf[i] = JPEG_LINE_BUF[0][i];
+            }
+        }
+        jpeg_data_len += rlen;
+        jpeg_data_ok   = 1;
+    }
+
+    if (jpeg_data_ok == 2)
+    {
+        __HAL_DMA_SET_COUNTER(&hdma_dcmi, JPEG_LINE_SIZE);
+        __HAL_DMA_ENABLE(&hdma_dcmi);
+
+        jpeg_data_ok  = 0;
+        jpeg_data_len = 0;
+    }
+}
+
+int rt_hw_ov5640_init(void)
+{
+    extern void rt_hw_dcmi_dma_config(rt_uint32_t dst_addr1, rt_uint32_t dst_addr2, rt_uint16_t len);
+
+    static rt_uint16_t id = 0;
+    rt_device_t dcmi_dev = RT_NULL;
+
+    i2c_bus = rt_i2c_bus_device_find(I2C_NAME);
+    if (i2c_bus == RT_NULL)
+    {
+        LOG_E("can't find %c deivce", I2C_NAME);
+        return RT_ERROR;
+    }
+
+    ov5640_hard_reset(i2c_bus);
+    ov5640_read_id(i2c_bus, &id);
+    ov5640_config(i2c_bus);
+    ov5640_rgb565_mode(i2c_bus);        /* rgb565 mode */
+    ov5640_focus_init(i2c_bus);
+    ov5640_jpeg_mode(i2c_bus);          /* jpeg mode */
+    ov5640_set_light(i2c_bus, 0);       /* auto mode  */
+    ov5640_color_saturation(i2c_bus, 3);
+    ov5640_set_brightness(i2c_bus, 4);  /* brigetness 0 */
+    ov5640_contrast(i2c_bus, 3);
+    ov5640_set_sharpness(i2c_bus, 33);
+    ov5640_focus_constant(i2c_bus);
+
+    /* dcmi init */
+    dcmi_dev = rt_device_find("dcmi");
+    if (dcmi_dev == RT_NULL)
+    {
+        LOG_E("can't find dcmi device!");
+        return RT_ERROR;
+    }
+    rt_device_open(dcmi_dev, RT_DEVICE_FLAG_RDWR);
+
+    rt_hw_dcmi_dma_config((rt_uint32_t)&JPEG_LINE_BUF[0], (rt_uint32_t)&JPEG_LINE_BUF[1], JPEG_LINE_SIZE);
+    ov5640_set_outsize(i2c_bus, 4, 0, jpeg_picture_size[1][0], jpeg_picture_size[1][1]);
+
+    return RT_EOK;
+}
+INIT_APP_EXPORT(rt_hw_ov5640_init);
+
+int camera_sample(int argc, char **argv)
+{
+
+    int fd = -1;
+    rt_uint32_t i, jpg_start, jpg_len;
+    rt_uint16_t tickstart = 0;
+    rt_uint8_t jpg_head = 0;
+    rt_uint8_t *p = RT_NULL;
+
+    if (argc != 2)
+    {
+        rt_kprintf("Usage:\n");
+        rt_kprintf("camera_sample file.jpg\n");
+        return -1;
+    }
+
+    /* start dcmi capture */
+    __HAL_DMA_ENABLE(&hdma_dcmi);
+    dcmi.Instance->CR |= DCMI_CR_CAPTURE;
+
+    tickstart = rt_tick_get();
+    while (1)
+    {
+        if (rt_tick_get() - tickstart > 1000)
+        {
+            LOG_E("picture capture overtime!");
+            break;
+        }
+
+        if (jpeg_data_ok == 1)
+        {
+            dcmi.Instance->CR &= ~(DCMI_CR_CAPTURE);
+            tickstart = rt_tick_get();
+            while(dcmi.Instance->CR & 0x01)
+            {
+                if (rt_tick_get() - tickstart > 0x1000)
+                {
+                    rt_kprintf("dcmi close failed!\n");
+                    jpeg_data_ok = 2;
+                    break;
+                }
+            }
+            __HAL_DMA_DISABLE(&hdma_dcmi);
+
+            p = (rt_uint8_t *)JPEG_DATA_BUF;
+            jpg_len  = 0;
+            jpg_head = 0;
+            for (i = 0; i < jpeg_data_len * 4; i++)
+            {
+                /* jpg head */
+                if ((p[i] == 0xFF) && (p[i + 1] == 0xD8))
+                {
+                    jpg_start = i;
+                    jpg_head = 1;
+                }
+                /* jpg end */
+                if ((p[i] == 0xFF) && (p[i + 1] == 0xD9) && jpg_head)
+                {
+                    jpg_len = i - jpg_start + 2; /* a picture len */
+                    break;
+                }
+            }
+
+            if (jpg_len)
+            {
+                p += jpg_start;
+
+                fd = open(argv[1], O_WRONLY | O_CREAT);
+                if (fd < 0)
+                {
+                    rt_kprintf("open file for recording failed!\n");
+                    return -RT_ERROR;
+                }
+                else
+                {
+                    write(fd, p, jpg_len);
+                    close(fd);
+                    rt_kprintf("picture capture complate!\n");
+
+                    break;
+                }
+            }
+
+            jpeg_data_ok = 2;
+        }
+    }
+
+    return RT_EOK;
+}
+MSH_CMD_EXPORT(camera_sample, record picture to a jpg file);
+
+#endif

+ 653 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_ov5640.h

@@ -0,0 +1,653 @@
+
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-07-27     thread-liu   first version
+ */
+
+#ifndef __DRV_OV5640_H__
+#define __DRV_OV5640_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** 
+  * @brief  OV5640 ID  
+  */  
+#define  OV5640_ID                                 0x5640U
+
+/* JPEG picture size table */
+static const unsigned short jpeg_picture_size[][2] =
+{
+        160, 120,   /* QQVGA */
+        320, 240,   /* QVGA */
+        640, 480,   /* VGA */
+        800, 600,   /* SVGA */
+        1024, 768,  /* XGA */
+        1280, 800,  /* WXGA */
+        1440, 900,  /* WXGA+ */
+        1280, 1024, /* SXGA */
+        1600, 1200, /* UXGA */
+        1920, 1080, /* 1080P */
+        2048, 1536, /* QXGA */
+        2592, 1944, /* 500W */
+};
+
+/* camera light mode */
+static const unsigned char OV5640_LIGHTMODE_TBL[5][7]=
+{ 
+	0x04,0X00,0X04,0X00,0X04,0X00,0X00,     /* Auto */
+	0x06,0X1C,0X04,0X00,0X04,0XF3,0X01,     /* Sunny */
+	0x05,0X48,0X04,0X00,0X07,0XCF,0X01,     /* Office */
+	0x06,0X48,0X04,0X00,0X04,0XD3,0X01,     /* Cloudy */ 
+	0x04,0X10,0X04,0X00,0X08,0X40,0X01,     /* Home */
+}; 
+
+/* Table of color saturation setting parameters */
+static const unsigned char OV5640_SATURATION_TBL[7][6]=
+{ 
+	0X0C,0x30,0X3D,0X3E,0X3D,0X01,      /* -3 */
+	0X10,0x3D,0X4D,0X4E,0X4D,0X01,      /* -2 */	
+	0X15,0x52,0X66,0X68,0X66,0X02,      /* -1 */	
+	0X1A,0x66,0X80,0X82,0X80,0X02,      /* 0 */	
+	0X1F,0x7A,0X9A,0X9C,0X9A,0X02,      /* 1 */	
+	0X24,0x8F,0XB3,0XB6,0XB3,0X03,      /* 2 */
+ 	0X2B,0xAB,0XD6,0XDA,0XD6,0X04,      /* 3 */
+};
+
+static const unsigned short OV5640_jpeg_reg_tbl[][2]=
+{
+	0x4300, 0x30, // YUV 422, YUYV
+	0x501f, 0x00, // YUV 422
+	// Input clock = 24Mhz
+	0x3035, 0x21, // PLL  
+	0x3036, 0x69, // PLL 
+	0x3c07, 0x07, // lightmeter 1 threshold[7:0] 
+	0x3820, 0x46, // flip
+	0x3821, 0x20, // mirror									 
+	0x3814, 0x11, // timing X inc 
+	0x3815, 0x11, // timing Y inc 
+	0x3800, 0x00, // HS 
+	0x3801, 0x00, // HS 
+	0x3802, 0x00, // VS 
+	0x3803, 0x00, // VS 
+	0x3804, 0x0a, // HW (HE)		 
+	0x3805, 0x3f, // HW (HE)
+	0x3806, 0x07, // VH (VE)		 
+	0x3807, 0x9f, // VH (VE) 
+	
+	0x3808, 0x02, // DVPHO 	   
+	0x3809, 0x80, // DVPHO 
+	0x380a, 0x01, // DVPVO 		
+	0x380b, 0xe0, // DVPVO
+
+	0x380c, 0x0b, // HTS 		//
+	0x380d, 0x1c, // HTS 
+	0x380e, 0x07, // VTS 		//
+	0x380f, 0xb0, // VTS 
+	0x3813, 0x04, // timing V offset   04
+	0x3618, 0x04,
+	0x3612, 0x2b,
+	0x3709, 0x12,
+	0x370c, 0x00, 
+	
+	0x4004, 0x06, // BLC line number 
+	0x3002, 0x00, // enable JFIFO, SFIFO, JPG 
+	0x3006, 0xff, // enable clock of JPEG2x, JPEG
+	0x4713, 0x03, // JPEG mode 3
+	0x4407, 0x01, // Quantization sacle 
+	0x460b, 0x35,
+	0x460c, 0x22,
+	0x4837, 0x16, // MIPI global timing 
+	0x3824, 0x02, // PCLK manual divider 
+	0x5001, 0xA3, // SDE on, Scaling on, CMX on, AWB on 
+	0x3503, 0x00, // AEC/AGC on	
+};
+
+/* RGB565 configuration, 15 frames */
+static const unsigned short ov5640_rgb565_reg_tbl[][2]=
+{
+	0x4300, 0X6F,
+	0X501F, 0x01,
+	// 1280x800, 15fps
+	// input clock 24Mhz, PCLK 42Mhz
+	0x3035, 0x41, // PLL
+	0x3036, 0x69, // PLL
+	0x3c07, 0x07, // lightmeter 1 threshold[7:0]
+	0x3820, 0x46, // flip
+	0x3821, 0x00, // mirror
+	0x3814, 0x31, // timing X inc
+	0x3815, 0x31, // timing Y inc
+	0x3800, 0x00, // HS
+	0x3801, 0x00, // HS
+	0x3802, 0x00, // VS
+	0x3803, 0x00, // VS
+	0x3804, 0x0a, // HW (HE)
+	0x3805, 0x3f, // HW (HE)
+	0x3806, 0x06, // VH (VE)
+	0x3807, 0xa9, // VH (VE)
+	0x3808, 0x05, // DVPHO
+	0x3809, 0x00, // DVPHO
+	0x380a, 0x02, // DVPVO
+	0x380b, 0xd0, // DVPVO
+	0x380c, 0x05, // HTS
+	0x380d, 0xF8, // HTS
+	0x380e, 0x03, // VTS
+	0x380f, 0x84, // VTS
+	0x3813, 0x04, // timing V offset
+	0x3618, 0x00,
+	0x3612, 0x29,
+	0x3709, 0x52,
+	0x370c, 0x03,
+	0x3a02, 0x02, // 60Hz max exposure
+	0x3a03, 0xe0, // 60Hz max exposure 
+ 
+	0x3a14, 0x02, // 50Hz max exposure
+	0x3a15, 0xe0, // 50Hz max exposure
+	0x4004, 0x02, // BLC line number
+	0x3002, 0x1c, // reset JFIFO, SFIFO, JPG
+	0x3006, 0xc3, // disable clock of JPEG2x, JPEG
+	0x4713, 0x03, // JPEG mode 3
+	0x4407, 0x04, // Quantization scale
+	0x460b, 0x37,
+	0x460c, 0x20,
+	0x4837, 0x16, // MIPI global timing
+	0x3824, 0x04, // PCLK manual divider
+	0x5001, 0xA3, // SDE on, scale on, UV average off, color matrix on, AWB on
+	0x3503, 0x00, // AEC/AGC on
+}; 
+
+static const unsigned short RGB565_Init[][2]=
+{ 
+	/* 24MHz input clock, 24MHz PCLK */
+	0x3008, 0x42, // software power down, bit[6]
+	0x3103, 0x03, // system clock from PLL, bit[1]
+	0x3017, 0xff, // FREX, Vsync, HREF, PCLK, D[9:6] output enable
+	0x3018, 0xff, // D[5:0], GPIO[1:0] output enable
+	0x3034, 0x1a, // MIPI 10-bit
+	0x3037, 0x13, // PLL root divider, bit[4], PLL pre-divider, bit[3:0]
+	0x3108, 0x01, // PCLK root divider, bit[5:4], SCLK2x root divider, bit[3:2]
+
+	// SCLK root divider, bit[1:0]
+	0x3630, 0x36,
+	0x3631, 0x0e,
+	0x3632, 0xe2,
+	0x3633, 0x12,
+	0x3621, 0xe0,
+	0x3704, 0xa0,
+	0x3703, 0x5a,
+	0x3715, 0x78,
+	0x3717, 0x01,
+	0x370b, 0x60,
+	0x3705, 0x1a,
+	0x3905, 0x02,
+	0x3906, 0x10,
+	0x3901, 0x0a,
+	0x3731, 0x12,
+	0x3600, 0x08, // VCM control
+	0x3601, 0x33, // VCM control
+	0x302d, 0x60, // system control
+	0x3620, 0x52,
+	0x371b, 0x20,
+	0x471c, 0x50,
+	0x3a13, 0x43, // pre-gain = 1.047x
+	0x3a18, 0x00, // gain ceiling
+	0x3a19, 0xf8, // gain ceiling = 15.5x
+	0x3635, 0x13,
+	0x3636, 0x03,
+	0x3634, 0x40,
+	0x3622, 0x01,
+	// 50/60Hz detection 50/60Hz
+	0x3c01, 0x34, // Band auto, bit[7]
+	0x3c04, 0x28, // threshold low sum
+	0x3c05, 0x98, // threshold high sum
+	0x3c06, 0x00, // light meter 1 threshold[15:8]
+	0x3c07, 0x08, // light meter 1 threshold[7:0]
+	0x3c08, 0x00, // light meter 2 threshold[15:8]
+	0x3c09, 0x1c, // light meter 2 threshold[7:0]
+	0x3c0a, 0x9c, // sample number[15:8]
+	0x3c0b, 0x40, // sample number[7:0]
+	0x3810, 0x00, // Timing Hoffset[11:8]
+	0x3811, 0x10, // Timing Hoffset[7:0]
+	0x3812, 0x00, // Timing Voffset[10:8]
+	0x3708, 0x64,
+	0x4001, 0x02, // BLC start from line 2
+	0x4005, 0x1a, // BLC always update
+	0x3000, 0x00, // enable blocks
+	0x3004, 0xff, // enable clocks
+	0x300e, 0x58, // MIPI power down, DVP enable
+	0x302e, 0x00,
+	0x4300, 0x30, // YUV 422, YUYV
+	0x501f, 0x00, // YUV 422
+	0x440e, 0x00,
+	0x5000, 0xa7, // Lenc on, raw gamma on, BPC on, WPC on, CIP on
+	// AEC target
+	0x3a0f, 0x30, // stable range in high
+	0x3a10, 0x28, // stable range in low
+	0x3a1b, 0x30, // stable range out high
+	0x3a1e, 0x26, // stable range out low
+	0x3a11, 0x60, // fast zone high
+	0x3a1f, 0x14, // fast zone low
+	// Lens correction
+	0x5800, 0x23,
+	0x5801, 0x14,
+	0x5802, 0x0f,
+	0x5803, 0x0f,
+	0x5804, 0x12,
+	0x5805, 0x26,
+	0x5806, 0x0c,
+	0x5807, 0x08,
+	0x5808, 0x05,
+	0x5809, 0x05,
+	0x580a, 0x08,
+
+	0x580b, 0x0d,
+	0x580c, 0x08,
+	0x580d, 0x03,
+	0x580e, 0x00,
+	0x580f, 0x00,
+	0x5810, 0x03,
+	0x5811, 0x09,
+	0x5812, 0x07,
+	0x5813, 0x03,
+	0x5814, 0x00,
+	0x5815, 0x01,
+	0x5816, 0x03,
+	0x5817, 0x08,
+	0x5818, 0x0d,
+	0x5819, 0x08,
+	0x581a, 0x05,
+	0x581b, 0x06,
+	0x581c, 0x08,
+	0x581d, 0x0e,
+	0x581e, 0x29,
+	0x581f, 0x17,
+	0x5820, 0x11,
+	0x5821, 0x11,
+	0x5822, 0x15,
+	0x5823, 0x28,
+	0x5824, 0x46,
+	0x5825, 0x26,
+	0x5826, 0x08,
+	0x5827, 0x26,
+	0x5828, 0x64,
+	0x5829, 0x26,
+	0x582a, 0x24,
+	0x582b, 0x22,
+	0x582c, 0x24,
+	0x582d, 0x24,
+	0x582e, 0x06,
+	0x582f, 0x22,
+	0x5830, 0x40,
+	0x5831, 0x42,
+	0x5832, 0x24,
+	0x5833, 0x26,
+	0x5834, 0x24,
+	0x5835, 0x22,
+	0x5836, 0x22,
+	0x5837, 0x26,
+	0x5838, 0x44,
+	0x5839, 0x24,
+	0x583a, 0x26,
+	0x583b, 0x28,
+	0x583c, 0x42,
+	0x583d, 0xce, // lenc BR offset
+	// AWB
+	0x5180, 0xff, // AWB B block
+	0x5181, 0xf2, // AWB control
+	0x5182, 0x00, // [7:4] max local counter, [3:0] max fast counter
+	0x5183, 0x14, // AWB advanced
+	0x5184, 0x25,
+	0x5185, 0x24,
+	0x5186, 0x09,
+	0x5187, 0x09,
+	0x5188, 0x09,
+	0x5189, 0x75,
+	0x518a, 0x54,
+	0x518b, 0xe0,
+	0x518c, 0xb2,
+	0x518d, 0x42,
+	0x518e, 0x3d,
+	0x518f, 0x56,
+	0x5190, 0x46,
+	0x5191, 0xf8, // AWB top limit
+	0x5192, 0x04, // AWB bottom limit
+	0x5193, 0x70, // red limit
+	0x5194, 0xf0, // green limit
+	0x5195, 0xf0, // blue limit
+	0x5196, 0x03, // AWB control
+	0x5197, 0x01, // local limit
+	0x5198, 0x04,
+	0x5199, 0x12,
+	0x519a, 0x04,
+	0x519b, 0x00,
+	0x519c, 0x06,
+	0x519d, 0x82,
+	0x519e, 0x38, // AWB control
+	// Gamma
+	0x5480, 0x01, // Gamma bias plus on, bit[0]
+	0x5481, 0x08,
+	0x5482, 0x14,
+	0x5483, 0x28,
+	0x5484, 0x51,
+	0x5485, 0x65,
+	0x5486, 0x71,
+	0x5487, 0x7d,
+	0x5488, 0x87,
+	0x5489, 0x91,
+	0x548a, 0x9a,
+	0x548b, 0xaa,
+	0x548c, 0xb8,
+	0x548d, 0xcd,
+	0x548e, 0xdd,
+	0x548f, 0xea,
+	0x5490, 0x1d,
+	// color matrix
+	0x5381, 0x1e, // CMX1 for Y
+	0x5382, 0x5b, // CMX2 for Y
+	0x5383, 0x08, // CMX3 for Y
+	0x5384, 0x0a, // CMX4 for U
+	0x5385, 0x7e, // CMX5 for U
+	0x5386, 0x88, // CMX6 for U
+	0x5387, 0x7c, // CMX7 for V
+	0x5388, 0x6c, // CMX8 for V
+	0x5389, 0x10, // CMX9 for V
+	0x538a, 0x01, // sign[9]
+	0x538b, 0x98, // sign[8:1]
+	// UV adjust UV
+	0x5580, 0x06, // saturation on, bit[1]
+	0x5583, 0x40,
+	0x5584, 0x10, 
+	0x5589, 0x10,
+	0x558a, 0x00,
+	0x558b, 0xf8,
+	0x501d, 0x40, // enable manual offset of contrast
+	// CIP
+	0x5300, 0x08, // CIP sharpen MT threshold 1
+	0x5301, 0x30, // CIP sharpen MT threshold 2
+	0x5302, 0x10, // CIP sharpen MT offset 1
+	0x5303, 0x00, // CIP sharpen MT offset 2
+	0x5304, 0x08, // CIP DNS threshold 1
+	0x5305, 0x30, // CIP DNS threshold 2
+	0x5306, 0x08, // CIP DNS offset 1
+	0x5307, 0x16, // CIP DNS offset 2
+	0x5309, 0x08, // CIP sharpen TH threshold 1
+	0x530a, 0x30, // CIP sharpen TH threshold 2
+	0x530b, 0x04, // CIP sharpen TH offset 1
+	0x530c, 0x06, // CIP sharpen TH offset 2
+	0x5025, 0x00, 
+	0x3008, 0x02, // wake up from standby, bit[6]
+
+	0x4740, 0X21, //VSYNC 
+}; 
+
+/* Autofocus initialization configuration  */ 
+const unsigned char OV5640_AF_Config[] =
+{
+	0x02, 0x0f, 0xd6, 0x02, 0x0a, 0x39, 0xc2, 0x01, 0x22, 0x22, 0x00, 0x02, 0x0f, 0xb2, 0xe5, 0x1f, //0x8000,
+	0x70, 0x72, 0xf5, 0x1e, 0xd2, 0x35, 0xff, 0xef, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xe4, 0xf6, 0x08, //0x8010,
+	0xf6, 0x0f, 0xbf, 0x34, 0xf2, 0x90, 0x0e, 0x93, 0xe4, 0x93, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, //0x8020,
+	0x04, 0x7f, 0x05, 0x80, 0x02, 0x7f, 0xfb, 0x78, 0xbd, 0xa6, 0x07, 0x12, 0x0f, 0x04, 0x40, 0x04, //0x8030,
+	0x7f, 0x03, 0x80, 0x02, 0x7f, 0x30, 0x78, 0xbc, 0xa6, 0x07, 0xe6, 0x18, 0xf6, 0x08, 0xe6, 0x78, //0x8040,
+	0xb9, 0xf6, 0x78, 0xbc, 0xe6, 0x78, 0xba, 0xf6, 0x78, 0xbf, 0x76, 0x33, 0xe4, 0x08, 0xf6, 0x78, //0x8050,
+	0xb8, 0x76, 0x01, 0x75, 0x4a, 0x02, 0x78, 0xb6, 0xf6, 0x08, 0xf6, 0x74, 0xff, 0x78, 0xc1, 0xf6, //0x8060,
+	0x08, 0xf6, 0x75, 0x1f, 0x01, 0x78, 0xbc, 0xe6, 0x75, 0xf0, 0x05, 0xa4, 0xf5, 0x4b, 0x12, 0x0a, //0x8070,
+	0xff, 0xc2, 0x37, 0x22, 0x78, 0xb8, 0xe6, 0xd3, 0x94, 0x00, 0x40, 0x02, 0x16, 0x22, 0xe5, 0x1f, //0x8080,
+	0xb4, 0x05, 0x23, 0xe4, 0xf5, 0x1f, 0xc2, 0x01, 0x78, 0xb6, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x78, //0x8090,
+	0x4e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xa2, 0x37, 0xe4, 0x33, 0xf5, 0x3c, 0x90, 0x30, 0x28, 0xf0, //0x80a0,
+	0x75, 0x1e, 0x10, 0xd2, 0x35, 0x22, 0xe5, 0x4b, 0x75, 0xf0, 0x05, 0x84, 0x78, 0xbc, 0xf6, 0x90, //0x80b0,
+	0x0e, 0x8c, 0xe4, 0x93, 0xff, 0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x78, //0x80c0,
+	0xbc, 0xe6, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0xef, 0x12, 0x0f, 0x0b, //0x80d0,
+	0xd3, 0x78, 0xb7, 0x96, 0xee, 0x18, 0x96, 0x40, 0x0d, 0x78, 0xbc, 0xe6, 0x78, 0xb9, 0xf6, 0x78, //0x80e0,
+	0xb6, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x90, 0x0e, 0x8c, 0xe4, 0x93, 0x12, 0x0f, 0x0b, 0xc3, 0x78, //0x80f0,
+	0xc2, 0x96, 0xee, 0x18, 0x96, 0x50, 0x0d, 0x78, 0xbc, 0xe6, 0x78, 0xba, 0xf6, 0x78, 0xc1, 0xa6, //0x8100,
+	0x06, 0x08, 0xa6, 0x07, 0x78, 0xb6, 0xe6, 0xfe, 0x08, 0xe6, 0xc3, 0x78, 0xc2, 0x96, 0xff, 0xee, //0x8110,
+	0x18, 0x96, 0x78, 0xc3, 0xf6, 0x08, 0xa6, 0x07, 0x90, 0x0e, 0x95, 0xe4, 0x18, 0x12, 0x0e, 0xe9, //0x8120,
+	0x40, 0x02, 0xd2, 0x37, 0x78, 0xbc, 0xe6, 0x08, 0x26, 0x08, 0xf6, 0xe5, 0x1f, 0x64, 0x01, 0x70, //0x8130,
+	0x4a, 0xe6, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xdf, 0x40, 0x05, 0x12, 0x0e, 0xda, 0x40, 0x39, 0x12, //0x8140,
+	0x0f, 0x02, 0x40, 0x04, 0x7f, 0xfe, 0x80, 0x02, 0x7f, 0x02, 0x78, 0xbd, 0xa6, 0x07, 0x78, 0xb9, //0x8150,
+	0xe6, 0x24, 0x03, 0x78, 0xbf, 0xf6, 0x78, 0xb9, 0xe6, 0x24, 0xfd, 0x78, 0xc0, 0xf6, 0x12, 0x0f, //0x8160,
+	0x02, 0x40, 0x06, 0x78, 0xc0, 0xe6, 0xff, 0x80, 0x04, 0x78, 0xbf, 0xe6, 0xff, 0x78, 0xbe, 0xa6, //0x8170,
+	0x07, 0x75, 0x1f, 0x02, 0x78, 0xb8, 0x76, 0x01, 0x02, 0x02, 0x4a, 0xe5, 0x1f, 0x64, 0x02, 0x60, //0x8180,
+	0x03, 0x02, 0x02, 0x2a, 0x78, 0xbe, 0xe6, 0xff, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xe0, 0x40, 0x08, //0x8190,
+	0x12, 0x0e, 0xda, 0x50, 0x03, 0x02, 0x02, 0x28, 0x12, 0x0f, 0x02, 0x40, 0x04, 0x7f, 0xff, 0x80, //0x81a0,
+	0x02, 0x7f, 0x01, 0x78, 0xbd, 0xa6, 0x07, 0x78, 0xb9, 0xe6, 0x04, 0x78, 0xbf, 0xf6, 0x78, 0xb9, //0x81b0,
+	0xe6, 0x14, 0x78, 0xc0, 0xf6, 0x18, 0x12, 0x0f, 0x04, 0x40, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, //0x81c0,
+	0x00, 0x78, 0xbf, 0xa6, 0x07, 0xd3, 0x08, 0xe6, 0x64, 0x80, 0x94, 0x80, 0x40, 0x04, 0xe6, 0xff, //0x81d0,
+	0x80, 0x02, 0x7f, 0x00, 0x78, 0xc0, 0xa6, 0x07, 0xc3, 0x18, 0xe6, 0x64, 0x80, 0x94, 0xb3, 0x50, //0x81e0,
+	0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x33, 0x78, 0xbf, 0xa6, 0x07, 0xc3, 0x08, 0xe6, 0x64, 0x80, //0x81f0,
+	0x94, 0xb3, 0x50, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x33, 0x78, 0xc0, 0xa6, 0x07, 0x12, 0x0f, //0x8200,
+	0x02, 0x40, 0x06, 0x78, 0xc0, 0xe6, 0xff, 0x80, 0x04, 0x78, 0xbf, 0xe6, 0xff, 0x78, 0xbe, 0xa6, //0x8210,
+	0x07, 0x75, 0x1f, 0x03, 0x78, 0xb8, 0x76, 0x01, 0x80, 0x20, 0xe5, 0x1f, 0x64, 0x03, 0x70, 0x26, //0x8220,
+	0x78, 0xbe, 0xe6, 0xff, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xe0, 0x40, 0x05, 0x12, 0x0e, 0xda, 0x40, //0x8230,
+	0x09, 0x78, 0xb9, 0xe6, 0x78, 0xbe, 0xf6, 0x75, 0x1f, 0x04, 0x78, 0xbe, 0xe6, 0x75, 0xf0, 0x05, //0x8240,
+	0xa4, 0xf5, 0x4b, 0x02, 0x0a, 0xff, 0xe5, 0x1f, 0xb4, 0x04, 0x10, 0x90, 0x0e, 0x94, 0xe4, 0x78, //0x8250,
+	0xc3, 0x12, 0x0e, 0xe9, 0x40, 0x02, 0xd2, 0x37, 0x75, 0x1f, 0x05, 0x22, 0x30, 0x01, 0x03, 0x02, //0x8260,
+	0x04, 0xc0, 0x30, 0x02, 0x03, 0x02, 0x04, 0xc0, 0x90, 0x51, 0xa5, 0xe0, 0x78, 0x93, 0xf6, 0xa3, //0x8270,
+	0xe0, 0x08, 0xf6, 0xa3, 0xe0, 0x08, 0xf6, 0xe5, 0x1f, 0x70, 0x3c, 0x75, 0x1e, 0x20, 0xd2, 0x35, //0x8280,
+	0x12, 0x0c, 0x7a, 0x78, 0x7e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8b, 0xa6, 0x09, 0x18, 0x76, //0x8290,
+	0x01, 0x12, 0x0c, 0x5b, 0x78, 0x4e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8b, 0xe6, 0x78, 0x6e, //0x82a0,
+	0xf6, 0x75, 0x1f, 0x01, 0x78, 0x93, 0xe6, 0x78, 0x90, 0xf6, 0x78, 0x94, 0xe6, 0x78, 0x91, 0xf6, //0x82b0,
+	0x78, 0x95, 0xe6, 0x78, 0x92, 0xf6, 0x22, 0x79, 0x90, 0xe7, 0xd3, 0x78, 0x93, 0x96, 0x40, 0x05, //0x82c0,
+	0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x93, 0xe7, 0x78, 0x90, 0x96, 0xff, 0x78, 0x88, 0x76, //0x82d0,
+	0x00, 0x08, 0xa6, 0x07, 0x79, 0x91, 0xe7, 0xd3, 0x78, 0x94, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, //0x82e0,
+	0x80, 0x08, 0xc3, 0x79, 0x94, 0xe7, 0x78, 0x91, 0x96, 0xff, 0x12, 0x0c, 0x8e, 0x79, 0x92, 0xe7, //0x82f0,
+	0xd3, 0x78, 0x95, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x95, 0xe7, 0x78, //0x8300,
+	0x92, 0x96, 0xff, 0x12, 0x0c, 0x8e, 0x12, 0x0c, 0x5b, 0x78, 0x8a, 0xe6, 0x25, 0xe0, 0x24, 0x4e, //0x8310,
+	0xf8, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8a, 0xe6, 0x24, 0x6e, 0xf8, 0xa6, 0x09, 0x78, 0x8a, //0x8320,
+	0xe6, 0x24, 0x01, 0xff, 0xe4, 0x33, 0xfe, 0xd3, 0xef, 0x94, 0x0f, 0xee, 0x64, 0x80, 0x94, 0x80, //0x8330,
+	0x40, 0x04, 0x7f, 0x00, 0x80, 0x05, 0x78, 0x8a, 0xe6, 0x04, 0xff, 0x78, 0x8a, 0xa6, 0x07, 0xe5, //0x8340,
+	0x1f, 0xb4, 0x01, 0x0a, 0xe6, 0x60, 0x03, 0x02, 0x04, 0xc0, 0x75, 0x1f, 0x02, 0x22, 0x12, 0x0c, //0x8350,
+	0x7a, 0x78, 0x80, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x12, 0x0c, 0x7a, 0x78, 0x82, 0xa6, 0x06, 0x08, //0x8360,
+	0xa6, 0x07, 0x78, 0x6e, 0xe6, 0x78, 0x8c, 0xf6, 0x78, 0x6e, 0xe6, 0x78, 0x8d, 0xf6, 0x7f, 0x01, //0x8370,
+	0xef, 0x25, 0xe0, 0x24, 0x4f, 0xf9, 0xc3, 0x78, 0x81, 0xe6, 0x97, 0x18, 0xe6, 0x19, 0x97, 0x50, //0x8380,
+	0x0a, 0x12, 0x0c, 0x82, 0x78, 0x80, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0x74, 0x6e, 0x2f, 0xf9, 0x78, //0x8390,
+	0x8c, 0xe6, 0xc3, 0x97, 0x50, 0x08, 0x74, 0x6e, 0x2f, 0xf8, 0xe6, 0x78, 0x8c, 0xf6, 0xef, 0x25, //0x83a0,
+	0xe0, 0x24, 0x4f, 0xf9, 0xd3, 0x78, 0x83, 0xe6, 0x97, 0x18, 0xe6, 0x19, 0x97, 0x40, 0x0a, 0x12, //0x83b0,
+	0x0c, 0x82, 0x78, 0x82, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0x74, 0x6e, 0x2f, 0xf9, 0x78, 0x8d, 0xe6, //0x83c0,
+	0xd3, 0x97, 0x40, 0x08, 0x74, 0x6e, 0x2f, 0xf8, 0xe6, 0x78, 0x8d, 0xf6, 0x0f, 0xef, 0x64, 0x10, //0x83d0,
+	0x70, 0x9e, 0xc3, 0x79, 0x81, 0xe7, 0x78, 0x83, 0x96, 0xff, 0x19, 0xe7, 0x18, 0x96, 0x78, 0x84, //0x83e0,
+	0xf6, 0x08, 0xa6, 0x07, 0xc3, 0x79, 0x8c, 0xe7, 0x78, 0x8d, 0x96, 0x08, 0xf6, 0xd3, 0x79, 0x81, //0x83f0,
+	0xe7, 0x78, 0x7f, 0x96, 0x19, 0xe7, 0x18, 0x96, 0x40, 0x05, 0x09, 0xe7, 0x08, 0x80, 0x06, 0xc3, //0x8400,
+	0x79, 0x7f, 0xe7, 0x78, 0x81, 0x96, 0xff, 0x19, 0xe7, 0x18, 0x96, 0xfe, 0x78, 0x86, 0xa6, 0x06, //0x8410,
+	0x08, 0xa6, 0x07, 0x79, 0x8c, 0xe7, 0xd3, 0x78, 0x8b, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, //0x8420,
+	0x08, 0xc3, 0x79, 0x8b, 0xe7, 0x78, 0x8c, 0x96, 0xff, 0x78, 0x8f, 0xa6, 0x07, 0xe5, 0x1f, 0x64, //0x8430,
+	0x02, 0x70, 0x69, 0x90, 0x0e, 0x91, 0x93, 0xff, 0x18, 0xe6, 0xc3, 0x9f, 0x50, 0x72, 0x12, 0x0c, //0x8440,
+	0x4a, 0x12, 0x0c, 0x2f, 0x90, 0x0e, 0x8e, 0x12, 0x0c, 0x38, 0x78, 0x80, 0x12, 0x0c, 0x6b, 0x7b, //0x8450,
+	0x04, 0x12, 0x0c, 0x1d, 0xc3, 0x12, 0x06, 0x45, 0x50, 0x56, 0x90, 0x0e, 0x92, 0xe4, 0x93, 0xff, //0x8460,
+	0x78, 0x8f, 0xe6, 0x9f, 0x40, 0x02, 0x80, 0x11, 0x90, 0x0e, 0x90, 0xe4, 0x93, 0xff, 0xd3, 0x78, //0x8470,
+	0x89, 0xe6, 0x9f, 0x18, 0xe6, 0x94, 0x00, 0x40, 0x03, 0x75, 0x1f, 0x05, 0x12, 0x0c, 0x4a, 0x12, //0x8480,
+	0x0c, 0x2f, 0x90, 0x0e, 0x8f, 0x12, 0x0c, 0x38, 0x78, 0x7e, 0x12, 0x0c, 0x6b, 0x7b, 0x40, 0x12, //0x8490,
+	0x0c, 0x1d, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x18, 0x75, 0x1f, 0x05, 0x22, 0xe5, 0x1f, 0xb4, 0x05, //0x84a0,
+	0x0f, 0xd2, 0x01, 0xc2, 0x02, 0xe4, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0xd2, 0x36, //0x84b0,
+	0x22, 0xef, 0x8d, 0xf0, 0xa4, 0xa8, 0xf0, 0xcf, 0x8c, 0xf0, 0xa4, 0x28, 0xce, 0x8d, 0xf0, 0xa4, //0x84c0,
+	0x2e, 0xfe, 0x22, 0xbc, 0x00, 0x0b, 0xbe, 0x00, 0x29, 0xef, 0x8d, 0xf0, 0x84, 0xff, 0xad, 0xf0, //0x84d0,
+	0x22, 0xe4, 0xcc, 0xf8, 0x75, 0xf0, 0x08, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xec, 0x33, 0xfc, //0x84e0,
+	0xee, 0x9d, 0xec, 0x98, 0x40, 0x05, 0xfc, 0xee, 0x9d, 0xfe, 0x0f, 0xd5, 0xf0, 0xe9, 0xe4, 0xce, //0x84f0,
+	0xfd, 0x22, 0xed, 0xf8, 0xf5, 0xf0, 0xee, 0x84, 0x20, 0xd2, 0x1c, 0xfe, 0xad, 0xf0, 0x75, 0xf0, //0x8500,
+	0x08, 0xef, 0x2f, 0xff, 0xed, 0x33, 0xfd, 0x40, 0x07, 0x98, 0x50, 0x06, 0xd5, 0xf0, 0xf2, 0x22, //0x8510,
+	0xc3, 0x98, 0xfd, 0x0f, 0xd5, 0xf0, 0xea, 0x22, 0xe8, 0x8f, 0xf0, 0xa4, 0xcc, 0x8b, 0xf0, 0xa4, //0x8520,
+	0x2c, 0xfc, 0xe9, 0x8e, 0xf0, 0xa4, 0x2c, 0xfc, 0x8a, 0xf0, 0xed, 0xa4, 0x2c, 0xfc, 0xea, 0x8e, //0x8530,
+	0xf0, 0xa4, 0xcd, 0xa8, 0xf0, 0x8b, 0xf0, 0xa4, 0x2d, 0xcc, 0x38, 0x25, 0xf0, 0xfd, 0xe9, 0x8f, //0x8540,
+	0xf0, 0xa4, 0x2c, 0xcd, 0x35, 0xf0, 0xfc, 0xeb, 0x8e, 0xf0, 0xa4, 0xfe, 0xa9, 0xf0, 0xeb, 0x8f, //0x8550,
+	0xf0, 0xa4, 0xcf, 0xc5, 0xf0, 0x2e, 0xcd, 0x39, 0xfe, 0xe4, 0x3c, 0xfc, 0xea, 0xa4, 0x2d, 0xce, //0x8560,
+	0x35, 0xf0, 0xfd, 0xe4, 0x3c, 0xfc, 0x22, 0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, //0x8570,
+	0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc, 0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, //0x8580,
+	0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40, 0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, //0x8590,
+	0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6, 0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, //0x85a0,
+	0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9, 0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, //0x85b0,
+	0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb, 0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, //0x85c0,
+	0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb, 0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, //0x85d0,
+	0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9, 0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, //0x85e0,
+	0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, //0x85f0,
+	0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a, 0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, //0x8600,
+	0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, //0x8610,
+	0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07, 0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, //0x8620,
+	0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8, 0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, //0x8630,
+	0xfa, 0xe4, 0xc8, 0xf9, 0x22, 0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, //0x8640,
+	0xf0, 0xe8, 0x9c, 0x45, 0xf0, 0x22, 0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, //0x8650,
+	0xee, 0x13, 0xfe, 0xef, 0x13, 0xff, 0xd8, 0xf1, 0x22, 0xe8, 0x60, 0x0f, 0xef, 0xc3, 0x33, 0xff, //0x8660,
+	0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xd8, 0xf1, 0x22, 0xe4, 0x93, 0xfc, 0x74, //0x8670,
+	0x01, 0x93, 0xfd, 0x74, 0x02, 0x93, 0xfe, 0x74, 0x03, 0x93, 0xff, 0x22, 0xe6, 0xfb, 0x08, 0xe6, //0x8680,
+	0xf9, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xcb, 0xf8, 0x22, 0xec, 0xf6, 0x08, 0xed, 0xf6, 0x08, 0xee, //0x8690,
+	0xf6, 0x08, 0xef, 0xf6, 0x22, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, //0x86a0,
+	0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, //0x86b0,
+	0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, //0x86c0,
+	0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0x38, 0x04, 0x78, 0x52, 0x12, 0x0b, 0xfd, 0x90, //0x86d0,
+	0x38, 0x00, 0xe0, 0xfe, 0xa3, 0xe0, 0xfd, 0xed, 0xff, 0xc3, 0x12, 0x0b, 0x9e, 0x90, 0x38, 0x10, //0x86e0,
+	0x12, 0x0b, 0x92, 0x90, 0x38, 0x06, 0x78, 0x54, 0x12, 0x0b, 0xfd, 0x90, 0x38, 0x02, 0xe0, 0xfe, //0x86f0,
+	0xa3, 0xe0, 0xfd, 0xed, 0xff, 0xc3, 0x12, 0x0b, 0x9e, 0x90, 0x38, 0x12, 0x12, 0x0b, 0x92, 0xa3, //0x8700,
+	0xe0, 0xb4, 0x31, 0x07, 0x78, 0x52, 0x79, 0x52, 0x12, 0x0c, 0x13, 0x90, 0x38, 0x14, 0xe0, 0xb4, //0x8710,
+	0x71, 0x15, 0x78, 0x52, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, //0x8720,
+	0xf9, 0x79, 0x53, 0xf7, 0xee, 0x19, 0xf7, 0x90, 0x38, 0x15, 0xe0, 0xb4, 0x31, 0x07, 0x78, 0x54, //0x8730,
+	0x79, 0x54, 0x12, 0x0c, 0x13, 0x90, 0x38, 0x15, 0xe0, 0xb4, 0x71, 0x15, 0x78, 0x54, 0xe6, 0xfe, //0x8740,
+	0x08, 0xe6, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x79, 0x55, 0xf7, 0xee, 0x19, //0x8750,
+	0xf7, 0x79, 0x52, 0x12, 0x0b, 0xd9, 0x09, 0x12, 0x0b, 0xd9, 0xaf, 0x47, 0x12, 0x0b, 0xb2, 0xe5, //0x8760,
+	0x44, 0xfb, 0x7a, 0x00, 0xfd, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x5a, 0xa6, 0x06, 0x08, 0xa6, //0x8770,
+	0x07, 0xaf, 0x45, 0x12, 0x0b, 0xb2, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x56, 0xa6, //0x8780,
+	0x06, 0x08, 0xa6, 0x07, 0xaf, 0x48, 0x78, 0x54, 0x12, 0x0b, 0xb4, 0xe5, 0x43, 0xfb, 0xfd, 0x7c, //0x8790,
+	0x00, 0x12, 0x04, 0xd3, 0x78, 0x5c, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xaf, 0x46, 0x7e, 0x00, 0x78, //0x87a0,
+	0x54, 0x12, 0x0b, 0xb6, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x58, 0xa6, 0x06, 0x08, //0x87b0,
+	0xa6, 0x07, 0xc3, 0x78, 0x5b, 0xe6, 0x94, 0x08, 0x18, 0xe6, 0x94, 0x00, 0x50, 0x05, 0x76, 0x00, //0x87c0,
+	0x08, 0x76, 0x08, 0xc3, 0x78, 0x5d, 0xe6, 0x94, 0x08, 0x18, 0xe6, 0x94, 0x00, 0x50, 0x05, 0x76, //0x87d0,
+	0x00, 0x08, 0x76, 0x08, 0x78, 0x5a, 0x12, 0x0b, 0xc6, 0xff, 0xd3, 0x78, 0x57, 0xe6, 0x9f, 0x18, //0x87e0,
+	0xe6, 0x9e, 0x40, 0x0e, 0x78, 0x5a, 0xe6, 0x13, 0xfe, 0x08, 0xe6, 0x78, 0x57, 0x12, 0x0c, 0x08, //0x87f0,
+	0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x78, 0x5e, 0x12, 0x0b, 0xbe, 0xff, 0xd3, 0x78, 0x59, 0xe6, //0x8800,
+	0x9f, 0x18, 0xe6, 0x9e, 0x40, 0x0e, 0x78, 0x5c, 0xe6, 0x13, 0xfe, 0x08, 0xe6, 0x78, 0x59, 0x12, //0x8810,
+	0x0c, 0x08, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xe4, 0xfc, 0xfd, 0x78, 0x62, 0x12, 0x06, 0x99, //0x8820,
+	0x78, 0x5a, 0x12, 0x0b, 0xc6, 0x78, 0x57, 0x26, 0xff, 0xee, 0x18, 0x36, 0xfe, 0x78, 0x66, 0x12, //0x8830,
+	0x0b, 0xbe, 0x78, 0x59, 0x26, 0xff, 0xee, 0x18, 0x36, 0xfe, 0xe4, 0xfc, 0xfd, 0x78, 0x6a, 0x12, //0x8840,
+	0x06, 0x99, 0x12, 0x0b, 0xce, 0x78, 0x66, 0x12, 0x06, 0x8c, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x08, //0x8850,
+	0x12, 0x0b, 0xce, 0x78, 0x66, 0x12, 0x06, 0x99, 0x78, 0x54, 0x12, 0x0b, 0xd0, 0x78, 0x6a, 0x12, //0x8860,
+	0x06, 0x8c, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x0a, 0x78, 0x54, 0x12, 0x0b, 0xd0, 0x78, 0x6a, 0x12, //0x8870,
+	0x06, 0x99, 0x78, 0x61, 0xe6, 0x90, 0x60, 0x01, 0xf0, 0x78, 0x65, 0xe6, 0xa3, 0xf0, 0x78, 0x69, //0x8880,
+	0xe6, 0xa3, 0xf0, 0x78, 0x55, 0xe6, 0xa3, 0xf0, 0x7d, 0x01, 0x78, 0x61, 0x12, 0x0b, 0xe9, 0x24, //0x8890,
+	0x01, 0x12, 0x0b, 0xa6, 0x78, 0x65, 0x12, 0x0b, 0xe9, 0x24, 0x02, 0x12, 0x0b, 0xa6, 0x78, 0x69, //0x88a0,
+	0x12, 0x0b, 0xe9, 0x24, 0x03, 0x12, 0x0b, 0xa6, 0x78, 0x6d, 0x12, 0x0b, 0xe9, 0x24, 0x04, 0x12, //0x88b0,
+	0x0b, 0xa6, 0x0d, 0xbd, 0x05, 0xd4, 0xc2, 0x0e, 0xc2, 0x06, 0x22, 0x85, 0x08, 0x41, 0x90, 0x30, //0x88c0,
+	0x24, 0xe0, 0xf5, 0x3d, 0xa3, 0xe0, 0xf5, 0x3e, 0xa3, 0xe0, 0xf5, 0x3f, 0xa3, 0xe0, 0xf5, 0x40, //0x88d0,
+	0xa3, 0xe0, 0xf5, 0x3c, 0xd2, 0x34, 0xe5, 0x41, 0x12, 0x06, 0xb1, 0x09, 0x31, 0x03, 0x09, 0x35, //0x88e0,
+	0x04, 0x09, 0x3b, 0x05, 0x09, 0x3e, 0x06, 0x09, 0x41, 0x07, 0x09, 0x4a, 0x08, 0x09, 0x5b, 0x12, //0x88f0,
+	0x09, 0x73, 0x18, 0x09, 0x89, 0x19, 0x09, 0x5e, 0x1a, 0x09, 0x6a, 0x1b, 0x09, 0xad, 0x80, 0x09, //0x8900,
+	0xb2, 0x81, 0x0a, 0x1d, 0x8f, 0x0a, 0x09, 0x90, 0x0a, 0x1d, 0x91, 0x0a, 0x1d, 0x92, 0x0a, 0x1d, //0x8910,
+	0x93, 0x0a, 0x1d, 0x94, 0x0a, 0x1d, 0x98, 0x0a, 0x17, 0x9f, 0x0a, 0x1a, 0xec, 0x00, 0x00, 0x0a, //0x8920,
+	0x38, 0x12, 0x0f, 0x74, 0x22, 0x12, 0x0f, 0x74, 0xd2, 0x03, 0x22, 0xd2, 0x03, 0x22, 0xc2, 0x03, //0x8930,
+	0x22, 0xa2, 0x37, 0xe4, 0x33, 0xf5, 0x3c, 0x02, 0x0a, 0x1d, 0xc2, 0x01, 0xc2, 0x02, 0xc2, 0x03, //0x8940,
+	0x12, 0x0d, 0x0d, 0x75, 0x1e, 0x70, 0xd2, 0x35, 0x02, 0x0a, 0x1d, 0x02, 0x0a, 0x04, 0x85, 0x40, //0x8950,
+	0x4a, 0x85, 0x3c, 0x4b, 0x12, 0x0a, 0xff, 0x02, 0x0a, 0x1d, 0x85, 0x4a, 0x40, 0x85, 0x4b, 0x3c, //0x8960,
+	0x02, 0x0a, 0x1d, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x85, 0x40, 0x31, 0x85, 0x3f, 0x30, 0x85, 0x3e, //0x8970,
+	0x2f, 0x85, 0x3d, 0x2e, 0x12, 0x0f, 0x46, 0x80, 0x1f, 0x75, 0x22, 0x00, 0x75, 0x23, 0x01, 0x74, //0x8980,
+	0xff, 0xf5, 0x2d, 0xf5, 0x2c, 0xf5, 0x2b, 0xf5, 0x2a, 0x12, 0x0f, 0x46, 0x85, 0x2d, 0x40, 0x85, //0x8990,
+	0x2c, 0x3f, 0x85, 0x2b, 0x3e, 0x85, 0x2a, 0x3d, 0xe4, 0xf5, 0x3c, 0x80, 0x70, 0x12, 0x0f, 0x16, //0x89a0,
+	0x80, 0x6b, 0x85, 0x3d, 0x45, 0x85, 0x3e, 0x46, 0xe5, 0x47, 0xc3, 0x13, 0xff, 0xe5, 0x45, 0xc3, //0x89b0,
+	0x9f, 0x50, 0x02, 0x8f, 0x45, 0xe5, 0x48, 0xc3, 0x13, 0xff, 0xe5, 0x46, 0xc3, 0x9f, 0x50, 0x02, //0x89c0,
+	0x8f, 0x46, 0xe5, 0x47, 0xc3, 0x13, 0xff, 0xfd, 0xe5, 0x45, 0x2d, 0xfd, 0xe4, 0x33, 0xfc, 0xe5, //0x89d0,
+	0x44, 0x12, 0x0f, 0x90, 0x40, 0x05, 0xe5, 0x44, 0x9f, 0xf5, 0x45, 0xe5, 0x48, 0xc3, 0x13, 0xff, //0x89e0,
+	0xfd, 0xe5, 0x46, 0x2d, 0xfd, 0xe4, 0x33, 0xfc, 0xe5, 0x43, 0x12, 0x0f, 0x90, 0x40, 0x05, 0xe5, //0x89f0,
+	0x43, 0x9f, 0xf5, 0x46, 0x12, 0x06, 0xd7, 0x80, 0x14, 0x85, 0x40, 0x48, 0x85, 0x3f, 0x47, 0x85, //0x8a00,
+	0x3e, 0x46, 0x85, 0x3d, 0x45, 0x80, 0x06, 0x02, 0x06, 0xd7, 0x12, 0x0d, 0x7e, 0x90, 0x30, 0x24, //0x8a10,
+	0xe5, 0x3d, 0xf0, 0xa3, 0xe5, 0x3e, 0xf0, 0xa3, 0xe5, 0x3f, 0xf0, 0xa3, 0xe5, 0x40, 0xf0, 0xa3, //0x8a20,
+	0xe5, 0x3c, 0xf0, 0x90, 0x30, 0x23, 0xe4, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, //0x8a30,
+	0xd0, 0x90, 0x3f, 0x0c, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x30, 0xe3, 0x74, 0x30, 0x36, 0x66, 0x90, //0x8a40,
+	0x60, 0x19, 0xe0, 0xf5, 0x0a, 0xa3, 0xe0, 0xf5, 0x0b, 0x90, 0x60, 0x1d, 0xe0, 0xf5, 0x14, 0xa3, //0x8a50,
+	0xe0, 0xf5, 0x15, 0x90, 0x60, 0x21, 0xe0, 0xf5, 0x0c, 0xa3, 0xe0, 0xf5, 0x0d, 0x90, 0x60, 0x29, //0x8a60,
+	0xe0, 0xf5, 0x0e, 0xa3, 0xe0, 0xf5, 0x0f, 0x90, 0x60, 0x31, 0xe0, 0xf5, 0x10, 0xa3, 0xe0, 0xf5, //0x8a70,
+	0x11, 0x90, 0x60, 0x39, 0xe0, 0xf5, 0x12, 0xa3, 0xe0, 0xf5, 0x13, 0x30, 0x01, 0x06, 0x30, 0x33, //0x8a80,
+	0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x09, 0x30, 0x02, 0x06, 0x30, 0x33, 0x03, 0xd3, 0x80, 0x01, //0x8a90,
+	0xc3, 0x92, 0x0a, 0x30, 0x33, 0x0c, 0x30, 0x03, 0x09, 0x20, 0x02, 0x06, 0x20, 0x01, 0x03, 0xd3, //0x8aa0,
+	0x80, 0x01, 0xc3, 0x92, 0x0b, 0x90, 0x30, 0x01, 0xe0, 0x44, 0x40, 0xf0, 0xe0, 0x54, 0xbf, 0xf0, //0x8ab0,
+	0xe5, 0x32, 0x30, 0xe1, 0x14, 0x30, 0x34, 0x11, 0x90, 0x30, 0x22, 0xe0, 0xf5, 0x08, 0xe4, 0xf0, //0x8ac0,
+	0x30, 0x00, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x08, 0xe5, 0x32, 0x30, 0xe5, 0x12, 0x90, 0x56, //0x8ad0,
+	0xa1, 0xe0, 0xf5, 0x09, 0x30, 0x31, 0x09, 0x30, 0x05, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0d, //0x8ae0,
+	0x90, 0x3f, 0x0c, 0xe5, 0x32, 0xf0, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, //0x8af0,
+	0x0e, 0x7e, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xff, 0xc3, 0x90, 0x0e, 0x7c, 0x74, 0x01, 0x93, //0x8b00,
+	0x9f, 0xff, 0xe4, 0x93, 0x9e, 0xfe, 0xe4, 0x8f, 0x3b, 0x8e, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0xab, //0x8b10,
+	0x3b, 0xaa, 0x3a, 0xa9, 0x39, 0xa8, 0x38, 0xaf, 0x4b, 0xfc, 0xfd, 0xfe, 0x12, 0x05, 0x28, 0x12, //0x8b20,
+	0x0d, 0xe1, 0xe4, 0x7b, 0xff, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0xb3, 0x12, 0x0d, 0xe1, 0x90, 0x0e, //0x8b30,
+	0x69, 0xe4, 0x12, 0x0d, 0xf6, 0x12, 0x0d, 0xe1, 0xe4, 0x85, 0x4a, 0x37, 0xf5, 0x36, 0xf5, 0x35, //0x8b40,
+	0xf5, 0x34, 0xaf, 0x37, 0xae, 0x36, 0xad, 0x35, 0xac, 0x34, 0xa3, 0x12, 0x0d, 0xf6, 0x8f, 0x37, //0x8b50,
+	0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0xe5, 0x3b, 0x45, 0x37, 0xf5, 0x3b, 0xe5, 0x3a, 0x45, 0x36, //0x8b60,
+	0xf5, 0x3a, 0xe5, 0x39, 0x45, 0x35, 0xf5, 0x39, 0xe5, 0x38, 0x45, 0x34, 0xf5, 0x38, 0xe4, 0xf5, //0x8b70,
+	0x22, 0xf5, 0x23, 0x85, 0x3b, 0x31, 0x85, 0x3a, 0x30, 0x85, 0x39, 0x2f, 0x85, 0x38, 0x2e, 0x02, //0x8b80,
+	0x0f, 0x46, 0xe0, 0xa3, 0xe0, 0x75, 0xf0, 0x02, 0xa4, 0xff, 0xae, 0xf0, 0xc3, 0x08, 0xe6, 0x9f, //0x8b90,
+	0xf6, 0x18, 0xe6, 0x9e, 0xf6, 0x22, 0xff, 0xe5, 0xf0, 0x34, 0x60, 0x8f, 0x82, 0xf5, 0x83, 0xec, //0x8ba0,
+	0xf0, 0x22, 0x78, 0x52, 0x7e, 0x00, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x02, 0x04, 0xc1, 0xe4, 0xfc, //0x8bb0,
+	0xfd, 0x12, 0x06, 0x99, 0x78, 0x5c, 0xe6, 0xc3, 0x13, 0xfe, 0x08, 0xe6, 0x13, 0x22, 0x78, 0x52, //0x8bc0,
+	0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xe4, 0xfc, 0xfd, 0x22, 0xe7, 0xc4, 0xf8, 0x54, 0xf0, 0xc8, 0x68, //0x8bd0,
+	0xf7, 0x09, 0xe7, 0xc4, 0x54, 0x0f, 0x48, 0xf7, 0x22, 0xe6, 0xfc, 0xed, 0x75, 0xf0, 0x04, 0xa4, //0x8be0,
+	0x22, 0x12, 0x06, 0x7c, 0x8f, 0x48, 0x8e, 0x47, 0x8d, 0x46, 0x8c, 0x45, 0x22, 0xe0, 0xfe, 0xa3, //0x8bf0,
+	0xe0, 0xfd, 0xee, 0xf6, 0xed, 0x08, 0xf6, 0x22, 0x13, 0xff, 0xc3, 0xe6, 0x9f, 0xff, 0x18, 0xe6, //0x8c00,
+	0x9e, 0xfe, 0x22, 0xe6, 0xc3, 0x13, 0xf7, 0x08, 0xe6, 0x13, 0x09, 0xf7, 0x22, 0xad, 0x39, 0xac, //0x8c10,
+	0x38, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0x28, 0x8f, 0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0x8c, 0x38, 0xab, //0x8c20,
+	0x37, 0xaa, 0x36, 0xa9, 0x35, 0xa8, 0x34, 0x22, 0x93, 0xff, 0xe4, 0xfc, 0xfd, 0xfe, 0x12, 0x05, //0x8c30,
+	0x28, 0x8f, 0x37, 0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0x22, 0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, //0x8c40,
+	0xff, 0xe4, 0x8f, 0x37, 0x8e, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0x22, 0x90, 0x0e, 0x8c, 0xe4, 0x93, //0x8c50,
+	0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe6, 0xfe, 0x08, 0xe6, 0xff, //0x8c60,
+	0xe4, 0x8f, 0x3b, 0x8e, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0x22, 0x78, 0x4e, 0xe6, 0xfe, 0x08, 0xe6, //0x8c70,
+	0xff, 0x22, 0xef, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x22, 0x78, 0x89, //0x8c80,
+	0xef, 0x26, 0xf6, 0x18, 0xe4, 0x36, 0xf6, 0x22, 0x75, 0x89, 0x03, 0x75, 0xa8, 0x01, 0x75, 0xb8, //0x8c90,
+	0x04, 0x75, 0x34, 0xff, 0x75, 0x35, 0x0e, 0x75, 0x36, 0x15, 0x75, 0x37, 0x0d, 0x12, 0x0e, 0x9a, //0x8ca0,
+	0x12, 0x00, 0x09, 0x12, 0x0f, 0x16, 0x12, 0x00, 0x06, 0xd2, 0x00, 0xd2, 0x34, 0xd2, 0xaf, 0x75, //0x8cb0,
+	0x34, 0xff, 0x75, 0x35, 0x0e, 0x75, 0x36, 0x49, 0x75, 0x37, 0x03, 0x12, 0x0e, 0x9a, 0x30, 0x08, //0x8cc0,
+	0x09, 0xc2, 0x34, 0x12, 0x08, 0xcb, 0xc2, 0x08, 0xd2, 0x34, 0x30, 0x0b, 0x09, 0xc2, 0x36, 0x12, //0x8cd0,
+	0x02, 0x6c, 0xc2, 0x0b, 0xd2, 0x36, 0x30, 0x09, 0x09, 0xc2, 0x36, 0x12, 0x00, 0x0e, 0xc2, 0x09, //0x8ce0,
+	0xd2, 0x36, 0x30, 0x0e, 0x03, 0x12, 0x06, 0xd7, 0x30, 0x35, 0xd3, 0x90, 0x30, 0x29, 0xe5, 0x1e, //0x8cf0,
+	0xf0, 0xb4, 0x10, 0x05, 0x90, 0x30, 0x23, 0xe4, 0xf0, 0xc2, 0x35, 0x80, 0xc1, 0xe4, 0xf5, 0x4b, //0x8d00,
+	0x90, 0x0e, 0x7a, 0x93, 0xff, 0xe4, 0x8f, 0x37, 0xf5, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0xaf, 0x37, //0x8d10,
+	0xae, 0x36, 0xad, 0x35, 0xac, 0x34, 0x90, 0x0e, 0x6a, 0x12, 0x0d, 0xf6, 0x8f, 0x37, 0x8e, 0x36, //0x8d20,
+	0x8d, 0x35, 0x8c, 0x34, 0x90, 0x0e, 0x72, 0x12, 0x06, 0x7c, 0xef, 0x45, 0x37, 0xf5, 0x37, 0xee, //0x8d30,
+	0x45, 0x36, 0xf5, 0x36, 0xed, 0x45, 0x35, 0xf5, 0x35, 0xec, 0x45, 0x34, 0xf5, 0x34, 0xe4, 0xf5, //0x8d40,
+	0x22, 0xf5, 0x23, 0x85, 0x37, 0x31, 0x85, 0x36, 0x30, 0x85, 0x35, 0x2f, 0x85, 0x34, 0x2e, 0x12, //0x8d50,
+	0x0f, 0x46, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x90, 0x0e, 0x72, 0x12, 0x0d, 0xea, 0x12, 0x0f, 0x46, //0x8d60,
+	0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x90, 0x0e, 0x6e, 0x12, 0x0d, 0xea, 0x02, 0x0f, 0x46, 0xe5, 0x40, //0x8d70,
+	0x24, 0xf2, 0xf5, 0x37, 0xe5, 0x3f, 0x34, 0x43, 0xf5, 0x36, 0xe5, 0x3e, 0x34, 0xa2, 0xf5, 0x35, //0x8d80,
+	0xe5, 0x3d, 0x34, 0x28, 0xf5, 0x34, 0xe5, 0x37, 0xff, 0xe4, 0xfe, 0xfd, 0xfc, 0x78, 0x18, 0x12, //0x8d90,
+	0x06, 0x69, 0x8f, 0x40, 0x8e, 0x3f, 0x8d, 0x3e, 0x8c, 0x3d, 0xe5, 0x37, 0x54, 0xa0, 0xff, 0xe5, //0x8da0,
+	0x36, 0xfe, 0xe4, 0xfd, 0xfc, 0x78, 0x07, 0x12, 0x06, 0x56, 0x78, 0x10, 0x12, 0x0f, 0x9a, 0xe4, //0x8db0,
+	0xff, 0xfe, 0xe5, 0x35, 0xfd, 0xe4, 0xfc, 0x78, 0x0e, 0x12, 0x06, 0x56, 0x12, 0x0f, 0x9d, 0xe4, //0x8dc0,
+	0xff, 0xfe, 0xfd, 0xe5, 0x34, 0xfc, 0x78, 0x18, 0x12, 0x06, 0x56, 0x78, 0x08, 0x12, 0x0f, 0x9a, //0x8dd0,
+	0x22, 0x8f, 0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0x8c, 0x38, 0x22, 0x12, 0x06, 0x7c, 0x8f, 0x31, 0x8e, //0x8de0,
+	0x30, 0x8d, 0x2f, 0x8c, 0x2e, 0x22, 0x93, 0xf9, 0xf8, 0x02, 0x06, 0x69, 0x00, 0x00, 0x00, 0x00, //0x8df0,
+	0x12, 0x01, 0x17, 0x08, 0x31, 0x15, 0x53, 0x54, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x13, 0x01, //0x8e00,
+	0x10, 0x01, 0x56, 0x40, 0x1a, 0x30, 0x29, 0x7e, 0x00, 0x30, 0x04, 0x20, 0xdf, 0x30, 0x05, 0x40, //0x8e10,
+	0xbf, 0x50, 0x03, 0x00, 0xfd, 0x50, 0x27, 0x01, 0xfe, 0x60, 0x00, 0x11, 0x00, 0x3f, 0x05, 0x30, //0x8e20,
+	0x00, 0x3f, 0x06, 0x22, 0x00, 0x3f, 0x01, 0x2a, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x36, 0x06, 0x07, //0x8e30,
+	0x00, 0x3f, 0x0b, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x40, 0xbf, 0x30, 0x01, 0x00, //0x8e40,
+	0xbf, 0x30, 0x29, 0x70, 0x00, 0x3a, 0x00, 0x00, 0xff, 0x3a, 0x00, 0x00, 0xff, 0x36, 0x03, 0x36, //0x8e50,
+	0x02, 0x41, 0x44, 0x58, 0x20, 0x18, 0x10, 0x0a, 0x04, 0x04, 0x00, 0x03, 0xff, 0x64, 0x00, 0x00, //0x8e60,
+	0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x06, 0x00, 0x03, 0x51, 0x00, 0x7a, //0x8e70,
+	0x50, 0x3c, 0x28, 0x1e, 0x10, 0x10, 0x50, 0x2d, 0x28, 0x16, 0x10, 0x10, 0x02, 0x00, 0x10, 0x0c, //0x8e80,
+	0x10, 0x04, 0x0c, 0x6e, 0x06, 0x05, 0x00, 0xa5, 0x5a, 0x00, 0xae, 0x35, 0xaf, 0x36, 0xe4, 0xfd, //0x8e90,
+	0xed, 0xc3, 0x95, 0x37, 0x50, 0x33, 0x12, 0x0f, 0xe2, 0xe4, 0x93, 0xf5, 0x38, 0x74, 0x01, 0x93, //0x8ea0,
+	0xf5, 0x39, 0x45, 0x38, 0x60, 0x23, 0x85, 0x39, 0x82, 0x85, 0x38, 0x83, 0xe0, 0xfc, 0x12, 0x0f, //0x8eb0,
+	0xe2, 0x74, 0x03, 0x93, 0x52, 0x04, 0x12, 0x0f, 0xe2, 0x74, 0x02, 0x93, 0x42, 0x04, 0x85, 0x39, //0x8ec0,
+	0x82, 0x85, 0x38, 0x83, 0xec, 0xf0, 0x0d, 0x80, 0xc7, 0x22, 0x78, 0xbe, 0xe6, 0xd3, 0x08, 0xff, //0x8ed0,
+	0xe6, 0x64, 0x80, 0xf8, 0xef, 0x64, 0x80, 0x98, 0x22, 0x93, 0xff, 0x7e, 0x00, 0xe6, 0xfc, 0x08, //0x8ee0,
+	0xe6, 0xfd, 0x12, 0x04, 0xc1, 0x78, 0xc1, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0xd3, 0xef, 0x9d, 0xee, //0x8ef0,
+	0x9c, 0x22, 0x78, 0xbd, 0xd3, 0xe6, 0x64, 0x80, 0x94, 0x80, 0x22, 0x25, 0xe0, 0x24, 0x0a, 0xf8, //0x8f00,
+	0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe5, 0x3c, 0xd3, 0x94, 0x00, 0x40, 0x0b, 0x90, 0x0e, 0x88, //0x8f10,
+	0x12, 0x0b, 0xf1, 0x90, 0x0e, 0x86, 0x80, 0x09, 0x90, 0x0e, 0x82, 0x12, 0x0b, 0xf1, 0x90, 0x0e, //0x8f20,
+	0x80, 0xe4, 0x93, 0xf5, 0x44, 0xa3, 0xe4, 0x93, 0xf5, 0x43, 0xd2, 0x06, 0x30, 0x06, 0x03, 0xd3, //0x8f30,
+	0x80, 0x01, 0xc3, 0x92, 0x0e, 0x22, 0xa2, 0xaf, 0x92, 0x32, 0xc2, 0xaf, 0xe5, 0x23, 0x45, 0x22, //0x8f40,
+	0x90, 0x0e, 0x5d, 0x60, 0x0e, 0x12, 0x0f, 0xcb, 0xe0, 0xf5, 0x2c, 0x12, 0x0f, 0xc8, 0xe0, 0xf5, //0x8f50,
+	0x2d, 0x80, 0x0c, 0x12, 0x0f, 0xcb, 0xe5, 0x30, 0xf0, 0x12, 0x0f, 0xc8, 0xe5, 0x31, 0xf0, 0xa2, //0x8f60,
+	0x32, 0x92, 0xaf, 0x22, 0xd2, 0x01, 0xc2, 0x02, 0xe4, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, //0x8f70,
+	0x33, 0xd2, 0x36, 0xd2, 0x01, 0xc2, 0x02, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0x22, //0x8f80,
+	0xfb, 0xd3, 0xed, 0x9b, 0x74, 0x80, 0xf8, 0x6c, 0x98, 0x22, 0x12, 0x06, 0x69, 0xe5, 0x40, 0x2f, //0x8f90,
+	0xf5, 0x40, 0xe5, 0x3f, 0x3e, 0xf5, 0x3f, 0xe5, 0x3e, 0x3d, 0xf5, 0x3e, 0xe5, 0x3d, 0x3c, 0xf5, //0x8fa0,
+	0x3d, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x3f, 0x0d, 0xe0, 0xf5, 0x33, 0xe5, 0x33, //0x8fb0,
+	0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, 0x0e, 0x5f, 0xe4, 0x93, 0xfe, 0x74, 0x01, //0x8fc0,
+	0x93, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0xcd, 0x02, //0x8fd0,
+	0x0c, 0x98, 0x8f, 0x82, 0x8e, 0x83, 0x75, 0xf0, 0x04, 0xed, 0x02, 0x06, 0xa5,                   //0x8fe0
+}; 
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 31 - 31
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_pmic.c

@@ -798,47 +798,47 @@ static rt_err_t rt_hw_pmic_init_register(void)
     stpmu1_write_reg(BUCK_ICC_TURNOFF_REG, 0x30);
     stpmu1_write_reg(LDO_ICC_TURNOFF_REG, 0x3b);
 
-  /* vddcore */
-  STPMU1_Regulator_Voltage_Set(STPMU1_BUCK1, 1200);
-  STPMU1_Regulator_Enable(STPMU1_BUCK1);
+    /* vddcore */
+    STPMU1_Regulator_Voltage_Set(STPMU1_BUCK1, 1200);
+    STPMU1_Regulator_Enable(STPMU1_BUCK1);
 
-  /* vddddr */
-  STPMU1_Regulator_Voltage_Set(STPMU1_BUCK2, 1350);
-  STPMU1_Regulator_Enable(STPMU1_BUCK2);
+    /* vddddr */
+    STPMU1_Regulator_Voltage_Set(STPMU1_BUCK2, 1350);
+    STPMU1_Regulator_Enable(STPMU1_BUCK2);
 
-  /* vdd */
-  STPMU1_Regulator_Voltage_Set(STPMU1_BUCK3, 3300);
-  STPMU1_Regulator_Enable(STPMU1_BUCK3);
+    /* vdd */
+    STPMU1_Regulator_Voltage_Set(STPMU1_BUCK3, 3300);
+    STPMU1_Regulator_Enable(STPMU1_BUCK3);
 
-  /* 3v3 */
-  STPMU1_Regulator_Voltage_Set(STPMU1_BUCK4, 3300);
-  STPMU1_Regulator_Enable(STPMU1_BUCK4);
+    /* 3v3 */
+    STPMU1_Regulator_Voltage_Set(STPMU1_BUCK4, 3300);
+    STPMU1_Regulator_Enable(STPMU1_BUCK4);
 
-  /* vdda */
-  STPMU1_Regulator_Voltage_Set(STPMU1_LDO1, 2900);
-  STPMU1_Regulator_Enable(STPMU1_LDO1);
+    /* vdda */
+    STPMU1_Regulator_Voltage_Set(STPMU1_LDO1, 2900);
+    STPMU1_Regulator_Enable(STPMU1_LDO1);
 
-  /* 2v8 */
-  STPMU1_Regulator_Voltage_Set(STPMU1_LDO2, 2800);
-  STPMU1_Regulator_Enable(STPMU1_LDO2);
+    /* 2v8 */
+    STPMU1_Regulator_Voltage_Set(STPMU1_LDO2, 2800);
+    STPMU1_Regulator_Enable(STPMU1_LDO2);
 
-  /* vtt_ddr  lod3 mode buck2/2 */
-  STPMU1_Regulator_Voltage_Set(STPMU1_LDO3, 0xFFFF);
-  STPMU1_Regulator_Enable(STPMU1_LDO3);
+    /* vtt_ddr  lod3 mode buck2/2 */
+    STPMU1_Regulator_Voltage_Set(STPMU1_LDO3, 0xFFFF);
+    STPMU1_Regulator_Enable(STPMU1_LDO3);
 
-  /* vdd_usb */
-  STPMU1_Regulator_Voltage_Set(STPMU1_LDO4, 3300);
-  STPMU1_Regulator_Enable(STPMU1_LDO4);
+    /* vdd_usb */
+    STPMU1_Regulator_Voltage_Set(STPMU1_LDO4, 3300);
+    STPMU1_Regulator_Enable(STPMU1_LDO4);
 
-  /* vdd_sd */
-  STPMU1_Regulator_Voltage_Set(STPMU1_LDO5, 2900);
-  STPMU1_Regulator_Enable(STPMU1_LDO5);
+    /* vdd_sd */
+    STPMU1_Regulator_Voltage_Set(STPMU1_LDO5, 2900);
+    STPMU1_Regulator_Enable(STPMU1_LDO5);
 
-  /* 1v8 */
-  STPMU1_Regulator_Voltage_Set(STPMU1_LDO6, 1800);
-  STPMU1_Regulator_Enable(STPMU1_LDO6);
+    /* 1v8 */
+    STPMU1_Regulator_Voltage_Set(STPMU1_LDO6, 1800);
+    STPMU1_Regulator_Enable(STPMU1_LDO6);
 
-  STPMU1_Regulator_Enable(STPMU1_VREFDDR);
+    STPMU1_Regulator_Enable(STPMU1_VREFDDR);
 
     return RT_EOK;
 }

+ 202 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_pwr.c

@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-07-27     thread-liu        first version
+ */
+
+#include "board.h"
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.pwr"
+#include <drv_log.h>
+
+extern int lptim_start(void);
+extern int lptim_stop(void);
+
+static RCC_ClkInitTypeDef  RCC_ClkInit = {0};
+
+#define __WAIT_EVENT_TIMEOUT(__CONDITION__, __TIMEOUT_VAL__)                 \
+  do {                                                                       \
+    __IO uint32_t count = __TIMEOUT_VAL__ * (SystemCoreClock / 20U / 1000U); \
+    do                                                                       \
+    {                                                                        \
+      if (count-- == 0U)                                                     \
+      {                                                                      \
+        return  HAL_TIMEOUT;                                                 \
+      }                                                                      \
+    }                                                                        \
+    while (__CONDITION__ == 0U);                                             \
+  } while(0)
+
+/* Back up clock tree */
+static void backup_cm4_clocks(void)
+{
+    rt_uint32_t *pFLatency = NULL;
+
+    /* Back up MCU clock configuration */
+    HAL_RCC_GetClockConfig(&RCC_ClkInit, pFLatency);
+}
+
+/* Restore the CM4 clock source muxer and the CM4 prescaler. */
+rt_err_t restore_cm4_clock(void)
+{
+    /* Update SystemCoreClock variable */
+    SystemCoreClock = HAL_RCC_GetSystemCoreClockFreq();
+
+    /* Enable PLL3 if needed */
+    if (RCC_ClkInit.MCUInit.MCU_Clock == RCC_MCUSSOURCE_PLL3)
+    {
+    /* Enable PLL3 */
+    __HAL_RCC_PLL3_ENABLE();
+
+    /* Wait till PLL3 is ready */
+    __WAIT_EVENT_TIMEOUT(__HAL_RCC_GET_FLAG(RCC_FLAG_PLL3RDY), CLOCKSWITCH_TIMEOUT_VALUE);
+
+    /* Enable PLL3 outputs */
+    __HAL_RCC_PLL3CLKOUT_ENABLE(RCC_PLL3_DIVP | RCC_PLL3_DIVQ | RCC_PLL3_DIVR);
+    }
+
+    /* Configure MCU clock only */
+    __HAL_RCC_MCU_SOURCE(RCC_ClkInit.MCUInit.MCU_Clock);
+
+    /* Wait till MCU is ready */
+    __WAIT_EVENT_TIMEOUT(__HAL_RCC_GET_FLAG(RCC_FLAG_MCUSSRCRDY),
+                       CLOCKSWITCH_TIMEOUT_VALUE);
+
+    /* Update SystemCoreClock variable */
+    SystemCoreClock = HAL_RCC_GetSystemCoreClockFreq();
+
+    /* Reconfigure Systick */
+    if (HAL_InitTick(uwTickPrio) != HAL_OK)
+    {
+        return RT_ERROR;
+    }
+
+    /* Set MCU division factor */
+    __HAL_RCC_MCU_DIV(RCC_ClkInit.MCUInit.MCU_Div);
+
+    /* Wait till MCUDIV is ready */
+    __WAIT_EVENT_TIMEOUT(__HAL_RCC_GET_FLAG(RCC_FLAG_MCUDIVRDY),
+                       CLOCKSWITCH_TIMEOUT_VALUE);
+
+    /* Update SystemCoreClock variable */
+    SystemCoreClock = HAL_RCC_GetSystemCoreClockFreq();
+
+    /* Reconfigure Systick */
+    if (HAL_InitTick(uwTickPrio) != HAL_OK)
+    {
+        return RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+void RCC_WAKEUP_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    HAL_RCC_WAKEUP_IRQHandler();
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+void HAL_RCC_WAKEUP_Callback()
+{
+    if (__HAL_PWR_GET_FLAG(PWR_FLAG_STOP) == 1U)
+    {
+        __HAL_PWR_CLEAR_FLAG(PWR_FLAG_STOP);
+    }
+
+    restore_cm4_clock();
+    /* All level of ITs can interrupt */
+    __set_BASEPRI(0U);
+
+    rt_kprintf("system exit stop mode success!\n");
+}
+
+static void enter_sleep_mode(void)
+{
+    __set_BASEPRI((1) << (8 - __NVIC_PRIO_BITS));
+
+    lptim_start();
+
+    HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
+}
+
+static void enter_stop_mode(void)
+{
+    /*
+     * Only the IT with the highest priority (0 value) can interrupt.
+     * RCC_WAKEUP_IRQn IT is intended to have the highest priority and to be the
+     * only one IT having this value
+     * RCC_WAKEUP_IRQn is generated only when RCC is completely resumed from
+     * CSTOP (protection mechanism)
+     */
+    __set_BASEPRI((1) << (8 - __NVIC_PRIO_BITS));
+
+    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_STOP);
+    backup_cm4_clocks();
+    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
+}
+
+static void pm_wackup_key_init(void)
+{
+    GPIO_InitTypeDef GPIO_InitStruct = {0};
+
+    __HAL_RCC_GPIOA_CLK_ENABLE();
+
+    GPIO_InitStruct.Pin = GPIO_PIN_13;
+    GPIO_InitStruct.Pull = GPIO_PULLUP;
+    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    HAL_NVIC_SetPriority(EXTI13_IRQn, 0x01, 0);
+    HAL_NVIC_EnableIRQ(EXTI13_IRQn);
+}
+
+int drv_pm_hw_init(void)
+{
+    pm_wackup_key_init();
+
+    return RT_EOK;
+}
+INIT_BOARD_EXPORT(drv_pm_hw_init);
+
+static int pwr_sample(int argc, char *argv[])
+{
+    if (argc > 1)
+    {
+        if (!rt_strcmp(argv[1], "stop"))
+        {
+           rt_kprintf("system will enter stop mode! you can press USER2 button to exit this mode\n");
+           enter_stop_mode();
+           return RT_EOK;
+
+        }
+        else if (!rt_strcmp(argv[1], "sleep"))
+        {
+           rt_kprintf("system will enter sleep mode! lptim1 will wake up the system\n");
+           enter_sleep_mode();
+           return RT_EOK;
+        }
+        else
+        {
+            goto _exit;
+        }
+    }
+_exit:
+    {
+        rt_kprintf("Usage:\n");
+        rt_kprintf("pwr_sample stop      - system enter stop mode\n");
+        rt_kprintf("pwr_sample sleep     - system enter sleep mode\n");
+    }
+
+    return -RT_ERROR;
+}
+MSH_CMD_EXPORT(pwr_sample, enter low power mode sample);

+ 180 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_qspi_flash.c

@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-07-07     thread-liu   first version
+ */
+ 
+#include <board.h>
+#include <drv_qspi.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <finsh.h>
+
+#ifdef BSP_USING_QSPI_FLASH
+
+#include "spi_flash.h"
+#include "spi_flash_sfud.h"
+
+/**
+* @brief QSPI MSP Initialization
+* This function configures the hardware resources used in this example
+* @param hqspi: QSPI handle pointer
+* @retval None
+*/
+void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi)
+{
+  GPIO_InitTypeDef GPIO_InitStruct = {0};
+  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+  
+  if(hqspi->Instance==QUADSPI)
+  {
+  /* USER CODE BEGIN QUADSPI_MspInit 0 */
+    if (IS_ENGINEERING_BOOT_MODE())
+    {
+        PeriphClkInit.Sdmmc12ClockSelection = RCC_QSPICLKSOURCE_ACLK;
+        PeriphClkInit.PeriphClockSelection  = RCC_PERIPHCLK_QSPI;
+        if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
+        {
+            Error_Handler();
+        }
+    }
+   /* USER CODE END QUADSPI_MspInit 0 */
+    /* Peripheral clock enable */
+    __HAL_RCC_QSPI_CLK_ENABLE();
+  
+    __HAL_RCC_GPIOF_CLK_ENABLE();
+    __HAL_RCC_GPIOB_CLK_ENABLE();
+    /**QUADSPI GPIO Configuration    
+    PF6     ------> QUADSPI_BK1_IO3
+    PF7     ------> QUADSPI_BK1_IO2
+    PF8     ------> QUADSPI_BK1_IO0
+    PF9     ------> QUADSPI_BK1_IO1
+    PF10     ------> QUADSPI_CLK
+    PB6     ------> QUADSPI_BK1_NCS 
+    */
+    GPIO_InitStruct.Pin = GPIO_PIN_10;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
+    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
+    
+    GPIO_InitStruct.Pin = GPIO_PIN_6;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_PULLUP;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
+    GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+    
+    GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_6;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
+    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
+    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
+
+    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
+    GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
+    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
+
+    /**QUADSPI GPIO Configuration
+    PC0     ------> QUADSPI_BK2_NCS
+    PH3     ------> QUADSPI_BK2_IO1
+    PG7     ------> QUADSPI_BK2_IO3
+    PG10     ------> QUADSPI_BK2_IO2
+    PH2     ------> QUADSPI_BK2_IO0
+    */
+    GPIO_InitStruct.Pin = GPIO_PIN_0;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_PULLUP;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
+    GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
+    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_2;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
+    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
+    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
+    
+    GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_10;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
+    GPIO_InitStruct.Alternate = GPIO_AF11_QUADSPI;
+    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
+    
+  /* USER CODE BEGIN QUADSPI_MspInit 1 */
+
+  /* USER CODE END QUADSPI_MspInit 1 */
+  }
+}
+
+/**
+* @brief QSPI MSP De-Initialization
+* This function freeze the hardware resources used in this example
+* @param hqspi: QSPI handle pointer
+* @retval None
+*/
+void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* hqspi)
+{
+  if(hqspi->Instance==QUADSPI)
+  {
+  /* USER CODE BEGIN QUADSPI_MspDeInit 0 */
+
+  /* USER CODE END QUADSPI_MspDeInit 0 */
+    /* Peripheral clock disable */
+    __HAL_RCC_QSPI_CLK_DISABLE();
+  
+    /**QUADSPI GPIO Configuration    
+    PC0     ------> QUADSPI_BK2_NCS
+    PF10     ------> QUADSPI_CLK
+    PB6     ------> QUADSPI_BK1_NCS
+    PH3     ------> QUADSPI_BK2_IO1
+    PG7     ------> QUADSPI_BK2_IO3
+    PG10     ------> QUADSPI_BK2_IO2
+    PF7     ------> QUADSPI_BK1_IO2
+    PF6     ------> QUADSPI_BK1_IO3
+    PH2     ------> QUADSPI_BK2_IO0
+    PF8     ------> QUADSPI_BK1_IO0
+    PF9     ------> QUADSPI_BK1_IO1 
+    */
+    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0);
+    
+    HAL_GPIO_DeInit(GPIOF, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10);
+
+    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6);
+
+    HAL_GPIO_DeInit(GPIOH, GPIO_PIN_3|GPIO_PIN_2);
+
+    HAL_GPIO_DeInit(GPIOG, GPIO_PIN_7|GPIO_PIN_10);
+    
+  /* USER CODE BEGIN QUADSPI_MspDeInit 1 */
+
+  /* USER CODE END QUADSPI_MspDeInit 1 */
+  }
+
+}
+
+static int rt_hw_qspi_flash_with_sfud_init(void)
+{
+    stm32_qspi_bus_attach_device("qspi1", "qspi10", RT_NULL, 4, RT_NULL, RT_NULL);
+    /* init MX25L51245G */
+    if (RT_NULL == rt_sfud_flash_probe("MX25L51245G", "qspi10"))
+    {
+        return -RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+INIT_DEVICE_EXPORT(rt_hw_qspi_flash_with_sfud_init);
+
+#endif /* BSP_USING_QSPI_FLASH */

+ 111 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_rs485.c

@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-10-24     thread-liu        first version
+ */
+
+#include <board.h>
+#include "drv_rs485.h"
+
+#ifdef BSP_USING_RS485
+
+#define RS485_OUT       rt_pin_write(BSP_RS485_RTS_PIN, PIN_HIGH)
+#define RS485_IN        rt_pin_write(BSP_RS485_RTS_PIN, PIN_LOW)
+
+static rt_device_t serial = {0};
+static struct rt_semaphore rx_sem = {0};
+
+/* uart send data callback function */
+static rt_err_t rs485_output(rt_device_t dev, void * buffer)
+{
+    return RT_EOK;
+}
+
+/* uart receive data callback function */
+static rt_err_t rs485_input(rt_device_t dev, rt_size_t size)
+{
+    rt_sem_release(&rx_sem);
+    
+    return RT_EOK;
+}
+
+/* send string */
+int rs485_send_data(char *tbuf, rt_uint16_t t_len)
+{
+    /* change rs485 mode */
+    RS485_OUT;
+    
+    /* send data */
+    rt_device_write(serial, 0, tbuf, t_len);
+    
+    /* change rs485 mode */
+    RS485_IN;
+    
+    return RT_EOK;
+}
+
+static void rs485_thread_entry(void *parameter)
+{
+    char ch;
+
+    while (1)
+    {
+        /* A byte of data is read from a serial port, and if it is not read, it waits for the received semaphore */
+        while (rt_device_read(serial, -1, &ch, 1) != 1)
+        {
+            rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
+        }
+        
+        /* The data read through the serial port output dislocation */
+        ch = ch + 1;
+        
+        /* send char */
+        rs485_send_data(&ch, 1);
+    }
+}
+
+/* rs485 rts pin init */
+static int rs485_init(void)
+{
+    /* find uart device */
+    serial = rt_device_find(RS485_UART_DEVICE_NAME);
+    if (!serial)
+    {
+        rt_kprintf("find %s failed!\n", RS485_UART_DEVICE_NAME);
+        return RT_ERROR;
+    }  
+
+    rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
+
+    /* set receive data callback function */
+    rt_device_set_rx_indicate(serial, rs485_input);
+    
+    /* set the send completion callback function */
+    rt_device_set_tx_complete(serial, rs485_output);
+        
+    rt_pin_mode(BSP_RS485_RTS_PIN, PIN_MODE_OUTPUT);
+    
+    RS485_IN;
+    
+    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
+    /* create rs485 thread */
+    rt_thread_t thread = rt_thread_create("rs485", rs485_thread_entry, RT_NULL, 1024, 25, 10);
+
+    if (thread != RT_NULL)
+    {
+        rt_thread_startup(thread);
+    }
+    else
+    {
+        return RT_ERROR;
+    }
+    
+    return RT_EOK;    
+}
+INIT_DEVICE_EXPORT(rs485_init);
+
+#endif /* bsp_using_RS485 */

+ 25 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_rs485.h

@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-10-24     thread-liu        first version
+ */
+
+#ifndef __DRV_RS485_H__
+#define __DRV_RS485_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RS485_SEND_MODE      0
+#define RS485_RECV_MODE      1
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* drv_rs485.h */

+ 303 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_spdifrx.c

@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-07-28     thread-liu        the first version
+ */
+
+#include "board.h"
+
+#if defined(BSP_USING_SPDIFRX)
+#include "drv_spdifrx.h"
+
+#define DRV_DEBUG
+#define LOG_TAG             "drv.spdifrx"
+#include <drv_log.h>
+
+struct stm32_spdifrx
+{
+    struct rt_device dev;  
+    SPDIFRX_HandleTypeDef spdifrx;
+    SAI_HandleTypeDef sai4;
+    volatile rt_uint8_t complate;
+};
+static struct stm32_spdifrx rt_spdifrx = {0};
+
+extern DMA_HandleTypeDef hdma_spdifrx_rx;
+extern DMA_HandleTypeDef hdma_sai4_a;
+
+static void sai4a_init(SAI_HandleTypeDef* sai)
+{
+    sai->Instance                 = SAI4_Block_A;
+    sai->Init.Protocol            = SAI_SPDIF_PROTOCOL;
+    sai->Init.AudioMode           = SAI_MODEMASTER_TX;
+    sai->Init.Synchro             = SAI_ASYNCHRONOUS;
+    sai->Init.OutputDrive         = SAI_OUTPUTDRIVE_DISABLE;
+    sai->Init.FIFOThreshold       = SAI_FIFOTHRESHOLD_EMPTY;
+    sai->Init.AudioFrequency      = SAI_AUDIO_FREQUENCY_96K;
+    sai->Init.MonoStereoMode      = SAI_STEREOMODE;
+    sai->Init.CompandingMode      = SAI_NOCOMPANDING;
+    sai->Init.PdmInit.Activation  = DISABLE;
+    sai->Init.PdmInit.MicPairsNbr = 0;
+    sai->Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
+    sai->Init.DataSize            = SAI_DATASIZE_24;
+    sai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
+    sai->Init.ClockStrobing       = SAI_CLOCKSTROBING_FALLINGEDGE;
+    
+    sai->FrameInit.FrameLength       = 64;
+    sai->FrameInit.ActiveFrameLength = 32;
+    sai->FrameInit.FSDefinition      = SAI_FS_STARTFRAME;
+    sai->FrameInit.FSPolarity        = SAI_FS_ACTIVE_LOW;
+    sai->FrameInit.FSOffset          = SAI_FS_FIRSTBIT;
+
+    sai->SlotInit.FirstBitOffset = 0;
+    sai->SlotInit.SlotSize       = SAI_SLOTSIZE_DATASIZE;
+    sai->SlotInit.SlotNumber     = 4;
+    sai->SlotInit.SlotActive     = SAI_SLOTACTIVE_ALL;
+    
+    if (HAL_SAI_Init(sai) != HAL_OK)
+    {
+        Error_Handler();
+    }
+}
+
+void DMA1_Stream7_IRQHandler(void)
+{ 
+    /* enter interrupt */
+    rt_interrupt_enter();
+    
+    HAL_DMA_IRQHandler(&hdma_spdifrx_rx);
+    
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+void DMA1_Stream2_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    
+    HAL_DMA_IRQHandler(&hdma_sai4_a);
+    
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+void HAL_SPDIFRX_RxCpltCallback(SPDIFRX_HandleTypeDef *hspdif)
+{
+    rt_spdifrx.complate = SET;
+}
+
+static rt_err_t _init(rt_device_t dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+    struct stm32_spdifrx *device = (struct stm32_spdifrx *)dev;
+    
+    device->spdifrx.Instance = SPDIFRX;
+    HAL_SPDIFRX_DeInit(&device->spdifrx); 
+    
+    device->spdifrx.Init.InputSelection     = SPDIFRX_INPUT_IN1;
+    device->spdifrx.Init.Retries            = SPDIFRX_MAXRETRIES_15;
+    device->spdifrx.Init.WaitForActivity    = SPDIFRX_WAITFORACTIVITY_ON;
+    device->spdifrx.Init.ChannelSelection   = SPDIFRX_CHANNEL_A;
+    device->spdifrx.Init.DataFormat         = SPDIFRX_DATAFORMAT_MSB;
+    device->spdifrx.Init.StereoMode         = SPDIFRX_STEREOMODE_ENABLE;
+    device->spdifrx.Init.PreambleTypeMask   = SPDIFRX_PREAMBLETYPEMASK_ON;
+    device->spdifrx.Init.ChannelStatusMask  = SPDIFRX_CHANNELSTATUS_ON;  
+    
+    if (HAL_SPDIFRX_Init(&device->spdifrx) != HAL_OK)
+    {
+        return RT_ERROR;
+    }
+    
+    sai4a_init(&device->sai4);
+    
+    rt_spdifrx.complate = RESET;
+    
+    return RT_EOK;
+}
+
+static rt_err_t _open(rt_device_t dev, rt_uint16_t oflag)
+{
+    RT_ASSERT(dev != RT_NULL);
+    
+    return RT_EOK;
+}
+
+static rt_err_t _close(rt_device_t dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+    
+    return RT_EOK;
+}
+
+static rt_size_t _read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+    rt_uint32_t tickstart = 0;
+    
+    RT_ASSERT(dev != RT_NULL);
+    struct stm32_spdifrx *device = (struct stm32_spdifrx *)dev;
+    rt_err_t result = RT_EOK;
+    
+    result = HAL_SPDIFRX_ReceiveDataFlow_DMA(&device->spdifrx, (uint32_t *)buffer, size);
+    if (result != HAL_OK)
+    {
+        return 0;
+    }
+    
+    if(device->spdifrx.ErrorCode != HAL_SPDIFRX_ERROR_NONE)
+    {
+        return 0;
+    }
+    
+    tickstart = rt_tick_get();
+    while (rt_spdifrx.complate == RESET)
+    {
+        if (rt_tick_get() - tickstart > 0xFFFF)
+        {
+            return 0;
+        }
+    }
+    
+    rt_spdifrx.complate = RESET;
+    
+    return size;
+}
+
+static rt_size_t _write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    struct stm32_spdifrx *device = (struct stm32_spdifrx *)dev;
+    rt_err_t result = RT_EOK;
+    
+    result = HAL_SAI_Transmit_DMA(&device->sai4, (rt_uint8_t *)buffer, size);
+    if (result != HAL_OK)
+    {
+        return RT_ERROR;
+    }
+    
+    return RT_EOK;
+}
+
+static rt_err_t _control(rt_device_t dev, int cmd, void *args)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    return RT_EOK;
+}
+
+int spdifrx_init(void)
+{
+    rt_spdifrx.dev.type      = RT_Device_Class_Miscellaneous;
+    rt_spdifrx.dev.init      = _init;
+    rt_spdifrx.dev.open      = _open;
+    rt_spdifrx.dev.close     = _close;
+    rt_spdifrx.dev.read      = _read;
+    rt_spdifrx.dev.write     = _write;
+    rt_spdifrx.dev.control   = _control;
+    rt_spdifrx.dev.user_data = RT_NULL;
+
+    rt_device_register(&rt_spdifrx.dev, "spdifrx", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
+    rt_device_init(&rt_spdifrx.dev);
+    
+    LOG_I("spdifrx init success!");
+    
+    return RT_EOK; 
+}
+INIT_DEVICE_EXPORT(spdifrx_init);
+
+#ifdef FINSH_USING_MSH
+#include <finsh.h>
+
+#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
+static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
+{
+    unsigned char *buf = (unsigned char *)ptr;
+    int i, j;
+
+    for (i = 0; i < buflen; i += 16)
+    {
+        rt_kprintf("%08X: ", i);
+
+        for (j = 0; j < 16; j++)
+            if (i + j < buflen)
+                rt_kprintf("%02X ", buf[i + j]);
+            else
+                rt_kprintf("   ");
+        rt_kprintf(" ");
+
+        for (j = 0; j < 16; j++)
+            if (i + j < buflen)
+                rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
+        rt_kprintf("\n");
+    }
+}
+
+static int spdifrx_sample(int argc, char **argv)
+{
+    extern SAI_HandleTypeDef hsai_block4_a;
+
+    if (argc != 1)
+    {
+        rt_kprintf("Usage:\n");
+        rt_kprintf("spdifrx_sample\n");
+        return -1;
+    }
+    
+    /* 16 bit Data Buffer for Transmission */ 
+    static rt_uint16_t tx_buffer[64] = {
+    0x5152, 0x5354, 0x5556, 0x5758, 0x595A, 0x5B5C, 0x5D5E, 0x5F60,
+    0x6162, 0x6364, 0x6566, 0x6768, 0x696A, 0x6B6C, 0x6D6E, 0x6F70,
+    0x7172, 0x7374, 0x7576, 0x7778, 0x797A, 0x7B7C, 0x7D7E, 0x7F80,
+    0x8182, 0x8384, 0x8586, 0x8788, 0x898A, 0x8B8C, 0x8D8E, 0x8F90,
+    0x5152, 0x5354, 0x5556, 0x5758, 0x595A, 0x5B5C, 0x5D5E, 0x5F60,
+    0x6162, 0x6364, 0x6566, 0x6768, 0x696A, 0x6B6C, 0x6D6E, 0x6F70,
+    0x7172, 0x7374, 0x7576, 0x7778, 0x797A, 0x7B7C, 0x7D7E, 0x7F80,
+    0x8182, 0x8384, 0x8586, 0x8788, 0x898A, 0x8B8C, 0x8D8E, 0x8F90};
+    
+    static rt_uint32_t *rx_buffer = NULL;
+    rt_uint8_t size = 64;
+    struct rt_device *dev = RT_NULL;
+    
+    dev = rt_device_find("spdifrx");
+    if (dev == RT_NULL)
+    {
+        rt_kprintf("can't find spdifrx device!\n");
+    }
+
+    rt_device_open(dev, RT_DEVICE_OFLAG_RDWR);
+    
+    rt_kprintf("spdifrx test tx data : \n");
+    dump_hex((rt_uint8_t *)tx_buffer, size);
+    
+    rx_buffer = (rt_uint32_t *)rt_malloc(size);
+    
+    rt_device_write(dev, 0, tx_buffer, size);
+    rt_device_read(dev, 0, rx_buffer, size);
+    
+    /* Compare the received data with the expected one */    
+    while (size--)
+    {
+        if (((rx_buffer[size] & 0x00ffff00) >>  8) != (tx_buffer[size]))
+        {
+            rt_kprintf("spdirex loopback mode test failed!\n");
+            
+            return RT_ERROR;
+        }
+    }
+    
+    rt_kprintf("spdifrx rx : \n");
+    dump_hex((rt_uint8_t *)rx_buffer, size);
+    
+    rt_kprintf("spdirex loopback mode test success!\n");
+    
+    return RT_EOK;
+}
+MSH_CMD_EXPORT(spdifrx_sample, spdifrx loopback test);
+#endif
+
+#endif

+ 0 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_spdifrx.h


+ 115 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_wwdg.c

@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-06-18     thread-liu        the first version
+ */
+
+#include <board.h>
+
+#if defined(BSP_USING_WWDG)
+#include "drv_config.h"
+#include <string.h>
+#include <stdlib.h>
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.wwg"
+#include <drv_log.h>
+
+#define LED5_PIN  GET_PIN(A, 14)
+
+static rt_uint8_t feed_flag = 0;
+static WWDG_HandleTypeDef hwwdg1;  
+
+void WWDG1_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    
+    HAL_WWDG_IRQHandler(&hwwdg1);
+    
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)
+{
+    if(hwwdg->Instance==WWDG1)
+    {
+        if (feed_flag)
+        {
+            HAL_WWDG_Refresh(&hwwdg1);
+            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_14);
+        }
+    }
+}
+
+static void wwdg_init()
+{
+    rt_pin_mode(LED5_PIN, PIN_MODE_OUTPUT);
+        
+    hwwdg1.Instance       = WWDG1;
+    hwwdg1.Init.Prescaler = WWDG_PRESCALER_8;
+    hwwdg1.Init.Window    = 0X5F;
+    hwwdg1.Init.Counter   = 0x7F;
+    hwwdg1.Init.EWIMode   = WWDG_EWI_ENABLE;
+      
+    if (HAL_WWDG_Init(&hwwdg1) != HAL_OK)
+    {
+        Error_Handler();
+    }
+    
+    feed_flag = 1;
+}
+
+static void wwdg_control(uint8_t pre_value)
+{
+    if(pre_value > 7)
+    {
+       pre_value = 7; 
+    }
+    hwwdg1.Instance->CFR &= ~(7 << 11);     /* clear WDGTB[2:0] */
+    hwwdg1.Instance->CFR |= pre_value << 11; /* set WDGTB[2:0] */	
+}
+
+static void wwdg_stop(void)
+{
+    feed_flag = 0;
+}
+
+static int wwdg_sample(int argc, char *argv[])
+{
+    if (argc > 1)
+    {
+        if (!strcmp(argv[1], "run"))
+        { 
+            wwdg_init();
+        }
+        else if (!strcmp(argv[1], "set"))
+        {
+            if (argc > 2)
+            {
+                wwdg_control(atoi(argv[2]));
+            }     
+        }
+        else if (!strcmp(argv[1], "stop"))
+        {
+            wwdg_stop();
+        }
+    }
+    else
+    {
+        rt_kprintf("Usage:\n");
+        rt_kprintf("wwdg_sample run            - open wwdg, when feed wwdg in wwdg irq, the LD5 will blink\n");
+        rt_kprintf("wwdg_sample stop           - stop to feed wwdg, system will reset\n");
+        rt_kprintf("wwdg_sample set            - set the wwdg prescaler, wwdg_sample set [0 - 7]\n");
+    }
+
+    return RT_EOK;
+}
+MSH_CMD_EXPORT(wwdg_sample, window watch dog sample);
+
+#endif

+ 1602 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/mfxstm32l152.c

@@ -0,0 +1,1602 @@
+/** 
+  ******************************************************************************
+  * @file    mfxstm32l152.c
+  * @author  MCD Application Team
+  * @brief   This file provides a set of functions needed to manage the MFXSTM32L152
+  *          IO Expander devices.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+  *
+  ******************************************************************************
+  */  
+
+/* Includes ------------------------------------------------------------------*/
+#include "mfxstm32l152.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup Component
+  * @{
+  */ 
+  
+/** @defgroup MFXSTM32L152
+  * @{
+  */   
+  
+/* Private typedef -----------------------------------------------------------*/
+
+/** @defgroup MFXSTM32L152_Private_Types_Definitions
+  * @{
+  */ 
+ 
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup MFXSTM32L152_Private_Defines
+  * @{
+  */ 
+#define MFXSTM32L152_MAX_INSTANCE         3
+
+/* Private macro -------------------------------------------------------------*/
+
+/** @defgroup MFXSTM32L152_Private_Macros
+  * @{
+  */ 
+  
+/* Private variables ---------------------------------------------------------*/
+
+/** @defgroup MFXSTM32L152_Private_Variables
+  * @{
+  */ 
+
+/* Touch screen driver structure initialization */  
+TS_DrvTypeDef mfxstm32l152_ts_drv = 
+{
+  mfxstm32l152_Init,
+  mfxstm32l152_ReadID,
+  mfxstm32l152_Reset,
+  
+  mfxstm32l152_TS_Start,
+  mfxstm32l152_TS_DetectTouch,
+  mfxstm32l152_TS_GetXY,
+  
+  mfxstm32l152_TS_EnableIT,
+  mfxstm32l152_TS_ClearIT,
+  mfxstm32l152_TS_ITStatus,
+  mfxstm32l152_TS_DisableIT,
+};
+
+/* IO driver structure initialization */ 
+IO_DrvTypeDef mfxstm32l152_io_drv = 
+{
+  mfxstm32l152_Init,
+  mfxstm32l152_ReadID,
+  mfxstm32l152_Reset,
+  
+  mfxstm32l152_IO_Start,
+  mfxstm32l152_IO_Config,
+  mfxstm32l152_IO_WritePin,
+  mfxstm32l152_IO_ReadPin,
+  
+  mfxstm32l152_IO_EnableIT,
+  mfxstm32l152_IO_DisableIT,
+  mfxstm32l152_IO_ITStatus,
+  mfxstm32l152_IO_ClearIT,
+};
+
+/* IDD driver structure initialization */
+IDD_DrvTypeDef mfxstm32l152_idd_drv =
+{
+  mfxstm32l152_Init,
+  mfxstm32l152_DeInit,
+  mfxstm32l152_ReadID,
+  mfxstm32l152_Reset,
+  mfxstm32l152_LowPower,
+  mfxstm32l152_WakeUp,
+
+  mfxstm32l152_IDD_Start,
+  mfxstm32l152_IDD_Config,
+  mfxstm32l152_IDD_GetValue,
+
+  mfxstm32l152_IDD_EnableIT,
+  mfxstm32l152_IDD_ClearIT,
+  mfxstm32l152_IDD_GetITStatus,
+  mfxstm32l152_IDD_DisableIT,
+
+  mfxstm32l152_Error_EnableIT,
+  mfxstm32l152_Error_ClearIT,
+  mfxstm32l152_Error_GetITStatus,
+  mfxstm32l152_Error_DisableIT,
+  mfxstm32l152_Error_ReadSrc,
+  mfxstm32l152_Error_ReadMsg
+};
+
+
+/* mfxstm32l152 instances by address */
+uint8_t mfxstm32l152[MFXSTM32L152_MAX_INSTANCE] = {0};
+/**
+  * @}
+  */ 
+    
+/* Private function prototypes -----------------------------------------------*/
+
+/** @defgroup MFXSTM32L152_Private_Function_Prototypes
+  * @{
+  */
+static uint8_t mfxstm32l152_GetInstance(uint16_t DeviceAddr); 
+static uint8_t  mfxstm32l152_ReleaseInstance(uint16_t DeviceAddr);
+static void mfxstm32l152_reg24_setPinValue(uint16_t DeviceAddr, uint8_t RegisterAddr, uint32_t PinPosition, uint8_t PinValue );
+
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup MFXSTM32L152_Private_Functions
+  * @{
+  */
+
+/**
+  * @brief  Initialize the mfxstm32l152 and configure the needed hardware resources
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None
+  */
+void mfxstm32l152_Init(uint16_t DeviceAddr)
+{
+  uint8_t instance;
+  uint8_t empty;
+  
+  /* Check if device instance already exists */
+  instance = mfxstm32l152_GetInstance(DeviceAddr);
+  
+  /* To prevent double initialization */
+  if(instance == 0xFF)
+  {
+    /* Look for empty instance */
+    empty = mfxstm32l152_GetInstance(0);
+    
+    if(empty < MFXSTM32L152_MAX_INSTANCE)
+    {
+      /* Register the current device instance */
+      mfxstm32l152[empty] = DeviceAddr;
+      
+      /* Initialize IO BUS layer */
+      MFX_IO_Init();
+    }
+  }
+  
+  mfxstm32l152_SetIrqOutPinPolarity(DeviceAddr, MFXSTM32L152_OUT_PIN_POLARITY_HIGH);
+  mfxstm32l152_SetIrqOutPinType(DeviceAddr, MFXSTM32L152_OUT_PIN_TYPE_PUSHPULL);
+}
+
+/**
+  * @brief  DeInitialize the mfxstm32l152 and unconfigure the needed hardware resources
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None
+  */
+void mfxstm32l152_DeInit(uint16_t DeviceAddr)
+{
+  uint8_t instance;
+  
+  /* release existing instance */
+  instance = mfxstm32l152_ReleaseInstance(DeviceAddr);
+  
+  /* De-Init only if instance was previously registered */
+  if(instance != 0xFF)
+  {
+    /* De-Initialize IO BUS layer */
+    MFX_IO_DeInit();
+  }
+}
+
+/**
+  * @brief  Reset the mfxstm32l152 by Software.
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @retval None
+  */
+void mfxstm32l152_Reset(uint16_t DeviceAddr)
+{
+  /* Soft Reset */  
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL, MFXSTM32L152_SWRST);
+
+  /* Wait for a delay to ensure registers erasing */
+  rt_thread_delay(10);
+}
+
+/**
+  * @brief  Put mfxstm32l152 Device in Low Power standby mode
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None
+  */
+void  mfxstm32l152_LowPower(uint16_t DeviceAddr)
+{
+  /* Enter standby mode */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL, MFXSTM32L152_STANDBY);
+
+  /* enable wakeup pin */
+  MFX_IO_EnableWakeupPin();
+}
+
+/**
+  * @brief  WakeUp mfxstm32l152 from standby mode
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None
+  */
+void  mfxstm32l152_WakeUp(uint16_t DeviceAddr)
+{
+  uint8_t instance;
+  
+  /* Check if device instance already exists */
+  instance = mfxstm32l152_GetInstance(DeviceAddr);
+  
+  /* if instance does not exist, first initialize pins*/
+  if(instance == 0xFF)
+  {
+    /* enable wakeup pin */
+    MFX_IO_EnableWakeupPin();
+  }
+
+  /* toggle wakeup pin */
+  MFX_IO_Wakeup();
+}
+
+/**
+  * @brief  Read the MFXSTM32L152 IO Expander device ID.
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @retval The Device ID (two bytes).
+  */
+uint16_t mfxstm32l152_ReadID(uint16_t DeviceAddr)
+{
+  uint8_t id;
+  
+  /* Wait for a delay to ensure the state of registers */
+  rt_thread_mdelay(1);
+
+  /* Initialize IO BUS layer */
+  MFX_IO_Init();
+  
+  id = MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_ID);
+  
+  /* Return the device ID value */
+  return (id);
+}
+
+/**
+  * @brief  Read the MFXSTM32L152 device firmware version.
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @retval The Device FW version (two bytes).
+  */
+uint16_t mfxstm32l152_ReadFwVersion(uint16_t DeviceAddr)
+{
+  uint8_t  data[2];
+
+  MFX_IO_ReadMultiple((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_FW_VERSION_MSB, data, sizeof(data)) ;
+
+  /* Recompose MFX firmware value */
+  return ((data[0] << 8) | data[1]);
+}
+
+/**
+  * @brief  Enable the interrupt mode for the selected IT source
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @param Source: The interrupt source to be configured, could be:
+  *   @arg  MFXSTM32L152_IRQ_GPIO: IO interrupt 
+  *   @arg  MFXSTM32L152_IRQ_IDD : IDD interrupt    
+  *   @arg  MFXSTM32L152_IRQ_ERROR : Error interrupt    
+  *   @arg  MFXSTM32L152_IRQ_TS_DET : Touch Screen Controller Touch Detected interrupt  
+  *   @arg  MFXSTM32L152_IRQ_TS_NE : Touch Screen FIFO Not Empty  
+  *   @arg  MFXSTM32L152_IRQ_TS_TH : Touch Screen FIFO threshold triggered  
+  *   @arg  MFXSTM32L152_IRQ_TS_FULL : Touch Screen FIFO Full  
+  *   @arg  MFXSTM32L152_IRQ_TS_OVF : Touch Screen FIFO Overflow  
+  * @retval None
+  */  
+void mfxstm32l152_EnableITSource(uint16_t DeviceAddr, uint8_t Source)
+{
+  uint8_t tmp = 0;
+  
+  /* Get the current value of the INT_EN register */
+  tmp = MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_SRC_EN);
+
+  /* Set the interrupts to be Enabled */    
+  tmp |= Source; 
+  
+  /* Set the register */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_SRC_EN, tmp);
+}
+
+/**
+  * @brief  Disable the interrupt mode for the selected IT source
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @param  Source: The interrupt source to be configured, could be:
+  *   @arg  MFXSTM32L152_IRQ_GPIO: IO interrupt 
+  *   @arg  MFXSTM32L152_IRQ_IDD : IDD interrupt    
+  *   @arg  MFXSTM32L152_IRQ_ERROR : Error interrupt    
+  *   @arg  MFXSTM32L152_IRQ_TS_DET : Touch Screen Controller Touch Detected interrupt  
+  *   @arg  MFXSTM32L152_IRQ_TS_NE : Touch Screen FIFO Not Empty  
+  *   @arg  MFXSTM32L152_IRQ_TS_TH : Touch Screen FIFO threshold triggered  
+  *   @arg  MFXSTM32L152_IRQ_TS_FULL : Touch Screen FIFO Full  
+  *   @arg  MFXSTM32L152_IRQ_TS_OVF : Touch Screen FIFO Overflow  
+  * @retval None
+  */
+void mfxstm32l152_DisableITSource(uint16_t DeviceAddr, uint8_t Source)
+{
+  uint8_t tmp = 0;
+  
+  /* Get the current value of the INT_EN register */
+  tmp = MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_SRC_EN);
+
+  /* Set the interrupts to be Enabled */    
+  tmp &= ~Source; 
+  
+  /* Set the register */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_SRC_EN, tmp);
+}
+
+
+/**
+  * @brief  Returns the selected Global interrupt source pending bit value
+  * @param  DeviceAddr: Device address on communication Bus. 
+  * @param  Source: the Global interrupt source to be checked, could be:
+  *   @arg  MFXSTM32L152_IRQ_GPIO: IO interrupt 
+  *   @arg  MFXSTM32L152_IRQ_IDD : IDD interrupt    
+  *   @arg  MFXSTM32L152_IRQ_ERROR : Error interrupt    
+  *   @arg  MFXSTM32L152_IRQ_TS_DET : Touch Screen Controller Touch Detected interrupt  
+  *   @arg  MFXSTM32L152_IRQ_TS_NE : Touch Screen FIFO Not Empty  
+  *   @arg  MFXSTM32L152_IRQ_TS_TH : Touch Screen FIFO threshold triggered  
+  *   @arg  MFXSTM32L152_IRQ_TS_FULL : Touch Screen FIFO Full  
+  *   @arg  MFXSTM32L152_IRQ_TS_OVF : Touch Screen FIFO Overflow  
+  * @retval The value of the checked Global interrupt source status.
+  */
+uint8_t mfxstm32l152_GlobalITStatus(uint16_t DeviceAddr, uint8_t Source)
+{
+  /* Return the global IT source status (pending or not)*/
+  return((MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_PENDING) & Source));
+}
+
+/**
+  * @brief  Clear the selected Global interrupt pending bit(s)
+  * @param  DeviceAddr: Device address on communication Bus. 
+  * @param  Source: the Global interrupt source to be cleared, could be any combination
+  *         of the below values. The acknowledge signal for MFXSTM32L152_GPIOs configured in input 
+  *         with interrupt is not on this register but in IRQ_GPI_ACK1, IRQ_GPI_ACK2 registers.          
+  *   @arg  MFXSTM32L152_IRQ_IDD : IDD interrupt    
+  *   @arg  MFXSTM32L152_IRQ_ERROR : Error interrupt    
+  *   @arg  MFXSTM32L152_IRQ_TS_DET : Touch Screen Controller Touch Detected interrupt  
+  *   @arg  MFXSTM32L152_IRQ_TS_NE : Touch Screen FIFO Not Empty  
+  *   @arg  MFXSTM32L152_IRQ_TS_TH : Touch Screen FIFO threshold triggered  
+  *   @arg  MFXSTM32L152_IRQ_TS_FULL : Touch Screen FIFO Full  
+  *   @arg  MFXSTM32L152_IRQ_TS_OVF : Touch Screen FIFO Overflow  
+  *  /\/\ IMPORTANT NOTE /\/\ must not use MFXSTM32L152_IRQ_GPIO as argument, see IRQ_GPI_ACK1 and IRQ_GPI_ACK2 registers 
+  * @retval None
+  */
+void mfxstm32l152_ClearGlobalIT(uint16_t DeviceAddr, uint8_t Source)
+{
+  /* Write 1 to the bits that have to be cleared */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_ACK, Source);
+}
+
+/**
+  * @brief  Set the global interrupt Polarity of IRQ_OUT_PIN.
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @param  Polarity: the IT mode polarity, could be one of the following values:
+  *   @arg  MFXSTM32L152_OUT_PIN_POLARITY_LOW: Interrupt output line is active Low edge      
+  *   @arg  MFXSTM32L152_OUT_PIN_POLARITY_HIGH: Interrupt line output is active High edge              
+  * @retval None
+  */
+void mfxstm32l152_SetIrqOutPinPolarity(uint16_t DeviceAddr, uint8_t Polarity)
+{
+  uint8_t tmp = 0;
+  
+  /* Get the current register value */ 
+  tmp = MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_MFX_IRQ_OUT);
+  
+  /* Mask the polarity bits */
+  tmp &= ~(uint8_t)0x02;
+    
+  /* Modify the Interrupt Output line configuration */
+  tmp |= Polarity;
+  
+  /* Set the new register value */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_MFX_IRQ_OUT, tmp);
+
+  /* Wait for 1 ms for MFX to change IRQ_out pin config, before activate it */
+  rt_thread_delay(1);
+  
+}
+
+/**
+  * @brief  Set the global interrupt Type of IRQ_OUT_PIN. 
+  * @param  DeviceAddr: Device address on communication Bus.      
+  * @param  Type: Interrupt line activity type, could be one of the following values:
+  *   @arg  MFXSTM32L152_OUT_PIN_TYPE_OPENDRAIN: Open Drain output Interrupt line          
+  *   @arg  MFXSTM32L152_OUT_PIN_TYPE_PUSHPULL: Push Pull output Interrupt line            
+  * @retval None
+  */
+void mfxstm32l152_SetIrqOutPinType(uint16_t DeviceAddr, uint8_t Type)
+{
+  uint8_t tmp = 0;
+  
+  /* Get the current register value */ 
+  tmp = MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_MFX_IRQ_OUT);
+  
+  /* Mask the type bits */
+  tmp &= ~(uint8_t)0x01;
+    
+  /* Modify the Interrupt Output line configuration */
+  tmp |= Type;
+  
+  /* Set the new register value */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_MFX_IRQ_OUT, tmp);
+
+  /* Wait for 1 ms for MFX to change IRQ_out pin config, before activate it */
+  rt_thread_delay(1);
+  
+}
+
+
+/* ------------------------------------------------------------------ */
+/* ----------------------- GPIO ------------------------------------- */
+/* ------------------------------------------------------------------ */
+
+
+/**
+  * @brief  Start the IO functionality used and enable the AF for selected IO pin(s).
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @param  AF_en: 0 to disable, else enabled. 
+  * @retval None
+  */
+void mfxstm32l152_IO_Start(uint16_t DeviceAddr, uint32_t IO_Pin)
+{
+  uint8_t mode;
+  
+  /* Get the current register value */
+  mode = MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL);
+  
+  /* Set the IO Functionalities to be Enabled */    
+  mode |= MFXSTM32L152_GPIO_EN;  
+  
+  /* Enable ALTERNATE functions */
+  /* AGPIO[0..3] can be either IDD or GPIO */ 
+  /* AGPIO[4..7] can be either TS or GPIO */ 
+  /* if IDD or TS are enabled no matter the value this bit GPIO are not available for those pins */
+  /*  however the MFX will waste some cycles to to handle these potential GPIO (pooling, etc) */ 
+  /* so if IDD and TS are both active it is better to let ALTERNATE off (0) */
+  /* if however IDD or TS are not connected then set it on gives more GPIOs availability */
+  /* remind that AGPIO are less efficient then normal GPIO (They use pooling rather then EXTI */
+  if (IO_Pin > 0xFFFF)
+  {
+    mode |= MFXSTM32L152_ALTERNATE_GPIO_EN;  
+  }
+  else
+  {
+    mode &= ~MFXSTM32L152_ALTERNATE_GPIO_EN;  
+  }  
+
+  /* Write the new register value */  
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL, mode);
+  
+  /* Wait for 1 ms for MFX to change IRQ_out pin config, before activate it */
+  rt_thread_delay(1);
+}
+
+/**
+  * @brief  Configures the IO pin(s) according to IO mode structure value.
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @param  IO_Pin: The output pin to be set or reset. This parameter can be one 
+  *         of the following values:   
+  *   @arg  MFXSTM32L152_GPIO_PIN_x: where x can be from 0 to 23.
+  * @param  IO_Mode: The IO pin mode to configure, could be one of the following values:
+  *   @arg  IO_MODE_INPUT
+  *   @arg  IO_MODE_OUTPUT
+  *   @arg  IO_MODE_IT_RISING_EDGE
+  *   @arg  IO_MODE_IT_FALLING_EDGE
+  *   @arg  IO_MODE_IT_LOW_LEVEL
+  *   @arg  IO_MODE_IT_HIGH_LEVEL            
+  *   @arg  IO_MODE_INPUT_PU,
+  *   @arg  IO_MODE_INPUT_PD,
+  *   @arg  IO_MODE_OUTPUT_OD_PU,
+  *   @arg  IO_MODE_OUTPUT_OD_PD,
+  *   @arg  IO_MODE_OUTPUT_PP_PU,
+  *   @arg  IO_MODE_OUTPUT_PP_PD,
+  *   @arg  IO_MODE_IT_RISING_EDGE_PU
+  *   @arg  IO_MODE_IT_FALLING_EDGE_PU
+  *   @arg  IO_MODE_IT_LOW_LEVEL_PU
+  *   @arg  IO_MODE_IT_HIGH_LEVEL_PU
+  *   @arg  IO_MODE_IT_RISING_EDGE_PD
+  *   @arg  IO_MODE_IT_FALLING_EDGE_PD
+  *   @arg  IO_MODE_IT_LOW_LEVEL_PD
+  *   @arg  IO_MODE_IT_HIGH_LEVEL_PD
+  * @retval None
+  */
+uint8_t mfxstm32l152_IO_Config(uint16_t DeviceAddr, uint32_t IO_Pin, IO_ModeTypedef IO_Mode)
+{
+  uint8_t error_code = 0;
+
+  /* Configure IO pin according to selected IO mode */
+  switch(IO_Mode)
+  {
+  case IO_MODE_OFF: /* Off or analog mode */
+  case IO_MODE_ANALOG: /* Off or analog mode */
+    mfxstm32l152_IO_DisablePinIT(DeviceAddr, IO_Pin); /* first disable IT */
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITHOUT_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_DOWN);
+    break;
+
+  case IO_MODE_INPUT: /* Input mode */
+    mfxstm32l152_IO_DisablePinIT(DeviceAddr, IO_Pin); /* first disable IT */
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITHOUT_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    break;
+    
+  case IO_MODE_INPUT_PU: /* Input mode */
+    mfxstm32l152_IO_DisablePinIT(DeviceAddr, IO_Pin); /* first disable IT */
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITH_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    break;
+    
+  case IO_MODE_INPUT_PD: /* Input mode */
+    mfxstm32l152_IO_DisablePinIT(DeviceAddr, IO_Pin); /* first disable IT */
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITH_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_DOWN);
+    break;
+
+  case IO_MODE_OUTPUT: /* Output mode */
+  case IO_MODE_OUTPUT_PP_PD: /* Output mode */
+    mfxstm32l152_IO_DisablePinIT(DeviceAddr, IO_Pin); /* first disable IT */
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_OUT);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPO_PUSH_PULL);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_DOWN);
+    break;
+
+  case IO_MODE_OUTPUT_PP_PU: /* Output mode */
+    mfxstm32l152_IO_DisablePinIT(DeviceAddr, IO_Pin); /* first disable IT */
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_OUT);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPO_PUSH_PULL);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    break;
+
+  case IO_MODE_OUTPUT_OD_PD: /* Output mode */
+    mfxstm32l152_IO_DisablePinIT(DeviceAddr, IO_Pin); /* first disable IT */
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_OUT);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPO_OPEN_DRAIN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_DOWN);
+    break;
+
+  case IO_MODE_OUTPUT_OD_PU: /* Output mode */
+    mfxstm32l152_IO_DisablePinIT(DeviceAddr, IO_Pin); /* first disable IT */
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_OUT);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPO_OPEN_DRAIN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    break;
+
+  case IO_MODE_IT_RISING_EDGE: /* Interrupt rising edge mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN); 
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITHOUT_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_EDGE);
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_HLRE);
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin); /* last to do: enable IT */
+    break;
+
+  case IO_MODE_IT_RISING_EDGE_PU: /* Interrupt rising edge mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITH_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_EDGE);
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_HLRE);
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;
+
+  case IO_MODE_IT_RISING_EDGE_PD: /* Interrupt rising edge mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITH_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_DOWN);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_EDGE);      
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_HLRE); 
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;
+
+  case IO_MODE_IT_FALLING_EDGE: /* Interrupt falling edge mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITHOUT_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_EDGE);
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_LLFE);
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;
+
+  case IO_MODE_IT_FALLING_EDGE_PU: /* Interrupt falling edge mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITH_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_EDGE);
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_LLFE);
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;
+
+  case IO_MODE_IT_FALLING_EDGE_PD: /* Interrupt falling edge mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN); 
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITH_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_DOWN);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_EDGE);    
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_LLFE); 
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;
+
+  case IO_MODE_IT_LOW_LEVEL: /* Low level interrupt mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN); 
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITHOUT_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_LEVEL);
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_LLFE);
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;
+
+  case IO_MODE_IT_LOW_LEVEL_PU: /* Low level interrupt mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITH_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_LEVEL);
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_LLFE);
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;
+
+  case IO_MODE_IT_LOW_LEVEL_PD: /* Low level interrupt mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITH_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_DOWN);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_LEVEL);
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_LLFE);      
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;
+    
+  case IO_MODE_IT_HIGH_LEVEL: /* High level interrupt mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN); 
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITHOUT_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_LEVEL);
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_HLRE);
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;
+
+  case IO_MODE_IT_HIGH_LEVEL_PU: /* High level interrupt mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITH_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_UP);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_LEVEL);
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_HLRE);
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;
+
+  case IO_MODE_IT_HIGH_LEVEL_PD: /* High level interrupt mode */
+    mfxstm32l152_IO_EnableIT(DeviceAddr);
+    mfxstm32l152_IO_InitPin(DeviceAddr, IO_Pin, MFXSTM32L152_GPIO_DIR_IN);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_TYPE1, IO_Pin, MFXSTM32L152_GPI_WITH_PULL_RESISTOR);
+    mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_PUPD1, IO_Pin, MFXSTM32L152_GPIO_PULL_DOWN);
+    mfxstm32l152_IO_SetIrqEvtMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_EVT_LEVEL);
+    mfxstm32l152_IO_SetIrqTypeMode(DeviceAddr, IO_Pin, MFXSTM32L152_IRQ_GPI_TYPE_HLRE);  
+    mfxstm32l152_IO_EnablePinIT(DeviceAddr, IO_Pin);  /* last to do: enable IT */
+    break;    
+  
+  default:
+    error_code = (uint8_t) IO_Mode;
+    break;    
+  } 
+
+  return error_code;
+}
+
+/**
+  * @brief  Initialize the selected IO pin direction.
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  IO_Pin: The IO pin to be configured. This parameter could be any 
+  *         combination of the following values:
+  *   @arg  MFXSTM32L152_GPIO_PIN_x: Where x can be from 0 to 23.   
+  * @param  Direction: could be MFXSTM32L152_GPIO_DIR_IN or MFXSTM32L152_GPIO_DIR_OUT.      
+  * @retval None
+  */
+void mfxstm32l152_IO_InitPin(uint16_t DeviceAddr, uint32_t IO_Pin, uint8_t Direction)
+{
+  mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_DIR1, IO_Pin, Direction);
+}
+
+/**
+  * @brief  Set the global interrupt Type. 
+  * @param  DeviceAddr: Device address on communication Bus.      
+  * @param  IO_Pin: The IO pin to be configured. This parameter could be any 
+  *         combination of the following values:
+  *   @arg  MFXSTM32L152_GPIO_PIN_x: Where x can be from 0 to 23.   
+  * @param  Evt: Interrupt line activity type, could be one of the following values:
+  *   @arg  MFXSTM32L152_IRQ_GPI_EVT_LEVEL: Interrupt line is active in level model         
+  *   @arg  MFXSTM32L152_IRQ_GPI_EVT_EDGE: Interrupt line is active in edge model           
+  * @retval None
+  */
+void mfxstm32l152_IO_SetIrqEvtMode(uint16_t DeviceAddr, uint32_t IO_Pin, uint8_t Evt)
+{
+  mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_GPI_EVT1, IO_Pin, Evt);
+  rt_thread_delay(1);
+}
+
+/**
+  * @brief  Configure the Edge for which a transition is detectable for the
+  *         selected pin.
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  IO_Pin: The IO pin to be configured. This parameter could be any 
+  *         combination of the following values:
+  *   @arg  MFXSTM32L152_GPIO_PIN_x: Where x can be from 0 to 23.  
+  * @param  Evt: Interrupt line activity type, could be one of the following values:
+  *   @arg  MFXSTM32L152_IRQ_GPI_TYPE_LLFE: Interrupt line is active in Low Level or Falling Edge         
+  *   @arg  MFXSTM32L152_IRQ_GPI_TYPE_HLRE: Interrupt line is active in High Level or Rising Edge           
+  * @retval None
+  */
+void mfxstm32l152_IO_SetIrqTypeMode(uint16_t DeviceAddr, uint32_t IO_Pin, uint8_t Type)
+{
+  mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_GPI_TYPE1, IO_Pin, Type);
+  rt_thread_delay(1);
+}
+
+/**
+  * @brief  When GPIO is in output mode, puts the corresponding GPO in High (1) or Low (0) level.
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @param  IO_Pin: The output pin to be set or reset. This parameter can be one 
+  *         of the following values:
+  *   @arg  MFXSTM32L152_GPIO_PIN_x: where x can be from 0 to 23. 
+  * @param PinState: The new IO pin state.
+  * @retval None
+  */
+void mfxstm32l152_IO_WritePin(uint16_t DeviceAddr, uint32_t IO_Pin, uint8_t PinState)
+{
+  /* Apply the bit value to the selected pin */
+  if (PinState != 0)
+  {
+    /* Set the SET register */
+	mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPO_SET1, IO_Pin, 1);
+  }
+  else
+  {
+    /* Set the CLEAR register */
+	mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_GPO_CLR1, IO_Pin, 1);
+  } 
+}
+
+/**
+  * @brief  Return the state of the selected IO pin(s).
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @param  IO_Pin: The output pin to be set or reset. This parameter can be one 
+  *         of the following values:
+  *   @arg  MFXSTM32L152_GPIO_PIN_x: where x can be from 0 to 23. 
+  * @retval IO pin(s) state.
+  */
+uint32_t mfxstm32l152_IO_ReadPin(uint16_t DeviceAddr, uint32_t IO_Pin)
+{
+  uint32_t  tmp1 = 0;
+  uint32_t  tmp2 = 0;
+  uint32_t  tmp3 = 0;
+  
+  if(IO_Pin & 0x000000FF)
+  {
+    tmp1 = (uint32_t) MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_STATE1);
+  }
+  if(IO_Pin & 0x0000FF00)
+  {
+    tmp2 = (uint32_t) MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_STATE2);
+  }
+  if(IO_Pin & 0x00FF0000)
+  {
+    tmp3 = (uint32_t) MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_GPIO_STATE3);
+  }
+
+  tmp3 = tmp1 + (tmp2 << 8) + (tmp3 << 16);
+  
+  return(tmp3 & IO_Pin);
+}
+
+/**
+  * @brief  Enable the global IO interrupt source.
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @retval None
+  */
+void mfxstm32l152_IO_EnableIT(uint16_t DeviceAddr)
+{ 
+  MFX_IO_ITConfig();
+    
+  /* Enable global IO IT source */
+  mfxstm32l152_EnableITSource(DeviceAddr, MFXSTM32L152_IRQ_GPIO);
+}
+
+/**
+  * @brief  Disable the global IO interrupt source.
+  * @param  DeviceAddr: Device address on communication Bus.   
+  * @retval None
+  */
+void mfxstm32l152_IO_DisableIT(uint16_t DeviceAddr)
+{
+  /* Disable global IO IT source */
+  mfxstm32l152_DisableITSource(DeviceAddr, MFXSTM32L152_IRQ_GPIO);    
+}
+  
+/**
+  * @brief  Enable interrupt mode for the selected IO pin(s).
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  IO_Pin: The IO interrupt to be enabled. This parameter could be any 
+  *         combination of the following values:
+  *   @arg  MFXSTM32L152_GPIO_PIN_x: where x can be from 0 to 23.
+  * @retval None
+  */
+void mfxstm32l152_IO_EnablePinIT(uint16_t DeviceAddr, uint32_t IO_Pin)
+{
+  mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_GPI_SRC1, IO_Pin, 1);
+}
+
+/**
+  * @brief  Disable interrupt mode for the selected IO pin(s).
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  IO_Pin: The IO interrupt to be disabled. This parameter could be any 
+  *         combination of the following values:
+  *   @arg  MFXSTM32L152_GPIO_PIN_x: where x can be from 0 to 23.
+  * @retval None
+  */
+void mfxstm32l152_IO_DisablePinIT(uint16_t DeviceAddr, uint32_t IO_Pin)
+{
+  mfxstm32l152_reg24_setPinValue(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_GPI_SRC1, IO_Pin, 0);
+}
+
+
+/**
+  * @brief  Check the status of the selected IO interrupt pending bit
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  IO_Pin: The IO interrupt to be checked could be:
+  *   @arg  MFXSTM32L152_GPIO_PIN_x Where x can be from 0 to 23.             
+  * @retval Status of the checked IO pin(s).
+  */
+uint32_t mfxstm32l152_IO_ITStatus(uint16_t DeviceAddr, uint32_t IO_Pin)
+{
+  /* Get the Interrupt status */
+  uint8_t   tmp1 = 0;
+  uint16_t  tmp2 = 0;
+  uint32_t  tmp3 = 0;
+  
+  if(IO_Pin & 0xFF)
+  {
+    tmp1 = MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_GPI_PENDING1);
+  }
+  if(IO_Pin & 0xFFFF00)
+  {
+    tmp2 = (uint16_t) MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_GPI_PENDING2);
+  }
+  if(IO_Pin & 0xFFFF0000)
+  {
+    tmp3 = (uint32_t) MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_GPI_PENDING3);
+  } 
+  
+  tmp3 = tmp1 + (tmp2 << 8) + (tmp3 << 16);
+  
+  return(tmp3 & IO_Pin);
+}
+
+/**
+  * @brief  Clear the selected IO interrupt pending bit(s). It clear automatically also the general MFXSTM32L152_REG_ADR_IRQ_PENDING
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  IO_Pin: the IO interrupt to be cleared, could be:
+  *   @arg  MFXSTM32L152_GPIO_PIN_x: Where x can be from 0 to 23.            
+  * @retval None
+  */
+void mfxstm32l152_IO_ClearIT(uint16_t DeviceAddr, uint32_t IO_Pin)
+{
+  /* Clear the IO IT pending bit(s) by acknowledging */
+  /* it cleans automatically also the Global IRQ_GPIO */
+  /* normally this function is called under interrupt */
+  uint8_t pin_0_7, pin_8_15, pin_16_23;
+
+  pin_0_7   = IO_Pin & 0x0000ff;
+  pin_8_15  = IO_Pin >> 8;
+  pin_8_15   = pin_8_15 & 0x00ff;
+  pin_16_23 = IO_Pin >> 16;
+
+  if (pin_0_7)
+  {
+    MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_GPI_ACK1, pin_0_7);
+  }
+  if (pin_8_15)
+  {
+    MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_GPI_ACK2, pin_8_15);
+  }
+  if (pin_16_23)
+  {
+    MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_IRQ_GPI_ACK3, pin_16_23);
+  }
+}
+
+
+/**
+  * @brief  Enable the AF for aGPIO.
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @retval None
+  */
+void mfxstm32l152_IO_EnableAF(uint16_t DeviceAddr)
+{
+  uint8_t mode;
+
+  /* Get the current register value */
+  mode = MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL);
+  
+  /* Enable ALTERNATE functions */
+  /* AGPIO[0..3] can be either IDD or GPIO */ 
+  /* AGPIO[4..7] can be either TS or GPIO */ 
+  /* if IDD or TS are enabled no matter the value this bit GPIO are not available for those pins */
+  /*  however the MFX will waste some cycles to to handle these potential GPIO (pooling, etc) */ 
+  /* so if IDD and TS are both active it is better to let ALTERNATE disabled (0) */
+  /* if however IDD or TS are not connected then set it on gives more GPIOs availability */
+  /* remind that AGPIO are less efficient then normal GPIO (they use pooling rather then EXTI) */
+  mode |= MFXSTM32L152_ALTERNATE_GPIO_EN;  
+ 
+  /* Write the new register value */  
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL, mode);
+}
+
+/**
+  * @brief  Disable the AF for aGPIO.
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @retval None
+  */
+ void mfxstm32l152_IO_DisableAF(uint16_t DeviceAddr)
+{
+  uint8_t mode;
+
+  /* Get the current register value */
+  mode = MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL);
+  
+  /* Enable ALTERNATE functions */
+  /* AGPIO[0..3] can be either IDD or GPIO */ 
+  /* AGPIO[4..7] can be either TS or GPIO */ 
+  /* if IDD or TS are enabled no matter the value this bit GPIO are not available for those pins */
+  /*  however the MFX will waste some cycles to to handle these potential GPIO (pooling, etc) */ 
+  /* so if IDD and TS are both active it is better to let ALTERNATE disabled (0) */
+  /* if however IDD or TS are not connected then set it on gives more GPIOs availability */
+  /* remind that AGPIO are less efficient then normal GPIO (they use pooling rather then EXTI) */
+  mode &= ~MFXSTM32L152_ALTERNATE_GPIO_EN;  
+ 
+  /* Write the new register value */  
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL, mode);
+  
+}
+
+
+/* ------------------------------------------------------------------ */
+/* --------------------- TOUCH SCREEN ------------------------------- */
+/* ------------------------------------------------------------------ */
+
+/**
+  * @brief  Configures the touch Screen Controller (Single point detection)
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None.
+  */
+void mfxstm32l152_TS_Start(uint16_t DeviceAddr)
+{
+  uint8_t mode;
+
+  /* Get the current register value */
+  mode = MFX_IO_Read(DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL);
+  
+  /* Set the Functionalities to be Enabled */    
+  mode |= MFXSTM32L152_TS_EN;  
+  
+  /* Set the new register value */  
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL, mode);
+     
+  /* Wait for 2 ms */
+  rt_thread_delay(2); 
+  
+  /* Select 2 nF filter capacitor */
+  /* Configuration: 
+     - Touch average control    : 4 samples
+     - Touch delay time         : 500 uS
+     - Panel driver setting time: 500 uS 
+  */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_TS_SETTLING, 0x32);
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_TS_TOUCH_DET_DELAY, 0x5);
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_TS_AVE, 0x04);
+  
+  /* Configure the Touch FIFO threshold: single point reading */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_TS_FIFO_TH, 0x01);
+  
+  /* Clear the FIFO memory content. */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_TS_FIFO_TH, MFXSTM32L152_TS_CLEAR_FIFO);
+
+  /* Touch screen control configuration :
+     - No window tracking index
+   */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_TS_TRACK, 0x00);
+  
+ 
+  /*  Clear all the IT status pending bits if any */
+  mfxstm32l152_IO_ClearIT(DeviceAddr, 0xFFFFFF);
+
+  /* Wait for 1 ms delay */
+  rt_thread_delay(1);
+}
+
+/**
+  * @brief  Return if there is touch detected or not.
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval Touch detected state.
+  */
+uint8_t mfxstm32l152_TS_DetectTouch(uint16_t DeviceAddr)
+{
+  uint8_t state;
+  uint8_t ret = 0;
+ 
+  state = MFX_IO_Read(DeviceAddr, MFXSTM32L152_TS_FIFO_STA);
+  state = ((state & (uint8_t)MFXSTM32L152_TS_CTRL_STATUS) == (uint8_t)MFXSTM32L152_TS_CTRL_STATUS);
+  
+  if(state > 0)
+  {
+    if(MFX_IO_Read(DeviceAddr, MFXSTM32L152_TS_FIFO_LEVEL) > 0)
+    {
+      ret = 1;
+    }
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Get the touch screen X and Y positions values
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  X: Pointer to X position value
+  * @param  Y: Pointer to Y position value   
+  * @retval None.
+  */
+void mfxstm32l152_TS_GetXY(uint16_t DeviceAddr, uint16_t *X, uint16_t *Y)
+{
+  uint8_t  data_xy[3];
+
+  MFX_IO_ReadMultiple(DeviceAddr, MFXSTM32L152_TS_XY_DATA, data_xy, sizeof(data_xy)) ;
+  
+  /* Calculate positions values */
+  *X = (data_xy[1]<<4) + (data_xy[0]>>4); 
+  *Y = (data_xy[2]<<4) + (data_xy[0]&4); 
+
+  /* Reset the FIFO memory content. */
+  MFX_IO_Write(DeviceAddr, MFXSTM32L152_TS_FIFO_TH, MFXSTM32L152_TS_CLEAR_FIFO);
+}
+
+/**
+  * @brief  Configure the selected source to generate a global interrupt or not
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @retval None
+  */
+void mfxstm32l152_TS_EnableIT(uint16_t DeviceAddr)
+{
+  MFX_IO_ITConfig();
+  
+  /* Enable global TS IT source */
+  mfxstm32l152_EnableITSource(DeviceAddr, MFXSTM32L152_IRQ_TS_DET);
+}
+
+/**
+  * @brief  Configure the selected source to generate a global interrupt or not
+  * @param  DeviceAddr: Device address on communication Bus.    
+  * @retval None
+  */
+void mfxstm32l152_TS_DisableIT(uint16_t DeviceAddr)
+{
+  /* Disable global TS IT source */
+  mfxstm32l152_DisableITSource(DeviceAddr, MFXSTM32L152_IRQ_TS_DET);    
+}
+
+/**
+  * @brief  Configure the selected source to generate a global interrupt or not
+  * @param  DeviceAddr: Device address on communication Bus.    
+  * @retval TS interrupts status
+  */
+uint8_t mfxstm32l152_TS_ITStatus(uint16_t DeviceAddr)
+{
+  /* Return TS interrupts status */
+  return(mfxstm32l152_GlobalITStatus(DeviceAddr, MFXSTM32L152_IRQ_TS));
+}
+
+/**
+  * @brief  Configure the selected source to generate a global interrupt or not
+  * @param  DeviceAddr: Device address on communication Bus.  
+  * @retval None
+  */
+void mfxstm32l152_TS_ClearIT(uint16_t DeviceAddr)
+{
+  /* Clear the global TS IT source */
+  mfxstm32l152_ClearGlobalIT(DeviceAddr, MFXSTM32L152_IRQ_TS);
+}
+
+/* ------------------------------------------------------------------ */
+/* --------------------- IDD MEASUREMENT ---------------------------- */
+/* ------------------------------------------------------------------ */
+
+/**
+  * @brief  Launch IDD current measurement
+  * @param  DeviceAddr: Device address on communication Bus
+  * @retval None.
+  */
+void mfxstm32l152_IDD_Start(uint16_t DeviceAddr)
+{
+  uint8_t mode = 0;
+
+  /* Get the current register value */
+  mode = MFX_IO_Read((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_CTRL);
+
+  /* Set the Functionalities to be enabled */
+  mode |= MFXSTM32L152_IDD_CTRL_REQ;
+
+  /* Start measurement campaign */
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_CTRL, mode);
+}
+
+/**
+  * @brief  Configures the IDD current measurement
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  MfxIddConfig: Parameters depending on hardware config.
+  * @retval None
+  */
+void mfxstm32l152_IDD_Config(uint16_t DeviceAddr, IDD_ConfigTypeDef MfxIddConfig)
+{
+  uint8_t value = 0;
+  uint8_t mode = 0;
+
+  /* Get the current register value */
+  mode = MFX_IO_Read((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL);
+
+  if((mode & MFXSTM32L152_IDD_EN) != MFXSTM32L152_IDD_EN)
+  {
+    /* Set the Functionalities to be enabled */
+    mode |= MFXSTM32L152_IDD_EN;
+
+    /* Set the new register value */
+    MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_SYS_CTRL, mode);
+  }
+
+  /* Control register setting: number of shunts */
+  value =  ((MfxIddConfig.ShuntNbUsed << 1) & MFXSTM32L152_IDD_CTRL_SHUNT_NB);
+  value |= (MfxIddConfig.VrefMeasurement & MFXSTM32L152_IDD_CTRL_VREF_DIS);
+  value |= (MfxIddConfig.Calibration & MFXSTM32L152_IDD_CTRL_CAL_DIS);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_CTRL, value);
+
+  /* Idd pre delay configuration: unit and value*/
+  value = (MfxIddConfig.PreDelayUnit & MFXSTM32L152_IDD_PREDELAY_UNIT) |
+          (MfxIddConfig.PreDelayValue & MFXSTM32L152_IDD_PREDELAY_VALUE);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_PRE_DELAY, value);
+
+  /* Shunt 0 register value: MSB then LSB */
+  value = (uint8_t) (MfxIddConfig.Shunt0Value >> 8);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT0_MSB, value);
+  value = (uint8_t) (MfxIddConfig.Shunt0Value);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT0_LSB, value);
+
+  /* Shunt 1 register value: MSB then LSB */
+  value = (uint8_t) (MfxIddConfig.Shunt1Value >> 8);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT1_MSB, value);
+  value = (uint8_t) (MfxIddConfig.Shunt1Value);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT1_LSB, value);
+
+  /* Shunt 2 register value: MSB then LSB */
+  value = (uint8_t) (MfxIddConfig.Shunt2Value >> 8);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT2_MSB, value);
+  value = (uint8_t) (MfxIddConfig.Shunt2Value);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT2_LSB, value);
+
+  /* Shunt 3 register value: MSB then LSB */
+  value = (uint8_t) (MfxIddConfig.Shunt3Value >> 8);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT3_MSB, value);
+  value = (uint8_t) (MfxIddConfig.Shunt3Value);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT3_LSB, value);
+
+  /* Shunt 4 register value: MSB then LSB */
+  value = (uint8_t) (MfxIddConfig.Shunt4Value >> 8);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT4_MSB, value);
+  value = (uint8_t) (MfxIddConfig.Shunt4Value);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT4_LSB, value);
+
+  /* Shunt 0 stabilization delay */
+  value = MfxIddConfig.Shunt0StabDelay;
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SH0_STABILIZATION, value);
+
+  /* Shunt 1 stabilization delay */
+  value = MfxIddConfig.Shunt1StabDelay;
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SH1_STABILIZATION, value);
+
+  /* Shunt 2 stabilization delay */
+  value = MfxIddConfig.Shunt2StabDelay;
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SH2_STABILIZATION, value);
+
+  /* Shunt 3 stabilization delay */
+  value = MfxIddConfig.Shunt3StabDelay;
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SH3_STABILIZATION, value);
+
+  /* Shunt 4 stabilization delay */
+  value = MfxIddConfig.Shunt4StabDelay;
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SH4_STABILIZATION, value);
+
+  /* Idd ampli gain value: MSB then LSB */
+  value = (uint8_t) (MfxIddConfig.AmpliGain >> 8);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_GAIN_MSB, value);
+  value = (uint8_t) (MfxIddConfig.AmpliGain);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_GAIN_LSB, value);
+
+  /* Idd VDD min value: MSB then LSB */
+  value = (uint8_t) (MfxIddConfig.VddMin >> 8);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_VDD_MIN_MSB, value);
+  value = (uint8_t) (MfxIddConfig.VddMin);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_VDD_MIN_LSB, value);
+
+  /* Idd number of measurements */
+  value = MfxIddConfig.MeasureNb;
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_NBR_OF_MEAS, value);
+
+  /* Idd delta delay configuration: unit and value */
+  value = (MfxIddConfig.DeltaDelayUnit & MFXSTM32L152_IDD_DELTADELAY_UNIT) |
+          (MfxIddConfig.DeltaDelayValue & MFXSTM32L152_IDD_DELTADELAY_VALUE);
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_MEAS_DELTA_DELAY, value);
+
+  /* Idd number of shut on board */
+  value = MfxIddConfig.ShuntNbOnBoard;
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNTS_ON_BOARD, value);
+}
+
+/**
+  * @brief  This function allows to modify number of shunt used for a measurement
+  * @param  DeviceAddr: Device address on communication Bus
+  * @retval None.
+  */
+void mfxstm32l152_IDD_ConfigShuntNbLimit(uint16_t DeviceAddr, uint8_t ShuntNbLimit)
+{
+  uint8_t mode = 0;
+
+  /* Get the current register value */
+  mode = MFX_IO_Read((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_CTRL);
+
+  /* Clear number of shunt limit */
+  mode &= ~(MFXSTM32L152_IDD_CTRL_SHUNT_NB);
+
+  /* Clear number of shunt limit */
+  mode |= ((ShuntNbLimit << 1) & MFXSTM32L152_IDD_CTRL_SHUNT_NB);
+
+  /* Write noewx desired limit */
+  MFX_IO_Write((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_CTRL, mode);
+}
+
+/**
+  * @brief  Get Idd current value
+  * @param  DeviceAddr: Device address on communication Bus
+  * @param  ReadValue: Pointer on value to be read
+  * @retval Idd value in 10 nA.
+  */
+void mfxstm32l152_IDD_GetValue(uint16_t DeviceAddr, uint32_t *ReadValue)
+{
+  uint8_t  data[3];
+
+  MFX_IO_ReadMultiple((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_VALUE_MSB, data, sizeof(data)) ;
+
+  /* Recompose Idd current value */
+  *ReadValue = (data[0] << 16) | (data[1] << 8) | data[2];
+
+}
+
+/**
+  * @brief  Get Last shunt used for measurement
+  * @param  DeviceAddr: Device address on communication Bus
+  * @retval Last shunt used 
+  */
+uint8_t  mfxstm32l152_IDD_GetShuntUsed(uint16_t DeviceAddr)
+{
+  return(MFX_IO_Read((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_IDD_SHUNT_USED));
+}
+
+/**
+  * @brief  Configure mfx to enable Idd interrupt
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None
+  */
+void mfxstm32l152_IDD_EnableIT(uint16_t DeviceAddr)
+{
+  MFX_IO_ITConfig();
+
+  /* Enable global IDD interrupt source */
+  mfxstm32l152_EnableITSource(DeviceAddr, MFXSTM32L152_IRQ_IDD);
+}
+
+/**
+  * @brief  Clear Idd global interrupt
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None
+  */
+void mfxstm32l152_IDD_ClearIT(uint16_t DeviceAddr)
+{
+  /* Clear the global IDD interrupt source */
+  mfxstm32l152_ClearGlobalIT(DeviceAddr, MFXSTM32L152_IRQ_IDD);
+}
+
+/**
+  * @brief  get Idd interrupt status
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval IDD interrupts status
+  */
+uint8_t mfxstm32l152_IDD_GetITStatus(uint16_t DeviceAddr)
+{
+  /* Return IDD interrupt status */
+  return(mfxstm32l152_GlobalITStatus(DeviceAddr, MFXSTM32L152_IRQ_IDD));
+}
+
+/**
+  * @brief  disable Idd interrupt
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None.
+  */
+void mfxstm32l152_IDD_DisableIT(uint16_t DeviceAddr)
+{
+  /* Disable global IDD interrupt source */
+  mfxstm32l152_DisableITSource(DeviceAddr, MFXSTM32L152_IRQ_IDD);
+}
+
+
+/* ------------------------------------------------------------------ */
+/* --------------------- ERROR MANAGEMENT --------------------------- */
+/* ------------------------------------------------------------------ */
+
+/**
+  * @brief  Read Error Source.
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval Error message code with error source
+  */
+uint8_t mfxstm32l152_Error_ReadSrc(uint16_t DeviceAddr)
+{
+  /* Get the current source register value */
+  return(MFX_IO_Read((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_ERROR_SRC));
+}
+
+/**
+  * @brief  Read Error Message
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval Error message code with error source
+  */
+uint8_t mfxstm32l152_Error_ReadMsg(uint16_t DeviceAddr)
+{
+  /* Get the current message register value */
+  return(MFX_IO_Read((uint8_t) DeviceAddr, MFXSTM32L152_REG_ADR_ERROR_MSG));
+}
+
+/**
+  * @brief  Enable Error global interrupt
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None
+  */
+
+void mfxstm32l152_Error_EnableIT(uint16_t DeviceAddr)
+{
+  MFX_IO_ITConfig();
+
+  /* Enable global Error interrupt source */
+  mfxstm32l152_EnableITSource(DeviceAddr, MFXSTM32L152_IRQ_ERROR);
+}
+
+/**
+  * @brief  Clear Error global interrupt
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None
+  */
+void mfxstm32l152_Error_ClearIT(uint16_t DeviceAddr)
+{
+  /* Clear the global Error interrupt source */
+  mfxstm32l152_ClearGlobalIT(DeviceAddr, MFXSTM32L152_IRQ_ERROR);
+}
+
+/**
+  * @brief  get Error interrupt status
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval Error interrupts status
+  */
+uint8_t mfxstm32l152_Error_GetITStatus(uint16_t DeviceAddr)
+{
+  /* Return Error interrupt status */
+  return(mfxstm32l152_GlobalITStatus(DeviceAddr, MFXSTM32L152_IRQ_ERROR));
+}
+
+/**
+  * @brief  disable Error interrupt
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval None.
+  */
+void mfxstm32l152_Error_DisableIT(uint16_t DeviceAddr)
+{
+  /* Disable global Error interrupt source */
+  mfxstm32l152_DisableITSource(DeviceAddr, MFXSTM32L152_IRQ_ERROR);
+}
+
+/**
+  * @brief  FOR DEBUG ONLY
+  */
+uint8_t mfxstm32l152_ReadReg(uint16_t DeviceAddr, uint8_t RegAddr)
+{
+  /* Get the current register value */ 
+  return(MFX_IO_Read((uint8_t) DeviceAddr, RegAddr));
+}
+
+void mfxstm32l152_WriteReg(uint16_t DeviceAddr, uint8_t RegAddr, uint8_t Value)
+{
+  /* set the current register value */ 
+  MFX_IO_Write((uint8_t) DeviceAddr, RegAddr, Value);
+}
+
+/* ------------------------------------------------------------------ */
+/* ----------------------- Private functions ------------------------ */
+/* ------------------------------------------------------------------ */
+/**
+  * @brief  Check if the device instance of the selected address is already registered
+  *         and return its index  
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval Index of the device instance if registered, 0xFF if not.
+  */
+static uint8_t mfxstm32l152_GetInstance(uint16_t DeviceAddr)
+{
+  uint8_t idx = 0;
+  
+  /* Check all the registered instances */
+  for(idx = 0; idx < MFXSTM32L152_MAX_INSTANCE ; idx ++)
+  {
+    if(mfxstm32l152[idx] == DeviceAddr)
+    {
+      return idx; 
+    }
+  }
+  
+  return 0xFF;
+}
+
+/**
+  * @brief  Release registered device instance
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval Index of released device instance, 0xFF if not.
+  */
+static uint8_t mfxstm32l152_ReleaseInstance(uint16_t DeviceAddr)
+{
+  uint8_t idx = 0;
+  
+  /* Check for all the registered instances */
+  for(idx = 0; idx < MFXSTM32L152_MAX_INSTANCE ; idx ++)
+  {
+    if(mfxstm32l152[idx] == DeviceAddr)
+    {
+      mfxstm32l152[idx] = 0;
+      return idx;
+    }
+  }
+  return 0xFF;
+}
+
+/**
+  * @brief  Internal routine
+  * @param  DeviceAddr: Device address on communication Bus. 
+  * @param  RegisterAddr: Register Address
+  * @param  PinPosition: Pin [0:23]
+  * @param  PinValue: 0/1
+  * @retval None
+  */
+void mfxstm32l152_reg24_setPinValue(uint16_t DeviceAddr, uint8_t RegisterAddr, uint32_t PinPosition, uint8_t PinValue )
+{
+  uint8_t tmp = 0;
+  uint8_t pin_0_7, pin_8_15, pin_16_23;
+
+  pin_0_7   = PinPosition & 0x0000ff;
+  pin_8_15  = PinPosition >> 8;
+  pin_8_15   = pin_8_15 & 0x00ff;
+  pin_16_23 = PinPosition >> 16;
+  
+  if (pin_0_7)
+  {  
+    /* Get the current register value */ 
+    tmp = MFX_IO_Read(DeviceAddr, RegisterAddr);
+  
+    /* Set the selected pin direction */
+    if (PinValue != 0)
+    {
+      tmp |= (uint8_t)pin_0_7;
+    }  
+    else 
+    {
+      tmp &= ~(uint8_t)pin_0_7;
+    }
+  
+    /* Set the new register value */
+    MFX_IO_Write(DeviceAddr, RegisterAddr, tmp);
+  }
+
+  if (pin_8_15)
+  {
+    /* Get the current register value */ 
+    tmp = MFX_IO_Read(DeviceAddr, RegisterAddr+1);
+  
+    /* Set the selected pin direction */
+    if (PinValue != 0)
+    {
+      tmp |= (uint8_t)pin_8_15;
+    }  
+    else 
+    {
+      tmp &= ~(uint8_t)pin_8_15;
+    }
+  
+    /* Set the new register value */
+    MFX_IO_Write(DeviceAddr, RegisterAddr+1, tmp);
+  }  
+
+  if (pin_16_23)
+  {
+    /* Get the current register value */ 
+    tmp = MFX_IO_Read(DeviceAddr, RegisterAddr+2);
+  
+    /* Set the selected pin direction */
+    if (PinValue != 0)
+    {
+      tmp |= (uint8_t)pin_16_23;
+    }  
+    else 
+    {
+      tmp &= ~(uint8_t)pin_16_23;
+    }
+  
+    /* Set the new register value */
+    MFX_IO_Write(DeviceAddr, RegisterAddr+2, tmp);
+  } 
+}
+
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */      
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 853 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/mfxstm32l152.h

@@ -0,0 +1,853 @@
+/**
+  ******************************************************************************
+  * @file    mfxstm32l152.h
+  * @author  MCD Application Team
+  * @brief   This file contains all the functions prototypes for the
+  *          mfxstm32l152.c IO expander driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+  *
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __MFXSTM32L152_H
+#define __MFXSTM32L152_H
+
+#include "board.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif   
+   
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup Component
+  * @{
+  */
+    
+/** @defgroup MFXSTM32L152
+  * @{
+  */    
+
+ /**
+  * @brief  GPIO: IO Pins definition
+  */
+#define MFXSTM32L152_GPIO_PIN_0                  ((uint32_t)0x0001)
+#define MFXSTM32L152_GPIO_PIN_1                  ((uint32_t)0x0002)
+#define MFXSTM32L152_GPIO_PIN_2                  ((uint32_t)0x0004)
+#define MFXSTM32L152_GPIO_PIN_3                  ((uint32_t)0x0008)
+#define MFXSTM32L152_GPIO_PIN_4                  ((uint32_t)0x0010)
+#define MFXSTM32L152_GPIO_PIN_5                  ((uint32_t)0x0020)
+#define MFXSTM32L152_GPIO_PIN_6                  ((uint32_t)0x0040)
+#define MFXSTM32L152_GPIO_PIN_7                  ((uint32_t)0x0080)
+
+#define MFXSTM32L152_GPIO_PIN_8                  ((uint32_t)0x0100)
+#define MFXSTM32L152_GPIO_PIN_9                  ((uint32_t)0x0200)
+#define MFXSTM32L152_GPIO_PIN_10                 ((uint32_t)0x0400)
+#define MFXSTM32L152_GPIO_PIN_11                 ((uint32_t)0x0800)
+#define MFXSTM32L152_GPIO_PIN_12                 ((uint32_t)0x1000)
+#define MFXSTM32L152_GPIO_PIN_13                 ((uint32_t)0x2000)
+#define MFXSTM32L152_GPIO_PIN_14                 ((uint32_t)0x4000)
+#define MFXSTM32L152_GPIO_PIN_15                 ((uint32_t)0x8000)
+
+#define MFXSTM32L152_GPIO_PIN_16               ((uint32_t)0x010000)
+#define MFXSTM32L152_GPIO_PIN_17               ((uint32_t)0x020000)
+#define MFXSTM32L152_GPIO_PIN_18               ((uint32_t)0x040000)
+#define MFXSTM32L152_GPIO_PIN_19               ((uint32_t)0x080000)
+#define MFXSTM32L152_GPIO_PIN_20               ((uint32_t)0x100000)
+#define MFXSTM32L152_GPIO_PIN_21               ((uint32_t)0x200000)
+#define MFXSTM32L152_GPIO_PIN_22               ((uint32_t)0x400000)
+#define MFXSTM32L152_GPIO_PIN_23               ((uint32_t)0x800000)
+
+#define MFXSTM32L152_AGPIO_PIN_0               MFXSTM32L152_GPIO_PIN_16
+#define MFXSTM32L152_AGPIO_PIN_1               MFXSTM32L152_GPIO_PIN_17
+#define MFXSTM32L152_AGPIO_PIN_2               MFXSTM32L152_GPIO_PIN_18
+#define MFXSTM32L152_AGPIO_PIN_3               MFXSTM32L152_GPIO_PIN_19
+#define MFXSTM32L152_AGPIO_PIN_4               MFXSTM32L152_GPIO_PIN_20
+#define MFXSTM32L152_AGPIO_PIN_5               MFXSTM32L152_GPIO_PIN_21
+#define MFXSTM32L152_AGPIO_PIN_6               MFXSTM32L152_GPIO_PIN_22
+#define MFXSTM32L152_AGPIO_PIN_7               MFXSTM32L152_GPIO_PIN_23
+
+#define MFXSTM32L152_GPIO_PINS_ALL             ((uint32_t)0xFFFFFF)
+#define IO_PIN_ALL                             MFXSTM32L152_GPIO_PINS_ALL
+/**
+  * @brief  IO Bit SET and Bit RESET enumeration
+  */
+typedef enum
+{
+  IO_PIN_RESET = 0,
+  IO_PIN_SET
+}IO_PinState;
+
+typedef enum
+{
+   IO_MODE_INPUT = 0,   /* input floating */
+   IO_MODE_OUTPUT,      /* output Push Pull */
+   IO_MODE_IT_RISING_EDGE,   /* float input - irq detect on rising edge */
+   IO_MODE_IT_FALLING_EDGE,  /* float input - irq detect on falling edge */
+   IO_MODE_IT_LOW_LEVEL,     /* float input - irq detect on low level */
+   IO_MODE_IT_HIGH_LEVEL,    /* float input - irq detect on high level */
+   /* following modes only available on MFX*/
+   IO_MODE_ANALOG,           /* analog mode */
+   IO_MODE_OFF,              /* when pin isn't used*/
+   IO_MODE_INPUT_PU,         /* input with internal pull up resistor */
+   IO_MODE_INPUT_PD,         /* input with internal pull down resistor */
+   IO_MODE_OUTPUT_OD,          /* Open Drain output without internal resistor */
+   IO_MODE_OUTPUT_OD_PU,       /* Open Drain output with  internal pullup resistor */
+   IO_MODE_OUTPUT_OD_PD,       /* Open Drain output with  internal pulldown resistor */
+   IO_MODE_OUTPUT_PP,          /* PushPull output without internal resistor */
+   IO_MODE_OUTPUT_PP_PU,       /* PushPull output with  internal pullup resistor */
+   IO_MODE_OUTPUT_PP_PD,       /* PushPull output with  internal pulldown resistor */
+   IO_MODE_IT_RISING_EDGE_PU,   /* push up resistor input - irq on rising edge  */
+   IO_MODE_IT_RISING_EDGE_PD,   /* push dw resistor input - irq on rising edge  */
+   IO_MODE_IT_FALLING_EDGE_PU,  /* push up resistor input - irq on falling edge */
+   IO_MODE_IT_FALLING_EDGE_PD,  /* push dw resistor input - irq on falling edge */
+   IO_MODE_IT_LOW_LEVEL_PU,     /* push up resistor input - irq detect on low level */
+   IO_MODE_IT_LOW_LEVEL_PD,     /* push dw resistor input - irq detect on low level */
+   IO_MODE_IT_HIGH_LEVEL_PU,    /* push up resistor input - irq detect on high level */
+   IO_MODE_IT_HIGH_LEVEL_PD,    /* push dw resistor input - irq detect on high level */
+
+}IO_ModeTypedef;
+
+/** @defgroup IO_Driver_structure  IO Driver structure
+  * @{
+  */
+typedef struct
+{  
+  void       (*Init)(uint16_t);
+  uint16_t   (*ReadID)(uint16_t);
+  void       (*Reset)(uint16_t);
+  
+  void       (*Start)(uint16_t, uint32_t);
+  uint8_t    (*Config)(uint16_t, uint32_t, IO_ModeTypedef);
+  void       (*WritePin)(uint16_t, uint32_t, uint8_t);
+  uint32_t   (*ReadPin)(uint16_t, uint32_t);
+  
+  void       (*EnableIT)(uint16_t);
+  void       (*DisableIT)(uint16_t);
+  uint32_t    (*ITStatus)(uint16_t, uint32_t);
+  void       (*ClearIT)(uint16_t, uint32_t);
+    
+}IO_DrvTypeDef;
+
+typedef struct
+{
+  uint16_t AmpliGain;       /*!< Specifies ampli gain value
+                                 */
+  uint16_t VddMin;          /*!< Specifies minimum MCU VDD can reach to protect MCU from reset
+                                  */
+  uint16_t Shunt0Value;     /*!< Specifies value of Shunt 0 if existing
+                                 */
+  uint16_t Shunt1Value;     /*!< Specifies value of Shunt 1 if existing
+                                 */
+  uint16_t Shunt2Value;     /*!< Specifies value of Shunt 2 if existing
+                                 */
+  uint16_t Shunt3Value;     /*!< Specifies value of Shunt 3 if existing
+                                 */
+  uint16_t Shunt4Value;     /*!< Specifies value of Shunt 4 if existing
+                                  */
+  uint16_t Shunt0StabDelay; /*!< Specifies delay of Shunt 0 stabilization if existing
+                                  */
+  uint16_t Shunt1StabDelay; /*!< Specifies delay of Shunt 1 stabilization if existing
+                                  */
+  uint16_t Shunt2StabDelay; /*!< Specifies delay of Shunt 2 stabilization if existing
+                                  */
+  uint16_t Shunt3StabDelay; /*!< Specifies delay of Shunt 3 stabilization if existing
+                                  */
+  uint16_t Shunt4StabDelay; /*!< Specifies delay of Shunt 4 stabilization if existing
+                                  */
+  uint8_t ShuntNbOnBoard;   /*!< Specifies number of shunts that are present on board
+                                 This parameter can be a value of @ref IDD_shunt_number */
+  uint8_t ShuntNbUsed;      /*!< Specifies number of shunts used for measurement
+                                 This parameter can be a value of @ref IDD_shunt_number */
+  uint8_t VrefMeasurement;  /*!< Specifies if Vref is automatically measured before each Idd measurement
+                                 This parameter can be a value of @ref IDD_Vref_Measurement */
+  uint8_t Calibration;      /*!< Specifies if calibration is done before each Idd measurement
+                                  */
+  uint8_t PreDelayUnit;     /*!< Specifies Pre delay unit 
+                                 This parameter can be a value of @ref IDD_PreDelay */
+  uint8_t PreDelayValue;    /*!< Specifies Pre delay value in selected unit
+                                  */
+  uint8_t MeasureNb;        /*!< Specifies number of Measure to be performed 
+                                 This parameter can be a value between 1 and 256 */
+  uint8_t DeltaDelayUnit;   /*!< Specifies Delta delay unit
+                                  This parameter can be a value of @ref IDD_DeltaDelay */
+  uint8_t DeltaDelayValue;  /*!< Specifies Delta delay between 2 measures
+                                  value can be between 1 and 128 */
+}IDD_ConfigTypeDef;
+/**
+  * @}
+  */
+
+/** @defgroup IDD_Driver_structure  IDD Driver structure
+  * @{
+  */
+typedef struct
+{
+  void       (*Init)(uint16_t);
+  void       (*DeInit)(uint16_t);
+  uint16_t   (*ReadID)(uint16_t);
+  void       (*Reset)(uint16_t);
+  void       (*LowPower)(uint16_t);
+  void       (*WakeUp)(uint16_t);
+  void       (*Start)(uint16_t);
+  void       (*Config)(uint16_t,IDD_ConfigTypeDef);
+  void       (*GetValue)(uint16_t, uint32_t *);
+  void       (*EnableIT)(uint16_t);
+  void       (*ClearIT)(uint16_t);
+  uint8_t    (*GetITStatus)(uint16_t);
+  void       (*DisableIT)(uint16_t);
+  void       (*ErrorEnableIT)(uint16_t);
+  void       (*ErrorClearIT)(uint16_t);
+  uint8_t    (*ErrorGetITStatus)(uint16_t);
+  void       (*ErrorDisableIT)(uint16_t);
+  uint8_t    (*ErrorGetSrc)(uint16_t);
+  uint8_t    (*ErrorGetCode)(uint16_t);
+}IDD_DrvTypeDef;
+
+typedef struct
+{  
+  void       (*Init)(uint16_t);
+  uint16_t   (*ReadID)(uint16_t);
+  void       (*Reset)(uint16_t);
+  void       (*Start)(uint16_t);
+  uint8_t    (*DetectTouch)(uint16_t);
+  void       (*GetXY)(uint16_t, uint16_t*, uint16_t*);
+  void       (*EnableIT)(uint16_t);
+  void       (*ClearIT)(uint16_t);
+  uint8_t    (*GetITStatus)(uint16_t);
+  void       (*DisableIT)(uint16_t);
+}TS_DrvTypeDef;
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup MFXSTM32L152_Exported_Types
+  * @{
+  */ 
+typedef struct
+{
+  uint8_t SYS_CTRL;
+  uint8_t ERROR_SRC;
+  uint8_t ERROR_MSG;
+  uint8_t IRQ_OUT;
+  uint8_t IRQ_SRC_EN;
+  uint8_t IRQ_PENDING;
+  uint8_t IDD_CTRL;
+  uint8_t IDD_PRE_DELAY;
+  uint8_t IDD_SHUNT0_MSB;
+  uint8_t IDD_SHUNT0_LSB;
+  uint8_t IDD_SHUNT1_MSB;
+  uint8_t IDD_SHUNT1_LSB;
+  uint8_t IDD_SHUNT2_MSB;
+  uint8_t IDD_SHUNT2_LSB;
+  uint8_t IDD_SHUNT3_MSB;
+  uint8_t IDD_SHUNT3_LSB;
+  uint8_t IDD_SHUNT4_MSB;
+  uint8_t IDD_SHUNT4_LSB;
+  uint8_t IDD_GAIN_MSB;
+  uint8_t IDD_GAIN_LSB;
+  uint8_t IDD_VDD_MIN_MSB;
+  uint8_t IDD_VDD_MIN_LSB;
+  uint8_t IDD_VALUE_MSB;
+  uint8_t IDD_VALUE_MID;
+  uint8_t IDD_VALUE_LSB;
+  uint8_t IDD_CAL_OFFSET_MSB;
+  uint8_t IDD_CAL_OFFSET_LSB;
+  uint8_t IDD_SHUNT_USED;
+}IDD_dbgTypeDef;
+
+/**
+  * @}
+  */
+
+/* Exported constants --------------------------------------------------------*/
+  
+/** @defgroup MFXSTM32L152_Exported_Constants
+  * @{
+  */ 
+
+ /**
+  * @brief  MFX COMMON defines
+  */
+   
+ /**
+  * @brief  Register address: chip IDs (R)
+  */
+#define MFXSTM32L152_REG_ADR_ID                 ((uint8_t)0x00)
+ /**
+  * @brief  Register address: chip FW_VERSION  (R)
+  */
+#define MFXSTM32L152_REG_ADR_FW_VERSION_MSB     ((uint8_t)0x01)
+#define MFXSTM32L152_REG_ADR_FW_VERSION_LSB     ((uint8_t)0x00)
+ /**
+  * @brief  Register address: System Control Register (R/W)
+  */
+#define MFXSTM32L152_REG_ADR_SYS_CTRL           ((uint8_t)0x40)
+ /**
+  * @brief  Register address: Vdd monitoring (R)
+  */
+#define MFXSTM32L152_REG_ADR_VDD_REF_MSB        ((uint8_t)0x06)
+#define MFXSTM32L152_REG_ADR_VDD_REF_LSB        ((uint8_t)0x07)
+ /**
+  * @brief  Register address: Error source
+  */
+#define MFXSTM32L152_REG_ADR_ERROR_SRC          ((uint8_t)0x03)
+ /**
+  * @brief  Register address: Error Message
+  */
+#define MFXSTM32L152_REG_ADR_ERROR_MSG          ((uint8_t)0x04)
+
+ /**
+  * @brief  Reg Addr IRQs: to config the pin that informs Main MCU that MFX events appear
+  */
+#define MFXSTM32L152_REG_ADR_MFX_IRQ_OUT        ((uint8_t)0x41)
+ /**
+  * @brief  Reg Addr IRQs: to select the events which activate the MFXSTM32L152_IRQ_OUT signal
+  */
+#define MFXSTM32L152_REG_ADR_IRQ_SRC_EN         ((uint8_t)0x42)
+ /**
+  * @brief  Reg Addr IRQs: the Main MCU must read the IRQ_PENDING register to know the interrupt reason
+  */
+#define MFXSTM32L152_REG_ADR_IRQ_PENDING        ((uint8_t)0x08)
+ /**
+  * @brief  Reg Addr IRQs: the Main MCU must acknowledge it thanks to a writing access to the IRQ_ACK register
+  */
+#define MFXSTM32L152_REG_ADR_IRQ_ACK            ((uint8_t)0x44)
+   
+  /**
+  * @brief  MFXSTM32L152_REG_ADR_ID choices
+  */
+#define MFXSTM32L152_ID_1                    ((uint8_t)0x7B)
+#define MFXSTM32L152_ID_2                    ((uint8_t)0x79)
+   
+  /**
+  * @brief  MFXSTM32L152_REG_ADR_SYS_CTRL choices
+  */
+#define MFXSTM32L152_SWRST                    ((uint8_t)0x80)
+#define MFXSTM32L152_STANDBY                  ((uint8_t)0x40)
+#define MFXSTM32L152_ALTERNATE_GPIO_EN        ((uint8_t)0x08) /* by the way if IDD and TS are enabled they take automatically the AF pins*/
+#define MFXSTM32L152_IDD_EN                   ((uint8_t)0x04)
+#define MFXSTM32L152_TS_EN                    ((uint8_t)0x02)
+#define MFXSTM32L152_GPIO_EN                  ((uint8_t)0x01)
+
+  /**
+  * @brief  MFXSTM32L152_REG_ADR_ERROR_SRC choices
+  */
+#define MFXSTM32L152_IDD_ERROR_SRC             ((uint8_t)0x04)  /* Error raised by Idd */
+#define MFXSTM32L152_TS_ERROR_SRC              ((uint8_t)0x02)  /* Error raised by Touch Screen */
+#define MFXSTM32L152_GPIO_ERROR_SRC            ((uint8_t)0x01)  /* Error raised by Gpio */
+
+ /**
+  * @brief  MFXSTM32L152_REG_ADR_MFX_IRQ_OUT choices
+  */
+#define MFXSTM32L152_OUT_PIN_TYPE_OPENDRAIN   ((uint8_t)0x00)
+#define MFXSTM32L152_OUT_PIN_TYPE_PUSHPULL    ((uint8_t)0x01)
+#define MFXSTM32L152_OUT_PIN_POLARITY_LOW     ((uint8_t)0x00)
+#define MFXSTM32L152_OUT_PIN_POLARITY_HIGH    ((uint8_t)0x02)
+
+ /**
+   * @brief  REG_ADR_IRQ_SRC_EN, REG_ADR_IRQ_PENDING & REG_ADR_IRQ_ACK choices
+  */
+#define MFXSTM32L152_IRQ_TS_OVF               ((uint8_t)0x80)  /* TouchScreen FIFO Overflow irq*/
+#define MFXSTM32L152_IRQ_TS_FULL              ((uint8_t)0x40)  /* TouchScreen FIFO Full irq*/
+#define MFXSTM32L152_IRQ_TS_TH                ((uint8_t)0x20)  /* TouchScreen FIFO threshold triggered irq*/
+#define MFXSTM32L152_IRQ_TS_NE                ((uint8_t)0x10)  /* TouchScreen FIFO Not Empty irq*/
+#define MFXSTM32L152_IRQ_TS_DET               ((uint8_t)0x08)  /* TouchScreen Detect irq*/
+#define MFXSTM32L152_IRQ_ERROR                ((uint8_t)0x04)  /* Error message from MFXSTM32L152 firmware irq */
+#define MFXSTM32L152_IRQ_IDD                  ((uint8_t)0x02)  /* IDD function irq */
+#define MFXSTM32L152_IRQ_GPIO                 ((uint8_t)0x01)  /* General GPIO irq (only for SRC_EN and PENDING) */
+#define MFXSTM32L152_IRQ_ALL                  ((uint8_t)0xFF)  /* All global interrupts          */
+#define MFXSTM32L152_IRQ_TS                  (MFXSTM32L152_IRQ_TS_DET | MFXSTM32L152_IRQ_TS_NE |  MFXSTM32L152_IRQ_TS_TH | MFXSTM32L152_IRQ_TS_FULL | MFXSTM32L152_IRQ_TS_OVF ) 
+
+   
+ /**
+  * @brief  GPIO: 24 programmable input/output called MFXSTM32L152_GPIO[23:0] are provided
+  */
+
+ /**
+   * @brief  Reg addr: GPIO DIRECTION (R/W): GPIO pins direction: (0) input, (1) output.
+  */
+#define MFXSTM32L152_REG_ADR_GPIO_DIR1          ((uint8_t)0x60)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_GPIO_DIR2          ((uint8_t)0x61)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_GPIO_DIR3          ((uint8_t)0x62)  /* agpio [0:7] */
+ /**
+  * @brief  Reg addr: GPIO TYPE (R/W): If GPIO in output: (0) output push pull, (1) output open drain.
+  *                          If GPIO in input: (0) input without pull resistor, (1) input with pull resistor.
+  */
+#define MFXSTM32L152_REG_ADR_GPIO_TYPE1         ((uint8_t)0x64)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_GPIO_TYPE2         ((uint8_t)0x65)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_GPIO_TYPE3         ((uint8_t)0x66)  /* agpio [0:7] */
+ /**
+  * @brief  Reg addr: GPIO PULL_UP_PULL_DOWN (R/W):  discussion open with Jean Claude
+  */
+#define MFXSTM32L152_REG_ADR_GPIO_PUPD1         ((uint8_t)0x68)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_GPIO_PUPD2         ((uint8_t)0x69)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_GPIO_PUPD3         ((uint8_t)0x6A)  /* agpio [0:7] */
+ /**
+  * @brief  Reg addr: GPIO SET (W): When GPIO is in output mode, write (1) puts the corresponding GPO in High level.
+  */
+#define MFXSTM32L152_REG_ADR_GPO_SET1           ((uint8_t)0x6C)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_GPO_SET2           ((uint8_t)0x6D)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_GPO_SET3           ((uint8_t)0x6E)  /* agpio [0:7] */
+ /**
+  * @brief  Reg addr: GPIO CLEAR (W): When GPIO is in output mode, write (1) puts the corresponding GPO in Low level.
+  */
+#define MFXSTM32L152_REG_ADR_GPO_CLR1           ((uint8_t)0x70)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_GPO_CLR2           ((uint8_t)0x71)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_GPO_CLR3           ((uint8_t)0x72)  /* agpio [0:7] */
+ /**
+  * @brief  Reg addr: GPIO STATE (R): Give state of the GPIO pin.
+  */
+#define MFXSTM32L152_REG_ADR_GPIO_STATE1         ((uint8_t)0x10)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_GPIO_STATE2         ((uint8_t)0x11)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_GPIO_STATE3         ((uint8_t)0x12)  /* agpio [0:7] */
+
+  /**
+  * @brief  GPIO IRQ_GPIs
+  */
+/* GPIOs can INDIVIDUALLY generate interruption to the Main MCU thanks to the MFXSTM32L152_IRQ_OUT signal */
+/* the general MFXSTM32L152_IRQ_GPIO_SRC_EN shall be enabled too          */
+  /**
+  * @brief  GPIO IRQ_GPI_SRC1/2/3 (R/W): registers enable or not the feature to generate irq
+  */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_SRC1       ((uint8_t)0x48)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_SRC2       ((uint8_t)0x49)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_SRC3       ((uint8_t)0x4A)  /* agpio [0:7] */
+  /**
+  * @brief  GPIO IRQ_GPI_EVT1/2/3 (R/W): Irq generated on level (0) or edge (1).
+  */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_EVT1       ((uint8_t)0x4C)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_EVT2       ((uint8_t)0x4D)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_EVT3       ((uint8_t)0x4E)  /* agpio [0:7] */
+  /**
+  * @brief  GPIO IRQ_GPI_TYPE1/2/3 (R/W): Irq generated on (0) : Low level or Falling edge. (1) : High level or Rising edge.
+  */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_TYPE1      ((uint8_t)0x50)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_TYPE2      ((uint8_t)0x51)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_TYPE3      ((uint8_t)0x52)  /* agpio [0:7] */
+  /**
+  * @brief  GPIO IRQ_GPI_PENDING1/2/3 (R): irq occurs
+  */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_PENDING1   ((uint8_t)0x0C)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_PENDING2   ((uint8_t)0x0D)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_PENDING3   ((uint8_t)0x0E)  /* agpio [0:7] */
+  /**
+  * @brief  GPIO IRQ_GPI_ACK1/2/3 (W): Write (1) to acknowledge IRQ event
+  */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_ACK1       ((uint8_t)0x54)  /* gpio [0:7] */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_ACK2       ((uint8_t)0x55)  /* gpio [8:15] */
+#define MFXSTM32L152_REG_ADR_IRQ_GPI_ACK3       ((uint8_t)0x56)  /* agpio [0:7] */
+
+   
+ /**
+  * @brief  GPIO: IO Pins definition
+  */
+#define MFXSTM32L152_GPIO_PIN_0                  ((uint32_t)0x0001)
+#define MFXSTM32L152_GPIO_PIN_1                  ((uint32_t)0x0002)
+#define MFXSTM32L152_GPIO_PIN_2                  ((uint32_t)0x0004)
+#define MFXSTM32L152_GPIO_PIN_3                  ((uint32_t)0x0008)
+#define MFXSTM32L152_GPIO_PIN_4                  ((uint32_t)0x0010)
+#define MFXSTM32L152_GPIO_PIN_5                  ((uint32_t)0x0020)
+#define MFXSTM32L152_GPIO_PIN_6                  ((uint32_t)0x0040)
+#define MFXSTM32L152_GPIO_PIN_7                  ((uint32_t)0x0080)
+
+#define MFXSTM32L152_GPIO_PIN_8                  ((uint32_t)0x0100) 
+#define MFXSTM32L152_GPIO_PIN_9                  ((uint32_t)0x0200) 
+#define MFXSTM32L152_GPIO_PIN_10                 ((uint32_t)0x0400) 
+#define MFXSTM32L152_GPIO_PIN_11                 ((uint32_t)0x0800)
+#define MFXSTM32L152_GPIO_PIN_12                 ((uint32_t)0x1000) 
+#define MFXSTM32L152_GPIO_PIN_13                 ((uint32_t)0x2000) 
+#define MFXSTM32L152_GPIO_PIN_14                 ((uint32_t)0x4000) 
+#define MFXSTM32L152_GPIO_PIN_15                 ((uint32_t)0x8000) 
+
+#define MFXSTM32L152_GPIO_PIN_16               ((uint32_t)0x010000)
+#define MFXSTM32L152_GPIO_PIN_17               ((uint32_t)0x020000)
+#define MFXSTM32L152_GPIO_PIN_18               ((uint32_t)0x040000)
+#define MFXSTM32L152_GPIO_PIN_19               ((uint32_t)0x080000)
+#define MFXSTM32L152_GPIO_PIN_20               ((uint32_t)0x100000)
+#define MFXSTM32L152_GPIO_PIN_21               ((uint32_t)0x200000)
+#define MFXSTM32L152_GPIO_PIN_22               ((uint32_t)0x400000)
+#define MFXSTM32L152_GPIO_PIN_23               ((uint32_t)0x800000)
+
+#define MFXSTM32L152_AGPIO_PIN_0               MFXSTM32L152_GPIO_PIN_16
+#define MFXSTM32L152_AGPIO_PIN_1               MFXSTM32L152_GPIO_PIN_17
+#define MFXSTM32L152_AGPIO_PIN_2               MFXSTM32L152_GPIO_PIN_18
+#define MFXSTM32L152_AGPIO_PIN_3               MFXSTM32L152_GPIO_PIN_19
+#define MFXSTM32L152_AGPIO_PIN_4               MFXSTM32L152_GPIO_PIN_20
+#define MFXSTM32L152_AGPIO_PIN_5               MFXSTM32L152_GPIO_PIN_21
+#define MFXSTM32L152_AGPIO_PIN_6               MFXSTM32L152_GPIO_PIN_22
+#define MFXSTM32L152_AGPIO_PIN_7               MFXSTM32L152_GPIO_PIN_23
+
+#define MFXSTM32L152_GPIO_PINS_ALL             ((uint32_t)0xFFFFFF)
+
+ /**
+  * @brief  GPIO: constant
+  */
+#define MFXSTM32L152_GPIO_DIR_IN                ((uint8_t)0x0)  
+#define MFXSTM32L152_GPIO_DIR_OUT               ((uint8_t)0x1)  
+#define MFXSTM32L152_IRQ_GPI_EVT_LEVEL          ((uint8_t)0x0)  
+#define MFXSTM32L152_IRQ_GPI_EVT_EDGE           ((uint8_t)0x1)  
+#define MFXSTM32L152_IRQ_GPI_TYPE_LLFE          ((uint8_t)0x0)  /* Low Level Falling Edge */
+#define MFXSTM32L152_IRQ_GPI_TYPE_HLRE          ((uint8_t)0x1)  /*High Level Raising Edge */
+#define MFXSTM32L152_GPI_WITHOUT_PULL_RESISTOR  ((uint8_t)0x0)  
+#define MFXSTM32L152_GPI_WITH_PULL_RESISTOR     ((uint8_t)0x1)  
+#define MFXSTM32L152_GPO_PUSH_PULL              ((uint8_t)0x0)  
+#define MFXSTM32L152_GPO_OPEN_DRAIN             ((uint8_t)0x1)  
+#define MFXSTM32L152_GPIO_PULL_DOWN             ((uint8_t)0x0)  
+#define MFXSTM32L152_GPIO_PULL_UP               ((uint8_t)0x1)   
+   
+   
+  /**
+  * @brief  TOUCH SCREEN Registers
+  */
+
+  /**
+  * @brief  Touch Screen Registers
+  */
+#define MFXSTM32L152_TS_SETTLING            ((uint8_t)0xA0)
+#define MFXSTM32L152_TS_TOUCH_DET_DELAY     ((uint8_t)0xA1)
+#define MFXSTM32L152_TS_AVE                 ((uint8_t)0xA2)
+#define MFXSTM32L152_TS_TRACK               ((uint8_t)0xA3)
+#define MFXSTM32L152_TS_FIFO_TH             ((uint8_t)0xA4)
+#define MFXSTM32L152_TS_FIFO_STA            ((uint8_t)0x20)
+#define MFXSTM32L152_TS_FIFO_LEVEL          ((uint8_t)0x21)
+#define MFXSTM32L152_TS_XY_DATA             ((uint8_t)0x24)
+
+  /**
+  * @brief TS registers masks
+  */
+#define MFXSTM32L152_TS_CTRL_STATUS         ((uint8_t)0x08)
+#define MFXSTM32L152_TS_CLEAR_FIFO          ((uint8_t)0x80)
+
+
+/**
+  * @brief  Register address: Idd control register (R/W)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_CTRL           ((uint8_t)0x80)
+
+/**
+  * @brief  Register address: Idd pre delay  register (R/W)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_PRE_DELAY      ((uint8_t)0x81)
+
+/**
+  * @brief  Register address: Idd Shunt registers (R/W)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT0_MSB     ((uint8_t)0x82)
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT0_LSB     ((uint8_t)0x83)
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT1_MSB     ((uint8_t)0x84)
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT1_LSB     ((uint8_t)0x85)
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT2_MSB     ((uint8_t)0x86)
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT2_LSB     ((uint8_t)0x87)
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT3_MSB     ((uint8_t)0x88)
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT3_LSB     ((uint8_t)0x89)
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT4_MSB     ((uint8_t)0x8A)
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT4_LSB     ((uint8_t)0x8B)
+
+/**
+  * @brief  Register address: Idd ampli gain register (R/W)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_GAIN_MSB       ((uint8_t)0x8C)
+#define MFXSTM32L152_REG_ADR_IDD_GAIN_LSB       ((uint8_t)0x8D)
+
+/**
+  * @brief  Register address: Idd VDD min register (R/W)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_VDD_MIN_MSB    ((uint8_t)0x8E)
+#define MFXSTM32L152_REG_ADR_IDD_VDD_MIN_LSB    ((uint8_t)0x8F)
+
+/**
+  * @brief  Register address: Idd value register (R)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_VALUE_MSB      ((uint8_t)0x14)
+#define MFXSTM32L152_REG_ADR_IDD_VALUE_MID      ((uint8_t)0x15)
+#define MFXSTM32L152_REG_ADR_IDD_VALUE_LSB      ((uint8_t)0x16)
+
+/**
+  * @brief  Register address: Idd calibration offset register (R)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_CAL_OFFSET_MSB ((uint8_t)0x18)
+#define MFXSTM32L152_REG_ADR_IDD_CAL_OFFSET_LSB ((uint8_t)0x19)
+
+/**
+  * @brief  Register address: Idd shunt used offset register (R)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_SHUNT_USED     ((uint8_t)0x1A)
+
+/**
+  * @brief  Register address: shunt stabilisation delay registers (R/W)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_SH0_STABILIZATION  ((uint8_t)0x90)
+#define MFXSTM32L152_REG_ADR_IDD_SH1_STABILIZATION  ((uint8_t)0x91)
+#define MFXSTM32L152_REG_ADR_IDD_SH2_STABILIZATION  ((uint8_t)0x92)
+#define MFXSTM32L152_REG_ADR_IDD_SH3_STABILIZATION  ((uint8_t)0x93)
+#define MFXSTM32L152_REG_ADR_IDD_SH4_STABILIZATION  ((uint8_t)0x94)
+
+/**
+  * @brief  Register address: Idd number of measurements register (R/W)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_NBR_OF_MEAS    ((uint8_t)0x96)
+
+/**
+  * @brief  Register address: Idd delta delay between 2 measurements register (R/W)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_MEAS_DELTA_DELAY  ((uint8_t)0x97)
+
+/**
+  * @brief  Register address: Idd number of shunt on board register (R/W)
+  */
+#define MFXSTM32L152_REG_ADR_IDD_SHUNTS_ON_BOARD  ((uint8_t)0x98)
+
+ 
+
+/** @defgroup IDD_Control_Register_Defines  IDD Control Register Defines
+  * @{
+  */
+/**
+  * @brief  IDD control register masks
+  */
+#define MFXSTM32L152_IDD_CTRL_REQ                       ((uint8_t)0x01)
+#define MFXSTM32L152_IDD_CTRL_SHUNT_NB                  ((uint8_t)0x0E)
+#define MFXSTM32L152_IDD_CTRL_VREF_DIS                  ((uint8_t)0x40)
+#define MFXSTM32L152_IDD_CTRL_CAL_DIS                   ((uint8_t)0x80)
+
+/**
+  * @brief  IDD Shunt Number
+  */
+#define MFXSTM32L152_IDD_SHUNT_NB_1                     ((uint8_t) 0x01)
+#define MFXSTM32L152_IDD_SHUNT_NB_2                     ((uint8_t) 0x02)
+#define MFXSTM32L152_IDD_SHUNT_NB_3                     ((uint8_t) 0x03)
+#define MFXSTM32L152_IDD_SHUNT_NB_4                     ((uint8_t) 0x04)
+#define MFXSTM32L152_IDD_SHUNT_NB_5                     ((uint8_t) 0x05)
+
+/**
+  * @brief  Vref Measurement
+  */
+#define MFXSTM32L152_IDD_VREF_AUTO_MEASUREMENT_ENABLE   ((uint8_t) 0x00)
+#define MFXSTM32L152_IDD_VREF_AUTO_MEASUREMENT_DISABLE  ((uint8_t) 0x70)
+
+/**
+  * @brief  IDD Calibration
+  */
+#define MFXSTM32L152_IDD_AUTO_CALIBRATION_ENABLE        ((uint8_t) 0x00)
+#define MFXSTM32L152_IDD_AUTO_CALIBRATION_DISABLE       ((uint8_t) 0x80)
+/**
+  * @}
+  */
+
+/** @defgroup IDD_PreDelay_Defines  IDD PreDelay Defines
+  * @{
+  */
+/**
+  * @brief  IDD PreDelay masks
+  */
+#define MFXSTM32L152_IDD_PREDELAY_UNIT                  ((uint8_t) 0x80)
+#define MFXSTM32L152_IDD_PREDELAY_VALUE                 ((uint8_t) 0x7F)
+
+
+/**
+  * @brief  IDD PreDelay unit
+  */
+#define MFXSTM32L152_IDD_PREDELAY_0_5_MS                ((uint8_t) 0x00)
+#define MFXSTM32L152_IDD_PREDELAY_20_MS                 ((uint8_t) 0x80)
+/**
+  * @}
+  */
+
+/** @defgroup IDD_DeltaDelay_Defines  IDD Delta DElay Defines
+  * @{
+  */
+/**
+  * @brief  IDD Delta Delay masks
+  */
+#define MFXSTM32L152_IDD_DELTADELAY_UNIT                ((uint8_t) 0x80)
+#define MFXSTM32L152_IDD_DELTADELAY_VALUE               ((uint8_t) 0x7F)
+
+
+/**
+  * @brief  IDD Delta Delay unit
+  */
+#define MFXSTM32L152_IDD_DELTADELAY_0_5_MS              ((uint8_t) 0x00)
+#define MFXSTM32L152_IDD_DELTADELAY_20_MS               ((uint8_t) 0x80)
+
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+ 
+/* Exported macro ------------------------------------------------------------*/
+   
+/** @defgroup MFXSTM32L152_Exported_Macros
+  * @{
+  */ 
+
+/**
+  * @}
+  */ 
+
+/* Exported functions --------------------------------------------------------*/
+  
+/** @defgroup MFXSTM32L152_Exported_Functions
+  * @{
+  */
+
+/** 
+  * @brief MFXSTM32L152 Control functions
+  */
+void     mfxstm32l152_Init(uint16_t DeviceAddr);
+void     mfxstm32l152_DeInit(uint16_t DeviceAddr);
+void     mfxstm32l152_Reset(uint16_t DeviceAddr);
+uint16_t mfxstm32l152_ReadID(uint16_t DeviceAddr);
+uint16_t mfxstm32l152_ReadFwVersion(uint16_t DeviceAddr);
+void     mfxstm32l152_LowPower(uint16_t DeviceAddr);
+void     mfxstm32l152_WakeUp(uint16_t DeviceAddr);
+
+void     mfxstm32l152_EnableITSource(uint16_t DeviceAddr, uint8_t Source);
+void     mfxstm32l152_DisableITSource(uint16_t DeviceAddr, uint8_t Source);
+uint8_t  mfxstm32l152_GlobalITStatus(uint16_t DeviceAddr, uint8_t Source);
+void     mfxstm32l152_ClearGlobalIT(uint16_t DeviceAddr, uint8_t Source);
+
+void     mfxstm32l152_SetIrqOutPinPolarity(uint16_t DeviceAddr, uint8_t Polarity);
+void     mfxstm32l152_SetIrqOutPinType(uint16_t DeviceAddr, uint8_t Type);
+
+
+/** 
+  * @brief MFXSTM32L152 IO functionalities functions
+  */
+void     mfxstm32l152_IO_Start(uint16_t DeviceAddr, uint32_t IO_Pin);
+uint8_t  mfxstm32l152_IO_Config(uint16_t DeviceAddr, uint32_t IO_Pin, IO_ModeTypedef IO_Mode);
+void     mfxstm32l152_IO_WritePin(uint16_t DeviceAddr, uint32_t IO_Pin, uint8_t PinState);
+uint32_t mfxstm32l152_IO_ReadPin(uint16_t DeviceAddr, uint32_t IO_Pin);
+void     mfxstm32l152_IO_EnableIT(uint16_t DeviceAddr);
+void     mfxstm32l152_IO_DisableIT(uint16_t DeviceAddr);
+uint32_t mfxstm32l152_IO_ITStatus(uint16_t DeviceAddr, uint32_t IO_Pin);
+void     mfxstm32l152_IO_ClearIT(uint16_t DeviceAddr, uint32_t IO_Pin);
+
+void     mfxstm32l152_IO_InitPin(uint16_t DeviceAddr, uint32_t IO_Pin, uint8_t Direction);
+void     mfxstm32l152_IO_EnableAF(uint16_t DeviceAddr);
+void     mfxstm32l152_IO_DisableAF(uint16_t DeviceAddr);
+void     mfxstm32l152_IO_SetIrqTypeMode(uint16_t DeviceAddr, uint32_t IO_Pin, uint8_t Type);
+void     mfxstm32l152_IO_SetIrqEvtMode(uint16_t DeviceAddr, uint32_t IO_Pin, uint8_t Evt);
+void     mfxstm32l152_IO_EnablePinIT(uint16_t DeviceAddr, uint32_t IO_Pin);
+void     mfxstm32l152_IO_DisablePinIT(uint16_t DeviceAddr, uint32_t IO_Pin);
+
+/** 
+  * @brief MFXSTM32L152 Touch screen functionalities functions
+  */
+void     mfxstm32l152_TS_Start(uint16_t DeviceAddr);
+uint8_t  mfxstm32l152_TS_DetectTouch(uint16_t DeviceAddr);
+void     mfxstm32l152_TS_GetXY(uint16_t DeviceAddr, uint16_t *X, uint16_t *Y);
+void     mfxstm32l152_TS_EnableIT(uint16_t DeviceAddr);
+void     mfxstm32l152_TS_DisableIT(uint16_t DeviceAddr);
+uint8_t  mfxstm32l152_TS_ITStatus (uint16_t DeviceAddr);
+void     mfxstm32l152_TS_ClearIT (uint16_t DeviceAddr);
+
+/**
+  * @brief MFXSTM32L152 IDD current measurement functionalities functions
+  */
+void     mfxstm32l152_IDD_Start(uint16_t DeviceAddr);
+void     mfxstm32l152_IDD_Config(uint16_t DeviceAddr, IDD_ConfigTypeDef MfxIddConfig);
+void     mfxstm32l152_IDD_ConfigShuntNbLimit(uint16_t DeviceAddr, uint8_t ShuntNbLimit);
+void     mfxstm32l152_IDD_GetValue(uint16_t DeviceAddr, uint32_t *ReadValue);
+uint8_t  mfxstm32l152_IDD_GetShuntUsed(uint16_t DeviceAddr);
+void     mfxstm32l152_IDD_EnableIT(uint16_t DeviceAddr);
+void     mfxstm32l152_IDD_ClearIT(uint16_t DeviceAddr);
+uint8_t  mfxstm32l152_IDD_GetITStatus(uint16_t DeviceAddr);
+void     mfxstm32l152_IDD_DisableIT(uint16_t DeviceAddr);
+
+/**
+  * @brief MFXSTM32L152 Error management functions
+  */
+uint8_t  mfxstm32l152_Error_ReadSrc(uint16_t DeviceAddr);
+uint8_t  mfxstm32l152_Error_ReadMsg(uint16_t DeviceAddr);
+void     mfxstm32l152_Error_EnableIT(uint16_t DeviceAddr);
+void     mfxstm32l152_Error_ClearIT(uint16_t DeviceAddr);
+uint8_t  mfxstm32l152_Error_GetITStatus(uint16_t DeviceAddr);
+void     mfxstm32l152_Error_DisableIT(uint16_t DeviceAddr);
+
+uint8_t  mfxstm32l152_ReadReg(uint16_t DeviceAddr, uint8_t RegAddr);
+void     mfxstm32l152_WriteReg(uint16_t DeviceAddr, uint8_t RegAddr, uint8_t Value);
+
+
+
+/** 
+  * @brief iobus prototypes (they should be defined in common/stm32_iobus.h)
+  */
+void     MFX_IO_Init(void);
+void     MFX_IO_DeInit(void);
+void     MFX_IO_ITConfig (void);
+void     MFX_IO_EnableWakeupPin(void);
+void     MFX_IO_Wakeup(void);
+void     MFX_IO_Delay(uint32_t delay);
+void     MFX_IO_Write(uint16_t addr, uint8_t reg, uint8_t value);
+uint8_t  MFX_IO_Read(uint16_t addr, uint8_t reg);
+uint16_t MFX_IO_ReadMultiple(uint16_t addr, uint8_t reg, uint8_t *buffer, uint16_t length);
+
+/**
+  * @}
+  */ 
+
+/* Touch screen driver structure */
+extern TS_DrvTypeDef mfxstm32l152_ts_drv;
+
+/* IO driver structure */
+extern IO_DrvTypeDef mfxstm32l152_io_drv;
+
+/* IDD driver structure */
+extern IDD_DrvTypeDef mfxstm32l152_idd_drv;
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __MFXSTM32L152_H */
+
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */       
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 85 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/spi_sample.c

@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-09-15     thread-liu   first version
+ */
+
+#include "board.h"
+
+#if defined(BSP_USING_SPI1)
+#include <drv_spi.h>
+
+#define SPI_NAME            "spi1"
+#define SPI_DEVICE_NAME     "spi10"
+static struct rt_spi_device *spi_dev = RT_NULL;
+
+/* attach spi1 device */
+static int rt_spi_device_init(void)
+{
+    struct rt_spi_configuration cfg;
+
+    rt_hw_spi_device_attach(SPI_NAME, SPI_DEVICE_NAME, NULL, NULL);
+
+    cfg.data_width = 8;
+    cfg.mode   = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB | RT_SPI_NO_CS;
+    cfg.max_hz = 1 *1000 *1000;
+
+    spi_dev = (struct rt_spi_device *)rt_device_find(SPI_DEVICE_NAME);
+    
+    if (RT_NULL == spi_dev)
+    {
+        rt_kprintf("spi sample run failed! can't find %s device!\n", SPI_NAME);
+        return RT_ERROR;
+    }
+    
+    rt_spi_configure(spi_dev, &cfg);
+    
+    return RT_EOK;
+}
+INIT_APP_EXPORT(rt_spi_device_init);
+
+/* spi5 loopback mode test case */
+static int spi_sample(int argc, char **argv)
+{
+    rt_uint8_t t_buf[8], r_buf[8];     
+    int i = 0; 
+    static struct rt_spi_message msg1;
+    
+    if (argc != 9)
+    {
+        rt_kprintf("Usage:\n");
+        rt_kprintf("spi_sample 1 2 3 4 5 6 7 8\n");
+        return -RT_ERROR;
+    }
+    
+    for (i = 0; i < 8; i++)
+    {
+        t_buf[i] = atoi(argv[i+1]);
+    }
+    
+    msg1.send_buf   = &t_buf;
+    msg1.recv_buf   = &r_buf;
+    msg1.length     = sizeof(t_buf);
+    msg1.cs_take    = 1;
+    msg1.cs_release = 0;
+    msg1.next       = RT_NULL;
+
+    rt_spi_transfer_message(spi_dev, &msg1);
+
+    rt_kprintf("spi rbuf : ");
+    for (i = 0; i < sizeof(t_buf); i++)
+    {
+        rt_kprintf("%x ", r_buf[i]);
+    }
+
+    rt_kprintf("\nspi loopback mode test over!\n");
+
+    return RT_EOK;
+}
+MSH_CMD_EXPORT(spi_sample, spi loopback test);
+
+#endif /* BSP_USING_SPI5 */

+ 160 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/timer_sample.c

@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-07-27     thread-liu        first version
+ */
+
+#include <board.h>
+
+#if defined(BSP_USING_TIM14) && defined(BSP_USING_ADC2)
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define HWTIMER_DEV_NAME   "timer14"
+#define HWADC_DEV_NAME     "adc2"
+#define REFER_VOLTAGE       330         /* voltage reference */
+#define CONVERT_BITS        (1 << 12)   /* Conversion digit */
+#define ADC_DEV_CHANNEL     6
+
+static rt_adc_device_t adc_dev = RT_NULL;
+
+static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
+{
+    rt_uint32_t value = 0 , vol = 0;
+    
+    /* read adc value */
+    value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
+    rt_kprintf("the value is :%d \n", value);
+    
+    vol = value * REFER_VOLTAGE / CONVERT_BITS;
+    rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
+
+    return 0;
+}
+
+static int hwtimer_stop(void)
+{
+    rt_err_t ret = RT_EOK;
+    rt_device_t hw_dev = RT_NULL;
+
+    hw_dev = rt_device_find(HWTIMER_DEV_NAME);
+    if (hw_dev == RT_NULL)
+    {
+        rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME);
+        return RT_ERROR;
+    }
+
+    ret = rt_device_close(hw_dev);
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("close %s device failed!\n", HWTIMER_DEV_NAME);
+        return ret;
+    }
+    
+    /* close adc channel */
+    ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
+    
+    return ret;
+}
+
+static int hwtimer_start(void)
+{
+    rt_err_t ret = RT_EOK;
+    rt_hwtimerval_t timeout_s;     
+    rt_device_t hw_dev = RT_NULL;
+    
+    rt_hwtimer_mode_t mode;
+        
+    hw_dev = rt_device_find(HWTIMER_DEV_NAME);
+    if (hw_dev == RT_NULL)
+    {
+        rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME);
+        return RT_ERROR;
+    }
+
+    /* find adc dev */
+    adc_dev = (rt_adc_device_t)rt_device_find(HWADC_DEV_NAME);
+    if (adc_dev == RT_NULL)
+    {
+        rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWADC_DEV_NAME);
+        return RT_ERROR;
+    }
+    
+    /* Open the device in read/write mode */
+    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("open %s device failed!\n", HWTIMER_DEV_NAME);
+        return ret;
+    }
+
+    /* Set the timeout callback function */
+    rt_device_set_rx_indicate(hw_dev, timeout_cb);
+
+    /* Set the mode to periodic timer */
+    mode = HWTIMER_MODE_PERIOD;
+    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("set mode failed! ret is :%d\n", ret);
+        return ret;
+    }
+
+    timeout_s.sec = 5;
+    timeout_s.usec = 0;
+
+    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
+    {
+        rt_kprintf("set timeout value failed\n");
+        return RT_ERROR;
+    }
+
+    rt_thread_mdelay(3500);
+
+    rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s));
+    rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec);
+    
+    /* enable adc channel */
+    ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
+    
+    return ret;
+}
+
+static int tim_sample(int argc, char *argv[])
+{
+    if (argc > 1)
+    {
+        if (!rt_strcmp(argv[1], "start"))
+        { 
+           rt_kprintf("tim14 will start\n"); 
+           hwtimer_start();
+           return RT_EOK;
+        }
+        else if (!rt_strcmp(argv[1], "stop"))
+        {
+            hwtimer_stop();
+            rt_kprintf("stop tim14 success!\n");
+            return RT_EOK;
+        }
+        else
+        {
+            goto _exit;
+        }
+    }
+_exit:
+    {
+        rt_kprintf("Usage:\n");
+        rt_kprintf("tim_sample start         - start TIM14 \n");
+        rt_kprintf("tim_sample stop          - stop TIM14 \n");
+    }
+    
+    return RT_ERROR;
+}
+MSH_CMD_EXPORT(tim_sample, tim sample);
+
+#endif

+ 1 - 1
bsp/stm32/stm32mp157a-st-ev1/rtconfig.py

@@ -23,7 +23,7 @@ elif CROSS_TOOL == 'keil':
     EXEC_PATH   = r'C:/Keil_v5'
 elif CROSS_TOOL == 'iar':
     PLATFORM    = 'iar'
-    EXEC_PATH   = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0'
+    EXEC_PATH   = r'D:\software\Embedded Workbench 8.3'
 
 if os.getenv('RTT_EXEC_PATH'):
     EXEC_PATH = os.getenv('RTT_EXEC_PATH')