[Cryptech-Commits] [user/shatov/stm32_sdram] 01/01: Initial commit of code, that initializes the two on-board SDRAM chips. Includes simple memory test program.

git at cryptech.is git at cryptech.is
Sun May 22 11:34:51 UTC 2016


This is an automated email from the git hooks/post-receive script.

meisterpaul1 at yandex.ru pushed a commit to branch master
in repository user/shatov/stm32_sdram.

commit 8eea37e61e919819e6ef51d8a1c1bd04cfd0892a
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Sun May 22 14:21:03 2016 +0300

    Initial commit of code, that initializes the two on-board SDRAM chips. Includes simple memory test program.
    
    Note, that there turns out to be a bug in low-level HAL driver, so this commit includes corrected stm32f4xx_ll_fmc.c
---
 fmc.c                |  438 +++++++++++++
 fmc.h                |   76 +++
 gpio.c               |   95 +++
 gpio.h               |   72 +++
 main.c               |  445 +++++++++++++
 mxconstants.h        |   58 ++
 stm32-sdram.c        |  106 +++
 stm32-sdram.h        |   43 ++
 stm32f4xx_hal_conf.h |  448 +++++++++++++
 stm32f4xx_hal_msp.c  |   81 +++
 stm32f4xx_it.c       |  167 +++++
 stm32f4xx_it.h       |   62 ++
 stm32f4xx_ll_fmc.c   | 1738 ++++++++++++++++++++++++++++++++++++++++++++++++++
 13 files changed, 3829 insertions(+)

