mbed library sources

Fork of mbed-src by mbed official

Revision:
532:fe11edbda85c
Parent:
384:ef87175507f1
Child:
613:bc40b8d2aec4
--- a/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_nand.c	Thu Apr 30 13:00:08 2015 +0100
+++ b/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_nand.c	Thu Apr 30 13:45:11 2015 +0100
@@ -2,8 +2,8 @@
   ******************************************************************************
   * @file    stm32f4xx_hal_nand.c
   * @author  MCD Application Team
-  * @version V1.1.0
-  * @date    19-June-2014
+  * @version V1.3.0
+  * @date    09-March-2015
   * @brief   NAND HAL module driver.
   *          This file provides a generic firmware to drive NAND memories mounted 
   *          as external device.
@@ -55,7 +55,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
   *
   * Redistribution and use in source and binary forms, with or without modification,
   * are permitted provided that the following conditions are met:
@@ -89,26 +89,44 @@
   * @{
   */
 
-/** @defgroup NAND 
-  * @brief NAND driver modules
+
+#ifdef HAL_NAND_MODULE_ENABLED
+
+#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\
+    defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
+    defined(STM32F446xx)
+
+/** @defgroup NAND NAND 
+  * @brief NAND HAL module driver
   * @{
   */
-#ifdef HAL_NAND_MODULE_ENABLED
-
-#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
 
 /* Private typedef -----------------------------------------------------------*/
 /* Private define ------------------------------------------------------------*/
+/** @defgroup NAND_Private_Constants NAND Private Constants
+  * @{
+  */
+
+/**
+  * @}
+  */
+
 /* Private macro -------------------------------------------------------------*/    
+/** @defgroup NAND_Private_Macros NAND Private Macros
+  * @{
+  */
+
+/**
+  * @}
+  */
 /* Private variables ---------------------------------------------------------*/
 /* Private function prototypes -----------------------------------------------*/
-/* Private functions ---------------------------------------------------------*/
-
-/** @defgroup NAND_Private_Functions
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup NAND_Exported_Functions NAND Exported Functions
   * @{
   */
     
-/** @defgroup NAND_Group1 Initialization and de-initialization functions 
+/** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions 
   * @brief    Initialization and Configuration functions 
   *
   @verbatim    
@@ -141,6 +159,8 @@
 
   if(hnand->State == HAL_NAND_STATE_RESET)
   {
+    /* Allocate lock resource and initialize it */
+    hnand->Lock = HAL_UNLOCKED;
     /* Initialize the low level hardware (MSP) */
     HAL_NAND_MspInit(hnand);
   } 
@@ -280,7 +300,7 @@
   * @}
   */
   
-/** @defgroup NAND_Group2 Input and Output functions 
+/** @defgroup NAND_Exported_Functions_Group2 Input and Output functions 
   * @brief    Input Output and memory control functions 
   *
   @verbatim    
@@ -305,7 +325,7 @@
 HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID)
 {
   __IO uint32_t data = 0;
-  uint32_t deviceAddress = 0;
+  uint32_t deviceaddress = 0;
 
   /* Process Locked */
   __HAL_LOCK(hnand);  
@@ -319,34 +339,34 @@
   /* Identify the device address */
   if(hnand->Init.NandBank == FMC_NAND_BANK2)
   {
-    deviceAddress = NAND_DEVICE1;
+    deviceaddress = NAND_DEVICE1;
   }
   else
   {
-    deviceAddress = NAND_DEVICE2;
+    deviceaddress = NAND_DEVICE2;
   }
   
   /* Update the NAND controller state */ 
   hnand->State = HAL_NAND_STATE_BUSY;
   
-  /* Send Read ID command sequence */ 	
-  *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA))  = NAND_CMD_READID;
-  *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00;
+  /* Send Read ID command sequence */   
+  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA))  = NAND_CMD_READID;
+  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
 
-  /* Read the electronic signature from NAND flash */	
-  data = *(__IO uint32_t *)deviceAddress;
+  /* Read the electronic signature from NAND flash */  
+  data = *(__IO uint32_t *)deviceaddress;
   
   /* Return the data read */
