]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_M7_STM32F7_STM32756G-EVAL_IAR_Keil/ST_Library/stm32f7xx_hal_nand.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_STM32F7_STM32756G-EVAL_IAR_Keil / ST_Library / stm32f7xx_hal_nand.c
diff --git a/FreeRTOS/Demo/CORTEX_M7_STM32F7_STM32756G-EVAL_IAR_Keil/ST_Library/stm32f7xx_hal_nand.c b/FreeRTOS/Demo/CORTEX_M7_STM32F7_STM32756G-EVAL_IAR_Keil/ST_Library/stm32f7xx_hal_nand.c
new file mode 100644 (file)
index 0000000..5e96d33
--- /dev/null
@@ -0,0 +1,1014 @@
+/**\r
+  ******************************************************************************\r
+  * @file    stm32f7xx_hal_nand.c\r
+  * @author  MCD Application Team\r
+  * @version V1.0.0RC1\r
+  * @date    24-March-2015\r
+  * @brief   NAND HAL module driver.\r
+  *          This file provides a generic firmware to drive NAND memories mounted \r
+  *          as external device.\r
+  *         \r
+  @verbatim\r
+  ==============================================================================\r
+                         ##### How to use this driver #####\r
+  ==============================================================================    \r
+    [..]\r
+      This driver is a generic layered driver which contains a set of APIs used to \r
+      control NAND flash memories. It uses the FMC/FSMC layer functions to interface \r
+      with NAND devices. This driver is used as follows:\r
+    \r
+      (+) NAND flash memory configuration sequence using the function HAL_NAND_Init() \r
+          with control and timing parameters for both common and attribute spaces.\r
+            \r
+      (+) Read NAND flash memory maker and device IDs using the function\r
+          HAL_NAND_Read_ID(). The read information is stored in the NAND_ID_TypeDef \r
+          structure declared by the function caller. \r
+        \r
+      (+) Access NAND flash memory by read/write operations using the functions\r
+          HAL_NAND_Read_Page()/HAL_NAND_Read_SpareArea(), HAL_NAND_Write_Page()/HAL_NAND_Write_SpareArea()\r
+          to read/write page(s)/spare area(s). These functions use specific device \r
+          information (Block, page size..) predefined by the user in the HAL_NAND_Info_TypeDef \r
+          structure. The read/write address information is contained by the Nand_Address_Typedef\r
+          structure passed as parameter.\r
+        \r
+      (+) Perform NAND flash Reset chip operation using the function HAL_NAND_Reset().\r
+        \r
+      (+) Perform NAND flash erase block operation using the function HAL_NAND_Erase_Block().\r
+          The erase block address information is contained in the Nand_Address_Typedef \r
+          structure passed as parameter.\r
+    \r
+      (+) Read the NAND flash status operation using the function HAL_NAND_Read_Status().\r
+        \r
+      (+) You can also control the NAND device by calling the control APIs HAL_NAND_ECC_Enable()/\r
+          HAL_NAND_ECC_Disable() to respectively enable/disable the ECC code correction\r
+          feature or the function HAL_NAND_GetECC() to get the ECC correction code. \r
+       \r
+      (+) You can monitor the NAND device HAL state by calling the function\r
+          HAL_NAND_GetState()  \r
+\r
+    [..]\r
+      (@) This driver is a set of generic APIs which handle standard NAND flash operations.\r
+          If a NAND flash device contains different operations and/or implementations, \r
+          it should be implemented separately.\r
+\r
+  @endverbatim\r
+  ******************************************************************************\r
+  * @attention\r
+  *\r
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>\r
+  *\r
+  * Redistribution and use in source and binary forms, with or without modification,\r
+  * are permitted provided that the following conditions are met:\r
+  *   1. Redistributions of source code must retain the above copyright notice,\r
+  *      this list of conditions and the following disclaimer.\r
+  *   2. Redistributions in binary form must reproduce the above copyright notice,\r
+  *      this list of conditions and the following disclaimer in the documentation\r
+  *      and/or other materials provided with the distribution.\r
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors\r
+  *      may be used to endorse or promote products derived from this software\r
+  *      without specific prior written permission.\r
+  *\r
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+  *\r
+  ******************************************************************************\r
+  */ \r
+\r
+/* Includes ------------------------------------------------------------------*/\r
+#include "stm32f7xx_hal.h"\r
+\r
+/** @addtogroup STM32F7xx_HAL_Driver\r
+  * @{\r
+  */\r
+\r
+\r
+#ifdef HAL_NAND_MODULE_ENABLED\r
+\r
+#if defined(STM32F756xx) || defined(STM32F746xx)\r
+\r
+/** @defgroup NAND NAND \r
+  * @brief NAND HAL module driver\r
+  * @{\r
+  */\r
+\r
+/* Private typedef -----------------------------------------------------------*/\r
+/* Private Constants ------------------------------------------------------------*/\r
+/* Private macro -------------------------------------------------------------*/    \r
+/* Private variables ---------------------------------------------------------*/\r
+/* Private function prototypes -----------------------------------------------*/\r
+/* Exported functions ---------------------------------------------------------*/\r
+\r
+/** @defgroup NAND_Exported_Functions NAND Exported Functions\r
+  * @{\r
+  */\r
+    \r
+/** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions \r
+  * @brief    Initialization and Configuration functions \r
+  *\r
+  @verbatim    \r
+  ==============================================================================\r
+            ##### NAND Initialization and de-initialization functions #####\r
+  ==============================================================================\r
+  [..]  \r
+    This section provides functions allowing to initialize/de-initialize\r
+    the NAND memory\r
+  \r
+@endverbatim\r
+  * @{\r
+  */\r
+    \r
+/**\r
+  * @brief  Perform NAND memory Initialization sequence\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @param  ComSpace_Timing: pointer to Common space timing structure\r
+  * @param  AttSpace_Timing: pointer to Attribute space timing structure\r
+  * @retval HAL status\r
+  */\r
+HAL_StatusTypeDef  HAL_NAND_Init(NAND_HandleTypeDef *hnand, FMC_NAND_PCC_TimingTypeDef *ComSpace_Timing, FMC_NAND_PCC_TimingTypeDef *AttSpace_Timing)\r
+{\r
+  /* Check the NAND handle state */\r
+  if(hnand == NULL)\r
+  {\r
+     return HAL_ERROR;\r
+  }\r
+\r
+  if(hnand->State == HAL_NAND_STATE_RESET)\r
+  {\r
+    /* Initialize the low level hardware (MSP) */\r
+    HAL_NAND_MspInit(hnand);\r
+  } \r
+\r
+  /* Initialize NAND control Interface */\r
+  FMC_NAND_Init(hnand->Instance, &(hnand->Init));\r
+  \r
+  /* Initialize NAND common space timing Interface */  \r
+  FMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank);\r
+  \r
+  /* Initialize NAND attribute space timing Interface */  \r
+  FMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank);\r
+  \r
+  /* Enable the NAND device */\r
+  __FMC_NAND_ENABLE(hnand->Instance);\r
+  \r
+  /* Update the NAND controller state */\r
+  hnand->State = HAL_NAND_STATE_READY;\r
+\r
+  return HAL_OK;\r
+}\r
+\r
+/**\r
+  * @brief  Perform NAND memory De-Initialization sequence\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @retval HAL status\r
+  */\r
+HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand)  \r
+{\r
+  /* Initialize the low level hardware (MSP) */\r
+  HAL_NAND_MspDeInit(hnand);\r
+\r
+  /* Configure the NAND registers with their reset values */\r
+  FMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank);\r
+\r
+  /* Reset the NAND controller state */\r
+  hnand->State = HAL_NAND_STATE_RESET;\r
+\r
+  /* Release Lock */\r
+  __HAL_UNLOCK(hnand);\r
+\r
+  return HAL_OK;\r
+}\r
+\r
+/**\r
+  * @brief  NAND MSP Init\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @retval None\r
+  */\r
+__weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand)\r
+{\r
+  /* NOTE : This function Should not be modified, when the callback is needed,\r
+            the HAL_NAND_MspInit could be implemented in the user file\r
+   */ \r
+}\r
+\r
+/**\r
+  * @brief  NAND MSP DeInit\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @retval None\r
+  */\r
+__weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand)\r
+{\r
+  /* NOTE : This function Should not be modified, when the callback is needed,\r
+            the HAL_NAND_MspDeInit could be implemented in the user file\r
+   */ \r
+}\r
+\r
+\r
+/**\r
+  * @brief  This function handles NAND device interrupt request.\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @retval HAL status\r
+*/\r
+void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand)\r
+{\r
+  /* Check NAND interrupt Rising edge flag */\r
+  if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE))\r
+  {\r
+    /* NAND interrupt callback*/\r
+    HAL_NAND_ITCallback(hnand);\r
+  \r
+    /* Clear NAND interrupt Rising edge pending bit */\r
+    __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_RISING_EDGE);\r
+  }\r
+  \r
+  /* Check NAND interrupt Level flag */\r
+  if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL))\r
+  {\r
+    /* NAND interrupt callback*/\r
+    HAL_NAND_ITCallback(hnand);\r
+  \r
+    /* Clear NAND interrupt Level pending bit */\r
+    __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_LEVEL);\r
+  }\r
+\r
+  /* Check NAND interrupt Falling edge flag */\r
+  if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE))\r
+  {\r
+    /* NAND interrupt callback*/\r
+    HAL_NAND_ITCallback(hnand);\r
+  \r
+    /* Clear NAND interrupt Falling edge pending bit */\r
+    __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_FALLING_EDGE);\r
+  }\r
+  \r
+  /* Check NAND interrupt FIFO empty flag */\r
+  if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT))\r
+  {\r
+    /* NAND interrupt callback*/\r
+    HAL_NAND_ITCallback(hnand);\r
+  \r
+    /* Clear NAND interrupt FIFO empty pending bit */\r
+    __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_FEMPT);\r
+  }  \r
+\r
+}\r
+\r
+/**\r
+  * @brief  NAND interrupt feature callback\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @retval None\r
+  */\r
+__weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand)\r
+{\r
+  /* NOTE : This function Should not be modified, when the callback is needed,\r
+            the HAL_NAND_ITCallback could be implemented in the user file\r
+   */\r
+}\r
\r
+/**\r
+  * @}\r
+  */\r
+  \r
+/** @defgroup NAND_Exported_Functions_Group2 Input and Output functions \r
+  * @brief    Input Output and memory control functions \r
+  *\r
+  @verbatim    \r
+  ==============================================================================\r
+                    ##### NAND Input and Output functions #####\r
+  ==============================================================================\r
+  [..]  \r
+    This section provides functions allowing to use and control the NAND \r
+    memory\r
+  \r
+@endverbatim\r
+  * @{\r
+  */\r
+\r
+/**\r
+  * @brief  Read the NAND memory electronic signature\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @param  pNAND_ID: NAND ID structure\r
+  * @retval HAL status\r
+  */\r
+HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID)\r
+{\r
+  __IO uint32_t data = 0;\r
+  uint32_t deviceAddress = 0;\r
+\r
+  /* Process Locked */\r
+  __HAL_LOCK(hnand);  \r
+  \r
+  /* Check the NAND controller state */\r
+  if(hnand->State == HAL_NAND_STATE_BUSY)\r
+  {\r
+     return HAL_BUSY;\r
+  }\r
+  \r
+  /* Identify the device address */\r
+  deviceAddress = NAND_DEVICE;\r
+  \r
+  /* Update the NAND controller state */ \r
+  hnand->State = HAL_NAND_STATE_BUSY;\r
+  \r
+  /* Send Read ID command sequence */  \r
+  *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA))  = NAND_CMD_READID;\r
+  *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00;\r
+\r
+  /* Read the electronic signature from NAND flash */  \r
+  data = *(__IO uint32_t *)deviceAddress;\r
+  \r
+  /* Return the data read */\r
+  pNAND_ID->Maker_Id   = ADDR_1ST_CYCLE(data);\r
+  pNAND_ID->Device_Id  = ADDR_2ND_CYCLE(data);\r
+  pNAND_ID->Third_Id   = ADDR_3RD_CYCLE(data);\r
+  pNAND_ID->Fourth_Id  = ADDR_4TH_CYCLE(data);\r
+  \r
+  /* Update the NAND controller state */ \r
+  hnand->State = HAL_NAND_STATE_READY;\r
+  \r
+  /* Process unlocked */\r
+  __HAL_UNLOCK(hnand);   \r
+   \r
+  return HAL_OK;\r
+}\r
+\r
+/**\r
+  * @brief  NAND memory reset\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @retval HAL status\r
+  */\r
+HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand)\r
+{\r
+  uint32_t deviceAddress = 0;\r
+  \r
+  /* Process Locked */\r
+  __HAL_LOCK(hnand);\r
+    \r
+  /* Check the NAND controller state */\r
+  if(hnand->State == HAL_NAND_STATE_BUSY)\r
+  {\r
+     return HAL_BUSY;\r
+  }\r
+\r
+  /* Identify the device address */  \r
+  deviceAddress = NAND_DEVICE;\r
+  \r
+  /* Update the NAND controller state */   \r
+  hnand->State = HAL_NAND_STATE_BUSY; \r
+  \r
+  /* Send NAND reset command */  \r
+  *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = 0xFF;\r
+    \r
+  \r
+  /* Update the NAND controller state */   \r
+  hnand->State = HAL_NAND_STATE_READY;\r
+  \r
+  /* Process unlocked */\r
+  __HAL_UNLOCK(hnand);    \r
+  \r
+  return HAL_OK;\r
+  \r
+}\r
+  \r
+/**\r
+  * @brief  Read Page(s) from NAND memory block \r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @param  pAddress : pointer to NAND address structure\r
+  * @param  pBuffer : pointer to destination read buffer\r
+  * @param  NumPageToRead : number of pages to read from block \r
+  * @retval HAL status\r
+  */\r
+HAL_StatusTypeDef HAL_NAND_Read_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead)\r
+{   \r
+  __IO uint32_t index  = 0;\r
+  uint32_t deviceAddress = 0, size = 0, numPagesRead = 0, nandAddress = 0;\r
+  \r
+  /* Process Locked */\r
+  __HAL_LOCK(hnand); \r
+  \r
+  /* Check the NAND controller state */\r
+  if(hnand->State == HAL_NAND_STATE_BUSY)\r
+  {\r
+     return HAL_BUSY;\r
+  }\r
+  \r
+  /* Identify the device address */\r
+  deviceAddress = NAND_DEVICE;\r
+\r
+  /* Update the NAND controller state */ \r
+  hnand->State = HAL_NAND_STATE_BUSY;\r
+  \r
+  /* NAND raw address calculation */\r
+  nandAddress = ARRAY_ADDRESS(pAddress, hnand);\r
+  \r
+  /* Page(s) read loop */  \r
+  while((NumPageToRead != 0) && (nandAddress < ((hnand->Info.BlockSize) * (hnand->Info.PageSize) * (hnand->Info.ZoneSize))))\r
+  {       \r
+    /* update the buffer size */\r
+    size = (hnand->Info.PageSize) + ((hnand->Info.PageSize) * numPagesRead);\r
+    \r
+    /* Send read page command sequence */\r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_A;  \r
+   \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00; \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandAddress); \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandAddress); \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandAddress);\r
+  \r
+    /* for 512 and 1 GB devices, 4th cycle is required */    \r
+    if(hnand->Info.BlockNbr >= 1024)\r
+    {\r
+      *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_4TH_CYCLE(nandAddress);\r
+    }\r
+  \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA))  = NAND_CMD_AREA_TRUE1;\r
+      \r
+    /* Get Data into Buffer */    \r
+    for(index = 0; index < size; index++)\r
+    {\r
+      *(uint8_t *)pBuffer++ = *(uint8_t *)deviceAddress;\r
+    }\r
+    \r
+    /* Increment read pages number */\r
+    numPagesRead++;\r
+    \r
+    /* Decrement pages to read */\r
+    NumPageToRead--;\r
+    \r
+    /* Increment the NAND address */\r
+    nandAddress = (uint32_t)(nandAddress + (hnand->Info.PageSize * 8));\r
+    \r
+  }\r
+  \r
+  /* Update the NAND controller state */ \r
+  hnand->State = HAL_NAND_STATE_READY;\r
+  \r
+  /* Process unlocked */\r
+  __HAL_UNLOCK(hnand);  \r
+    \r
+  return HAL_OK;\r
+\r
+}\r
+\r
+/**\r
+  * @brief  Write Page(s) to NAND memory block \r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @param  pAddress : pointer to NAND address structure\r
+  * @param  pBuffer : pointer to source buffer to write  \r
+  * @param  NumPageToWrite  : number of pages to write to block \r
+  * @retval HAL status\r
+  */\r
+HAL_StatusTypeDef HAL_NAND_Write_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite)\r
+{\r
+  __IO uint32_t index = 0;\r
+  uint32_t tickstart = 0;\r
+  uint32_t deviceAddress = 0, size = 0, numPagesWritten = 0, nandAddress = 0;\r
+  \r
+  /* Process Locked */\r
+  __HAL_LOCK(hnand);  \r
+\r
+  /* Check the NAND controller state */\r
+  if(hnand->State == HAL_NAND_STATE_BUSY)\r
+  {\r
+     return HAL_BUSY;\r
+  }\r
+  \r
+  /* Identify the device address */\r
+  deviceAddress = NAND_DEVICE;\r
+  \r
+  /* Update the NAND controller state */ \r
+  hnand->State = HAL_NAND_STATE_BUSY;\r
+  \r
+  /* NAND raw address calculation */\r
+  nandAddress = ARRAY_ADDRESS(pAddress, hnand);\r
+  \r
+  /* Page(s) write loop */\r
+  while((NumPageToWrite != 0) && (nandAddress < ((hnand->Info.BlockSize) * (hnand->Info.PageSize) * (hnand->Info.ZoneSize))))\r
+  {  \r
+    /* update the buffer size */\r
+    size = (hnand->Info.PageSize) + ((hnand->Info.PageSize) * numPagesWritten);\r
\r
+    /* Send write page command sequence */\r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_A;\r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE0;\r
+\r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00;  \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandAddress);  \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandAddress);  \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandAddress);\r
+    __DSB();\r
+    \r
+    /* for 512 and 1 GB devices, 4th cycle is required */     \r
+    if(hnand->Info.BlockNbr >= 1024)\r
+    {\r
+      *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_4TH_CYCLE(nandAddress);\r
+      __DSB();\r
+    }\r
+  \r
+    /* Write data to memory */\r
+    for(index = 0; index < size; index++)\r
+    {\r
+      *(__IO uint8_t *)deviceAddress = *(uint8_t *)pBuffer++;\r
+      __DSB();\r
+    }\r
+   \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;\r
+    \r
+    /* Read status until NAND is ready */\r
+    while(HAL_NAND_Read_Status(hnand) != NAND_READY)\r
+    {\r
+      /* Get tick */\r
+      tickstart = HAL_GetTick();\r
+    \r
+      if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)\r
+      {\r
+        return HAL_TIMEOUT; \r
+      } \r
+    }    \r
\r
+    /* Increment written pages number */\r
+    numPagesWritten++;\r
+    \r
+    /* Decrement pages to write */\r
+    NumPageToWrite--;\r
+    \r
+    /* Increment the NAND address */\r
+    nandAddress = (uint32_t)(nandAddress + (hnand->Info.PageSize * 8));\r
+  }\r
+  \r
+  /* Update the NAND controller state */ \r
+  hnand->State = HAL_NAND_STATE_READY;\r
+  \r
+  /* Process unlocked */\r
+  __HAL_UNLOCK(hnand);      \r
+  \r
+  return HAL_OK;\r
+}\r
+\r
+/**\r
+  * @brief  Read Spare area(s) from NAND memory \r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @param  pAddress : pointer to NAND address structure\r
+  * @param  pBuffer: pointer to source buffer to write  \r
+  * @param  NumSpareAreaToRead: Number of spare area to read  \r
+  * @retval HAL status\r
+*/\r
+HAL_StatusTypeDef HAL_NAND_Read_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead)\r
+{\r
+  __IO uint32_t index = 0; \r
+  uint32_t deviceAddress = 0, size = 0, numSpareAreaRead = 0, nandAddress = 0;\r
+  \r
+  /* Process Locked */\r
+  __HAL_LOCK(hnand);  \r
+  \r
+  /* Check the NAND controller state */\r
+  if(hnand->State == HAL_NAND_STATE_BUSY)\r
+  {\r
+     return HAL_BUSY;\r
+  }\r
+  \r
+  /* Identify the device address */\r
+  deviceAddress = NAND_DEVICE;\r
+  \r
+  /* Update the NAND controller state */\r
+  hnand->State = HAL_NAND_STATE_BUSY;\r
+  \r
+  /* NAND raw address calculation */\r
+  nandAddress = ARRAY_ADDRESS(pAddress, hnand);    \r
+  \r
+  /* Spare area(s) read loop */ \r
+  while((NumSpareAreaToRead != 0) && (nandAddress < ((hnand->Info.BlockSize) * (hnand->Info.SpareAreaSize) * (hnand->Info.ZoneSize))))\r
+  {     \r
+    \r
+    /* update the buffer size */\r
+    size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * numSpareAreaRead);   \r
+\r
+    /* Send read spare area command sequence */     \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_C;\r
+    \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00; \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandAddress);     \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandAddress);     \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandAddress);\r
+  \r
+    /* for 512 and 1 GB devices, 4th cycle is required */    \r
+    if(hnand->Info.BlockNbr >= 1024)\r
+    {\r
+      *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_4TH_CYCLE(nandAddress);\r
+    } \r
+\r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;    \r
+    \r
+    /* Get Data into Buffer */\r
+    for(index = 0; index < size; index++)\r
+    {\r
+      *(uint8_t *)pBuffer++ = *(uint8_t *)deviceAddress;\r
+    }\r
+    \r
+    /* Increment read spare areas number */\r
+    numSpareAreaRead++;\r
+    \r
+    /* Decrement spare areas to read */\r
+    NumSpareAreaToRead--;\r
+    \r
+    /* Increment the NAND address */\r
+    nandAddress = (uint32_t)(nandAddress + (hnand->Info.SpareAreaSize));\r
+  }\r
+  \r
+  /* Update the NAND controller state */\r
+  hnand->State = HAL_NAND_STATE_READY;\r
+  \r
+  /* Process unlocked */\r
+  __HAL_UNLOCK(hnand);     \r
+\r
+  return HAL_OK;  \r
+}\r
+\r
+/**\r
+  * @brief  Write Spare area(s) to NAND memory \r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @param  pAddress : pointer to NAND address structure\r
+  * @param  pBuffer : pointer to source buffer to write  \r
+  * @param  NumSpareAreaTowrite  : number of spare areas to write to block\r
+  * @retval HAL status\r
+  */\r
+HAL_StatusTypeDef HAL_NAND_Write_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite)\r
+{\r
+  __IO uint32_t index = 0;\r
+  uint32_t tickstart = 0;\r
+  uint32_t deviceAddress = 0, size = 0, numSpareAreaWritten = 0, nandAddress = 0;\r
+\r
+  /* Process Locked */\r
+  __HAL_LOCK(hnand); \r
+  \r
+  /* Check the NAND controller state */\r
+  if(hnand->State == HAL_NAND_STATE_BUSY)\r
+  {\r
+     return HAL_BUSY;\r
+  }\r
+  \r
+  /* Identify the device address */\r
+  deviceAddress = NAND_DEVICE;\r
+  \r
+  /* Update the FMC_NAND controller state */\r
+  hnand->State = HAL_NAND_STATE_BUSY;  \r
+  \r
+  /* NAND raw address calculation */\r
+  nandAddress = ARRAY_ADDRESS(pAddress, hnand);  \r
+  \r
+  /* Spare area(s) write loop */\r
+  while((NumSpareAreaTowrite != 0) && (nandAddress < ((hnand->Info.BlockSize) * (hnand->Info.SpareAreaSize) * (hnand->Info.ZoneSize))))\r
+  {  \r
+    /* update the buffer size */\r
+    size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * numSpareAreaWritten);\r
+\r
+    /* Send write Spare area command sequence */\r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_C;\r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE0;\r
+\r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00;  \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandAddress);  \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandAddress);  \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandAddress); \r
+    __DSB();\r
+    /* for 512 and 1 GB devices, 4th cycle is required */     \r
+    if(hnand->Info.BlockNbr >= 1024)\r
+    {\r
+      *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_4TH_CYCLE(nandAddress);\r
+      __DSB();\r
+    }\r
+  \r
+    /* Write data to memory */\r
+    for(index = 0; index < size; index++)\r
+    {\r
+      *(__IO uint8_t *)deviceAddress = *(uint8_t *)pBuffer++;\r
+      __DSB();\r
+    }\r
+   \r
+    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;\r
+    __DSB();\r
+   \r
+    /* Read status until NAND is ready */\r
+    while(HAL_NAND_Read_Status(hnand) != NAND_READY)\r
+    {\r
+      /* Get tick */\r
+      tickstart = HAL_GetTick();\r
+    \r
+      if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)\r
+      {\r
+        return HAL_TIMEOUT; \r
+      }\r
+    }\r
+\r
+    /* Increment written spare areas number */\r
+    numSpareAreaWritten++;\r
+    \r
+    /* Decrement spare areas to write */\r
+    NumSpareAreaTowrite--;\r
+    \r
+    /* Increment the NAND address */\r
+    nandAddress = (uint32_t)(nandAddress + (hnand->Info.PageSize));\r
+  }\r
+\r
+  /* Update the NAND controller state */\r
+  hnand->State = HAL_NAND_STATE_READY;\r
+\r
+  /* Process unlocked */\r
+  __HAL_UNLOCK(hnand);\r
+    \r
+  return HAL_OK;  \r
+}\r
+\r
+/**\r
+  * @brief  NAND memory Block erase \r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @param  pAddress : pointer to NAND address structure\r
+  * @retval HAL status\r
+  */\r
+HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)\r
+{\r
+  uint32_t DeviceAddress = 0;\r
+  \r
+  /* Process Locked */\r
+  __HAL_LOCK(hnand);\r
+  \r
+  /* Check the NAND controller state */\r
+  if(hnand->State == HAL_NAND_STATE_BUSY)\r
+  {\r
+     return HAL_BUSY;\r
+  }\r
+  \r
+  /* Identify the device address */\r
+  DeviceAddress = NAND_DEVICE;\r
+  \r
+  /* Update the NAND controller state */\r
+  hnand->State = HAL_NAND_STATE_BUSY;  \r
+  \r
+  /* Send Erase block command sequence */\r
+  *(__IO uint8_t *)((uint32_t)(DeviceAddress | CMD_AREA)) = NAND_CMD_ERASE0;\r
+\r
+  *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand));\r
+  *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand));\r
+  *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand));\r
+  __DSB();\r
+  \r
+  /* for 512 and 1 GB devices, 4th cycle is required */     \r
+  if(hnand->Info.BlockNbr >= 1024)\r
+  {\r
+    *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = ADDR_4TH_CYCLE(ARRAY_ADDRESS(pAddress, hnand));\r
+    __DSB();\r
+  }  \r
+               \r
+  *(__IO uint8_t *)((uint32_t)(DeviceAddress | CMD_AREA)) = NAND_CMD_ERASE1; \r
+  __DSB();\r
+  \r
+  /* Update the NAND controller state */\r
+  hnand->State = HAL_NAND_STATE_READY;\r
+  \r
+  /* Process unlocked */\r
+  __HAL_UNLOCK(hnand);    \r
+  \r
+  return HAL_OK;  \r
+}\r
+\r
+/**\r
+  * @brief  NAND memory read status \r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @retval NAND status\r
+  */\r
+uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand)\r
+{\r
+  uint32_t data = 0;\r
+  uint32_t DeviceAddress = 0;\r
+  \r
+  /* Identify the device address */\r
+   DeviceAddress = NAND_DEVICE;\r
+\r
+  /* Send Read status operation command */\r
+  *(__IO uint8_t *)((uint32_t)(DeviceAddress | CMD_AREA)) = NAND_CMD_STATUS;\r
+  \r
+  /* Read status register data */\r
+  data = *(__IO uint8_t *)DeviceAddress;\r
+\r
+  /* Return the status */\r
+  if((data & NAND_ERROR) == NAND_ERROR)\r
+  {\r
+    return NAND_ERROR;\r
+  } \r
+  else if((data & NAND_READY) == NAND_READY)\r
+  {\r
+    return NAND_READY;\r
+  }\r
+\r
+  return NAND_BUSY; \r
+}\r
+\r
+/**\r
+  * @brief  Increment the NAND memory address\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @param pAddress: pointer to NAND address structure\r
+  * @retval The new status of the increment address operation. It can be:\r
+  *           - NAND_VALID_ADDRESS: When the new address is valid address\r
+  *           - NAND_INVALID_ADDRESS: When the new address is invalid address\r
+  */\r
+uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)\r
+{\r
+  uint32_t status = NAND_VALID_ADDRESS;\r
\r
+  /* Increment page address */\r
+  pAddress->Page++;\r
+\r
+  /* Check NAND address is valid */\r
+  if(pAddress->Page == hnand->Info.BlockSize)\r
+  {\r
+    pAddress->Page = 0;\r
+    pAddress->Block++;\r
+    \r
+    if(pAddress->Block == hnand->Info.ZoneSize)\r
+    {\r
+      pAddress->Block = 0;\r
+      pAddress->Zone++;\r
+\r
+      if(pAddress->Zone == (hnand->Info.ZoneSize/ hnand->Info.BlockNbr))\r
+      {\r
+        status = NAND_INVALID_ADDRESS;\r
+      }\r
+    }\r
+  } \r
+  \r
+  return (status);\r
+}\r
+/**\r
+  * @}\r
+  */\r
+\r
+/** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions \r
+ *  @brief   management functions \r
+ *\r
+@verbatim   \r
+  ==============================================================================\r
+                         ##### NAND Control functions #####\r
+  ==============================================================================  \r
+  [..]\r
+    This subsection provides a set of functions allowing to control dynamically\r
+    the NAND interface.\r
+\r
+@endverbatim\r
+  * @{\r
+  */ \r
+\r
+    \r
+/**\r
+  * @brief  Enables dynamically NAND ECC feature.\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @retval HAL status\r
+  */    \r
+HAL_StatusTypeDef  HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand)\r
+{\r
+  /* Check the NAND controller state */\r
+  if(hnand->State == HAL_NAND_STATE_BUSY)\r
+  {\r
+     return HAL_BUSY;\r
+  }\r
+\r
+  /* Update the NAND state */\r
+  hnand->State = HAL_NAND_STATE_BUSY;\r
+   \r
+  /* Enable ECC feature */\r
+  FMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank);\r
+  \r
+  /* Update the NAND state */\r
+  hnand->State = HAL_NAND_STATE_READY;\r
+  \r
+  return HAL_OK;  \r
+}\r
+\r
+/**\r
+  * @brief  Disables dynamically FMC_NAND ECC feature.\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @retval HAL status\r
+  */  \r
+HAL_StatusTypeDef  HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand)  \r
+{\r
+  /* Check the NAND controller state */\r
+  if(hnand->State == HAL_NAND_STATE_BUSY)\r
+  {\r
+     return HAL_BUSY;\r
+  }\r
+\r
+  /* Update the NAND state */\r
+  hnand->State = HAL_NAND_STATE_BUSY;\r
+    \r
+  /* Disable ECC feature */\r
+  FMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank);\r
+  \r
+  /* Update the NAND state */\r
+  hnand->State = HAL_NAND_STATE_READY;\r
+  \r
+  return HAL_OK;  \r
+}\r
+\r
+/**\r
+  * @brief  Disables dynamically NAND ECC feature.\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @param  ECCval: pointer to ECC value \r
+  * @param  Timeout: maximum timeout to wait    \r
+  * @retval HAL status\r
+  */\r
+HAL_StatusTypeDef  HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout)\r
+{\r
+  HAL_StatusTypeDef status = HAL_OK;\r
+  \r
+  /* Check the NAND controller state */\r
+  if(hnand->State == HAL_NAND_STATE_BUSY)\r
+  {\r
+     return HAL_BUSY;\r
+  }\r
+  \r
+  /* Update the NAND state */\r
+  hnand->State = HAL_NAND_STATE_BUSY;  \r
+   \r
+  /* Get NAND ECC value */\r
+  status = FMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout);\r
+  \r
+  /* Update the NAND state */\r
+  hnand->State = HAL_NAND_STATE_READY;\r
+\r
+  return status;  \r
+}\r
+                      \r
+/**\r
+  * @}\r
+  */\r
+  \r
+    \r
+/** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions  \r
+ *  @brief   Peripheral State functions \r
+ *\r
+@verbatim   \r
+  ==============================================================================\r
+                         ##### NAND State functions #####\r
+  ==============================================================================  \r
+  [..]\r
+    This subsection permits to get in run-time the status of the NAND controller \r
+    and the data flow.\r
+\r
+@endverbatim\r
+  * @{\r
+  */\r
+  \r
+/**\r
+  * @brief  return the NAND state\r
+  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains\r
+  *                the configuration information for NAND module.\r
+  * @retval HAL state\r
+  */\r
+HAL_NAND_StateTypeDef HAL_NAND_GetState(NAND_HandleTypeDef *hnand)\r
+{\r
+  return hnand->State;\r
+}\r
+\r
+/**\r
+  * @}\r
+  */  \r
+\r
+/**\r
+  * @}\r
+  */\r
+#endif /* STM32F756xx || STM32F746xx */\r
+#endif /* HAL_NAND_MODULE_ENABLED  */\r
+\r
+/**\r
+  * @}\r
+  */\r
+\r
+/**\r
+  * @}\r
+  */\r
+\r
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/\r