diff --git a/fmc.c b/fmc.c
new file mode 100644
index 0000000..bd03269
--- /dev/null
+++ b/fmc.c
@@ -0,0 +1,438 @@
+/**
+  ******************************************************************************
+  * File Name          : FMC.c
+  * Description        : This file provides code for the configuration
+  *                      of the FMC peripheral.
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2016 STMicroelectronics
+  *
+  * 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 "fmc.h"
+
+#include "gpio.h"
+
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+SDRAM_HandleTypeDef hsdram1;
+SDRAM_HandleTypeDef hsdram2;
+
+/* FMC initialization function */
+//-----------------------------------------------------------------------------
+void MX_FMC_Init(void)
+//-----------------------------------------------------------------------------
+{
+		// timing parameters
+  FMC_SDRAM_TimingTypeDef SdramTiming;
+
+		//
+		// following settings are for -75E speed grade memory chip
+		// clocked at only 90 MHz instead of the rated 133 MHz
+		//
+		
+  SdramTiming.LoadToActiveDelay			= 2;	// tMRD
+	
+  SdramTiming.ExitSelfRefreshDelay	= 7;	// 67 ns @ 90 MHz is 6.03 cycles, so in theory 6
+																					// can be used here, but let's be on the safe side
+	
+  SdramTiming.SelfRefreshTime				= 5;	// should be >= tRAS (5 cycles)
+	
+  SdramTiming.RowCycleDelay					= 8;	// tRC
+	
+  SdramTiming.WriteRecoveryTime			= 4;	// must be >= tRAS - tRCD (5 - 2 = 3 cycles),
+																					// and >= tRC - tRCD - tRP (8 - 2 - 2 = 4 cycles)
+	
+  SdramTiming.RPDelay								= 2;	// tRP
+	
+  SdramTiming.RCDDelay							= 2;	// tRCD
+	
+	
+		//
+		// configure the first bank
+		//
+		
+	
+		// memory type
+  hsdram1.Instance = FMC_SDRAM_DEVICE;
+  
+		// bank
+  hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
+	
+		// settings for IS42S32160F
+  hsdram1.Init.ColumnBitsNumber		= FMC_SDRAM_COLUMN_BITS_NUM_9;
+  hsdram1.Init.RowBitsNumber			= FMC_SDRAM_ROW_BITS_NUM_13;
+  hsdram1.Init.MemoryDataWidth		= FMC_SDRAM_MEM_BUS_WIDTH_32;
+  hsdram1.Init.InternalBankNumber	= FMC_SDRAM_INTERN_BANKS_NUM_4;
+  hsdram1.Init.CASLatency					= FMC_SDRAM_CAS_LATENCY_2;
+	
+		// write protection not needed
+  hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
+	
+		// memory clock is 90 MHz (HCLK / 2)
+  hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
+	
+		// read burst not needed
+  hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
+	
+		// additional pipeline stages not neeed
+  hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
+	
+		// call HAL layer
+	HAL_SDRAM_Init(&hsdram1, &SdramTiming);
+
+
+		//
+		// configure the second bank
+		//
+		
+		
+		// memory type
+  hsdram2.Instance = FMC_SDRAM_DEVICE;
+	
+		// bank number
+  hsdram2.Init.SDBank = FMC_SDRAM_BANK2;
+	
+		// settings for IS42S32160F
+  hsdram2.Init.ColumnBitsNumber		= FMC_SDRAM_COLUMN_BITS_NUM_9;
+  hsdram2.Init.RowBitsNumber			= FMC_SDRAM_ROW_BITS_NUM_13;
+  hsdram2.Init.MemoryDataWidth		= FMC_SDRAM_MEM_BUS_WIDTH_32;
+  hsdram2.Init.InternalBankNumber	= FMC_SDRAM_INTERN_BANKS_NUM_4;
+  hsdram2.Init.CASLatency					= FMC_SDRAM_CAS_LATENCY_2;
+	
+		// write protection not needed
+  hsdram2.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
+		
+		// memory clock is 90 MHz (HCLK / 2)
+  hsdram2.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
+		
+		// read burst not needed
+  hsdram2.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
+	
+		// additional pipeline stages not neeed
+  hsdram2.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
+  
+		// call HAL layer
+  HAL_SDRAM_Init(&hsdram2, &SdramTiming);
+
+}
+
+static int FMC_Initialized = 0;
+
+static void HAL_FMC_MspInit(void){
+  /* USER CODE BEGIN FMC_MspInit 0 */
+
+  /* USER CODE END FMC_MspInit 0 */
+  GPIO_InitTypeDef GPIO_InitStruct;
+  if (FMC_Initialized) {
+    return;
+  }
+  FMC_Initialized = 1;
+  /* Peripheral clock enable */
+  __HAL_RCC_FMC_CLK_ENABLE();
+  
+  /** FMC GPIO Configuration  
+  PI9   ------> FMC_D30
+  PI10   ------> FMC_D31
+  PF0   ------> FMC_A0
+  PF1   ------> FMC_A1
+  PF2   ------> FMC_A2
+  PF3   ------> FMC_A3
+  PF4   ------> FMC_A4
+  PF5   ------> FMC_A5
+  PC0   ------> FMC_SDNWE
+  PC2   ------> FMC_SDNE0
+  PC3   ------> FMC_SDCKE0
+  PF11   ------> FMC_SDNRAS
+  PF12   ------> FMC_A6
+  PF13   ------> FMC_A7
+  PF14   ------> FMC_A8
+  PF15   ------> FMC_A9
+  PG0   ------> FMC_A10
+  PG1   ------> FMC_A11
+  PE7   ------> FMC_D4
+  PE8   ------> FMC_D5
+  PE9   ------> FMC_D6
+  PE10   ------> FMC_D7
+  PE11   ------> FMC_D8
+  PE12   ------> FMC_D9
+  PE13   ------> FMC_D10
+  PE14   ------> FMC_D11
+  PE15   ------> FMC_D12
+  PH8   ------> FMC_D16
+  PH9   ------> FMC_D17
+  PH10   ------> FMC_D18
+  PH11   ------> FMC_D19
+  PH12   ------> FMC_D20
+  PD8   ------> FMC_D13
+  PD9   ------> FMC_D14
+  PD10   ------> FMC_D15
+  PD14   ------> FMC_D0
+  PD15   ------> FMC_D1
+  PG2   ------> FMC_A12
+  PG4   ------> FMC_BA0
+  PG5   ------> FMC_BA1
+  PG8   ------> FMC_SDCLK
+  PH13   ------> FMC_D21
+  PH14   ------> FMC_D22
+  PH15   ------> FMC_D23
+  PI0   ------> FMC_D24
+  PI1   ------> FMC_D25
+  PI2   ------> FMC_D26
+  PI3   ------> FMC_D27
+  PD0   ------> FMC_D2
+  PD1   ------> FMC_D3
+  PG15   ------> FMC_SDNCAS
+  PB5   ------> FMC_SDCKE1
+  PB6   ------> FMC_SDNE1
+  PE0   ------> FMC_NBL0
+  PE1   ------> FMC_NBL1
+  PI4   ------> FMC_NBL2
+  PI5   ------> FMC_NBL3
+  PI6   ------> FMC_D28
+  PI7   ------> FMC_D29
+  */
+  /* GPIO_InitStruct */
+  GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 
+                          |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5 
+                          |GPIO_PIN_6|GPIO_PIN_7;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
+
+  HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
+
+  /* GPIO_InitStruct */
+  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
+                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 
+                          |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
+
+  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
+
+  /* GPIO_InitStruct */
+  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
+
+  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+  /* GPIO_InitStruct */
+  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 
+                          |GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
+
+  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
+
+  /* GPIO_InitStruct */
+  GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 
+                          |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 
+                          |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
+
+  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
+
+  /* GPIO_InitStruct */
+  GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 
+                          |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
+
+  HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
+
+  /* GPIO_InitStruct */
+  GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 
+                          |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
+
+  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
+
+  /* GPIO_InitStruct */
+  GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
+
+  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+  /* USER CODE BEGIN FMC_MspInit 1 */
+
+  /* USER CODE END FMC_MspInit 1 */
+}
+
+void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef* hsdram){
+  /* USER CODE BEGIN SDRAM_MspInit 0 */
+
+  /* USER CODE END SDRAM_MspInit 0 */
+  HAL_FMC_MspInit();
+  /* USER CODE BEGIN SDRAM_MspInit 1 */
+
+  /* USER CODE END SDRAM_MspInit 1 */
+}
+
+static int FMC_DeInitialized = 0;
+
+static void HAL_FMC_MspDeInit(void){
+  /* USER CODE BEGIN FMC_MspDeInit 0 */
+
+  /* USER CODE END FMC_MspDeInit 0 */
+  if (FMC_DeInitialized) {
+    return;
+  }
+  FMC_DeInitialized = 1;
+  /* Peripheral clock enable */
+  __HAL_RCC_FMC_CLK_DISABLE();
+  
+  /** FMC GPIO Configuration  
+  PI9   ------> FMC_D30
+  PI10   ------> FMC_D31
+  PF0   ------> FMC_A0
+  PF1   ------> FMC_A1
+  PF2   ------> FMC_A2
+  PF3   ------> FMC_A3
+  PF4   ------> FMC_A4
+  PF5   ------> FMC_A5
+  PC0   ------> FMC_SDNWE
+  PC2   ------> FMC_SDNE0
+  PC3   ------> FMC_SDCKE0
+  PF11   ------> FMC_SDNRAS
+  PF12   ------> FMC_A6
+  PF13   ------> FMC_A7
+  PF14   ------> FMC_A8
+  PF15   ------> FMC_A9
+  PG0   ------> FMC_A10
+  PG1   ------> FMC_A11
+  PE7   ------> FMC_D4
+  PE8   ------> FMC_D5
+  PE9   ------> FMC_D6
+  PE10   ------> FMC_D7
+  PE11   ------> FMC_D8
+  PE12   ------> FMC_D9
+  PE13   ------> FMC_D10
+  PE14   ------> FMC_D11
+  PE15   ------> FMC_D12
+  PH8   ------> FMC_D16
+  PH9   ------> FMC_D17
+  PH10   ------> FMC_D18
+  PH11   ------> FMC_D19
+  PH12   ------> FMC_D20
+  PD8   ------> FMC_D13
+  PD9   ------> FMC_D14
+  PD10   ------> FMC_D15
+  PD14   ------> FMC_D0
+  PD15   ------> FMC_D1
+  PG2   ------> FMC_A12
+  PG4   ------> FMC_BA0
+  PG5   ------> FMC_BA1
+  PG8   ------> FMC_SDCLK
+  PH13   ------> FMC_D21
+  PH14   ------> FMC_D22
+  PH15   ------> FMC_D23
+  PI0   ------> FMC_D24
+  PI1   ------> FMC_D25
+  PI2   ------> FMC_D26
+  PI3   ------> FMC_D27
+  PD0   ------> FMC_D2
+  PD1   ------> FMC_D3
+  PG15   ------> FMC_SDNCAS
+  PB5   ------> FMC_SDCKE1
+  PB6   ------> FMC_SDNE1
+  PE0   ------> FMC_NBL0
+  PE1   ------> FMC_NBL1
+  PI4   ------> FMC_NBL2
+  PI5   ------> FMC_NBL3
+  PI6   ------> FMC_D28
+  PI7   ------> FMC_D29
+  */
+
+  HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 
+                          |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5 
+                          |GPIO_PIN_6|GPIO_PIN_7);
+
+  HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
+                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 
+                          |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
+
+  HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3);
+
+  HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4 
+                          |GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15);
+
+  HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 
+                          |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 
+                          |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1);
+
+  HAL_GPIO_DeInit(GPIOH, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 
+                          |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
+
+  HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 
+                          |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1);
+
+  HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5|GPIO_PIN_6);
+
+  /* USER CODE BEGIN FMC_MspDeInit 1 */
+
+  /* USER CODE END FMC_MspDeInit 1 */
+}
+
+void HAL_SDRAM_MspDeInit(SDRAM_HandleTypeDef* hsdram){
+  /* USER CODE BEGIN SDRAM_MspDeInit 0 */
+
+  /* USER CODE END SDRAM_MspDeInit 0 */
+  HAL_FMC_MspDeInit();
+  /* USER CODE BEGIN SDRAM_MspDeInit 1 */
+
+  /* USER CODE END SDRAM_MspDeInit 1 */
+}
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/fmc.h b/fmc.h
new file mode 100644
index 0000000..7ab5db4
--- /dev/null
+++ b/fmc.h
@@ -0,0 +1,76 @@
+/**
+  ******************************************************************************
+  * File Name          : FMC.h
+  * Description        : This file provides code for the configuration
+  *                      of the FMC peripheral.
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2016 STMicroelectronics
+  *
+  * 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 __FMC_H
+#define __FMC_H
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal.h"
+
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+extern SDRAM_HandleTypeDef hsdram1;
+extern SDRAM_HandleTypeDef hsdram2;
+
+/* USER CODE BEGIN Private defines */
+
+/* USER CODE END Private defines */
+
+void MX_FMC_Init(void);
+void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef* hsdram);
+void HAL_SDRAM_MspDeInit(SDRAM_HandleTypeDef* hsdram);
+
+/* USER CODE BEGIN Prototypes */
+
+/* USER CODE END Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__FMC_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/gpio.c b/gpio.c
new file mode 100644
index 0000000..d24af2a
--- /dev/null
+++ b/gpio.c
@@ -0,0 +1,95 @@
+/**
+  ******************************************************************************
+  * File Name          : gpio.c
+  * Description        : This file provides code for the configuration
+  *                      of all used GPIO pins.
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2016 STMicroelectronics
+  *
+  * 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 "gpio.h"
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/*----------------------------------------------------------------------------*/
+/* Configure GPIO                                                             */
+/*----------------------------------------------------------------------------*/
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
+
+/** Configure pins as 
+        * Analog 
+        * Input 
+        * Output
+        * EVENT_OUT
+        * EXTI
+*/
+void MX_GPIO_Init(void)
+{
+
+  GPIO_InitTypeDef GPIO_InitStruct;
+
+  /* GPIO Ports Clock Enable */
+  __HAL_RCC_GPIOI_CLK_ENABLE();
+  __HAL_RCC_GPIOF_CLK_ENABLE();
+  __HAL_RCC_GPIOC_CLK_ENABLE();
+  __HAL_RCC_GPIOG_CLK_ENABLE();
+  __HAL_RCC_GPIOE_CLK_ENABLE();
+  __HAL_RCC_GPIOH_CLK_ENABLE();
+  __HAL_RCC_GPIOD_CLK_ENABLE();
+  __HAL_RCC_GPIOK_CLK_ENABLE();
+  __HAL_RCC_GPIOB_CLK_ENABLE();
+
+  /*Configure GPIO pin Output Level */
+  HAL_GPIO_WritePin(GPIOK, ARM_LED_BLUE_Pin|ARM_LED_GREEN_Pin|ARM_LED_YELLOW_Pin|ARM_LED_RED_Pin, GPIO_PIN_RESET);
+
+  /*Configure GPIO pins : PKPin PKPin PKPin PKPin */
+  GPIO_InitStruct.Pin = ARM_LED_BLUE_Pin|ARM_LED_GREEN_Pin|ARM_LED_YELLOW_Pin|ARM_LED_RED_Pin;
+  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+  HAL_GPIO_Init(GPIOK, &GPIO_InitStruct);
+
+}
+
+/* USER CODE BEGIN 2 */
+
+/* USER CODE END 2 */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/gpio.h b/gpio.h
new file mode 100644
index 0000000..3f68180
--- /dev/null
+++ b/gpio.h
@@ -0,0 +1,72 @@
+/**
+  ******************************************************************************
+  * File Name          : gpio.h
+  * Description        : This file contains all the functions prototypes for 
+  *                      the gpio  
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2016 STMicroelectronics
+  *
+  * 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 __gpio_H
+#define __gpio_H
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal.h"
+
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+/* USER CODE BEGIN Private defines */
+
+/* USER CODE END Private defines */
+
+void MX_GPIO_Init(void);
+
+/* USER CODE BEGIN Prototypes */
+
+/* USER CODE END Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__ pinoutConfig_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..b925dbc
--- /dev/null
+++ b/main.c
@@ -0,0 +1,445 @@
+/**
+  ******************************************************************************
+  * File Name          : main.c
+  * Description        : Main program body
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2016 STMicroelectronics
+  *
+  * 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.
+  *
+  ******************************************************************************
+  */
+
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+#include "stm32f4xx_hal.h"
+#include "gpio.h"
+#include "fmc.h"
+#include "stm32-sdram.h"
+
+
+//-----------------------------------------------------------------------------
+// Prototypes
+//-----------------------------------------------------------------------------
+void SystemClock_Config(void);
+
+int	test_sdram_sequential(uint32_t *base_addr);
+int test_sdram_random(uint32_t *base_addr);
+int test_sdrams_interleaved(uint32_t *base_addr1, uint32_t *base_addr2);
+
+uint32_t lfsr_next_32(uint32_t lfsr);
+uint32_t lfsr_next_24(uint32_t lfsr);
+
+
+//-----------------------------------------------------------------------------
+// Locals
+//-----------------------------------------------------------------------------
+static uint32_t lfsr1;
+static uint32_t lfsr2;
+
+
+//-----------------------------------------------------------------------------
+int main(void)
+//-----------------------------------------------------------------------------
+{
+  HAL_Init();
+  SystemClock_Config();
+  MX_GPIO_Init();
+  MX_FMC_Init();
+
+		// run external memory initialization sequence
+	int ok = sdram_init(&hsdram1, &hsdram2);
+
+		// turn on green LED in case of success,
+		// and keep it on as long as we're happy
+	if (ok) HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_GREEN_Pin, GPIO_PIN_SET);
+	
+		// set LFSRs to some initial value, LFSRs will produce
+		// pseudo-random 32-bit patterns to test our memories
+	lfsr1 = 0xCCAA5533;
+	lfsr2 = 0xCCAA5533;
+	
+		// continuosly test both chips
+	while (ok)
+	{
+			// turn blue led off (testing chips separately)
+		HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_BLUE_Pin, GPIO_PIN_RESET);
+		
+			// run sequential write-then-read test for the first chip
+		ok = test_sdram_sequential(SDRAM_BASEADDR_CHIP1);
+		if (!ok) break;
+	
+			// run random write-then-read test for the first chip
+		ok = test_sdram_random(SDRAM_BASEADDR_CHIP1);
+		if (!ok) break;
+		
+			// run sequential write-then-read test for the second chip
+		ok = test_sdram_sequential(SDRAM_BASEADDR_CHIP2);
+		if (!ok) break;
+	
+			// run random write-then-read test for the second chip
+		ok = test_sdram_random(SDRAM_BASEADDR_CHIP2);
+		if (!ok) break;
+		
+			// turn blue led on (testing two chips at the same time)
+		HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_BLUE_Pin, GPIO_PIN_SET);
+		
+			// run interleaved write-then-read test for both chips at once
+		ok = test_sdrams_interleaved(SDRAM_BASEADDR_CHIP1, SDRAM_BASEADDR_CHIP2);
+		if (!ok) break;
+
+	}
+	
+		/* should only get here in case of failure */
+
+		//
+		// turn all leds off
+		//
+	HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_BLUE_Pin,   GPIO_PIN_RESET);
+	HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_GREEN_Pin,  GPIO_PIN_RESET);
+	HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_YELLOW_Pin, GPIO_PIN_RESET);
+	HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_RED_Pin,    GPIO_PIN_RESET);
+		
+		//
+		// repeatedly flash the red led to indicate failure
+		//
+	for (;;)
+	{
+		HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_RED_Pin, GPIO_PIN_RESET);
+		HAL_Delay(100);
+		
+		HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_RED_Pin, GPIO_PIN_SET);		
+		HAL_Delay(100);
+	}
+
+}
+
+
+//-----------------------------------------------------------------------------
+int	test_sdram_sequential(uint32_t *base_addr)
+//-----------------------------------------------------------------------------
+{
+		// memory offset
+	int offset;
+
+		// readback value
+	uint32_t sdram_readback;
+	
+	
+		/* This test fills entire memory chip with some pseudo-random pattern
+	     starting from the very first cell and going in linear fashion. It then
+	     reads entire memory and compares read values with what was written. */
+	
+	
+		// turn on yellow led to indicate, that we're writing
+	HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_YELLOW_Pin, GPIO_PIN_SET);
+	
+	
+		//
+		// Note, that SDRAM_SIZE is in BYTES, and since we write using
+		// 32-bit words, total number of words is SDRAM_SIZE / 4.
+		//
+	
+		// fill entire memory with "random" values
+	for (offset=0; offset<(SDRAM_SIZE >> 2); offset++)
+	{
+			// generate next "random" value to write
+		lfsr1 = lfsr_next_32(lfsr1);
+		
+			// write to memory
+		base_addr[offset] = lfsr1;
+	}
+	
+	
+		// turn off yellow led to indicate, that we're going to read
+	HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_YELLOW_Pin, GPIO_PIN_RESET);
+		
+	
+		// read entire memory and compare values
+	for (offset=0; offset<(SDRAM_SIZE >> 2); offset++)
+	{
+			// generate next "random" value (we use the second LFSR to catch up)
+		lfsr2 = lfsr_next_32(lfsr2);
+		
+			// read from memory
+		sdram_readback = base_addr[offset];
+		
+			// compare and abort test in case of mismatch
+		if (sdram_readback != lfsr2) return 0;
+	}
+		
+		// done
+	return 1;
+}
+
+
+//-----------------------------------------------------------------------------
+int	test_sdram_random(uint32_t *base_addr)
+//-----------------------------------------------------------------------------
+{
+		// cell counter, memory offset
+	int counter, offset;
+
+		// readback value
+	uint32_t sdram_readback;
+	
+	
+	/* This test fills entire memory chip with some pseudo-random pattern
+		 starting from the very first cell, but then jumping around in pseudo-
+	   random fashion to make sure, that SDRAM controller in STM32 handles
+	   bank, row and column switching correctly. It then reads entire memory
+	   and compares read values with what was written. */
+	
+	
+		// turn on yellow led to indicate, that we're writing
+	HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_YELLOW_Pin, GPIO_PIN_SET);
+	
+	
+		//
+		// Note, that SDRAM_SIZE is in BYTES, and since we write using
+		// 32-bit words, total number of words is SDRAM_SIZE / 4.
+		//
+	
+		// start with the first cell
+	for (counter=0, offset=0; counter<(SDRAM_SIZE >> 2); counter++)
+	{
+			// generate next "random" value to write
+		lfsr1 = lfsr_next_32(lfsr1);
+
+			// write to memory
+		base_addr[offset] = lfsr1;
+		
+			// generate next "random" address
+		
+			//
+			// Note, that for 64 MB memory with 32-bit data bus we need 24 bits
+			// of address, so we use 24-bit LFSR here. Since LFSR has only 2^^24-1
+			// states, i.e. all possible 24-bit values excluding 0, we have to
+			// manually kick it into some arbitrary state during the first iteration.
+			//
+		
+		offset = offset ? lfsr_next_24(offset) : 0x00DEC0DE;
+	}
+		
+	
+		// turn off yellow led to indicate, that we're going to read
+	HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_YELLOW_Pin, GPIO_PIN_RESET);
+	
+	
+		// read entire memory and compare values
+	for (counter=0, offset=0; counter<(SDRAM_SIZE >> 2); counter++)
+	{
+			// generate next "random" value (we use the second LFSR to catch up)
+		lfsr2 = lfsr_next_32(lfsr2);
+		
+			// read from memory
+		sdram_readback = base_addr[offset];
+		
+			// compare and abort test in case of mismatch
+		if (sdram_readback != lfsr2) return 0;
+		
+			// generate next "random" address
+		offset = offset ? lfsr_next_24(offset) : 0x00DEC0DE;
+	}
+	
+		//
+		// we should have walked exactly 2**24 iterations and returned
+		// back to the arbitrary starting address...
+		//
+		
+	if (offset != 0x00DEC0DE) return 0;
+	
+		
+			// done
+		return 1;
+}
+
+
+//-----------------------------------------------------------------------------
+int test_sdrams_interleaved(uint32_t *base_addr1, uint32_t *base_addr2)
+//-----------------------------------------------------------------------------
+{
+	// cell counter, memory offsets
+	int counter, offset1, offset2;
+
+		// readback value
+	uint32_t sdram_readback;
+	
+	
+	/* Basically this is the same as test_sdram_random() except that it
+		 tests both memory chips at the same time. */
+	
+	
+		// turn on yellow led to indicate, that we're writing
+	HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_YELLOW_Pin, GPIO_PIN_SET);
+	
+	
+		//
+		// Note, that SDRAM_SIZE is in BYTES, and since we write using
+		// 32-bit words, total number of words is SDRAM_SIZE / 4.
+		//
+	
+		// start with the first cell
+	for (counter=0, offset1=0, offset2=0; counter<(SDRAM_SIZE >> 2); counter++)
+	{
+			// generate next "random" value to write
+		lfsr1 = lfsr_next_32(lfsr1);
+
+			// write to memory
+		base_addr1[offset1] = lfsr1;
+		base_addr2[offset2] = lfsr1;
+		
+			// generate next "random" addresses (use different starting states!)
+		
+		offset1 = offset1 ? lfsr_next_24(offset1) : 0x00ABCDEF;
+		offset2 = offset2 ? lfsr_next_24(offset2) : 0x00FEDCBA;
+	}
+		
+	
+		// turn off yellow led to indicate, that we're going to read
+	HAL_GPIO_WritePin(ARM_LED_GPIO_Port, ARM_LED_YELLOW_Pin, GPIO_PIN_RESET);
+	
+	
+		// read entire memory and compare values
+	for (counter=0, offset1=0, offset2=0; counter<(SDRAM_SIZE >> 2); counter++)
+	{
+			// generate next "random" value (we use the second LFSR to catch up)
+		lfsr2 = lfsr_next_32(lfsr2);
+		
+			// read from the first memory and compare
+		sdram_readback = base_addr1[offset1];
+		if (sdram_readback != lfsr2) return 0;
+		
+			// read from the second memory and compare
+		sdram_readback = base_addr2[offset2];
+		if (sdram_readback != lfsr2) return 0;
+		
+			// generate next "random" addresses
+		offset1 = offset1 ? lfsr_next_24(offset1) : 0x00ABCDEF;
+		offset2 = offset2 ? lfsr_next_24(offset2) : 0x00FEDCBA;
+	}
+	
+		//
+		// we should have walked exactly 2**24 iterations and returned
+		// back to the arbitrary starting address...
+		//
+		
+	if (offset1 != 0x00ABCDEF) return 0;
+	if (offset2 != 0x00FEDCBA) return 0;
+	
+		
+			// done
+		return 1;
+}
+
+
+//-----------------------------------------------------------------------------
+void SystemClock_Config(void)
+//-----------------------------------------------------------------------------
+{
+
+  RCC_OscInitTypeDef RCC_OscInitStruct;
+  RCC_ClkInitTypeDef RCC_ClkInitStruct;
+
+  __HAL_RCC_PWR_CLK_ENABLE();
+
+  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
+
+  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
+  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
+  RCC_OscInitStruct.HSICalibrationValue = 16;
+  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
+  RCC_OscInitStruct.PLL.PLLM = 16;
+  RCC_OscInitStruct.PLL.PLLN = 360;
+  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
+  RCC_OscInitStruct.PLL.PLLQ = 4;
+  HAL_RCC_OscConfig(&RCC_OscInitStruct);
+
+  HAL_PWREx_EnableOverDrive();
+
+  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
+                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
+  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
+  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
+  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
+
+  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
+
+  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
+
+  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
+}
+
+
+
+//-----------------------------------------------------------------------------
+uint32_t lfsr_next_32(uint32_t lfsr)
+//-----------------------------------------------------------------------------
+{
+	uint32_t tap = 0;
+
+	tap ^= (lfsr >> 31);
+	tap ^= (lfsr >> 30);
+	tap ^= (lfsr >> 29);
+	tap ^= (lfsr >> 9);
+
+	return (lfsr << 1) | (tap & 1);
+}
+
+
+//-----------------------------------------------------------------------------
+uint32_t lfsr_next_24(uint32_t lfsr)
+//-----------------------------------------------------------------------------
+{
+	unsigned int tap = 0;
+
+	tap ^= (lfsr >> 23);
+	tap ^= (lfsr >> 22);
+	tap ^= (lfsr >> 21);
+	tap ^= (lfsr >> 16);
+
+	return ((lfsr << 1) | (tap & 1)) & 0x00FFFFFF;
+}
+
+
+//-----------------------------------------------------------------------------
+#ifdef USE_FULL_ASSERT
+//-----------------------------------------------------------------------------
+void assert_failed(uint8_t* file, uint32_t line)
+//-----------------------------------------------------------------------------
+{
+}
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// End-of-File
+//-----------------------------------------------------------------------------
diff --git a/mxconstants.h b/mxconstants.h
new file mode 100644
index 0000000..1af1291
--- /dev/null
+++ b/mxconstants.h
@@ -0,0 +1,58 @@
+/**
+  ******************************************************************************
+  * File Name          : mxconstants.h
+  * Description        : This file contains the common defines of the application
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2016 STMicroelectronics
+  *
+  * 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 ------------------------------------------------------------------*/
+
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+/* Private define ------------------------------------------------------------*/
+
+#define ARM_LED_BLUE_Pin GPIO_PIN_4
+#define ARM_LED_GREEN_Pin GPIO_PIN_5
+#define ARM_LED_YELLOW_Pin GPIO_PIN_6
+#define ARM_LED_RED_Pin GPIO_PIN_7
+#define ARM_LED_GPIO_Port GPIOK
+/* USER CODE BEGIN Private defines */
+
+/* USER CODE END Private defines */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+*/ 
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm32-sdram.c b/stm32-sdram.c
new file mode 100644
index 0000000..16386e8
--- /dev/null
+++ b/stm32-sdram.c
@@ -0,0 +1,106 @@
+//-----------------------------------------------------------------------------
+// stm32-sdram.c
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+#include "stm32f4xx_hal.h"
+#include "stm32-sdram.h"
+
+
+//-----------------------------------------------------------------------------
+int sdram_init(SDRAM_HandleTypeDef *sdram1, SDRAM_HandleTypeDef *sdram2)
+//-----------------------------------------------------------------------------
+{
+	HAL_StatusTypeDef ok;						// status
+	FMC_SDRAM_CommandTypeDef cmd;		// command
+
+	
+		//
+		// enable clocking
+		//
+	cmd.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
+	cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+	cmd.AutoRefreshNumber = 1;
+	cmd.ModeRegisterDefinition = 0;
+	
+	HAL_Delay(1);
+	ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
+	if (ok != HAL_OK) return 0;
+	
+		//
+		// precharge all banks
+		//
+	cmd.CommandMode = FMC_SDRAM_CMD_PALL;
+	cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+	cmd.AutoRefreshNumber = 1;
+	cmd.ModeRegisterDefinition = 0;
+	
+	HAL_Delay(1);
+	ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
+	if (ok != HAL_OK) return 0;
+	
+	
+		//
+		// send two auto-refresh commands in a row
+		//
+	cmd.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
+	cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+	cmd.AutoRefreshNumber = 1;
+	cmd.ModeRegisterDefinition = 0;
+		
+	ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
+	if (ok != HAL_OK) return 1;
+		
+	ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
+	if (ok != HAL_OK) return 1;	
+	
+		
+		//
+		// load mode register
+		//
+	cmd.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
+	cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
+	cmd.AutoRefreshNumber = 1;
+	cmd.ModeRegisterDefinition = 	SDRAM_MODEREG_BURST_LENGTH_1					|
+																SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL		|
+																SDRAM_MODEREG_CAS_LATENCY_2						|
+																SDRAM_MODEREG_OPERATING_MODE_STANDARD	|
+																SDRAM_MODEREG_WRITEBURST_MODE_SINGLE	;
+
+	ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1);
+	if (ok != HAL_OK) return 1;
+
+
+		//
+		// set number of consequtive auto-refresh commands
+		// and program refresh rate
+		//
+
+		//
+		// RefreshRate = 64 ms / 8192 cyc = 7.8125 us/cyc
+		//
+		// RefreshCycles = 7.8125 us * 90 MHz = 703
+		//
+		// According to the formula on p.1665 of the reference manual,
+		// we also need to subtract 20 from the value, so the target
+		// refresh rate is 703 - 20 = 683.
+		//
+		
+	ok = HAL_SDRAM_SetAutoRefreshNumber(sdram1, 8);
+	if (ok != HAL_OK) return 1;
+
+	HAL_SDRAM_ProgramRefreshRate(sdram1, 683);
+	if (ok != HAL_OK) return 1;
+	
+	
+		// done
+	return 1;
+}
+
+
+//-----------------------------------------------------------------------------
+// End-of-File
+//-----------------------------------------------------------------------------
diff --git a/stm32-sdram.h b/stm32-sdram.h
new file mode 100644
index 0000000..2e4361c
--- /dev/null
+++ b/stm32-sdram.h
@@ -0,0 +1,43 @@
+//-----------------------------------------------------------------------------
+// stm32-sdram.h
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Defined Values
+//-----------------------------------------------------------------------------
+
+	/* Base Addresses */
+#define SDRAM_BASEADDR_CHIP1		((uint32_t *)0xC0000000)
+#define SDRAM_BASEADDR_CHIP2		((uint32_t *)0xD0000000)
+
+	/* Memory Size */
+#define SDRAM_SIZE		0x4000000		// 64 MBytes (512 Mbits)
+
+	/* Mode Register Bits */
+#define SDRAM_MODEREG_BURST_LENGTH_1             ((uint16_t)0x0000)
+#define SDRAM_MODEREG_BURST_LENGTH_2             ((uint16_t)0x0001)
+#define SDRAM_MODEREG_BURST_LENGTH_4             ((uint16_t)0x0002)
+#define SDRAM_MODEREG_BURST_LENGTH_8             ((uint16_t)0x0004)
+
+#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL      ((uint16_t)0x0000)
+#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED     ((uint16_t)0x0008)
+
+#define SDRAM_MODEREG_CAS_LATENCY_2              ((uint16_t)0x0020)
+#define SDRAM_MODEREG_CAS_LATENCY_3              ((uint16_t)0x0030)
+
+#define SDRAM_MODEREG_OPERATING_MODE_STANDARD    ((uint16_t)0x0000)
+
+#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
+#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE     ((uint16_t)0x0200)
+
+
+//-----------------------------------------------------------------------------
+// Prototypes
+//-----------------------------------------------------------------------------
+int sdram_init(SDRAM_HandleTypeDef *sdram1, SDRAM_HandleTypeDef *sdram2);
+
+
+//-----------------------------------------------------------------------------
+// End-of-File
+//-----------------------------------------------------------------------------
diff --git a/stm32f4xx_hal_conf.h b/stm32f4xx_hal_conf.h
new file mode 100644
index 0000000..8c6c92e
--- /dev/null
+++ b/stm32f4xx_hal_conf.h
@@ -0,0 +1,448 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_hal_conf.h
+  * @brief   HAL configuration file.             
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© COPYRIGHT(c) 2016 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 __STM32F4xx_HAL_CONF_H
+#define __STM32F4xx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "mxconstants.h" 
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* ########################## Module Selection ############################## */
+/**
+  * @brief This is the list of modules to be used in the HAL driver 
+  */
+#define HAL_MODULE_ENABLED  
+
+//#define HAL_ADC_MODULE_ENABLED   
+//#define HAL_CAN_MODULE_ENABLED   
+//#define HAL_CRC_MODULE_ENABLED   
+//#define HAL_CRYP_MODULE_ENABLED   
+//#define HAL_DAC_MODULE_ENABLED   
+//#define HAL_DCMI_MODULE_ENABLED   
+//#define HAL_DMA2D_MODULE_ENABLED   
+//#define HAL_ETH_MODULE_ENABLED   
+//#define HAL_NAND_MODULE_ENABLED   
+//#define HAL_NOR_MODULE_ENABLED   
+//#define HAL_PCCARD_MODULE_ENABLED   
+//#define HAL_SRAM_MODULE_ENABLED   
+#define HAL_SDRAM_MODULE_ENABLED
+//#define HAL_HASH_MODULE_ENABLED   
+//#define HAL_I2C_MODULE_ENABLED   
+//#define HAL_I2S_MODULE_ENABLED   
+//#define HAL_IWDG_MODULE_ENABLED   
+//#define HAL_LTDC_MODULE_ENABLED   
+//#define HAL_RNG_MODULE_ENABLED   
+//#define HAL_RTC_MODULE_ENABLED   
+//#define HAL_SAI_MODULE_ENABLED   
+//#define HAL_SD_MODULE_ENABLED   
+//#define HAL_SPI_MODULE_ENABLED   
+//#define HAL_TIM_MODULE_ENABLED   
+//#define HAL_UART_MODULE_ENABLED   
+//#define HAL_USART_MODULE_ENABLED   
+//#define HAL_IRDA_MODULE_ENABLED   
+//#define HAL_SMARTCARD_MODULE_ENABLED   
+//#define HAL_WWDG_MODULE_ENABLED   
+//#define HAL_PCD_MODULE_ENABLED   
+//#define HAL_HCD_MODULE_ENABLED   
+//#define HAL_DSI_MODULE_ENABLED   
+//#define HAL_QSPI_MODULE_ENABLED   
+//#define HAL_QSPI_MODULE_ENABLED   
+//#define HAL_CEC_MODULE_ENABLED   
+//#define HAL_FMPI2C_MODULE_ENABLED   
+//#define HAL_SPDIFRX_MODULE_ENABLED   
+//#define HAL_DFSDM_MODULE_ENABLED   
+//#define HAL_LPTIM_MODULE_ENABLED   
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+
+/* ########################## HSE/HSI Values adaptation ##################### */
+/**
+  * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+  *        This value is used by the RCC HAL module to compute the system frequency
+  *        (when HSE is used as system clock source, directly or through the PLL).  
+  */
+#if !defined  (HSE_VALUE) 
+  #define HSE_VALUE    ((uint32_t)25000000U) /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined  (HSE_STARTUP_TIMEOUT)
+  #define HSE_STARTUP_TIMEOUT    ((uint32_t)100U)   /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+  * @brief Internal High Speed oscillator (HSI) value.
+  *        This value is used by the RCC HAL module to compute the system frequency
+  *        (when HSI is used as system clock source, directly or through the PLL). 
+  */
+#if !defined  (HSI_VALUE)
+  #define HSI_VALUE    ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+  * @brief Internal Low Speed oscillator (LSI) value.
+  */
+#if !defined  (LSI_VALUE) 
+ #define LSI_VALUE  ((uint32_t)32000U)       /*!< LSI Typical Value in Hz*/
+#endif /* LSI_VALUE */                      /*!< Value of the Internal Low Speed oscillator in Hz
+                                             The real value may vary depending on the variations
+                                             in voltage and temperature.*/
+/**
+  * @brief External Low Speed oscillator (LSE) value.
+  */
+#if !defined  (LSE_VALUE)
+ #define LSE_VALUE  ((uint32_t)32768U)    /*!< Value of the External Low Speed oscillator in Hz */
+#endif /* LSE_VALUE */
+
+#if !defined  (LSE_STARTUP_TIMEOUT)
+  #define LSE_STARTUP_TIMEOUT    ((uint32_t)5000U)   /*!< Time out for LSE start up, in ms */
+#endif /* LSE_STARTUP_TIMEOUT */
+
+/**
+  * @brief External clock source for I2S peripheral
+  *        This value is used by the I2S HAL module to compute the I2S clock source 
+  *        frequency, this source is inserted directly through I2S_CKIN pad. 
+  */
+#if !defined  (EXTERNAL_CLOCK_VALUE)
+  #define EXTERNAL_CLOCK_VALUE    ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/
+#endif /* EXTERNAL_CLOCK_VALUE */
+
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+   ===  you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+  * @brief This is the HAL system configuration section
+  */
+#define  VDD_VALUE		      ((uint32_t)3300U) /*!< Value of VDD in mv */           
+#define  TICK_INT_PRIORITY            ((uint32_t)0U)   /*!< tick interrupt priority */            
+#define  USE_RTOS                     0U     
+#define  PREFETCH_ENABLE              1U
+#define  INSTRUCTION_CACHE_ENABLE     1U
+#define  DATA_CACHE_ENABLE            1U
+
+/* ########################## Assert Selection ############################## */
+/**
+  * @brief Uncomment the line below to expanse the "assert_param" macro in the 
+  *        HAL drivers code
+  */
+/* #define USE_FULL_ASSERT    1U */
+
+/* ################## Ethernet peripheral configuration ##################### */
+
+/* Section 1 : Ethernet peripheral configuration */
+
+/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
+#define MAC_ADDR0   2U
+#define MAC_ADDR1   0U
+#define MAC_ADDR2   0U
+#define MAC_ADDR3   0U
+#define MAC_ADDR4   0U
+#define MAC_ADDR5   0U
+
+/* Definition of the Ethernet driver buffers size and count */   
+#define ETH_RX_BUF_SIZE                ETH_MAX_PACKET_SIZE /* buffer size for receive               */
+#define ETH_TX_BUF_SIZE                ETH_MAX_PACKET_SIZE /* buffer size for transmit              */
+#define ETH_RXBUFNB                    ((uint32_t)4U)       /* 4 Rx buffers of size ETH_RX_BUF_SIZE  */
+#define ETH_TXBUFNB                    ((uint32_t)4U)       /* 4 Tx buffers of size ETH_TX_BUF_SIZE  */
+
+/* Section 2: PHY configuration section */
+
+/* DP83848 PHY Address*/ 
+#define DP83848_PHY_ADDRESS             0x01U
+/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ 
+#define PHY_RESET_DELAY                 ((uint32_t)0x000000FFU)
+/* PHY Configuration delay */
+#define PHY_CONFIG_DELAY                ((uint32_t)0x00000FFFU)
+
+#define PHY_READ_TO                     ((uint32_t)0x0000FFFFU)
+#define PHY_WRITE_TO                    ((uint32_t)0x0000FFFFU)
+
+/* Section 3: Common PHY Registers */
+
+#define PHY_BCR                         ((uint16_t)0x0000U)    /*!< Transceiver Basic Control Register   */
+#define PHY_BSR                         ((uint16_t)0x0001U)    /*!< Transceiver Basic Status Register    */
+ 
+#define PHY_RESET                       ((uint16_t)0x8000U)  /*!< PHY Reset */
+#define PHY_LOOPBACK                    ((uint16_t)0x4000U)  /*!< Select loop-back mode */
+#define PHY_FULLDUPLEX_100M             ((uint16_t)0x2100U)  /*!< Set the full-duplex mode at 100 Mb/s */
+#define PHY_HALFDUPLEX_100M             ((uint16_t)0x2000U)  /*!< Set the half-duplex mode at 100 Mb/s */
+#define PHY_FULLDUPLEX_10M              ((uint16_t)0x0100U)  /*!< Set the full-duplex mode at 10 Mb/s  */
+#define PHY_HALFDUPLEX_10M              ((uint16_t)0x0000U)  /*!< Set the half-duplex mode at 10 Mb/s  */
+#define PHY_AUTONEGOTIATION             ((uint16_t)0x1000U)  /*!< Enable auto-negotiation function     */
+#define PHY_RESTART_AUTONEGOTIATION     ((uint16_t)0x0200U)  /*!< Restart auto-negotiation function    */
+#define PHY_POWERDOWN                   ((uint16_t)0x0800U)  /*!< Select the power down mode           */
+#define PHY_ISOLATE                     ((uint16_t)0x0400U)  /*!< Isolate PHY from MII                 */
+
+#define PHY_AUTONEGO_COMPLETE           ((uint16_t)0x0020U)  /*!< Auto-Negotiation process completed   */
+#define PHY_LINKED_STATUS               ((uint16_t)0x0004U)  /*!< Valid link established               */
+#define PHY_JABBER_DETECTION            ((uint16_t)0x0002U)  /*!< Jabber condition detected            */
+  
+/* Section 4: Extended PHY Registers */
+
+#define PHY_SR                          ((uint16_t)0x0010U)    /*!< PHY status register Offset                      */
+#define PHY_MICR                        ((uint16_t)0x0011U)    /*!< MII Interrupt Control Register                  */
+#define PHY_MISR                        ((uint16_t)0x0012U)    /*!< MII Interrupt Status and Misc. Control Register */
+ 
+#define PHY_LINK_STATUS                 ((uint16_t)0x0001U)  /*!< PHY Link mask                                   */
+#define PHY_SPEED_STATUS                ((uint16_t)0x0002U)  /*!< PHY Speed mask                                  */
+#define PHY_DUPLEX_STATUS               ((uint16_t)0x0004U)  /*!< PHY Duplex mask                                 */
+
+#define PHY_MICR_INT_EN                 ((uint16_t)0x0002U)  /*!< PHY Enable interrupts                           */
+#define PHY_MICR_INT_OE                 ((uint16_t)0x0001U)  /*!< PHY Enable output interrupt events              */
+
+#define PHY_MISR_LINK_INT_EN            ((uint16_t)0x0020U)  /*!< Enable Interrupt on change of link status       */
+#define PHY_LINK_INTERRUPT              ((uint16_t)0x2000U)  /*!< PHY link status interrupt mask                  */
+
+/* ################## SPI peripheral configuration ########################## */
+
+/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
+* Activated: CRC code is present inside driver
+* Deactivated: CRC code cleaned from driver
+*/
+
+#define USE_SPI_CRC                     0U
+
+/* Includes ------------------------------------------------------------------*/
+/**
+  * @brief Include module's header file 
+  */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+  #include "stm32f4xx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+  #include "stm32f4xx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+  #include "stm32f4xx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+   
+#ifdef HAL_CORTEX_MODULE_ENABLED
+  #include "stm32f4xx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+  #include "stm32f4xx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_CAN_MODULE_ENABLED
+  #include "stm32f4xx_hal_can.h"
+#endif /* HAL_CAN_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+  #include "stm32f4xx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+  #include "stm32f4xx_hal_cryp.h" 
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_DMA2D_MODULE_ENABLED
+  #include "stm32f4xx_hal_dma2d.h"
+#endif /* HAL_DMA2D_MODULE_ENABLED */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+  #include "stm32f4xx_hal_dac.h"
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+#ifdef HAL_DCMI_MODULE_ENABLED
+  #include "stm32f4xx_hal_dcmi.h"
+#endif /* HAL_DCMI_MODULE_ENABLED */
+
+#ifdef HAL_ETH_MODULE_ENABLED
+  #include "stm32f4xx_hal_eth.h"
+#endif /* HAL_ETH_MODULE_ENABLED */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+  #include "stm32f4xx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+ 
+#ifdef HAL_SRAM_MODULE_ENABLED
+  #include "stm32f4xx_hal_sram.h"
+#endif /* HAL_SRAM_MODULE_ENABLED */
+
+#ifdef HAL_NOR_MODULE_ENABLED
+  #include "stm32f4xx_hal_nor.h"
+#endif /* HAL_NOR_MODULE_ENABLED */
+
+#ifdef HAL_NAND_MODULE_ENABLED
+  #include "stm32f4xx_hal_nand.h"
+#endif /* HAL_NAND_MODULE_ENABLED */
+
+#ifdef HAL_PCCARD_MODULE_ENABLED
+  #include "stm32f4xx_hal_pccard.h"
+#endif /* HAL_PCCARD_MODULE_ENABLED */ 
+  
+#ifdef HAL_SDRAM_MODULE_ENABLED
+  #include "stm32f4xx_hal_sdram.h"
+#endif /* HAL_SDRAM_MODULE_ENABLED */      
+
+#ifdef HAL_HASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_hash.h"
+#endif /* HAL_HASH_MODULE_ENABLED */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_I2S_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2s.h"
+#endif /* HAL_I2S_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LTDC_MODULE_ENABLED
+ #include "stm32f4xx_hal_ltdc.h"
+#endif /* HAL_LTDC_MODULE_ENABLED */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32f4xx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+ #include "stm32f4xx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+ #include "stm32f4xx_hal_sai.h"
+#endif /* HAL_SAI_MODULE_ENABLED */
+
+#ifdef HAL_SD_MODULE_ENABLED
+ #include "stm32f4xx_hal_sd.h"
+#endif /* HAL_SD_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32f4xx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32f4xx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32f4xx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+#ifdef HAL_HCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_hcd.h"
+#endif /* HAL_HCD_MODULE_ENABLED */
+   
+#ifdef HAL_DSI_MODULE_ENABLED
+ #include "stm32f4xx_hal_dsi.h"
+#endif /* HAL_DSI_MODULE_ENABLED */
+
+#ifdef HAL_QSPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_qspi.h"
+#endif /* HAL_QSPI_MODULE_ENABLED */
+
+#ifdef HAL_CEC_MODULE_ENABLED
+ #include "stm32f4xx_hal_cec.h"
+#endif /* HAL_CEC_MODULE_ENABLED */
+
+#ifdef HAL_FMPI2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_fmpi2c.h"
+#endif /* HAL_FMPI2C_MODULE_ENABLED */
+
+#ifdef HAL_SPDIFRX_MODULE_ENABLED
+ #include "stm32f4xx_hal_spdifrx.h"
+#endif /* HAL_SPDIFRX_MODULE_ENABLED */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_lptim.h"
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+   
+/* Exported macro ------------------------------------------------------------*/
+#ifdef  USE_FULL_ASSERT
+/**
+  * @brief  The assert_param macro is used for function's parameters check.
+  * @param  expr: If expr is false, it calls assert_failed function
+  *         which reports the name of the source file and the source
+  *         line number of the call that failed. 
+  *         If expr is true, it returns no value.
+  * @retval None
+  */
+  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+  void assert_failed(uint8_t* file, uint32_t line);
+#else
+  #define assert_param(expr) ((void)0)
+#endif /* USE_FULL_ASSERT */    
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_HAL_CONF_H */
+ 
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm32f4xx_hal_msp.c b/stm32f4xx_hal_msp.c
new file mode 100644
index 0000000..bb215f8
--- /dev/null
+++ b/stm32f4xx_hal_msp.c
@@ -0,0 +1,81 @@
+/**
+  ******************************************************************************
+  * File Name          : stm32f4xx_hal_msp.c
+  * Description        : This file provides code for the MSP Initialization 
+  *                      and de-Initialization codes.
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2016 STMicroelectronics
+  *
+  * 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 "stm32f4xx_hal.h"
+
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/**
+  * Initializes the Global MSP.
+  */
+void HAL_MspInit(void)
+{
+  /* USER CODE BEGIN MspInit 0 */
+
+  /* USER CODE END MspInit 0 */
+
+  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
+
+  /* System interrupt init*/
+  /* MemoryManagement_IRQn interrupt configuration */
+  HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0);
+  /* BusFault_IRQn interrupt configuration */
+  HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0);
+  /* UsageFault_IRQn interrupt configuration */
+  HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0);
+  /* DebugMonitor_IRQn interrupt configuration */
+  HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0);
+  /* SysTick_IRQn interrupt configuration */
+  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
+
+  /* USER CODE BEGIN MspInit 1 */
+
+  /* USER CODE END MspInit 1 */
+}
+
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm32f4xx_it.c b/stm32f4xx_it.c
new file mode 100644
index 0000000..9613330
--- /dev/null
+++ b/stm32f4xx_it.c
@@ -0,0 +1,167 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_it.c
+  * @brief   Interrupt Service Routines.
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2016 STMicroelectronics
+  *
+  * 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 "stm32f4xx_hal.h"
+#include "stm32f4xx.h"
+#include "stm32f4xx_it.h"
+
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/* External variables --------------------------------------------------------*/
+
+/******************************************************************************/
+/*            Cortex-M4 Processor Interruption and Exception Handlers         */ 
+/******************************************************************************/
+
+/**
+* @brief This function handles Non maskable interrupt.
+*/
+void NMI_Handler(void)
+{
+  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
+
+  /* USER CODE END NonMaskableInt_IRQn 0 */
+  
+  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
+
+  /* USER CODE END NonMaskableInt_IRQn 1 */
+}
+
+/**
+* @brief This function handles Hard fault interrupt.
+*/
+void HardFault_Handler(void)
+{
+  /* USER CODE BEGIN HardFault_IRQn 0 */
+
+  /* USER CODE END HardFault_IRQn 0 */
+  while (1)
+  {
+  }
+  /* USER CODE BEGIN HardFault_IRQn 1 */
+
+  /* USER CODE END HardFault_IRQn 1 */
+}
+
+/**
+* @brief This function handles Memory management fault.
+*/
+void MemManage_Handler(void)
+{
+  /* USER CODE BEGIN MemoryManagement_IRQn 0 */
+
+  /* USER CODE END MemoryManagement_IRQn 0 */
+  while (1)
+  {
+  }
+  /* USER CODE BEGIN MemoryManagement_IRQn 1 */
+
+  /* USER CODE END MemoryManagement_IRQn 1 */
+}
+
+/**
+* @brief This function handles Pre-fetch fault, memory access fault.
+*/
+void BusFault_Handler(void)
+{
+  /* USER CODE BEGIN BusFault_IRQn 0 */
+
+  /* USER CODE END BusFault_IRQn 0 */
+  while (1)
+  {
+  }
+  /* USER CODE BEGIN BusFault_IRQn 1 */
+
+  /* USER CODE END BusFault_IRQn 1 */
+}
+
+/**
+* @brief This function handles Undefined instruction or illegal state.
+*/
+void UsageFault_Handler(void)
+{
+  /* USER CODE BEGIN UsageFault_IRQn 0 */
+
+  /* USER CODE END UsageFault_IRQn 0 */
+  while (1)
+  {
+  }
+  /* USER CODE BEGIN UsageFault_IRQn 1 */
+
+  /* USER CODE END UsageFault_IRQn 1 */
+}
+
+/**
+* @brief This function handles Debug monitor.
+*/
+void DebugMon_Handler(void)
+{
+  /* USER CODE BEGIN DebugMonitor_IRQn 0 */
+
+  /* USER CODE END DebugMonitor_IRQn 0 */
+  while (1)
+  {
+  }
+  /* USER CODE BEGIN DebugMonitor_IRQn 1 */
+
+  /* USER CODE END DebugMonitor_IRQn 1 */
+}
+
+/**
+* @brief This function handles System tick timer.
+*/
+void SysTick_Handler(void)
+{
+  /* USER CODE BEGIN SysTick_IRQn 0 */
+
+  /* USER CODE END SysTick_IRQn 0 */
+  HAL_IncTick();
+  HAL_SYSTICK_IRQHandler();
+  /* USER CODE BEGIN SysTick_IRQn 1 */
+
+  /* USER CODE END SysTick_IRQn 1 */
+}
+
+/******************************************************************************/
+/* STM32F4xx Peripheral Interrupt Handlers                                    */
+/* Add here the Interrupt Handlers for the used peripherals.                  */
+/* For the available peripheral interrupt handler names,                      */
+/* please refer to the startup file (startup_stm32f4xx.s).                    */
+/******************************************************************************/
+
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm32f4xx_it.h b/stm32f4xx_it.h
new file mode 100644
index 0000000..5ff769a
--- /dev/null
+++ b/stm32f4xx_it.h
@@ -0,0 +1,62 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_it.h
+  * @brief   This file contains the headers of the interrupt handlers.
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2016 STMicroelectronics
+  *
+  * 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 __STM32F4xx_IT_H
+#define __STM32F4xx_IT_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+/* Includes ------------------------------------------------------------------*/
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+void NMI_Handler(void);
+void HardFault_Handler(void);
+void MemManage_Handler(void);
+void BusFault_Handler(void);
+void UsageFault_Handler(void);
+void DebugMon_Handler(void);
+void SysTick_Handler(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_IT_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm32f4xx_ll_fmc.c b/stm32f4xx_ll_fmc.c
new file mode 100644
index 0000000..91dda06
--- /dev/null
+++ b/stm32f4xx_ll_fmc.c
@@ -0,0 +1,1738 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_ll_fmc.c
+  * @author  MCD Application Team
+  * @version V1.4.4
+  * @date    22-January-2016
+  * @brief   FMC Low Layer HAL module driver.
+  *    
+  *          This file provides firmware functions to manage the following 
+  *          functionalities of the Flexible Memory Controller (FMC) peripheral memories:
+  *           + Initialization/de-initialization functions
+  *           + Peripheral Control functions 
+  *           + Peripheral State functions
+  *         
+  @verbatim
+  ==============================================================================
+                        ##### FMC peripheral features #####
+  ==============================================================================
+  [..] The Flexible memory controller (FMC) includes three memory controllers:
+       (+) The NOR/PSRAM memory controller
+       (+) The NAND/PC Card memory controller
+       (+) The Synchronous DRAM (SDRAM) controller 
+       
+  [..] The FMC functional block makes the interface with synchronous and asynchronous static
+       memories, SDRAM memories, and 16-bit PC memory cards. Its main purposes are:
+       (+) to translate AHB transactions into the appropriate external device protocol
+       (+) to meet the access time requirements of the external memory devices
+   
+  [..] All external memories share the addresses, data and control signals with the controller.
+       Each external device is accessed by means of a unique Chip Select. The FMC performs
+       only one access at a time to an external device.
+       The main features of the FMC controller are the following:
+        (+) Interface with static-memory mapped devices including:
+           (++) Static random access memory (SRAM)
+           (++) Read-only memory (ROM)
+           (++) NOR Flash memory/OneNAND Flash memory
+           (++) PSRAM (4 memory banks)
+           (++) 16-bit PC Card compatible devices
+           (++) Two banks of NAND Flash memory with ECC hardware to check up to 8 Kbytes of
+                data
+        (+) Interface with synchronous DRAM (SDRAM) memories
+        (+) Independent Chip Select control for each memory bank
+        (+) Independent configuration for each memory bank
+                    
+  @endverbatim
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© COPYRIGHT(c) 2016 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 "stm32f4xx_hal.h"
+
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup FMC_LL  FMC Low Layer
+  * @brief FMC driver modules
+  * @{
+  */
+
+#if defined (HAL_SRAM_MODULE_ENABLED) || defined(HAL_NOR_MODULE_ENABLED) || defined(HAL_NAND_MODULE_ENABLED) || defined(HAL_PCCARD_MODULE_ENABLED) || defined(HAL_SDRAM_MODULE_ENABLED)
+
+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @addtogroup FMC_LL_Private_Functions
+  * @{
+  */
+
+/** @addtogroup FMC_LL_NORSRAM
+  * @brief  NORSRAM Controller functions 
+  *
+  @verbatim 
+  ==============================================================================   
+                   ##### How to use NORSRAM device driver #####
+  ==============================================================================
+ 
+  [..] 
+    This driver contains a set of APIs to interface with the FMC NORSRAM banks in order
+    to run the NORSRAM external devices.
+      
+    (+) FMC NORSRAM bank reset using the function FMC_NORSRAM_DeInit() 
+    (+) FMC NORSRAM bank control configuration using the function FMC_NORSRAM_Init()
+    (+) FMC NORSRAM bank timing configuration using the function FMC_NORSRAM_Timing_Init()
+    (+) FMC NORSRAM bank extended timing configuration using the function 
+        FMC_NORSRAM_Extended_Timing_Init()
+    (+) FMC NORSRAM bank enable/disable write operation using the functions
+        FMC_NORSRAM_WriteOperation_Enable()/FMC_NORSRAM_WriteOperation_Disable()
+        
+
+ at endverbatim
+  * @{
+  */
+       
+/** @addtogroup FMC_LL_NORSRAM_Private_Functions_Group1
+  * @brief    Initialization and Configuration functions 
+  *
+  @verbatim    
+  ==============================================================================
+              ##### Initialization and de_initialization functions #####
+  ==============================================================================
+  [..]  
+    This section provides functions allowing to:
+    (+) Initialize and configure the FMC NORSRAM interface
+    (+) De-initialize the FMC NORSRAM interface 
+    (+) Configure the FMC clock and associated GPIOs    
+ 
+ at endverbatim
+  * @{
+  */
+  
+/**
+  * @brief  Initialize the FMC_NORSRAM device according to the specified
+  *         control parameters in the FMC_NORSRAM_InitTypeDef
+  * @param  Device: Pointer to NORSRAM device instance
+  * @param  Init: Pointer to NORSRAM Initialization structure   
+  * @retval HAL status
+  */
+HAL_StatusTypeDef  FMC_NORSRAM_Init(FMC_NORSRAM_TypeDef *Device, FMC_NORSRAM_InitTypeDef* Init)
+{ 
+  uint32_t tmpr = 0U;
+    
+  /* Check the parameters */
+  assert_param(IS_FMC_NORSRAM_DEVICE(Device));
+  assert_param(IS_FMC_NORSRAM_BANK(Init->NSBank));
+  assert_param(IS_FMC_MUX(Init->DataAddressMux));
+  assert_param(IS_FMC_MEMORY(Init->MemoryType));
+  assert_param(IS_FMC_NORSRAM_MEMORY_WIDTH(Init->MemoryDataWidth));
+  assert_param(IS_FMC_BURSTMODE(Init->BurstAccessMode));
+  assert_param(IS_FMC_WAIT_POLARITY(Init->WaitSignalPolarity));
+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
+  assert_param(IS_FMC_WRAP_MODE(Init->WrapMode));
+#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
+  assert_param(IS_FMC_WAIT_SIGNAL_ACTIVE(Init->WaitSignalActive));
+  assert_param(IS_FMC_WRITE_OPERATION(Init->WriteOperation));
+  assert_param(IS_FMC_WAITE_SIGNAL(Init->WaitSignal));
+  assert_param(IS_FMC_EXTENDED_MODE(Init->ExtendedMode));
+  assert_param(IS_FMC_ASYNWAIT(Init->AsynchronousWait));
+  assert_param(IS_FMC_WRITE_BURST(Init->WriteBurst));
+  assert_param(IS_FMC_CONTINOUS_CLOCK(Init->ContinuousClock));
+  assert_param(IS_FMC_PAGESIZE(Init->PageSize));
+#if defined (STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
+  assert_param(IS_FMC_WRITE_FIFO(Init->WriteFifo));
+#endif /* STM32F446xx || STM32F469xx || STM32F479xx */
+
+  /* Get the BTCR register value */
+  tmpr = Device->BTCR[Init->NSBank];
+
+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
+  /* Clear MBKEN, MUXEN, MTYP, MWID, FACCEN, BURSTEN, WAITPOL, WRAPMOD, WAITCFG, WREN,
+           WAITEN, EXTMOD, ASYNCWAIT, CPSIZE, CBURSTRW and CCLKEN bits */
+  tmpr &= ((uint32_t)~(FMC_BCR1_MBKEN     | FMC_BCR1_MUXEN    | FMC_BCR1_MTYP     | \
+                       FMC_BCR1_MWID      | FMC_BCR1_FACCEN   | FMC_BCR1_BURSTEN  | \
+                       FMC_BCR1_WAITPOL   | FMC_BCR1_WRAPMOD  | FMC_BCR1_WAITCFG  | \
+                       FMC_BCR1_WREN      | FMC_BCR1_WAITEN   | FMC_BCR1_EXTMOD   | \
+                       FMC_BCR1_ASYNCWAIT | FMC_BCR1_CPSIZE   | FMC_BCR1_CBURSTRW | \
+                       FMC_BCR1_CCLKEN));
+  
+  /* Set NORSRAM device control parameters */
+  tmpr |= (uint32_t)(Init->DataAddressMux       |\
+                    Init->MemoryType           |\
+                    Init->MemoryDataWidth      |\
+                    Init->BurstAccessMode      |\
+                    Init->WaitSignalPolarity   |\
+                    Init->WrapMode             |\
+                    Init->WaitSignalActive     |\
+                    Init->WriteOperation       |\
+                    Init->WaitSignal           |\
+                    Init->ExtendedMode         |\
+                    Init->AsynchronousWait     |\
+                    Init->PageSize             |\
+                    Init->WriteBurst           |\
+                    Init->ContinuousClock);
+#else /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) */
+  /* Clear MBKEN, MUXEN, MTYP, MWID, FACCEN, BURSTEN, WAITPOL, CPSIZE, WAITCFG, WREN,
+           WAITEN, EXTMOD, ASYNCWAIT, CBURSTRW, CCLKEN and WFDIS bits */
+  tmpr &= ((uint32_t)~(FMC_BCR1_MBKEN     | FMC_BCR1_MUXEN    | FMC_BCR1_MTYP     | \
+                       FMC_BCR1_MWID      | FMC_BCR1_FACCEN   | FMC_BCR1_BURSTEN  | \
+                       FMC_BCR1_WAITPOL   | FMC_BCR1_WAITCFG  | FMC_BCR1_CPSIZE   | \
+                       FMC_BCR1_WREN      | FMC_BCR1_WAITEN   | FMC_BCR1_EXTMOD   | \
+                       FMC_BCR1_ASYNCWAIT | FMC_BCR1_CBURSTRW | FMC_BCR1_CCLKEN   | \
+                       FMC_BCR1_WFDIS));
+  
+  /* Set NORSRAM device control parameters */
+  tmpr |= (uint32_t)(Init->DataAddressMux       |\
+                    Init->MemoryType           |\
+                    Init->MemoryDataWidth      |\
+                    Init->BurstAccessMode      |\
+                    Init->WaitSignalPolarity   |\
+                    Init->WaitSignalActive     |\
+                    Init->WriteOperation       |\
+                    Init->WaitSignal           |\
+                    Init->ExtendedMode         |\
+                    Init->AsynchronousWait     |\
+                    Init->WriteBurst           |\
+                    Init->ContinuousClock      |\
+                    Init->PageSize             |\
+                    Init->WriteFifo);
+#endif /*  defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) */
+                    
+  if(Init->MemoryType == FMC_MEMORY_TYPE_NOR)
+  {
+    tmpr |= (uint32_t)FMC_NORSRAM_FLASH_ACCESS_ENABLE;
+  }
+  
+  Device->BTCR[Init->NSBank] = tmpr;
+
+  /* Configure synchronous mode when Continuous clock is enabled for bank2..4 */
+  if((Init->ContinuousClock == FMC_CONTINUOUS_CLOCK_SYNC_ASYNC) && (Init->NSBank != FMC_NORSRAM_BANK1))
+  { 
+    Device->BTCR[FMC_NORSRAM_BANK1] |= (uint32_t)(Init->ContinuousClock);
+  }
+
+#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
+  if(Init->NSBank != FMC_NORSRAM_BANK1)
+  {
+    Device->BTCR[FMC_NORSRAM_BANK1] |= (uint32_t)(Init->WriteFifo);              
+  }
+#endif /* STM32F446xx || STM32F469xx || STM32F479xx */
+  
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitialize the FMC_NORSRAM peripheral 
+  * @param  Device: Pointer to NORSRAM device instance
+  * @param  ExDevice: Pointer to NORSRAM extended mode device instance  
+  * @param  Bank: NORSRAM bank number  
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NORSRAM_DeInit(FMC_NORSRAM_TypeDef *Device, FMC_NORSRAM_EXTENDED_TypeDef *ExDevice, uint32_t Bank)
+{
+  /* Check the parameters */
+  assert_param(IS_FMC_NORSRAM_DEVICE(Device));
+  assert_param(IS_FMC_NORSRAM_EXTENDED_DEVICE(ExDevice));
+  assert_param(IS_FMC_NORSRAM_BANK(Bank));
+  
+  /* Disable the FMC_NORSRAM device */
+  __FMC_NORSRAM_DISABLE(Device, Bank);
+  
+  /* De-initialize the FMC_NORSRAM device */
+  /* FMC_NORSRAM_BANK1 */
+  if(Bank == FMC_NORSRAM_BANK1)
+  {
+    Device->BTCR[Bank] = 0x000030DBU;
+  }
+  /* FMC_NORSRAM_BANK2, FMC_NORSRAM_BANK3 or FMC_NORSRAM_BANK4 */
+  else
+  {   
+    Device->BTCR[Bank] = 0x000030D2U;
+  }
+  
+  Device->BTCR[Bank + 1] = 0x0FFFFFFFU;
+  ExDevice->BWTR[Bank]   = 0x0FFFFFFFU;
+   
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initialize the FMC_NORSRAM Timing according to the specified
+  *         parameters in the FMC_NORSRAM_TimingTypeDef
+  * @param  Device: Pointer to NORSRAM device instance
+  * @param  Timing: Pointer to NORSRAM Timing structure
+  * @param  Bank: NORSRAM bank number  
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NORSRAM_Timing_Init(FMC_NORSRAM_TypeDef *Device, FMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank)
+{
+  uint32_t tmpr = 0U;
+  
+  /* Check the parameters */
+  assert_param(IS_FMC_NORSRAM_DEVICE(Device));
+  assert_param(IS_FMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime));
+  assert_param(IS_FMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime));
+  assert_param(IS_FMC_DATASETUP_TIME(Timing->DataSetupTime));
+  assert_param(IS_FMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration));
+  assert_param(IS_FMC_CLK_DIV(Timing->CLKDivision));
+  assert_param(IS_FMC_DATA_LATENCY(Timing->DataLatency));
+  assert_param(IS_FMC_ACCESS_MODE(Timing->AccessMode));
+  assert_param(IS_FMC_NORSRAM_BANK(Bank));
+  
+  /* Get the BTCR register value */
+  tmpr = Device->BTCR[Bank + 1U];
+
+  /* Clear ADDSET, ADDHLD, DATAST, BUSTURN, CLKDIV, DATLAT and ACCMOD bits */
+  tmpr &= ((uint32_t)~(FMC_BTR1_ADDSET  | FMC_BTR1_ADDHLD | FMC_BTR1_DATAST | \
+                       FMC_BTR1_BUSTURN | FMC_BTR1_CLKDIV | FMC_BTR1_DATLAT | \
+                       FMC_BTR1_ACCMOD));
+  
+  /* Set FMC_NORSRAM device timing parameters */  
+  tmpr |= (uint32_t)(Timing->AddressSetupTime                   |\
+                    ((Timing->AddressHoldTime) << 4U)           |\
+                    ((Timing->DataSetupTime) << 8U)             |\
+                    ((Timing->BusTurnAroundDuration) << 16U)    |\
+                    (((Timing->CLKDivision) - 1U) << 20U)         |\
+                    (((Timing->DataLatency) - 2U) << 24U)         |\
+                    (Timing->AccessMode));
+  
+  Device->BTCR[Bank + 1U] = tmpr;
+  
+  /* Configure Clock division value (in NORSRAM bank 1) when continuous clock is enabled */
+  if(HAL_IS_BIT_SET(Device->BTCR[FMC_NORSRAM_BANK1], FMC_BCR1_CCLKEN))
+  {
+    tmpr = (uint32_t)(Device->BTCR[FMC_NORSRAM_BANK1 + 1U] & ~(((uint32_t)0x0FU) << 20U)); 
+    tmpr |= (uint32_t)(((Timing->CLKDivision) - 1U) << 20U);
+    Device->BTCR[FMC_NORSRAM_BANK1 + 1U] = tmpr;
+  }  
+  
+  return HAL_OK;   
+}
+
+/**
+  * @brief  Initialize the FMC_NORSRAM Extended mode Timing according to the specified
+  *         parameters in the FMC_NORSRAM_TimingTypeDef
+  * @param  Device: Pointer to NORSRAM device instance
+  * @param  Timing: Pointer to NORSRAM Timing structure
+  * @param  Bank: NORSRAM bank number  
+  * @retval HAL status
+  */
+HAL_StatusTypeDef  FMC_NORSRAM_Extended_Timing_Init(FMC_NORSRAM_EXTENDED_TypeDef *Device, FMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank, uint32_t ExtendedMode)
+{  
+  uint32_t tmpr = 0U;
+ 
+  /* Check the parameters */
+  assert_param(IS_FMC_EXTENDED_MODE(ExtendedMode));
+  
+  /* Set NORSRAM device timing register for write configuration, if extended mode is used */
+  if(ExtendedMode == FMC_EXTENDED_MODE_ENABLE)
+  {
+    /* Check the parameters */
+    assert_param(IS_FMC_NORSRAM_EXTENDED_DEVICE(Device));  
+    assert_param(IS_FMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime));
+    assert_param(IS_FMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime));
+    assert_param(IS_FMC_DATASETUP_TIME(Timing->DataSetupTime));
+    assert_param(IS_FMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration));
+    assert_param(IS_FMC_ACCESS_MODE(Timing->AccessMode));
+    assert_param(IS_FMC_NORSRAM_BANK(Bank));  
+    
+    /* Get the BWTR register value */
+    tmpr = Device->BWTR[Bank];
+
+    /* Clear ADDSET, ADDHLD, DATAST, BUSTURN and ACCMOD bits */
+    tmpr &= ((uint32_t)~(FMC_BWTR1_ADDSET  | FMC_BWTR1_ADDHLD | FMC_BWTR1_DATAST | \
+                         FMC_BWTR1_BUSTURN | FMC_BWTR1_ACCMOD));
+    
+    tmpr |= (uint32_t)(Timing->AddressSetupTime                  |\
+                      ((Timing->AddressHoldTime) << 4U)          |\
+                      ((Timing->DataSetupTime) << 8U)            |\
+                      ((Timing->BusTurnAroundDuration) << 16U)   |\
+                      (Timing->AccessMode));
+
+    Device->BWTR[Bank] = tmpr;
+  }
+  else
+  {
+    Device->BWTR[Bank] = 0x0FFFFFFFU;
+  }   
+  
+  return HAL_OK;  
+}
+/**
+  * @}
+  */
+  
+/** @addtogroup FMC_LL_NORSRAM_Private_Functions_Group2
+ *  @brief   management functions 
+ *
+ at verbatim   
+  ==============================================================================
+                      ##### FMC_NORSRAM Control functions #####
+  ==============================================================================  
+  [..]
+    This subsection provides a set of functions allowing to control dynamically
+    the FMC NORSRAM interface.
+
+ at endverbatim
+  * @{
+  */
+/**
+  * @brief  Enables dynamically FMC_NORSRAM write operation.
+  * @param  Device: Pointer to NORSRAM device instance
+  * @param  Bank: NORSRAM bank number   
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NORSRAM_WriteOperation_Enable(FMC_NORSRAM_TypeDef *Device, uint32_t Bank)
+{
+  /* Check the parameters */
+  assert_param(IS_FMC_NORSRAM_DEVICE(Device));
+  assert_param(IS_FMC_NORSRAM_BANK(Bank));
+  
+  /* Enable write operation */
+  Device->BTCR[Bank] |= FMC_WRITE_OPERATION_ENABLE; 
+
+  return HAL_OK;  
+}
+
+/**
+  * @brief  Disables dynamically FMC_NORSRAM write operation.
+  * @param  Device: Pointer to NORSRAM device instance
+  * @param  Bank: NORSRAM bank number   
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NORSRAM_WriteOperation_Disable(FMC_NORSRAM_TypeDef *Device, uint32_t Bank)
+{ 
+  /* Check the parameters */
+  assert_param(IS_FMC_NORSRAM_DEVICE(Device));
+  assert_param(IS_FMC_NORSRAM_BANK(Bank));
+    
+  /* Disable write operation */
+  Device->BTCR[Bank] &= ~FMC_WRITE_OPERATION_ENABLE; 
+
+  return HAL_OK;  
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/** @addtogroup FMC_LL_NAND
+  * @brief    NAND Controller functions 
+  *
+  @verbatim 
+  ==============================================================================
+                    ##### How to use NAND device driver #####
+  ==============================================================================
+  [..]
+    This driver contains a set of APIs to interface with the FMC NAND banks in order
+    to run the NAND external devices.
+  
+    (+) FMC NAND bank reset using the function FMC_NAND_DeInit() 
+    (+) FMC NAND bank control configuration using the function FMC_NAND_Init()
+    (+) FMC NAND bank common space timing configuration using the function 
+        FMC_NAND_CommonSpace_Timing_Init()
+    (+) FMC NAND bank attribute space timing configuration using the function 
+        FMC_NAND_AttributeSpace_Timing_Init()
+    (+) FMC NAND bank enable/disable ECC correction feature using the functions
+        FMC_NAND_ECC_Enable()/FMC_NAND_ECC_Disable()
+    (+) FMC NAND bank get ECC correction code using the function FMC_NAND_GetECC()    
+
+ at endverbatim
+  * @{
+  */
+ 
+#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
+/** @defgroup HAL_FMC_NAND_Group1 Initialization/de-initialization functions 
+ *  @brief    Initialization and Configuration functions 
+ *
+ at verbatim    
+  ==============================================================================
+              ##### Initialization and de_initialization functions #####
+  ==============================================================================
+  [..]  
+    This section provides functions allowing to:
+    (+) Initialize and configure the FMC NAND interface
+    (+) De-initialize the FMC NAND interface 
+    (+) Configure the FMC clock and associated GPIOs
+        
+ at endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Initializes the FMC_NAND device according to the specified
+  *         control parameters in the FMC_NAND_HandleTypeDef
+  * @param  Device: Pointer to NAND device instance
+  * @param  Init: Pointer to NAND Initialization structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NAND_Init(FMC_NAND_TypeDef *Device, FMC_NAND_InitTypeDef *Init)
+{
+  uint32_t tmpr  = 0U; 
+    
+  /* Check the parameters */
+  assert_param(IS_FMC_NAND_DEVICE(Device));
+  assert_param(IS_FMC_NAND_BANK(Init->NandBank));
+  assert_param(IS_FMC_WAIT_FEATURE(Init->Waitfeature));
+  assert_param(IS_FMC_NAND_MEMORY_WIDTH(Init->MemoryDataWidth));
+  assert_param(IS_FMC_ECC_STATE(Init->EccComputation));
+  assert_param(IS_FMC_ECCPAGE_SIZE(Init->ECCPageSize));
+  assert_param(IS_FMC_TCLR_TIME(Init->TCLRSetupTime));
+  assert_param(IS_FMC_TAR_TIME(Init->TARSetupTime));   
+  
+  /* Get the NAND bank register value */
+  tmpr = Device->PCR;
+  
+  /* Clear PWAITEN, PBKEN, PTYP, PWID, ECCEN, TCLR, TAR and ECCPS bits */
+  tmpr &= ((uint32_t)~(FMC_PCR_PWAITEN  | FMC_PCR_PBKEN | FMC_PCR_PTYP | \
+                       FMC_PCR_PWID | FMC_PCR_ECCEN | FMC_PCR_TCLR | \
+                       FMC_PCR_TAR | FMC_PCR_ECCPS));  
+  
+  /* Set NAND device control parameters */
+  tmpr |= (uint32_t)(Init->Waitfeature                |\
+                     FMC_PCR_MEMORY_TYPE_NAND         |\
+                     Init->MemoryDataWidth            |\
+                     Init->EccComputation             |\
+                     Init->ECCPageSize                |\
+                     ((Init->TCLRSetupTime) << 9U)    |\
+                     ((Init->TARSetupTime) << 13U));
+
+  /* NAND bank registers configuration */
+  Device->PCR  = tmpr;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the FMC_NAND Common space Timing according to the specified
+  *         parameters in the FMC_NAND_PCC_TimingTypeDef
+  * @param  Device: Pointer to NAND device instance
+  * @param  Timing: Pointer to NAND timing structure
+  * @param  Bank: NAND bank number   
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NAND_CommonSpace_Timing_Init(FMC_NAND_TypeDef *Device, FMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank)
+{
+  uint32_t tmpr = 0U;  
+  
+  /* Check the parameters */
+  assert_param(IS_FMC_NAND_DEVICE(Device));
+  assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime));
+  assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime));
+  assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime));
+  assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime));
+  assert_param(IS_FMC_NAND_BANK(Bank));
+  
+  /* Get the NAND bank 2 register value */
+  tmpr = Device->PMEM;
+
+  
+  /* Clear MEMSETx, MEMWAITx, MEMHOLDx and MEMHIZx bits */
+  tmpr &= ((uint32_t)~(FMC_PMEM_MEMSET2  | FMC_PMEM_MEMWAIT2 | FMC_PMEM_MEMHOLD2 | \
+                       FMC_PMEM_MEMHIZ2)); 
+  
+  /* Set FMC_NAND device timing parameters */
+  tmpr |= (uint32_t)(Timing->SetupTime                     |\
+                       ((Timing->WaitSetupTime) << 8U)     |\
+                       ((Timing->HoldSetupTime) << 16U)    |\
+                       ((Timing->HiZSetupTime) << 24U)
+                       );
+                       
+  /* NAND bank  registers configuration */
+  Device->PMEM = tmpr;
+
+  return HAL_OK;  
+}
+
+/**
+  * @brief  Initializes the FMC_NAND Attribute space Timing according to the specified
+  *         parameters in the FMC_NAND_PCC_TimingTypeDef
+  * @param  Device: Pointer to NAND device instance
+  * @param  Timing: Pointer to NAND timing structure
+  * @param  Bank: NAND bank number 
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NAND_AttributeSpace_Timing_Init(FMC_NAND_TypeDef *Device, FMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank)
+{
+  uint32_t tmpr = 0U;  
+  
+  /* Check the parameters */ 
+  assert_param(IS_FMC_NAND_DEVICE(Device)); 
+  assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime));
+  assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime));
+  assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime));
+  assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime));
+  assert_param(IS_FMC_NAND_BANK(Bank));
+
+  /* Get the NAND bank  register value */
+  tmpr = Device->PATT;
+
+  /* Clear ATTSETx, ATTWAITx, ATTHOLDx and ATTHIZx bits */
+  tmpr &= ((uint32_t)~(FMC_PATT_ATTSET2  | FMC_PATT_ATTWAIT2 | FMC_PATT_ATTHOLD2 | \
+                       FMC_PATT_ATTHIZ2));
+  
+  /* Set FMC_NAND device timing parameters */
+  tmpr |= (uint32_t)(Timing->SetupTime                 |\
+                   ((Timing->WaitSetupTime) << 8U)     |\
+                   ((Timing->HoldSetupTime) << 16U)    |\
+                   ((Timing->HiZSetupTime) << 24U));
+
+  /* NAND bank registers configuration */
+  Device->PATT = tmpr; 
+ 
+  return HAL_OK;
+}
+
+
+/**
+  * @brief  DeInitializes the FMC_NAND device 
+  * @param  Device: Pointer to NAND device instance
+  * @param  Bank: NAND bank number
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NAND_DeInit(FMC_NAND_TypeDef *Device, uint32_t Bank)
+{
+  /* Check the parameters */ 
+  assert_param(IS_FMC_NAND_DEVICE(Device)); 
+  assert_param(IS_FMC_NAND_BANK(Bank));
+  
+  /* Disable the NAND Bank */
+  __FMC_NAND_DISABLE(Device, Bank);
+  
+  /* De-initialize the NAND Bank */
+  /* Set the FMC_NAND_BANK registers to their reset values */
+  Device->PCR  = 0x00000018U;
+  Device->SR   = 0x00000040U;
+  Device->PMEM = 0xFCFCFCFCU;
+  Device->PATT = 0xFCFCFCFCU;
+
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+  
+  
+/** @defgroup HAL_FMC_NAND_Group2 Control functions 
+ *  @brief   management functions 
+ *
+ at verbatim   
+  ==============================================================================
+                       ##### FMC_NAND Control functions #####
+  ==============================================================================  
+  [..]
+    This subsection provides a set of functions allowing to control dynamically
+    the FMC NAND interface.
+
+ at endverbatim
+  * @{
+  */ 
+
+    
+/**
+  * @brief  Enables dynamically FMC_NAND ECC feature.
+  * @param  Device: Pointer to NAND device instance
+  * @param  Bank: NAND bank number
+  * @retval HAL status
+  */    
+HAL_StatusTypeDef FMC_NAND_ECC_Enable(FMC_NAND_TypeDef *Device, uint32_t Bank)
+{
+  /* Check the parameters */ 
+  assert_param(IS_FMC_NAND_DEVICE(Device)); 
+  assert_param(IS_FMC_NAND_BANK(Bank));
+
+  /* Enable ECC feature */
+  Device->PCR |= FMC_PCR_ECCEN;
+
+  return HAL_OK;  
+}
+
+
+/**
+  * @brief  Disables dynamically FMC_NAND ECC feature.
+  * @param  Device: Pointer to NAND device instance
+  * @param  Bank: NAND bank number
+  * @retval HAL status
+  */  
+HAL_StatusTypeDef FMC_NAND_ECC_Disable(FMC_NAND_TypeDef *Device, uint32_t Bank)  
+{  
+  /* Check the parameters */ 
+  assert_param(IS_FMC_NAND_DEVICE(Device)); 
+  assert_param(IS_FMC_NAND_BANK(Bank));
+  
+  /* Disable ECC feature */
+  Device->PCR &= ~FMC_PCR_ECCEN;
+
+  return HAL_OK;  
+}
+
+/**
+  * @brief  Disables dynamically FMC_NAND ECC feature.
+  * @param  Device: Pointer to NAND device instance
+  * @param  ECCval: Pointer to ECC value
+  * @param  Bank: NAND bank number
+  * @param  Timeout: Timeout wait value  
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NAND_GetECC(FMC_NAND_TypeDef *Device, uint32_t *ECCval, uint32_t Bank, uint32_t Timeout)
+{
+  uint32_t tickstart = 0U;
+  
+  /* Check the parameters */ 
+  assert_param(IS_FMC_NAND_DEVICE(Device)); 
+  assert_param(IS_FMC_NAND_BANK(Bank));
+  
+  /* Get tick */ 
+  tickstart = HAL_GetTick();
+  
+  /* Wait until FIFO is empty */
+  while(__FMC_NAND_GET_FLAG(Device, Bank, FMC_FLAG_FEMPT) == RESET)
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
+      {
+        return HAL_TIMEOUT;
+      }
+    }  
+  }
+  
+  /* Get the ECCR register value */
+  *ECCval = (uint32_t)Device->ECCR;
+
+  return HAL_OK;  
+}
+
+/**
+  * @}
+  */
+
+#else /* defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) */
+/** @defgroup HAL_FMC_NAND_Group1 Initialization/de-initialization functions 
+ *  @brief    Initialization and Configuration functions 
+ *
+ at verbatim    
+  ==============================================================================
+              ##### Initialization and de_initialization functions #####
+  ==============================================================================
+  [..]  
+    This section provides functions allowing to:
+    (+) Initialize and configure the FMC NAND interface
+    (+) De-initialize the FMC NAND interface 
+    (+) Configure the FMC clock and associated GPIOs
+        
+ at endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the FMC_NAND device according to the specified
+  *         control parameters in the FMC_NAND_HandleTypeDef
+  * @param  Device: Pointer to NAND device instance
+  * @param  Init: Pointer to NAND Initialization structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NAND_Init(FMC_NAND_TypeDef *Device, FMC_NAND_InitTypeDef *Init)
+{
+  uint32_t tmpr  = 0U; 
+    
+  /* Check the parameters */
+  assert_param(IS_FMC_NAND_DEVICE(Device));
+  assert_param(IS_FMC_NAND_BANK(Init->NandBank));
+  assert_param(IS_FMC_WAIT_FEATURE(Init->Waitfeature));
+  assert_param(IS_FMC_NAND_MEMORY_WIDTH(Init->MemoryDataWidth));
+  assert_param(IS_FMC_ECC_STATE(Init->EccComputation));
+  assert_param(IS_FMC_ECCPAGE_SIZE(Init->ECCPageSize));
+  assert_param(IS_FMC_TCLR_TIME(Init->TCLRSetupTime));
+  assert_param(IS_FMC_TAR_TIME(Init->TARSetupTime));   
+
+  if(Init->NandBank == FMC_NAND_BANK2)
+  {
+    /* Get the NAND bank 2 register value */
+    tmpr = Device->PCR2;
+  }
+  else
+  {
+    /* Get the NAND bank 3 register value */
+    tmpr = Device->PCR3;
+  }
+  
+  /* Clear PWAITEN, PBKEN, PTYP, PWID, ECCEN, TCLR, TAR and ECCPS bits */
+  tmpr &= ((uint32_t)~(FMC_PCR2_PWAITEN  | FMC_PCR2_PBKEN | FMC_PCR2_PTYP | \
+                       FMC_PCR2_PWID | FMC_PCR2_ECCEN | FMC_PCR2_TCLR | \
+                       FMC_PCR2_TAR | FMC_PCR2_ECCPS));  
+  
+  /* Set NAND device control parameters */
+  tmpr |= (uint32_t)(Init->Waitfeature                 |\
+                     FMC_PCR_MEMORY_TYPE_NAND          |\
+                     Init->MemoryDataWidth             |\
+                     Init->EccComputation              |\
+                     Init->ECCPageSize                 |\
+                     ((Init->TCLRSetupTime) << 9U)     |\
+                     ((Init->TARSetupTime) << 13U));   
+  
+  if(Init->NandBank == FMC_NAND_BANK2)
+  {
+    /* NAND bank 2 registers configuration */
+    Device->PCR2  = tmpr;
+  }
+  else
+  {
+    /* NAND bank 3 registers configuration */
+    Device->PCR3  = tmpr;
+  }
+  
+  return HAL_OK;
+
+}
+
+/**
+  * @brief  Initializes the FMC_NAND Common space Timing according to the specified
+  *         parameters in the FMC_NAND_PCC_TimingTypeDef
+  * @param  Device: Pointer to NAND device instance
+  * @param  Timing: Pointer to NAND timing structure
+  * @param  Bank: NAND bank number   
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NAND_CommonSpace_Timing_Init(FMC_NAND_TypeDef *Device, FMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank)
+{
+  uint32_t tmpr = 0U;  
+  
+  /* Check the parameters */
+  assert_param(IS_FMC_NAND_DEVICE(Device));
+  assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime));
+  assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime));
+  assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime));
+  assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime));
+  assert_param(IS_FMC_NAND_BANK(Bank));
+  
+  if(Bank == FMC_NAND_BANK2)
+  {
+    /* Get the NAND bank 2 register value */
+    tmpr = Device->PMEM2;
+  }
+  else
+  {
+    /* Get the NAND bank 3 register value */
+    tmpr = Device->PMEM3;
+  } 
+  
+  /* Clear MEMSETx, MEMWAITx, MEMHOLDx and MEMHIZx bits */
+  tmpr &= ((uint32_t)~(FMC_PMEM2_MEMSET2  | FMC_PMEM2_MEMWAIT2 | FMC_PMEM2_MEMHOLD2 | \
+                       FMC_PMEM2_MEMHIZ2)); 
+  
+  /* Set FMC_NAND device timing parameters */
+  tmpr |= (uint32_t)(Timing->SetupTime                     |\
+                       ((Timing->WaitSetupTime) << 8U)     |\
+                       ((Timing->HoldSetupTime) << 16U)    |\
+                       ((Timing->HiZSetupTime) << 24U)
+                       );
+                            
+  if(Bank == FMC_NAND_BANK2)
+  {
+    /* NAND bank 2 registers configuration */
+    Device->PMEM2 = tmpr;
+  }
+  else
+  {
+    /* NAND bank 3 registers configuration */
+    Device->PMEM3 = tmpr;
+  }  
+  
+  return HAL_OK;  
+}
+
+/**
+  * @brief  Initializes the FMC_NAND Attribute space Timing according to the specified
+  *         parameters in the FMC_NAND_PCC_TimingTypeDef
+  * @param  Device: Pointer to NAND device instance
+  * @param  Timing: Pointer to NAND timing structure
+  * @param  Bank: NAND bank number 
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NAND_AttributeSpace_Timing_Init(FMC_NAND_TypeDef *Device, FMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank)
+{
+  uint32_t tmpr = 0U;  
+  
+  /* Check the parameters */ 
+  assert_param(IS_FMC_NAND_DEVICE(Device)); 
+  assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime));
+  assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime));
+  assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime));
+  assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime));
+  assert_param(IS_FMC_NAND_BANK(Bank));
+  
+  if(Bank == FMC_NAND_BANK2)
+  {
+    /* Get the NAND bank 2 register value */
+    tmpr = Device->PATT2;
+  }
+  else
+  {
+    /* Get the NAND bank 3 register value */
+    tmpr = Device->PATT3;
+  } 
+  
+  /* Clear ATTSETx, ATTWAITx, ATTHOLDx and ATTHIZx bits */
+  tmpr &= ((uint32_t)~(FMC_PATT2_ATTSET2  | FMC_PATT2_ATTWAIT2 | FMC_PATT2_ATTHOLD2 | \
+                       FMC_PATT2_ATTHIZ2));
+  
+  /* Set FMC_NAND device timing parameters */
+  tmpr |= (uint32_t)(Timing->SetupTime                  |\
+                   ((Timing->WaitSetupTime) << 8U)      |\
+                   ((Timing->HoldSetupTime) << 16U)     |\
+                   ((Timing->HiZSetupTime) << 24U));
+                       
+  if(Bank == FMC_NAND_BANK2)
+  {
+    /* NAND bank 2 registers configuration */
+    Device->PATT2 = tmpr;
+  }
+  else
+  {
+    /* NAND bank 3 registers configuration */
+    Device->PATT3 = tmpr;
+  }   
+  
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the FMC_NAND device 
+  * @param  Device: Pointer to NAND device instance
+  * @param  Bank: NAND bank number
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NAND_DeInit(FMC_NAND_TypeDef *Device, uint32_t Bank)
+{
+  /* Check the parameters */ 
+  assert_param(IS_FMC_NAND_DEVICE(Device)); 
+  assert_param(IS_FMC_NAND_BANK(Bank));
+      
+  /* Disable the NAND Bank */
+  __FMC_NAND_DISABLE(Device, Bank);
+ 
+  /* De-initialize the NAND Bank */
+  if(Bank == FMC_NAND_BANK2)
+  {
+    /* Set the FMC_NAND_BANK2 registers to their reset values */
+    Device->PCR2  = 0x00000018U;
+    Device->SR2   = 0x00000040U;
+    Device->PMEM2 = 0xFCFCFCFCU;
+    Device->PATT2 = 0xFCFCFCFCU;  
+  }
+  /* FMC_Bank3_NAND */  
+  else
+  {
+    /* Set the FMC_NAND_BANK3 registers to their reset values */
+    Device->PCR3  = 0x00000018U;
+    Device->SR3   = 0x00000040U;
+    Device->PMEM3 = 0xFCFCFCFCU;
+    Device->PATT3 = 0xFCFCFCFCU; 
+  }
+  
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @addtogroup FMC_LL_NAND_Private_Functions_Group2
+  *  @brief   management functions 
+  *
+ at verbatim   
+  ==============================================================================
+                       ##### FMC_NAND Control functions #####
+  ==============================================================================  
+  [..]
+    This subsection provides a set of functions allowing to control dynamically
+    the FMC NAND interface.
+
+ at endverbatim
+  * @{
+  */ 
+/**
+  * @brief  Enables dynamically FMC_NAND ECC feature.
+  * @param  Device: Pointer to NAND device instance
+  * @param  Bank: NAND bank number
+  * @retval HAL status
+  */    
+HAL_StatusTypeDef FMC_NAND_ECC_Enable(FMC_NAND_TypeDef *Device, uint32_t Bank)
+{
+  /* Check the parameters */ 
+  assert_param(IS_FMC_NAND_DEVICE(Device)); 
+  assert_param(IS_FMC_NAND_BANK(Bank));
+    
+  /* Enable ECC feature */
+  if(Bank == FMC_NAND_BANK2)
+  {
+    Device->PCR2 |= FMC_PCR2_ECCEN;
+  }
+  else
+  {
+    Device->PCR3 |= FMC_PCR3_ECCEN;
+  } 
+  
+  return HAL_OK;  
+}
+
+/**
+  * @brief  Disables dynamically FMC_NAND ECC feature.
+  * @param  Device: Pointer to NAND device instance
+  * @param  Bank: NAND bank number
+  * @retval HAL status
+  */  
+HAL_StatusTypeDef FMC_NAND_ECC_Disable(FMC_NAND_TypeDef *Device, uint32_t Bank)  
+{  
+  /* Check the parameters */ 
+  assert_param(IS_FMC_NAND_DEVICE(Device)); 
+  assert_param(IS_FMC_NAND_BANK(Bank));
+    
+  /* Disable ECC feature */
+  if(Bank == FMC_NAND_BANK2)
+  {
+    Device->PCR2 &= ~FMC_PCR2_ECCEN;
+  }
+  else
+  {
+    Device->PCR3 &= ~FMC_PCR3_ECCEN;
+  } 
+
+  return HAL_OK;  
+}
+
+/**
+  * @brief  Disables dynamically FMC_NAND ECC feature.
+  * @param  Device: Pointer to NAND device instance
+  * @param  ECCval: Pointer to ECC value
+  * @param  Bank: NAND bank number
+  * @param  Timeout: Timeout wait value  
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_NAND_GetECC(FMC_NAND_TypeDef *Device, uint32_t *ECCval, uint32_t Bank, uint32_t Timeout)
+{
+  uint32_t tickstart = 0U;
+
+  /* Check the parameters */ 
+  assert_param(IS_FMC_NAND_DEVICE(Device)); 
+  assert_param(IS_FMC_NAND_BANK(Bank));
+
+  /* Get tick */ 
+  tickstart = HAL_GetTick();
+
+  /* Wait until FIFO is empty */
+  while(__FMC_NAND_GET_FLAG(Device, Bank, FMC_FLAG_FEMPT) == RESET)
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
+      {
+        return HAL_TIMEOUT;
+      }
+    }  
+  }
+     
+  if(Bank == FMC_NAND_BANK2)
+  {    
+    /* Get the ECCR2 register value */
+    *ECCval = (uint32_t)Device->ECCR2;
+  }
+  else
+  {    
+    /* Get the ECCR3 register value */
+    *ECCval = (uint32_t)Device->ECCR3;
+  }
+
+  return HAL_OK;  
+}
+
+/**
+  * @}
+  */
+
+#endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) */
+/**
+  * @}
+  */
+
+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
+/** @addtogroup FMC_LL_PCCARD
+  * @brief    PCCARD Controller functions 
+  *
+  @verbatim 
+  ==============================================================================  
+                    ##### How to use PCCARD device driver #####
+  ==============================================================================
+  [..]
+    This driver contains a set of APIs to interface with the FMC PCCARD bank in order
+    to run the PCCARD/compact flash external devices.
+  
+    (+) FMC PCCARD bank reset using the function FMC_PCCARD_DeInit() 
+    (+) FMC PCCARD bank control configuration using the function FMC_PCCARD_Init()
+    (+) FMC PCCARD bank common space timing configuration using the function 
+        FMC_PCCARD_CommonSpace_Timing_Init()
+    (+) FMC PCCARD bank attribute space timing configuration using the function 
+        FMC_PCCARD_AttributeSpace_Timing_Init()
+    (+) FMC PCCARD bank IO space timing configuration using the function 
+        FMC_PCCARD_IOSpace_Timing_Init()
+ at endverbatim
+  * @{
+  */
+  
+/** @addtogroup FMC_LL_PCCARD_Private_Functions_Group1
+  *  @brief    Initialization and Configuration functions 
+  *
+ at verbatim    
+  ==============================================================================
+              ##### Initialization and de_initialization functions #####
+  ==============================================================================
+  [..]  
+    This section provides functions allowing to:
+    (+) Initialize and configure the FMC PCCARD interface
+    (+) De-initialize the FMC PCCARD interface 
+    (+) Configure the FMC clock and associated GPIOs
+        
+ at endverbatim
+  * @{
+  */
+  
+/**
+  * @brief  Initializes the FMC_PCCARD device according to the specified
+  *         control parameters in the FMC_PCCARD_HandleTypeDef
+  * @param  Device: Pointer to PCCARD device instance
+  * @param  Init: Pointer to PCCARD Initialization structure   
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_PCCARD_Init(FMC_PCCARD_TypeDef *Device, FMC_PCCARD_InitTypeDef *Init)
+{
+  uint32_t tmpr = 0U;
+
+  /* Check the parameters */ 
+  assert_param(IS_FMC_PCCARD_DEVICE(Device));
+  assert_param(IS_FMC_WAIT_FEATURE(Init->Waitfeature));
+  assert_param(IS_FMC_TCLR_TIME(Init->TCLRSetupTime));
+  assert_param(IS_FMC_TAR_TIME(Init->TARSetupTime));     
+  
+  /* Get PCCARD control register value */
+  tmpr = Device->PCR4;
+  
+  /* Clear TAR, TCLR, PWAITEN and PWID bits */
+  tmpr &= ((uint32_t)~(FMC_PCR4_TAR  | FMC_PCR4_TCLR | FMC_PCR4_PWAITEN | \
+                       FMC_PCR4_PWID));
+  
+  /* Set FMC_PCCARD device control parameters */
+  tmpr |= (uint32_t)(Init->Waitfeature              |\
+                     FMC_NAND_PCC_MEM_BUS_WIDTH_16  |\
+                    (Init->TCLRSetupTime << 9U)     |\
+                    (Init->TARSetupTime << 13U));
+  
+  Device->PCR4 = tmpr;
+  
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the FMC_PCCARD Common space Timing according to the specified
+  *         parameters in the FMC_NAND_PCC_TimingTypeDef
+  * @param  Device: Pointer to PCCARD device instance
+  * @param  Timing: Pointer to PCCARD timing structure 
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_PCCARD_CommonSpace_Timing_Init(FMC_PCCARD_TypeDef *Device, FMC_NAND_PCC_TimingTypeDef *Timing)
+{
+  uint32_t tmpr = 0U;
+  
+  /* Check the parameters */
+  assert_param(IS_FMC_PCCARD_DEVICE(Device));
+  assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime));
+  assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime));
+  assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime));
+  assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime));
+
+  /* Get PCCARD common space timing register value */
+  tmpr = Device->PMEM4;
+  
+  /* Clear MEMSETx, MEMWAITx, MEMHOLDx and MEMHIZx bits */
+  tmpr &= ((uint32_t)~(FMC_PMEM4_MEMSET4  | FMC_PMEM4_MEMWAIT4 | FMC_PMEM4_MEMHOLD4 | \
+                       FMC_PMEM4_MEMHIZ4)); 
+  /* Set PCCARD timing parameters */
+  tmpr |= (uint32_t)(Timing->SetupTime                  |\
+                    ((Timing->WaitSetupTime) << 8U)     |\
+                    ((Timing->HoldSetupTime) << 16U)    |\
+                    ((Timing->HiZSetupTime) << 24U)); 
+
+  Device->PMEM4 = tmpr;
+  
+  return HAL_OK;  
+}
+
+/**
+  * @brief  Initializes the FMC_PCCARD Attribute space Timing according to the specified
+  *         parameters in the FMC_NAND_PCC_TimingTypeDef
+  * @param  Device: Pointer to PCCARD device instance
+  * @param  Timing: Pointer to PCCARD timing structure  
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_PCCARD_AttributeSpace_Timing_Init(FMC_PCCARD_TypeDef *Device, FMC_NAND_PCC_TimingTypeDef *Timing)
+{
+  uint32_t tmpr = 0U;
+  
+  /* Check the parameters */ 
+  assert_param(IS_FMC_PCCARD_DEVICE(Device)); 
+  assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime));
+  assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime));
+  assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime));
+  assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime));
+
+  /* Get PCCARD timing parameters */
+  tmpr = Device->PATT4;
+
+  /* Clear ATTSETx, ATTWAITx, ATTHOLDx and ATTHIZx bits */
+  tmpr &= ((uint32_t)~(FMC_PATT4_ATTSET4  | FMC_PATT4_ATTWAIT4 | FMC_PATT4_ATTHOLD4 | \
+                       FMC_PATT4_ATTHIZ4));
+  
+  /* Set PCCARD timing parameters */
+  tmpr |= (uint32_t)(Timing->SetupTime                 |\
+                   ((Timing->WaitSetupTime) << 8U)     |\
+                   ((Timing->HoldSetupTime) << 16U)    |\
+                   ((Timing->HiZSetupTime) << 24U));
+  Device->PATT4 = tmpr;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the FMC_PCCARD IO space Timing according to the specified
+  *         parameters in the FMC_NAND_PCC_TimingTypeDef
+  * @param  Device: Pointer to PCCARD device instance
+  * @param  Timing: Pointer to PCCARD timing structure  
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_PCCARD_IOSpace_Timing_Init(FMC_PCCARD_TypeDef *Device, FMC_NAND_PCC_TimingTypeDef *Timing)
+{
+  uint32_t tmpr = 0;
+  
+  /* Check the parameters */  
+  assert_param(IS_FMC_PCCARD_DEVICE(Device));
+  assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime));
+  assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime));
+  assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime));
+  assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime));
+
+  /* Get FMC_PCCARD device timing parameters */
+  tmpr = Device->PIO4;
+
+  /* Clear IOSET4, IOWAIT4, IOHOLD4 and IOHIZ4 bits */
+  tmpr &= ((uint32_t)~(FMC_PIO4_IOSET4  | FMC_PIO4_IOWAIT4 | FMC_PIO4_IOHOLD4 | \
+                       FMC_PIO4_IOHIZ4));
+  
+  /* Set FMC_PCCARD device timing parameters */
+  tmpr |= (uint32_t)(Timing->SetupTime                   |\
+                     ((Timing->WaitSetupTime) << 8U)     |\
+                     ((Timing->HoldSetupTime) << 16U)    |\
+                     ((Timing->HiZSetupTime) << 24U));   
+  
+  Device->PIO4 = tmpr;
+ 
+  return HAL_OK;
+}
+                                           
+/**
+  * @brief  DeInitializes the FMC_PCCARD device 
+  * @param  Device: Pointer to PCCARD device instance
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_PCCARD_DeInit(FMC_PCCARD_TypeDef *Device)
+{
+  /* Check the parameters */  
+  assert_param(IS_FMC_PCCARD_DEVICE(Device));
+    
+  /* Disable the FMC_PCCARD device */
+  __FMC_PCCARD_DISABLE(Device);
+  
+  /* De-initialize the FMC_PCCARD device */
+  Device->PCR4    = 0x00000018U; 
+  Device->SR4     = 0x00000000U;	
+  Device->PMEM4   = 0xFCFCFCFCU;
+  Device->PATT4   = 0xFCFCFCFCU;
+  Device->PIO4    = 0xFCFCFCFCU;
+  
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
+
+
+/** @addtogroup FMC_LL_SDRAM
+  * @brief    SDRAM Controller functions 
+  *
+  @verbatim 
+  ==============================================================================
+                     ##### How to use SDRAM device driver #####
+  ==============================================================================
+  [..] 
+    This driver contains a set of APIs to interface with the FMC SDRAM banks in order
+    to run the SDRAM external devices.
+    
+    (+) FMC SDRAM bank reset using the function FMC_SDRAM_DeInit() 
+    (+) FMC SDRAM bank control configuration using the function FMC_SDRAM_Init()
+    (+) FMC SDRAM bank timing configuration using the function FMC_SDRAM_Timing_Init()
+    (+) FMC SDRAM bank enable/disable write operation using the functions
+        FMC_SDRAM_WriteOperation_Enable()/FMC_SDRAM_WriteOperation_Disable()   
+    (+) FMC SDRAM bank send command using the function FMC_SDRAM_SendCommand()      
+       
+ at endverbatim
+  * @{
+  */
+         
+/** @addtogroup FMC_LL_SDRAM_Private_Functions_Group1
+  *  @brief    Initialization and Configuration functions 
+  *
+ at verbatim    
+  ==============================================================================
+              ##### Initialization and de_initialization functions #####
+  ==============================================================================
+  [..]  
+    This section provides functions allowing to:
+    (+) Initialize and configure the FMC SDRAM interface
+    (+) De-initialize the FMC SDRAM interface 
+    (+) Configure the FMC clock and associated GPIOs
+        
+ at endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Initializes the FMC_SDRAM device according to the specified
+  *         control parameters in the FMC_SDRAM_InitTypeDef
+  * @param  Device: Pointer to SDRAM device instance
+  * @param  Init: Pointer to SDRAM Initialization structure   
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_SDRAM_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_InitTypeDef *Init)
+{
+  uint32_t tmpr1 = 0U;
+  uint32_t tmpr2 = 0U;
+    
+  /* Check the parameters */
+  assert_param(IS_FMC_SDRAM_DEVICE(Device));
+  assert_param(IS_FMC_SDRAM_BANK(Init->SDBank));
+  assert_param(IS_FMC_COLUMNBITS_NUMBER(Init->ColumnBitsNumber));
+  assert_param(IS_FMC_ROWBITS_NUMBER(Init->RowBitsNumber));
+  assert_param(IS_FMC_SDMEMORY_WIDTH(Init->MemoryDataWidth));
+  assert_param(IS_FMC_INTERNALBANK_NUMBER(Init->InternalBankNumber));
+  assert_param(IS_FMC_CAS_LATENCY(Init->CASLatency));
+  assert_param(IS_FMC_WRITE_PROTECTION(Init->WriteProtection));
+  assert_param(IS_FMC_SDCLOCK_PERIOD(Init->SDClockPeriod));
+  assert_param(IS_FMC_READ_BURST(Init->ReadBurst));
+  assert_param(IS_FMC_READPIPE_DELAY(Init->ReadPipeDelay));   
+
+  /* Set SDRAM bank configuration parameters */
+  if (Init->SDBank != FMC_SDRAM_BANK2) 
+  { 
+    tmpr1 = Device->SDCR[FMC_SDRAM_BANK1];
+    
+    /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */
+    tmpr1 &= ((uint32_t)~(FMC_SDCR1_NC  | FMC_SDCR1_NR | FMC_SDCR1_MWID | \
+                         FMC_SDCR1_NB  | FMC_SDCR1_CAS | FMC_SDCR1_WP | \
+                         FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE));
+  
+  
+    tmpr1 |= (uint32_t)(Init->ColumnBitsNumber   |\
+                                               Init->RowBitsNumber      |\
+                                               Init->MemoryDataWidth    |\
+                                               Init->InternalBankNumber |\
+                                               Init->CASLatency         |\
+                                               Init->WriteProtection    |\
+                                               Init->SDClockPeriod      |\
+                                               Init->ReadBurst          |\
+                                               Init->ReadPipeDelay
+                                               );
+    Device->SDCR[FMC_SDRAM_BANK1] = tmpr1;
+  }
+  else /* FMC_Bank2_SDRAM */                      
+  {
+///////////////////////////////
+// BEGIN PIECE OF WEIRD CODE //
+///////////////////////////////
+//
+//    tmpr1 = Device->SDCR[FMC_SDRAM_BANK1];
+//    
+//    /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */
+//    tmpr1 &= ((uint32_t)~(FMC_SDCR1_NC  | FMC_SDCR1_NR | FMC_SDCR1_MWID | \
+//                          FMC_SDCR1_NB  | FMC_SDCR1_CAS | FMC_SDCR1_WP | \
+//                          FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE));
+//    
+//    tmpr1 |= (uint32_t)(Init->SDClockPeriod      |\
+//                        Init->ReadBurst          |\
+//                        Init->ReadPipeDelay);  
+//
+///////////////////////////////
+// END PIECE OF WEIRD CODE   //
+///////////////////////////////
+		
+    tmpr2 = Device->SDCR[FMC_SDRAM_BANK1];
+    
+    /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */
+    tmpr2 &= ((uint32_t)~(FMC_SDCR2_NC  | FMC_SDCR2_NR | FMC_SDCR2_MWID | \
+                          FMC_SDCR2_NB  | FMC_SDCR2_CAS | FMC_SDCR2_WP | \
+                          FMC_SDCR2_SDCLK | FMC_SDCR2_RBURST | FMC_SDCR2_RPIPE));
+
+    tmpr2 |= (uint32_t)(Init->ColumnBitsNumber   |\
+                       Init->RowBitsNumber      |\
+                       Init->MemoryDataWidth    |\
+                       Init->InternalBankNumber |\
+                       Init->CASLatency         |\
+                       Init->WriteProtection);
+
+//
+//    Device->SDCR[FMC_SDRAM_BANK1] = tmpr1;
+//
+    Device->SDCR[FMC_SDRAM_BANK2] = tmpr2;
+  }  
+  
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the FMC_SDRAM device timing according to the specified
+  *         parameters in the FMC_SDRAM_TimingTypeDef
+  * @param  Device: Pointer to SDRAM device instance
+  * @param  Timing: Pointer to SDRAM Timing structure
+  * @param  Bank: SDRAM bank number   
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_SDRAM_Timing_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_TimingTypeDef *Timing, uint32_t Bank)
+{
+  uint32_t tmpr1 = 0U;
+  uint32_t tmpr2 = 0U;
+    
+  /* Check the parameters */
+  assert_param(IS_FMC_SDRAM_DEVICE(Device));
+  assert_param(IS_FMC_LOADTOACTIVE_DELAY(Timing->LoadToActiveDelay));
+  assert_param(IS_FMC_EXITSELFREFRESH_DELAY(Timing->ExitSelfRefreshDelay));
+  assert_param(IS_FMC_SELFREFRESH_TIME(Timing->SelfRefreshTime));
+  assert_param(IS_FMC_ROWCYCLE_DELAY(Timing->RowCycleDelay));
+  assert_param(IS_FMC_WRITE_RECOVERY_TIME(Timing->WriteRecoveryTime));
+  assert_param(IS_FMC_RP_DELAY(Timing->RPDelay));
+  assert_param(IS_FMC_RCD_DELAY(Timing->RCDDelay));
+  assert_param(IS_FMC_SDRAM_BANK(Bank));
+  
+  /* Set SDRAM device timing parameters */ 
+  if (Bank != FMC_SDRAM_BANK2) 
+  { 
+    tmpr1 = Device->SDTR[FMC_SDRAM_BANK1];
+    
+    /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */
+    tmpr1 &= ((uint32_t)~(FMC_SDTR1_TMRD  | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \
+                          FMC_SDTR1_TRC  | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \
+                          FMC_SDTR1_TRCD));
+    
+    tmpr1 |= (uint32_t)(((Timing->LoadToActiveDelay)-1U)           |\
+                       (((Timing->ExitSelfRefreshDelay)-1U) << 4U) |\
+                       (((Timing->SelfRefreshTime)-1U) << 8U)      |\
+                       (((Timing->RowCycleDelay)-1U) << 12U)       |\
+                       (((Timing->WriteRecoveryTime)-1U) <<16U)    |\
+                       (((Timing->RPDelay)-1U) << 20U)             |\
+                       (((Timing->RCDDelay)-1U) << 24U));
+    Device->SDTR[FMC_SDRAM_BANK1] = tmpr1;
+  }
+  else /* FMC_Bank2_SDRAM */
+  {  
+///////////////////////////////
+// BEGIN PIECE OF WEIRD CODE //
+///////////////////////////////
+//
+//    tmpr1 = Device->SDTR[FMC_SDRAM_BANK2];
+//    
+//    /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */
+//    tmpr1 &= ((uint32_t)~(FMC_SDTR1_TMRD  | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \
+//                          FMC_SDTR1_TRC  | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \
+//                          FMC_SDTR1_TRCD));
+//    
+//    tmpr1 |= (uint32_t)(((Timing->LoadToActiveDelay)-1U)           |\
+//                       (((Timing->ExitSelfRefreshDelay)-1U) << 4U) |\
+//                       (((Timing->SelfRefreshTime)-1U) << 8U)      |\
+//                       (((Timing->WriteRecoveryTime)-1U) <<16U)    |\
+//                       (((Timing->RCDDelay)-1U) << 24U));   
+//		
+///////////////////////////////
+// END PIECE OF WEIRD CODE   //
+///////////////////////////////
+
+    tmpr2 = Device->SDTR[FMC_SDRAM_BANK1];
+    
+    /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */
+    tmpr2 &= ((uint32_t)~(FMC_SDTR2_TMRD  | FMC_SDTR2_TXSR | FMC_SDTR2_TRAS | \
+                          FMC_SDTR2_TRC  | FMC_SDTR2_TWR | FMC_SDTR2_TRP | \
+                          FMC_SDTR2_TRCD));
+													
+		tmpr2 |= (uint32_t)(((Timing->LoadToActiveDelay)-1U)           |\
+                       (((Timing->ExitSelfRefreshDelay)-1U) << 4U) |\
+                       (((Timing->SelfRefreshTime)-1U) << 8U)      |\
+                       (((Timing->WriteRecoveryTime)-1U) <<16U)    |\
+                       (((Timing->RCDDelay)-1U) << 24U));
+
+//
+//    Device->SDTR[FMC_SDRAM_BANK2] = tmpr1;
+//
+    Device->SDTR[FMC_SDRAM_BANK2] = tmpr2;
+  }   
+  
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the FMC_SDRAM peripheral 
+  * @param  Device: Pointer to SDRAM device instance
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_SDRAM_DeInit(FMC_SDRAM_TypeDef *Device, uint32_t Bank)
+{
+  /* Check the parameters */
+  assert_param(IS_FMC_SDRAM_DEVICE(Device));
+  assert_param(IS_FMC_SDRAM_BANK(Bank));
+  
+  /* De-initialize the SDRAM device */
+  Device->SDCR[Bank] = 0x000002D0U;
+  Device->SDTR[Bank] = 0x0FFFFFFFU;    
+  Device->SDCMR      = 0x00000000U;
+  Device->SDRTR      = 0x00000000U;
+  Device->SDSR       = 0x00000000U;
+
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+  
+/** @addtogroup FMC_LL_SDRAMPrivate_Functions_Group2
+  *  @brief   management functions 
+  *
+ at verbatim   
+  ==============================================================================
+                      ##### FMC_SDRAM Control functions #####
+  ==============================================================================  
+  [..]
+    This subsection provides a set of functions allowing to control dynamically
+    the FMC SDRAM interface.
+
+ at endverbatim
+  * @{
+  */
+/**
+  * @brief  Enables dynamically FMC_SDRAM write protection.
+  * @param  Device: Pointer to SDRAM device instance
+  * @param  Bank: SDRAM bank number 
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_SDRAM_WriteProtection_Enable(FMC_SDRAM_TypeDef *Device, uint32_t Bank)
+{ 
+  /* Check the parameters */
+  assert_param(IS_FMC_SDRAM_DEVICE(Device));
+  assert_param(IS_FMC_SDRAM_BANK(Bank));
+  
+  /* Enable write protection */
+  Device->SDCR[Bank] |= FMC_SDRAM_WRITE_PROTECTION_ENABLE;
+  
+  return HAL_OK;  
+}
+
+/**
+  * @brief  Disables dynamically FMC_SDRAM write protection.
+  * @param  hsdram: FMC_SDRAM handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef FMC_SDRAM_WriteProtection_Disable(FMC_SDRAM_TypeDef *Device, uint32_t Bank)
+{
+  /* Check the parameters */
+  assert_param(IS_FMC_SDRAM_DEVICE(Device));
+  assert_param(IS_FMC_SDRAM_BANK(Bank));
+  
+  /* Disable write protection */
+  Device->SDCR[Bank] &= ~FMC_SDRAM_WRITE_PROTECTION_ENABLE;
+  
+  return HAL_OK;
+}
+  
+/**
+  * @brief  Send Command to the FMC SDRAM bank
+  * @param  Device: Pointer to SDRAM device instance
+  * @param  Command: Pointer to SDRAM command structure   
+  * @param  Timing: Pointer to SDRAM Timing structure
+  * @param  Timeout: Timeout wait value
+  * @retval HAL state
+  */  
+HAL_StatusTypeDef FMC_SDRAM_SendCommand(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_CommandTypeDef *Command, uint32_t Timeout)
+{
+  __IO uint32_t tmpr = 0U;
+  uint32_t tickstart = 0U;
+  
+  /* Check the parameters */
+  assert_param(IS_FMC_SDRAM_DEVICE(Device));
+  assert_param(IS_FMC_COMMAND_MODE(Command->CommandMode));
+  assert_param(IS_FMC_COMMAND_TARGET(Command->CommandTarget));
+  assert_param(IS_FMC_AUTOREFRESH_NUMBER(Command->AutoRefreshNumber));
+  assert_param(IS_FMC_MODE_REGISTER(Command->ModeRegisterDefinition));  
+
+  /* Set command register */
+  tmpr = (uint32_t)((Command->CommandMode)                  |\
+                    (Command->CommandTarget)                |\
+                    (((Command->AutoRefreshNumber)-1U) << 5U) |\
+                    ((Command->ModeRegisterDefinition) << 9U)
+                    );
+    
+  Device->SDCMR = tmpr;
+
+  /* Get tick */ 
+  tickstart = HAL_GetTick();
+
+  /* Wait until command is send */
+  while(HAL_IS_BIT_SET(Device->SDSR, FMC_SDSR_BUSY))
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
+      {
+        return HAL_TIMEOUT;
+      }
+    }
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Program the SDRAM Memory Refresh rate.
+  * @param  Device: Pointer to SDRAM device instance  
+  * @param  RefreshRate: The SDRAM refresh rate value.
+  * @retval HAL state
+  */
+HAL_StatusTypeDef FMC_SDRAM_ProgramRefreshRate(FMC_SDRAM_TypeDef *Device, uint32_t RefreshRate)
+{
+  /* Check the parameters */
+  assert_param(IS_FMC_SDRAM_DEVICE(Device));
+  assert_param(IS_FMC_REFRESH_RATE(RefreshRate));
+  
+  /* Set the refresh rate in command register */
+  Device->SDRTR |= (RefreshRate<<1U);
+  
+  return HAL_OK;   
+}
+
+/**
+  * @brief  Set the Number of consecutive SDRAM Memory auto Refresh commands.
+  * @param  Device: Pointer to SDRAM device instance  
+  * @param  AutoRefreshNumber: Specifies the auto Refresh number.       
+  * @retval None
+  */
+HAL_StatusTypeDef FMC_SDRAM_SetAutoRefreshNumber(FMC_SDRAM_TypeDef *Device, uint32_t AutoRefreshNumber)
+{
+  /* Check the parameters */
+  assert_param(IS_FMC_SDRAM_DEVICE(Device));
+  assert_param(IS_FMC_AUTOREFRESH_NUMBER(AutoRefreshNumber));
+  
+  /* Set the Auto-refresh number in command register */
+  Device->SDCMR |= (AutoRefreshNumber << 5U); 
+
+  return HAL_OK;  
+}
+
+/**
+  * @brief  Returns the indicated FMC SDRAM bank mode status.
+  * @param  Device: Pointer to SDRAM device instance  
+  * @param  Bank: Defines the FMC SDRAM bank. This parameter can be 
+  *                     FMC_Bank1_SDRAM or FMC_Bank2_SDRAM. 
+  * @retval The FMC SDRAM bank mode status, could be on of the following values:
+  *         FMC_SDRAM_NORMAL_MODE, FMC_SDRAM_SELF_REFRESH_MODE or 
+  *         FMC_SDRAM_POWER_DOWN_MODE.           
+  */
+uint32_t FMC_SDRAM_GetModeStatus(FMC_SDRAM_TypeDef *Device, uint32_t Bank)
+{
+  uint32_t tmpreg = 0U;
+  
+  /* Check the parameters */
+  assert_param(IS_FMC_SDRAM_DEVICE(Device));
+  assert_param(IS_FMC_SDRAM_BANK(Bank));
+
+  /* Get the corresponding bank mode */
+  if(Bank == FMC_SDRAM_BANK1)
+  {
+    tmpreg = (uint32_t)(Device->SDSR & FMC_SDSR_MODES1); 
+  }
+  else
+  {
+    tmpreg = ((uint32_t)(Device->SDSR & FMC_SDSR_MODES2) >> 2U);
+  }
+  
+  /* Return the mode status */
+  return tmpreg;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */
+#endif /* HAL_SRAM_MODULE_ENABLED || HAL_NOR_MODULE_ENABLED || HAL_NAND_MODULE_ENABLED || HAL_PCCARD_MODULE_ENABLED || HAL_SDRAM_MODULE_ENABLED */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/



More information about the Commits mailing list