TUKS MCU Introductory course / TUKS-COURSE-THERMOMETER

Fork of TUKS-COURSE-TIMER by TUKS MCU Introductory course

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32l4xx_hal_nand.c Source File

stm32l4xx_hal_nand.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_hal_nand.c
00004   * @author  MCD Application Team
00005   * @version V1.5.1
00006   * @date    31-May-2016
00007   * @brief   NAND HAL module driver.
00008   *          This file provides a generic firmware to drive NAND memories mounted 
00009   *          as external device.
00010   *         
00011   @verbatim
00012   ==============================================================================
00013                          ##### How to use this driver #####
00014   ==============================================================================    
00015     [..]
00016       This driver is a generic layered driver which contains a set of APIs used to 
00017       control NAND flash memories. It uses the FMC layer functions to interface 
00018       with NAND devices. This driver is used as follows:
00019     
00020       (+) NAND flash memory configuration sequence using the function HAL_NAND_Init() 
00021           with control and timing parameters for both common and attribute spaces.
00022             
00023       (+) Read NAND flash memory maker and device IDs using the function
00024           HAL_NAND_Read_ID(). The read information is stored in the NAND_ID_TypeDef 
00025           structure declared by the function caller. 
00026         
00027       (+) Access NAND flash memory by read/write operations using the functions
00028           HAL_NAND_Read_Page()/HAL_NAND_Read_SpareArea(), HAL_NAND_Write_Page()/HAL_NAND_Write_SpareArea()
00029           to read/write page(s)/spare area(s). These functions use specific device 
00030           information (Block, page size..) predefined by the user in the HAL_NAND_Info_TypeDef 
00031           structure. The read/write address information is contained by the Nand_Address_Typedef
00032           structure passed as parameter.
00033         
00034       (+) Perform NAND flash Reset chip operation using the function HAL_NAND_Reset().
00035         
00036       (+) Perform NAND flash erase block operation using the function HAL_NAND_Erase_Block().
00037           The erase block address information is contained in the Nand_Address_Typedef 
00038           structure passed as parameter.
00039     
00040       (+) Read the NAND flash status operation using the function HAL_NAND_Read_Status().
00041         
00042       (+) You can also control the NAND device by calling the control APIs HAL_NAND_ECC_Enable()/
00043           HAL_NAND_ECC_Disable() to respectively enable/disable the ECC code correction
00044           feature or the function HAL_NAND_GetECC() to get the ECC correction code. 
00045        
00046       (+) You can monitor the NAND device HAL state by calling the function
00047           HAL_NAND_GetState()  
00048 
00049     [..]
00050       (@) This driver is a set of generic APIs which handle standard NAND flash operations.
00051           If a NAND flash device contains different operations and/or implementations, 
00052           it should be implemented separately.
00053 
00054   @endverbatim
00055   ******************************************************************************
00056   * @attention
00057   *
00058   * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
00059   *
00060   * Redistribution and use in source and binary forms, with or without modification,
00061   * are permitted provided that the following conditions are met:
00062   *   1. Redistributions of source code must retain the above copyright notice,
00063   *      this list of conditions and the following disclaimer.
00064   *   2. Redistributions in binary form must reproduce the above copyright notice,
00065   *      this list of conditions and the following disclaimer in the documentation
00066   *      and/or other materials provided with the distribution.
00067   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00068   *      may be used to endorse or promote products derived from this software
00069   *      without specific prior written permission.
00070   *
00071   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00072   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00073   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00074   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00075   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00076   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00077   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00078   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00079   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00080   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00081   *
00082   ******************************************************************************
00083   */ 
00084 
00085 /* Includes ------------------------------------------------------------------*/
00086 #include "stm32l4xx_hal.h"
00087 
00088 #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
00089 
00090 /** @addtogroup STM32L4xx_HAL_Driver
00091   * @{
00092   */
00093 
00094 #ifdef HAL_NAND_MODULE_ENABLED
00095 
00096 /** @defgroup NAND NAND
00097   * @brief NAND HAL module driver
00098   * @{
00099   */
00100 
00101 /* Private typedef -----------------------------------------------------------*/
00102 /* Private define ------------------------------------------------------------*/
00103 /** @defgroup NAND_Private_Constants NAND Private Constants
00104   * @{
00105   */
00106 
00107 /**
00108   * @}
00109   */
00110 
00111 /* Private macro -------------------------------------------------------------*/    
00112 /** @defgroup NAND_Private_Macros NAND Private Macros
00113   * @{
00114   */
00115 
00116 /**
00117   * @}
00118   */
00119 
00120 /* Private variables ---------------------------------------------------------*/
00121 /* Private function prototypes -----------------------------------------------*/
00122 /** @defgroup NAND_Private_Functions NAND Private Functions
00123   * @{
00124   */
00125 static uint32_t NAND_AddressIncrement(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef* Address);
00126 /**
00127   * @}
00128   */
00129 
00130 /* Exported functions ---------------------------------------------------------*/
00131 
00132 /** @defgroup NAND_Exported_Functions NAND Exported Functions
00133   * @{
00134   */
00135     
00136 /** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions 
00137   * @brief    Initialization and Configuration functions 
00138   *
00139   @verbatim    
00140   ==============================================================================
00141             ##### NAND Initialization and de-initialization functions #####
00142   ==============================================================================
00143   [..]  
00144     This section provides functions allowing to initialize/de-initialize
00145     the NAND memory
00146   
00147 @endverbatim
00148   * @{
00149   */
00150     
00151 /**
00152   * @brief  Perform NAND memory Initialization sequence.
00153   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00154   *                the configuration information for NAND module.
00155   * @param  ComSpace_Timing: pointer to Common space timing structure
00156   * @param  AttSpace_Timing: pointer to Attribute space timing structure
00157   * @retval HAL status
00158   */
00159 HAL_StatusTypeDef  HAL_NAND_Init(NAND_HandleTypeDef *hnand, FMC_NAND_PCC_TimingTypeDef *ComSpace_Timing, FMC_NAND_PCC_TimingTypeDef *AttSpace_Timing)
00160 {
00161   /* Check the NAND handle state */
00162   if(hnand == NULL)
00163   {
00164      return HAL_ERROR;
00165   }
00166 
00167   if(hnand->State == HAL_NAND_STATE_RESET)
00168   {
00169     /* Allocate lock resource and initialize it */
00170     hnand->Lock = HAL_UNLOCKED;
00171 
00172     /* Initialize the low level hardware (MSP) */
00173     HAL_NAND_MspInit(hnand);
00174   } 
00175 
00176   /* Initialize NAND control Interface */
00177   FMC_NAND_Init(hnand->Instance, &(hnand->Init));
00178   
00179   /* Initialize NAND common space timing Interface */  
00180   FMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank);
00181   
00182   /* Initialize NAND attribute space timing Interface */  
00183   FMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank);
00184   
00185   /* Enable the NAND device */
00186   __FMC_NAND_ENABLE(hnand->Instance, hnand->Init.NandBank);
00187   
00188   /* Update the NAND controller state */
00189   hnand->State = HAL_NAND_STATE_READY;
00190 
00191   return HAL_OK;
00192 }
00193 
00194 /**
00195   * @brief  Perform NAND memory De-Initialization sequence.
00196   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00197   *                the configuration information for NAND module.
00198   * @retval HAL status
00199   */
00200 HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand)  
00201 {
00202   /* Initialize the low level hardware (MSP) */
00203   HAL_NAND_MspDeInit(hnand);
00204 
00205   /* Configure the NAND registers with their reset values */
00206   FMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank);
00207 
00208   /* Reset the NAND controller state */
00209   hnand->State = HAL_NAND_STATE_RESET;
00210 
00211   /* Release Lock */
00212   __HAL_UNLOCK(hnand);
00213 
00214   return HAL_OK;
00215 }
00216 
00217 /**
00218   * @brief  Initialize the NAND MSP.
00219   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00220   *                the configuration information for NAND module.
00221   * @retval None
00222   */
00223 __weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand)
00224 {
00225   /* Prevent unused argument(s) compilation warning */
00226   UNUSED(hnand);
00227 
00228   /* NOTE : This function should not be modified, when the callback is needed,
00229             the HAL_NAND_MspInit could be implemented in the user file
00230    */ 
00231 }
00232 
00233 /**
00234   * @brief  DeInitialize the NAND MSP.
00235   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00236   *                the configuration information for NAND module.
00237   * @retval None
00238   */
00239 __weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand)
00240 {
00241   /* Prevent unused argument(s) compilation warning */
00242   UNUSED(hnand);
00243 
00244   /* NOTE : This function should not be modified, when the callback is needed,
00245             the HAL_NAND_MspDeInit could be implemented in the user file
00246    */ 
00247 }
00248 
00249 
00250 /**
00251   * @brief  This function handles NAND device interrupt request.
00252   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00253   *                the configuration information for NAND module.
00254   * @retval HAL status
00255 */
00256 void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand)
00257 {
00258   /* Check NAND interrupt Rising edge flag */
00259   if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE))
00260   {
00261     /* NAND interrupt callback*/
00262     HAL_NAND_ITCallback(hnand);
00263   
00264     /* Clear NAND interrupt Rising edge pending bit */
00265     __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE);
00266   }
00267   
00268   /* Check NAND interrupt Level flag */
00269   if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL))
00270   {
00271     /* NAND interrupt callback*/
00272     HAL_NAND_ITCallback(hnand);
00273 
00274     /* Clear NAND interrupt Level pending bit */
00275     __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL);
00276   }
00277 
00278   /* Check NAND interrupt Falling edge flag */
00279   if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE))
00280   {
00281     /* NAND interrupt callback*/
00282     HAL_NAND_ITCallback(hnand);
00283   
00284     /* Clear NAND interrupt Falling edge pending bit */
00285     __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE);
00286   }
00287   
00288   /* Check NAND interrupt FIFO empty flag */
00289   if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT))
00290   {
00291     /* NAND interrupt callback*/
00292     HAL_NAND_ITCallback(hnand);
00293   
00294     /* Clear NAND interrupt FIFO empty pending bit */
00295     __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT);
00296   }  
00297 }
00298 
00299 /**
00300   * @brief  NAND interrupt feature callback.
00301   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00302   *                the configuration information for NAND module.
00303   * @retval None
00304   */
00305 __weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand)
00306 {
00307   /* Prevent unused argument(s) compilation warning */
00308   UNUSED(hnand);
00309 
00310   /* NOTE : This function should not be modified, when the callback is needed,
00311             the HAL_NAND_ITCallback could be implemented in the user file
00312    */
00313 }
00314  
00315 /**
00316   * @}
00317   */
00318   
00319 /** @defgroup NAND_Exported_Functions_Group2 Input and Output functions 
00320   * @brief    Input Output and memory control functions 
00321   *
00322   @verbatim    
00323   ==============================================================================
00324                     ##### NAND Input and Output functions #####
00325   ==============================================================================
00326   [..]  
00327     This section provides functions allowing to use and control the NAND 
00328     memory
00329   
00330 @endverbatim
00331   * @{
00332   */
00333 
00334 /**
00335   * @brief  Read the NAND memory electronic signature.
00336   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00337   *                the configuration information for NAND module.
00338   * @param  pNAND_ID: NAND ID structure
00339   * @retval HAL status
00340   */
00341 HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID)
00342 {
00343   __IO uint32_t data = 0;
00344   uint32_t deviceaddress = 0;
00345 
00346   /* Process Locked */
00347   __HAL_LOCK(hnand);  
00348   
00349   /* Check the NAND controller state */
00350   if(hnand->State == HAL_NAND_STATE_BUSY)
00351   {
00352      return HAL_BUSY;
00353   }
00354   
00355   /* Identify the device address */
00356   deviceaddress = NAND_DEVICE;
00357   
00358   /* Update the NAND controller state */ 
00359   hnand->State = HAL_NAND_STATE_BUSY;
00360   
00361   /* Send Read ID command sequence */   
00362   *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA))  = NAND_CMD_READID;
00363   *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
00364 
00365   /* Read the electronic signature from NAND flash */   
00366   data = *(__IO uint32_t *)deviceaddress;
00367   
00368   /* Return the data read */
00369   pNAND_ID->Maker_Id   = ADDR_1ST_CYCLE(data);
00370   pNAND_ID->Device_Id  = ADDR_2ND_CYCLE(data);
00371   pNAND_ID->Third_Id   = ADDR_3RD_CYCLE(data);
00372   pNAND_ID->Fourth_Id  = ADDR_4TH_CYCLE(data);
00373   
00374   /* Update the NAND controller state */ 
00375   hnand->State = HAL_NAND_STATE_READY;
00376   
00377   /* Process unlocked */
00378   __HAL_UNLOCK(hnand);   
00379    
00380   return HAL_OK;
00381 }
00382 
00383 /**
00384   * @brief  NAND memory reset.
00385   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00386   *                the configuration information for NAND module.
00387   * @retval HAL status
00388   */
00389 HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand)
00390 {
00391   uint32_t deviceaddress = 0;
00392   
00393   /* Process Locked */
00394   __HAL_LOCK(hnand);
00395     
00396   /* Check the NAND controller state */
00397   if(hnand->State == HAL_NAND_STATE_BUSY)
00398   {
00399      return HAL_BUSY;
00400   }
00401 
00402   /* Identify the device address */  
00403   deviceaddress = NAND_DEVICE;
00404   
00405   /* Update the NAND controller state */   
00406   hnand->State = HAL_NAND_STATE_BUSY; 
00407   
00408   /* Send NAND reset command */  
00409   *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF;
00410     
00411   
00412   /* Update the NAND controller state */   
00413   hnand->State = HAL_NAND_STATE_READY;
00414   
00415   /* Process unlocked */
00416   __HAL_UNLOCK(hnand);    
00417   
00418   return HAL_OK;
00419   
00420 }
00421 
00422 /**
00423   * @brief  Read Page(s) from NAND memory block.
00424   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00425   *                the configuration information for NAND module.
00426   * @param  pAddress: pointer to NAND address structure
00427   * @param  pBuffer: pointer to destination read buffer
00428   * @param  NumPageToRead: number of pages to read from block 
00429   * @retval HAL status
00430   */
00431 HAL_StatusTypeDef HAL_NAND_Read_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead)
00432 {   
00433   __IO uint32_t index  = 0;
00434   uint32_t deviceaddress = 0, size = 0, numpagesread = 0, addressstatus = NAND_VALID_ADDRESS;
00435   NAND_AddressTypeDef nandaddress;
00436   uint32_t addressoffset = 0;
00437   
00438   /* Process Locked */
00439   __HAL_LOCK(hnand); 
00440   
00441   /* Check the NAND controller state */
00442   if(hnand->State == HAL_NAND_STATE_BUSY)
00443   {
00444      return HAL_BUSY;
00445   }
00446   
00447   /* Identify the device address */
00448   deviceaddress = NAND_DEVICE;
00449 
00450   /* Update the NAND controller state */ 
00451   hnand->State = HAL_NAND_STATE_BUSY;
00452   
00453   /* Save the content of pAddress as it will be modified */
00454   nandaddress.Block     = pAddress->Block;
00455   nandaddress.Page      = pAddress->Page;
00456   nandaddress.Zone      = pAddress->Zone;
00457   
00458   /* Page(s) read loop */
00459   while((NumPageToRead != 0) && (addressstatus == NAND_VALID_ADDRESS))  
00460   {    
00461     /* update the buffer size */
00462     size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpagesread);
00463     
00464     /* Get the address offset */
00465     addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
00466     
00467     /* Send read page command sequence */
00468     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;  
00469    
00470     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 
00471     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); 
00472     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); 
00473     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset);
00474   
00475     /* for 512 and 1 GB devices, 4th cycle is required */    
00476     if(hnand->Info.BlockNbr >= 1024)
00477     {
00478       *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
00479     }
00480   
00481     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA))  = NAND_CMD_AREA_TRUE1;
00482       
00483     /* Get Data into Buffer */    
00484     for(; index < size; index++)
00485     {
00486       *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress;
00487     }
00488     
00489     /* Increment read pages number */
00490     numpagesread++;
00491     
00492     /* Decrement pages to read */
00493     NumPageToRead--;
00494     
00495     /* Increment the NAND address */
00496     addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
00497   }
00498   
00499   /* Update the NAND controller state */ 
00500   hnand->State = HAL_NAND_STATE_READY;
00501   
00502   /* Process unlocked */
00503   __HAL_UNLOCK(hnand);  
00504     
00505   return HAL_OK;
00506 
00507 }
00508 
00509 /**
00510   * @brief  Write Page(s) to NAND memory block.
00511   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00512   *                the configuration information for NAND module.
00513   * @param  pAddress: pointer to NAND address structure
00514   * @param  pBuffer: pointer to source buffer to write  
00515   * @param  NumPageToWrite: number of pages to write to block 
00516   * @retval HAL status
00517   */
00518 HAL_StatusTypeDef HAL_NAND_Write_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite)
00519 {
00520   __IO uint32_t index = 0;
00521   uint32_t tickstart = 0;
00522   uint32_t deviceaddress = 0 , size = 0, numpageswritten = 0, addressstatus = NAND_VALID_ADDRESS;
00523   NAND_AddressTypeDef nandaddress;
00524   uint32_t addressoffset = 0;
00525   
00526   /* Process Locked */
00527   __HAL_LOCK(hnand);  
00528 
00529   /* Check the NAND controller state */
00530   if(hnand->State == HAL_NAND_STATE_BUSY)
00531   {
00532      return HAL_BUSY;
00533   }
00534   
00535   /* Identify the device address */
00536   deviceaddress = NAND_DEVICE;
00537   
00538   /* Update the NAND controller state */ 
00539   hnand->State = HAL_NAND_STATE_BUSY;
00540   
00541   /* Save the content of pAddress as it will be modified */
00542   nandaddress.Block     = pAddress->Block;
00543   nandaddress.Page      = pAddress->Page;
00544   nandaddress.Zone      = pAddress->Zone;
00545     
00546   /* Page(s) write loop */
00547   while((NumPageToWrite != 0) && (addressstatus == NAND_VALID_ADDRESS))
00548   {  
00549     /* update the buffer size */
00550     size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpageswritten);
00551     
00552     /* Get the address offset */
00553     addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
00554  
00555     /* Send write page command sequence */
00556     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
00557     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
00558 
00559     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;  
00560     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset);  
00561     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset);  
00562     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset);
00563   
00564     /* for 512 and 1 GB devices, 4th cycle is required */     
00565     if(hnand->Info.BlockNbr >= 1024)
00566     {
00567       *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
00568     }
00569   
00570     /* Write data to memory */
00571     for(; index < size; index++)
00572     {
00573       *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++;
00574     }
00575    
00576     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
00577     
00578     /* Get tick */
00579     tickstart = HAL_GetTick();
00580     
00581     /* Read status until NAND is ready */
00582     while(HAL_NAND_Read_Status(hnand) != NAND_READY)
00583     {
00584       if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
00585       {
00586         return HAL_TIMEOUT; 
00587       } 
00588     }    
00589  
00590     /* Increment written pages number */
00591     numpageswritten++;
00592     
00593     /* Decrement pages to write */
00594     NumPageToWrite--;
00595     
00596     /* Increment the NAND address */
00597     addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
00598   }
00599   
00600   /* Update the NAND controller state */ 
00601   hnand->State = HAL_NAND_STATE_READY;
00602   
00603   /* Process unlocked */
00604   __HAL_UNLOCK(hnand);      
00605   
00606   return HAL_OK;
00607 }
00608 
00609 /**
00610   * @brief  Read Spare area(s) from NAND memory. 
00611   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00612   *                the configuration information for NAND module.
00613   * @param  pAddress: pointer to NAND address structure
00614   * @param  pBuffer: pointer to source buffer to write  
00615   * @param  NumSpareAreaToRead: Number of spare area to read  
00616   * @retval HAL status
00617 */
00618 HAL_StatusTypeDef HAL_NAND_Read_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead)
00619 {
00620   __IO uint32_t index   = 0; 
00621   uint32_t deviceaddress = 0, size = 0, num_spare_area_read = 0, addressstatus = NAND_VALID_ADDRESS;
00622   NAND_AddressTypeDef nandaddress;
00623   uint32_t addressoffset = 0;
00624   
00625   /* Process Locked */
00626   __HAL_LOCK(hnand);  
00627   
00628   /* Check the NAND controller state */
00629   if(hnand->State == HAL_NAND_STATE_BUSY)
00630   {
00631      return HAL_BUSY;
00632   }
00633   
00634   /* Identify the device address */
00635   deviceaddress = NAND_DEVICE;
00636   
00637   /* Update the NAND controller state */
00638   hnand->State = HAL_NAND_STATE_BUSY;    
00639   
00640   /* Save the content of pAddress as it will be modified */
00641   nandaddress.Block     = pAddress->Block;
00642   nandaddress.Page      = pAddress->Page;
00643   nandaddress.Zone      = pAddress->Zone;
00644   
00645   /* Spare area(s) read loop */ 
00646   while((NumSpareAreaToRead != 0) && (addressstatus == NAND_VALID_ADDRESS))
00647   { 
00648     /* update the buffer size */
00649     size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_read);   
00650 
00651     /* Get the address offset */
00652     addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
00653 
00654     /* Send read spare area command sequence */     
00655     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
00656     
00657     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 
00658     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset);     
00659     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset);     
00660     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset);
00661   
00662     /* for 512 and 1 GB devices, 4th cycle is required */    
00663     if(hnand->Info.BlockNbr >= 1024)
00664     {
00665       *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
00666     } 
00667 
00668     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;    
00669     
00670     /* Get Data into Buffer */
00671     for ( ;index < size; index++)
00672     {
00673       *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress;
00674     }
00675     
00676     /* Increment read spare areas number */
00677     num_spare_area_read++;
00678     
00679     /* Decrement spare areas to read */
00680     NumSpareAreaToRead--;
00681     
00682     /* Increment the NAND address */
00683     addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
00684   }
00685   
00686   /* Update the NAND controller state */
00687   hnand->State = HAL_NAND_STATE_READY;
00688   
00689   /* Process unlocked */
00690   __HAL_UNLOCK(hnand);     
00691 
00692   return HAL_OK;  
00693 }
00694 
00695 /**
00696   * @brief  Write Spare area(s) to NAND memory.
00697   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00698   *                the configuration information for NAND module.
00699   * @param  pAddress: pointer to NAND address structure
00700   * @param  pBuffer: pointer to source buffer to write  
00701   * @param  NumSpareAreaTowrite: number of spare areas to write to block
00702   * @retval HAL status
00703   */
00704 HAL_StatusTypeDef HAL_NAND_Write_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite)
00705 {
00706   __IO uint32_t index = 0;
00707   uint32_t tickstart = 0;
00708   uint32_t deviceaddress = 0, size = 0, num_spare_area_written = 0, addressstatus = NAND_VALID_ADDRESS;
00709   NAND_AddressTypeDef nandaddress;
00710   uint32_t addressoffset = 0;
00711 
00712   /* Process Locked */
00713   __HAL_LOCK(hnand); 
00714   
00715   /* Check the NAND controller state */
00716   if(hnand->State == HAL_NAND_STATE_BUSY)
00717   {
00718      return HAL_BUSY;
00719   }
00720   
00721   /* Identify the device address */
00722   deviceaddress = NAND_DEVICE;
00723   
00724   /* Update the FMC_NAND controller state */
00725   hnand->State = HAL_NAND_STATE_BUSY;  
00726   
00727   /* Save the content of pAddress as it will be modified */
00728   nandaddress.Block     = pAddress->Block;
00729   nandaddress.Page      = pAddress->Page;
00730   nandaddress.Zone      = pAddress->Zone;
00731   
00732   /* Spare area(s) write loop */
00733   while((NumSpareAreaTowrite != 0) && (addressstatus == NAND_VALID_ADDRESS))
00734   {  
00735     /* update the buffer size */
00736     size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_written);
00737 
00738     /* Get the address offset */
00739     addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
00740     
00741     /* Send write Spare area command sequence */
00742     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
00743     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
00744 
00745     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;  
00746     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset);  
00747     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset);  
00748     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); 
00749   
00750     /* for 512 and 1 GB devices, 4th cycle is required */     
00751     if(hnand->Info.BlockNbr >= 1024)
00752     {
00753       *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
00754     }
00755   
00756     /* Write data to memory */
00757     for(; index < size; index++)
00758     {
00759       *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++;
00760     }
00761    
00762     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
00763     
00764     /* Get tick */
00765     tickstart = HAL_GetTick();
00766    
00767     /* Read status until NAND is ready */
00768     while(HAL_NAND_Read_Status(hnand) != NAND_READY)
00769     {
00770       if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
00771       {
00772         return HAL_TIMEOUT; 
00773       }   
00774     }
00775 
00776     /* Increment written spare areas number */
00777     num_spare_area_written++;
00778     
00779     /* Decrement spare areas to write */
00780     NumSpareAreaTowrite--;
00781     
00782     /* Increment the NAND address */
00783     addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
00784   }
00785 
00786   /* Update the NAND controller state */
00787   hnand->State = HAL_NAND_STATE_READY;
00788 
00789   /* Process unlocked */
00790   __HAL_UNLOCK(hnand);
00791     
00792   return HAL_OK;  
00793 }
00794 
00795 /**
00796   * @brief  NAND memory Block erase.
00797   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00798   *                the configuration information for NAND module.
00799   * @param  pAddress: pointer to NAND address structure
00800   * @retval HAL status
00801   */
00802 HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
00803 {
00804   uint32_t deviceaddress = 0;
00805   uint32_t tickstart = 0;
00806   
00807   /* Process Locked */
00808   __HAL_LOCK(hnand);
00809   
00810   /* Check the NAND controller state */
00811   if(hnand->State == HAL_NAND_STATE_BUSY)
00812   {
00813      return HAL_BUSY;
00814   }
00815   
00816   /* Identify the device address */
00817   deviceaddress = NAND_DEVICE;
00818   
00819   /* Update the NAND controller state */
00820   hnand->State = HAL_NAND_STATE_BUSY;  
00821   
00822   /* Send Erase block command sequence */
00823   *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0;
00824 
00825   *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
00826   *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
00827   *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
00828   
00829   /* for 512 and 1 GB devices, 4th cycle is required */     
00830   if(hnand->Info.BlockNbr >= 1024)
00831   {
00832     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
00833   }  
00834         
00835   *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1; 
00836   
00837   /* Update the NAND controller state */
00838   hnand->State = HAL_NAND_STATE_READY;
00839   
00840   /* Get tick */
00841   tickstart = HAL_GetTick();
00842   
00843   /* Read status until NAND is ready */
00844   while(HAL_NAND_Read_Status(hnand) != NAND_READY)
00845   {
00846     if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
00847     {
00848       /* Process unlocked */
00849       __HAL_UNLOCK(hnand);    
00850   
00851       return HAL_TIMEOUT; 
00852     } 
00853   }    
00854  
00855   /* Process unlocked */
00856   __HAL_UNLOCK(hnand);    
00857   
00858   return HAL_OK;  
00859 }
00860 
00861 /**
00862   * @brief  NAND memory read status. 
00863   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00864   *                the configuration information for NAND module.
00865   * @retval NAND status
00866   */
00867 uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand)
00868 {
00869   uint32_t data = 0;
00870   uint32_t deviceaddress = 0;
00871   
00872   /* Prevent unused argument(s) compilation warning */
00873   UNUSED(hnand);
00874 
00875   /* Identify the device address */
00876    deviceaddress = NAND_DEVICE;
00877 
00878   /* Send Read status operation command */
00879   *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS;
00880   
00881   /* Read status register data */
00882   data = *(__IO uint8_t *)deviceaddress;
00883 
00884   /* Return the status */
00885   if((data & NAND_ERROR) == NAND_ERROR)
00886   {
00887     return NAND_ERROR;
00888   } 
00889   else if((data & NAND_READY) == NAND_READY)
00890   {
00891     return NAND_READY;
00892   }
00893 
00894   return NAND_BUSY; 
00895 }
00896 
00897 /**
00898   * @brief  Increment the NAND memory address.
00899   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00900   *                the configuration information for NAND module.
00901   * @param pAddress: pointer to NAND address structure
00902   * @retval The new status of the increment address operation. It can be:
00903   *           - NAND_VALID_ADDRESS: When the new address is valid address
00904   *           - NAND_INVALID_ADDRESS: When the new address is invalid address
00905   */
00906 uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
00907 {
00908   uint32_t status = NAND_VALID_ADDRESS;
00909  
00910   /* Increment page address */
00911   pAddress->Page++;
00912 
00913   /* Check NAND address is valid */
00914   if(pAddress->Page == hnand->Info.BlockSize)
00915   {
00916     pAddress->Page = 0;
00917     pAddress->Block++;
00918     
00919     if(pAddress->Block == hnand->Info.ZoneSize)
00920     {
00921       pAddress->Block = 0;
00922       pAddress->Zone++;
00923 
00924       if(pAddress->Zone == (hnand->Info.ZoneSize/ hnand->Info.BlockNbr))
00925       {
00926         status = NAND_INVALID_ADDRESS;
00927       }
00928     }
00929   } 
00930   
00931   return (status);
00932 }
00933 /**
00934   * @}
00935   */
00936 
00937 /** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions 
00938  *  @brief   management functions 
00939  *
00940 @verbatim   
00941   ==============================================================================
00942                          ##### NAND Control functions #####
00943   ==============================================================================  
00944   [..]
00945     This subsection provides a set of functions allowing to control dynamically
00946     the NAND interface.
00947 
00948 @endverbatim
00949   * @{
00950   */ 
00951 
00952     
00953 /**
00954   * @brief  Enable dynamically NAND ECC feature.
00955   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00956   *                the configuration information for NAND module.
00957   * @retval HAL status
00958   */    
00959 HAL_StatusTypeDef  HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand)
00960 {
00961   /* Check the NAND controller state */
00962   if(hnand->State == HAL_NAND_STATE_BUSY)
00963   {
00964      return HAL_BUSY;
00965   }
00966 
00967   /* Update the NAND state */
00968   hnand->State = HAL_NAND_STATE_BUSY;
00969    
00970   /* Enable ECC feature */
00971   FMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank);
00972   
00973   /* Update the NAND state */
00974   hnand->State = HAL_NAND_STATE_READY;
00975   
00976   return HAL_OK;  
00977 }
00978 
00979 /**
00980   * @brief  Disable dynamically NAND ECC feature.
00981   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
00982   *                the configuration information for NAND module.
00983   * @retval HAL status
00984   */  
00985 HAL_StatusTypeDef  HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand)  
00986 {
00987   /* Check the NAND controller state */
00988   if(hnand->State == HAL_NAND_STATE_BUSY)
00989   {
00990      return HAL_BUSY;
00991   }
00992 
00993   /* Update the NAND state */
00994   hnand->State = HAL_NAND_STATE_BUSY;
00995     
00996   /* Disable ECC feature */
00997   FMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank);
00998   
00999   /* Update the NAND state */
01000   hnand->State = HAL_NAND_STATE_READY;
01001   
01002   return HAL_OK;  
01003 }
01004 
01005 /**
01006   * @brief  Disable dynamically NAND ECC feature.
01007   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
01008   *                the configuration information for NAND module.
01009   * @param  ECCval: pointer to ECC value 
01010   * @param  Timeout: maximum timeout to wait    
01011   * @retval HAL status
01012   */
01013 HAL_StatusTypeDef  HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout)
01014 {
01015   HAL_StatusTypeDef status = HAL_OK;
01016   
01017   /* Check the NAND controller state */
01018   if(hnand->State == HAL_NAND_STATE_BUSY)
01019   {
01020      return HAL_BUSY;
01021   }
01022   
01023   /* Update the NAND state */
01024   hnand->State = HAL_NAND_STATE_BUSY;  
01025    
01026   /* Get NAND ECC value */
01027   status = FMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout);
01028   
01029   /* Update the NAND state */
01030   hnand->State = HAL_NAND_STATE_READY;
01031 
01032   return status;  
01033 }
01034                       
01035 /**
01036   * @}
01037   */
01038   
01039     
01040 /** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions 
01041  *  @brief   Peripheral State functions 
01042  *
01043 @verbatim   
01044   ==============================================================================
01045                          ##### NAND State functions #####
01046   ==============================================================================  
01047   [..]
01048     This subsection permits to get in run-time the status of the NAND controller 
01049     and the data flow.
01050 
01051 @endverbatim
01052   * @{
01053   */
01054   
01055 /**
01056   * @brief  Return the NAND handle state.
01057   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
01058   *                the configuration information for NAND module.
01059   * @retval HAL state
01060   */
01061 HAL_NAND_StateTypeDef HAL_NAND_GetState(NAND_HandleTypeDef *hnand)
01062 {
01063   /* Return NAND handle state */
01064   return hnand->State;
01065 }
01066 
01067 /**
01068   * @}
01069   */  
01070 
01071 /**
01072   * @}
01073   */
01074 
01075 /** @addtogroup NAND_Private_Functions
01076   * @{
01077   */
01078 
01079 /**
01080   * @brief  Increment the NAND memory address. 
01081   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
01082   *                the configuration information for NAND module.
01083   * @param  Address: address to be incremented.
01084   * @retval The new status of the increment address operation. It can be:
01085   *              - NAND_VALID_ADDRESS: When the new address is valid address
01086   *              - NAND_INVALID_ADDRESS: When the new address is invalid address   
01087   */
01088 static uint32_t NAND_AddressIncrement(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef* Address)
01089 {
01090   uint32_t status = NAND_VALID_ADDRESS;
01091  
01092   Address->Page++;
01093 
01094   if(Address->Page == hnand->Info.BlockSize)
01095   {
01096     Address->Page = 0;
01097     Address->Block++;
01098     
01099     if(Address->Block == hnand->Info.ZoneSize)
01100     {
01101       Address->Block = 0;
01102       Address->Zone++;
01103 
01104       if(Address->Zone == hnand->Info.BlockNbr)
01105       {
01106         status = NAND_INVALID_ADDRESS;
01107       }
01108     }
01109   } 
01110   
01111   return (status);
01112 }
01113 
01114 /**
01115   * @}
01116   */
01117 
01118 /**
01119   * @}
01120   */
01121 
01122 #endif /* HAL_NAND_MODULE_ENABLED  */
01123 
01124 /**
01125   * @}
01126   */
01127 
01128 #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */
01129 
01130 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/