-  pNAND_ID->Maker_Id   = __ADDR_1st_CYCLE(data);
-  pNAND_ID->Device_Id  = __ADDR_2nd_CYCLE(data);
-  pNAND_ID->Third_Id   = __ADDR_3rd_CYCLE(data);
-  pNAND_ID->Fourth_Id  = __ADDR_4th_CYCLE(data);
+  pNAND_ID->Maker_Id   = ADDR_1ST_CYCLE(data);
+  pNAND_ID->Device_Id  = ADDR_2ND_CYCLE(data);
+  pNAND_ID->Third_Id   = ADDR_3RD_CYCLE(data);
+  pNAND_ID->Fourth_Id  = ADDR_4TH_CYCLE(data);
   
   /* Update the NAND controller state */ 
   hnand->State = HAL_NAND_STATE_READY;
   
   /* Process unlocked */
-  __HAL_UNLOCK(hnand);   
+  __HAL_UNLOCK(hnand);
    
   return HAL_OK;
 }
@@ -359,44 +379,43 @@
   */
 HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand)
 {
-  uint32_t deviceAddress = 0;
-  
+  uint32_t deviceaddress = 0;
+
   /* Process Locked */
   __HAL_LOCK(hnand);
-    
+
   /* Check the NAND controller state */
   if(hnand->State == HAL_NAND_STATE_BUSY)
   {
      return HAL_BUSY;
   }
 
-  /* Identify the device address */  
+  /* Identify the device address */
   if(hnand->Init.NandBank == FMC_NAND_BANK2)
   {
-    deviceAddress = NAND_DEVICE1;
+    deviceaddress = NAND_DEVICE1;
   }
   else
   {
-    deviceAddress = NAND_DEVICE2;
+    deviceaddress = NAND_DEVICE2;
   }  
   
-  /* Update the NAND controller state */   
+  /* Update the NAND controller state */
   hnand->State = HAL_NAND_STATE_BUSY; 
   
   /* Send NAND reset command */  
-  *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = 0xFF;
-    
-  
-  /* Update the NAND controller state */   
+  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF;
+
+
+  /* Update the NAND controller state */
   hnand->State = HAL_NAND_STATE_READY;
   
   /* Process unlocked */
-  __HAL_UNLOCK(hnand);    
-  
+  __HAL_UNLOCK(hnand);
+
   return HAL_OK;
-  
+
 }
-
   
 /**
   * @brief  Read Page(s) from NAND memory block 
@@ -407,10 +426,12 @@
   * @param  NumPageToRead : number of pages to read from block 
   * @retval HAL status
   */
-HAL_StatusTypeDef HAL_NAND_Read_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead)
+HAL_StatusTypeDef HAL_NAND_Read_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead)
 {   
   __IO uint32_t index  = 0;
-  uint32_t deviceAddress = 0, numPagesRead = 0, nandAddress = 0, addressStatus = NAND_VALID_ADDRESS;
+  uint32_t deviceaddress = 0, size = 0, numpagesread = 0, addressstatus = NAND_VALID_ADDRESS;
+  NAND_AddressTypeDef nandaddress;
+  uint32_t addressoffset = 0;
   
   /* Process Locked */
   __HAL_LOCK(hnand); 
@@ -424,61 +445,68 @@
   /* Identify the device address */
   if(hnand->Init.NandBank == FMC_NAND_BANK2)
   {
-    deviceAddress = NAND_DEVICE1;
+    deviceaddress = NAND_DEVICE1;
   }
   else
   {
-    deviceAddress = NAND_DEVICE2;
+    deviceaddress = NAND_DEVICE2;
   }
 
-  /* Update the NAND controller state */ 
+  /* Update the NAND controller state */
   hnand->State = HAL_NAND_STATE_BUSY;
   
-  /* Page(s) read loop */
-  while((NumPageToRead != 0) && (addressStatus == NAND_VALID_ADDRESS))  
-  {	   
-    /* NAND raw address calculation */
-    nandAddress = __ARRAY_ADDRESS(pAddress, hnand);
+  /* Save the content of pAddress as it will be modified */
+  nandaddress.Block     = pAddress->Block;
+  nandaddress.Page      = pAddress->Page;
+  nandaddress.Zone      = pAddress->Zone;
+
+  /* Page(s) read loop */  
+  while((NumPageToRead != 0) && (addressstatus == NAND_VALID_ADDRESS))
+  {     
+    /* update the buffer size */
+    size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpagesread);
+    
+    /* Get the address offset */
+    addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
     
     /* Send read page command sequence */
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_A;  
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
    
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00; 
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_1st_CYCLE(nandAddress); 
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(nandAddress); 
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(nandAddress);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset);
   
-    /* for 512 and 1 GB devices, 4th cycle is required */    
-    if(hnand->Info.BlockNbr > 1024)
+    /* for 512 and 1 GB devices, 4th cycle is required */
+    if(hnand->Info.BlockNbr >= 1024)
     {
-      *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_4th_CYCLE(nandAddress);
+      *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
     }
   
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA))  = NAND_CMD_AREA_TRUE1;
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA))  = NAND_CMD_AREA_TRUE1;
       
     /* Get Data into Buffer */    
-    for(index = 0 ; index < hnand->Info.PageSize; index++)
+    for(index = size; index != 0; index--)
     {
-      *(uint8_t *)pBuffer++ = *(uint8_t *)deviceAddress;
+      *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress;
     }
     
     /* Increment read pages number */
-    numPagesRead++;
+    numpagesread++;
     
     /* Decrement pages to read */
     NumPageToRead--;
     
     /* Increment the NAND address */
-    HAL_NAND_Address_Inc(hnand, pAddress);
-    
+    addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress);
   }
   
-  /* Update the NAND controller state */ 
+  /* Update the NAND controller state */
   hnand->State = HAL_NAND_STATE_READY;
   
   /* Process unlocked */
-  __HAL_UNLOCK(hnand);  
-    
+  __HAL_UNLOCK(hnand);
+
   return HAL_OK;
 
 }
@@ -492,11 +520,13 @@
   * @param  NumPageToWrite  : number of pages to write to block 
   * @retval HAL status
   */
-HAL_StatusTypeDef HAL_NAND_Write_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite)
+HAL_StatusTypeDef HAL_NAND_Write_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite)
 {
-  __IO uint32_t index = 0;
+  __IO uint32_t index   = 0;
   uint32_t tickstart = 0;
-  uint32_t deviceAddress = 0 , numPagesWritten = 0, nandAddress = 0, addressStatus = NAND_VALID_ADDRESS;
+  uint32_t deviceaddress = 0 , size = 0, numpageswritten = 0, addressstatus = NAND_VALID_ADDRESS;
+  NAND_AddressTypeDef nandaddress;
+  uint32_t addressoffset = 0;
   
   /* Process Locked */
   __HAL_LOCK(hnand);  
@@ -510,78 +540,84 @@
   /* Identify the device address */
   if(hnand->Init.NandBank == FMC_NAND_BANK2)
   {
-    deviceAddress = NAND_DEVICE1;
+    deviceaddress = NAND_DEVICE1;
   }
   else
   {
-    deviceAddress = NAND_DEVICE2;
+    deviceaddress = NAND_DEVICE2;
   }
   
   /* Update the NAND controller state */ 
   hnand->State = HAL_NAND_STATE_BUSY;
   
+  /* Save the content of pAddress as it will be modified */
+  nandaddress.Block     = pAddress->Block;
+  nandaddress.Page      = pAddress->Page;
+  nandaddress.Zone      = pAddress->Zone;
+    
   /* Page(s) write loop */
-  while((NumPageToWrite != 0) && (addressStatus == NAND_VALID_ADDRESS))
-  {  
-    /* NAND raw address calculation */
-    nandAddress = __ARRAY_ADDRESS(pAddress, hnand);
- 
+  while((NumPageToWrite != 0) && (addressstatus == NAND_VALID_ADDRESS))
+  {
+    /* update the buffer size */
+    size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpageswritten);
+    
+    /* Get the address offset */
+    addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
+    
     /* Send write page command sequence */
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_A;
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE0;
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
 
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00;  
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_1st_CYCLE(nandAddress);  
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(nandAddress);  
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(nandAddress);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;  
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset);
   
     /* for 512 and 1 GB devices, 4th cycle is required */     
-    if(hnand->Info.BlockNbr > 1024)
+    if(hnand->Info.BlockNbr >= 1024)
     {
-      *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_4th_CYCLE(nandAddress);
+      *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
     }
   
     /* Write data to memory */
-    for(index = 0 ; index < hnand->Info.PageSize; index++)
+    for(index = size; index != 0; index--)
     {
-      *(__IO uint8_t *)deviceAddress = *(uint8_t *)pBuffer++;
+      *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++;
     }
    
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
+    
+    /* Get tick */
+    tickstart = HAL_GetTick();
     
     /* Read status until NAND is ready */
     while(HAL_NAND_Read_Status(hnand) != NAND_READY)
     {
-      /* Get tick */
-      tickstart = HAL_GetTick();
-    
       if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
       {
         return HAL_TIMEOUT; 
-      } 
-    }    
+      }
+    }
  
     /* Increment written pages number */
-    numPagesWritten++;
+    numpageswritten++;
     
     /* Decrement pages to write */
     NumPageToWrite--;
     
     /* Increment the NAND address */
-    HAL_NAND_Address_Inc(hnand, pAddress);
-      
+    addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress);
   }
   
   /* Update the NAND controller state */ 
   hnand->State = HAL_NAND_STATE_READY;
   
   /* Process unlocked */
-  __HAL_UNLOCK(hnand);      
+  __HAL_UNLOCK(hnand);
   
   return HAL_OK;
 }
 
-
 /**
   * @brief  Read Spare area(s) from NAND memory 
   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
@@ -591,10 +627,12 @@
   * @param  NumSpareAreaToRead: Number of spare area to read  
   * @retval HAL status
 */
-HAL_StatusTypeDef HAL_NAND_Read_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead)
+HAL_StatusTypeDef HAL_NAND_Read_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead)
 {
   __IO uint32_t index   = 0; 
-  uint32_t deviceAddress = 0, numSpareAreaRead = 0, nandAddress = 0, addressStatus = NAND_VALID_ADDRESS;
+  uint32_t deviceaddress = 0, size = 0, num_spare_area_read = 0, addressstatus = NAND_VALID_ADDRESS;
+  NAND_AddressTypeDef nandaddress;
+  uint32_t addressoffset = 0;
   
   /* Process Locked */
   __HAL_LOCK(hnand);  
@@ -608,59 +646,67 @@
   /* Identify the device address */
   if(hnand->Init.NandBank == FMC_NAND_BANK2)
   {
-    deviceAddress = NAND_DEVICE1;
+    deviceaddress = NAND_DEVICE1;
   }
   else
   {
-    deviceAddress = NAND_DEVICE2;
+    deviceaddress = NAND_DEVICE2;
   }
   
   /* Update the NAND controller state */
-  hnand->State = HAL_NAND_STATE_BUSY;    
+  hnand->State = HAL_NAND_STATE_BUSY;
+  
+  /* Save the content of pAddress as it will be modified */
+  nandaddress.Block     = pAddress->Block;
+  nandaddress.Page      = pAddress->Page;
+  nandaddress.Zone      = pAddress->Zone;
   
   /* Spare area(s) read loop */ 
-  while((NumSpareAreaToRead != 0) && (addressStatus == NAND_VALID_ADDRESS))
-  { 
-    /* NAND raw address calculation */
-    nandAddress = __ARRAY_ADDRESS(pAddress, hnand);     
+  while((NumSpareAreaToRead != 0) && (addressstatus == NAND_VALID_ADDRESS))
+  {     
+    /* update the buffer size */
+    size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_read);
 
+    /* Get the address offset */
+    addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
+    
     /* Send read spare area command sequence */     
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_C;
-    
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00; 
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_1st_CYCLE(nandAddress);     
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(nandAddress);     
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(nandAddress);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
+
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset);
   
     /* for 512 and 1 GB devices, 4th cycle is required */    
-    if(hnand->Info.BlockNbr > 1024)
+    if(hnand->Info.BlockNbr >= 1024)
     {
-      *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_4th_CYCLE(nandAddress);
+      *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
     } 
 
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;    
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
     
     /* Get Data into Buffer */
-    for(index = 0 ; index < hnand->Info.SpareAreaSize; index++)
+    for (index = size ;index != 0; index--)
     {
-      *(uint8_t *)pBuffer++ = *(uint8_t *)deviceAddress;
+      *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress;
     }
     
     /* Increment read spare areas number */
-    numSpareAreaRead++;
+    num_spare_area_read++;
     
     /* Decrement spare areas to read */
     NumSpareAreaToRead--;
     
     /* Increment the NAND address */
-    HAL_NAND_Address_Inc(hnand, pAddress);
+    addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress);
   }
   
   /* Update the NAND controller state */
   hnand->State = HAL_NAND_STATE_READY;
   
   /* Process unlocked */
-  __HAL_UNLOCK(hnand);     
+  __HAL_UNLOCK(hnand);
 
   return HAL_OK;  
 }
@@ -674,11 +720,13 @@
   * @param  NumSpareAreaTowrite  : number of spare areas to write to block
   * @retval HAL status
   */
-HAL_StatusTypeDef HAL_NAND_Write_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite)
+HAL_StatusTypeDef HAL_NAND_Write_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite)
 {
   __IO uint32_t index = 0;
   uint32_t tickstart = 0;
-  uint32_t deviceAddress = 0, numSpareAreaWritten = 0, nandAddress = 0, addressStatus = NAND_VALID_ADDRESS;
+  uint32_t deviceaddress = 0, size = 0, num_spare_area_written = 0, addressstatus = NAND_VALID_ADDRESS;
+  NAND_AddressTypeDef nandaddress;
+  uint32_t addressoffset = 0;
 
   /* Process Locked */
   __HAL_LOCK(hnand); 
@@ -692,67 +740,73 @@
   /* Identify the device address */
   if(hnand->Init.NandBank == FMC_NAND_BANK2)
   {
-    deviceAddress = NAND_DEVICE1;
+    deviceaddress = NAND_DEVICE1;
   }
   else
   {
-    deviceAddress = NAND_DEVICE2;
+    deviceaddress = NAND_DEVICE2;
   }
   
   /* Update the FMC_NAND controller state */
   hnand->State = HAL_NAND_STATE_BUSY;  
   
+  /* Save the content of pAddress as it will be modified */
+  nandaddress.Block     = pAddress->Block;
+  nandaddress.Page      = pAddress->Page;
+  nandaddress.Zone      = pAddress->Zone;
+  
   /* Spare area(s) write loop */
-  while((NumSpareAreaTowrite != 0) && (addressStatus == NAND_VALID_ADDRESS))
-  {  
-    /* NAND raw address calculation */
-    nandAddress = __ARRAY_ADDRESS(pAddress, hnand);
+  while((NumSpareAreaTowrite != 0) && (addressstatus == NAND_VALID_ADDRESS))
+  {
+    /* update the buffer size */
+    size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_written);
+
+    /* Get the address offset */
+    addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
     
     /* Send write Spare area command sequence */
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_C;
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE0;
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
 
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00;  
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_1st_CYCLE(nandAddress);  
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(nandAddress);  
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(nandAddress); 
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;  
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset);
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset);
   
     /* for 512 and 1 GB devices, 4th cycle is required */     
     if(hnand->Info.BlockNbr >= 1024)
     {
-      *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_4th_CYCLE(nandAddress);
+      *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
     }
   
     /* Write data to memory */
-    for(index = 0 ; index < hnand->Info.SpareAreaSize; index++)
+    for(; index < size; index++)
     {
-      *(__IO uint8_t *)deviceAddress = *(uint8_t *)pBuffer++;
+      *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++;
     }
    
-    *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
     
-   
+    /* Get tick */
+    tickstart = HAL_GetTick();
+    
     /* Read status until NAND is ready */
     while(HAL_NAND_Read_Status(hnand) != NAND_READY)
     {
-      /* Get tick */
-      tickstart = HAL_GetTick();
-    
       if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
       {
         return HAL_TIMEOUT; 
-      }   
+      }
     }
 
     /* Increment written spare areas number */
-    numSpareAreaWritten++;
+    num_spare_area_written++;
     
     /* Decrement spare areas to write */
     NumSpareAreaTowrite--;
     
     /* Increment the NAND address */
-    HAL_NAND_Address_Inc(hnand, pAddress); 
-      
+    addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress);
   }
 
   /* Update the NAND controller state */
@@ -761,7 +815,7 @@
   /* Process unlocked */
   __HAL_UNLOCK(hnand);
     
-  return HAL_OK;  
+  return HAL_OK;
 }
 
 /**
@@ -771,9 +825,10 @@
   * @param  pAddress : pointer to NAND address structure
   * @retval HAL status
   */
-HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress)
+HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
 {
-  uint32_t DeviceAddress = 0;
+  uint32_t deviceaddress = 0;
+  uint32_t tickstart = 0;
   
   /* Process Locked */
   __HAL_LOCK(hnand);
@@ -787,41 +842,55 @@
   /* Identify the device address */
   if(hnand->Init.NandBank == FMC_NAND_BANK2)
   {
-    DeviceAddress = NAND_DEVICE1;
+    deviceaddress = NAND_DEVICE1;
   }
   else
   {
-    DeviceAddress = NAND_DEVICE2;
+    deviceaddress = NAND_DEVICE2;
   }
   
   /* Update the NAND controller state */
   hnand->State = HAL_NAND_STATE_BUSY;  
   
   /* Send Erase block command sequence */
-  *(__IO uint8_t *)((uint32_t)(DeviceAddress | CMD_AREA)) = NAND_CMD_ERASE0;
+  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0;
 
-  *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = __ADDR_1st_CYCLE(__ARRAY_ADDRESS(pAddress, hnand));
-  *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(__ARRAY_ADDRESS(pAddress, hnand));
-  *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(__ARRAY_ADDRESS(pAddress, hnand));
+  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
+  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
+  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
   
   /* for 512 and 1 GB devices, 4th cycle is required */     
   if(hnand->Info.BlockNbr >= 1024)
   {
-    *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = __ADDR_4th_CYCLE(__ARRAY_ADDRESS(pAddress, hnand));
+    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
   }  
-		
-  *(__IO uint8_t *)((uint32_t)(DeviceAddress | CMD_AREA)) = NAND_CMD_ERASE1; 
+    
+  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1; 
   
   /* Update the NAND controller state */
   hnand->State = HAL_NAND_STATE_READY;
   
+  /* Get tick */
+  tickstart = HAL_GetTick();
+  
+  /* Read status until NAND is ready */
+  while(HAL_NAND_Read_Status(hnand) != NAND_READY)
+  {
+    if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
+    {
+      /* Process unlocked */
+      __HAL_UNLOCK(hnand);    
+  
+      return HAL_TIMEOUT; 
+    } 
+  }    
+ 
   /* Process unlocked */
   __HAL_UNLOCK(hnand);    
   
   return HAL_OK;  
 }
 
-
 /**
   * @brief  NAND memory read status 
   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
@@ -831,23 +900,23 @@
 uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand)
 {
   uint32_t data = 0;
-  uint32_t DeviceAddress = 0;
+  uint32_t deviceaddress = 0;
   
   /* Identify the device address */
   if(hnand->Init.NandBank == FMC_NAND_BANK2)
   {
-    DeviceAddress = NAND_DEVICE1;
+    deviceaddress = NAND_DEVICE1;
   }
   else
   {
-    DeviceAddress = NAND_DEVICE2;
+    deviceaddress = NAND_DEVICE2;
   } 
 
   /* Send Read status operation command */
-  *(__IO uint8_t *)((uint32_t)(DeviceAddress | CMD_AREA)) = NAND_CMD_STATUS;
+  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS;
   
   /* Read status register data */
-  data = *(__IO uint8_t *)DeviceAddress;
+  data = *(__IO uint8_t *)deviceaddress;
 
   /* Return the status */
   if((data & NAND_ERROR) == NAND_ERROR)
@@ -860,19 +929,18 @@
   }
 
   return NAND_BUSY; 
- 
 }
 
 /**
   * @brief  Increment the NAND memory address
   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
   *                the configuration information for NAND module.
-  * @param pAddress: pointer to NAND adress structure
+  * @param pAddress: pointer to NAND address structure
   * @retval The new status of the increment address operation. It can be:
   *           - NAND_VALID_ADDRESS: When the new address is valid address
   *           - NAND_INVALID_ADDRESS: When the new address is invalid address
   */
-uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress)
+uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
 {
   uint32_t status = NAND_VALID_ADDRESS;
  
@@ -899,13 +967,11 @@
   
   return (status);
 }
-
-
 /**
   * @}
   */
 
-/** @defgroup NAND_Group3 Control functions 
+/** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions 
  *  @brief   management functions 
  *
 @verbatim   
@@ -944,17 +1010,16 @@
   /* Update the NAND state */
   hnand->State = HAL_NAND_STATE_READY;
   
-  return HAL_OK;  
+  return HAL_OK;
 }
 
-
 /**
   * @brief  Disables dynamically FMC_NAND ECC feature.
   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
   *                the configuration information for NAND module.
   * @retval HAL status
   */  
-HAL_StatusTypeDef  HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand)  
+HAL_StatusTypeDef  HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand)
 {
   /* Check the NAND controller state */
   if(hnand->State == HAL_NAND_STATE_BUSY)
@@ -1003,13 +1068,13 @@
 
   return status;  
 }
-                      
+
 /**
   * @}
   */
   
     
-/** @defgroup NAND_Group4 State functions 
+/** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions 
  *  @brief   Peripheral State functions 
  *
 @verbatim   
@@ -1042,15 +1107,19 @@
 /**
   * @}
   */
-#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
+
+/**
+  * @}
+  */
+
+#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx ||\
+          STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx ||\
+          STM32F446xx */
+          
 #endif /* HAL_NAND_MODULE_ENABLED  */
 
 /**
   * @}
   */
 
-/**
-  * @}
-  */
-
 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/