]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F1/stm32f1xx_hal_nand.c
Merge commit 'f6d56675f9f981c5464f0ca7a1fbb0162154e8c5'
[max/tmk_keyboard.git] / tmk_core / tool / mbed / mbed-sdk / libraries / mbed / targets / cmsis / TARGET_STM / TARGET_STM32F1 / stm32f1xx_hal_nand.c
1 /**
2   ******************************************************************************
3   * @file    stm32f1xx_hal_nand.c
4   * @author  MCD Application Team
5   * @version V1.0.0
6   * @date    15-December-2014
7   * @brief   NAND HAL module driver.
8   *          This file provides a generic firmware to drive NAND memories mounted 
9   *          as external device.
10   *         
11   @verbatim
12   ==============================================================================
13                          ##### How to use this driver #####
14   ==============================================================================    
15     [..]
16       This driver is a generic layered driver which contains a set of APIs used to 
17       control NAND flash memories. It uses the FSMC/FSMC layer functions to interface 
18       with NAND devices. This driver is used as follows:
19     
20       (+) NAND flash memory configuration sequence using the function HAL_NAND_Init() 
21           with control and timing parameters for both common and attribute spaces.
22             
23       (+) Read NAND flash memory maker and device IDs using the function
24           HAL_NAND_Read_ID(). The read information is stored in the NAND_ID_TypeDef 
25           structure declared by the function caller. 
26         
27       (+) Access NAND flash memory by read/write operations using the functions
28           HAL_NAND_Read_Page()/HAL_NAND_Read_SpareArea(), HAL_NAND_Write_Page()/HAL_NAND_Write_SpareArea()
29           to read/write page(s)/spare area(s). These functions use specific device 
30           information (Block, page size..) predefined by the user in the HAL_NAND_Info_TypeDef 
31           structure. The read/write address information is contained by the Nand_Address_Typedef
32           structure passed as parameter.
33         
34       (+) Perform NAND flash Reset chip operation using the function HAL_NAND_Reset().
35         
36       (+) Perform NAND flash erase block operation using the function HAL_NAND_Erase_Block().
37           The erase block address information is contained in the Nand_Address_Typedef 
38           structure passed as parameter.
39     
40       (+) Read the NAND flash status operation using the function HAL_NAND_Read_Status().
41         
42       (+) You can also control the NAND device by calling the control APIs HAL_NAND_ECC_Enable()/
43           HAL_NAND_ECC_Disable() to respectively enable/disable the ECC code correction
44           feature or the function HAL_NAND_GetECC() to get the ECC correction code. 
45        
46       (+) You can monitor the NAND device HAL state by calling the function
47           HAL_NAND_GetState()  
48
49     [..]
50       (@) This driver is a set of generic APIs which handle standard NAND flash operations.
51           If a NAND flash device contains different operations and/or implementations, 
52           it should be implemented separately.
53
54   @endverbatim
55   ******************************************************************************
56   * @attention
57   *
58   * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
59   *
60   * Redistribution and use in source and binary forms, with or without modification,
61   * are permitted provided that the following conditions are met:
62   *   1. Redistributions of source code must retain the above copyright notice,
63   *      this list of conditions and the following disclaimer.
64   *   2. Redistributions in binary form must reproduce the above copyright notice,
65   *      this list of conditions and the following disclaimer in the documentation
66   *      and/or other materials provided with the distribution.
67   *   3. Neither the name of STMicroelectronics nor the names of its contributors
68   *      may be used to endorse or promote products derived from this software
69   *      without specific prior written permission.
70   *
71   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
72   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
74   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
75   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
76   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
77   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
78   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
79   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
81   *
82   ******************************************************************************
83   */ 
84
85 /* Includes ------------------------------------------------------------------*/
86 #include "stm32f1xx_hal.h"
87
88 /** @addtogroup STM32F1xx_HAL_Driver
89   * @{
90   */
91
92 #ifdef HAL_NAND_MODULE_ENABLED
93
94 #if defined (STM32F101xE) || defined(STM32F103xE) || defined(STM32F101xG) || defined(STM32F103xG)
95
96 /** @defgroup NAND NAND
97   * @brief NAND HAL module driver
98   * @{
99   */
100
101 /* Private typedef -----------------------------------------------------------*/
102 /* Private define ------------------------------------------------------------*/
103 /** @defgroup NAND_Private_Constants NAND Private Constants
104   * @{
105   */
106
107 /**
108   * @}
109   */
110
111 /* Private macro -------------------------------------------------------------*/    
112 /** @defgroup NAND_Private_Macros NAND Private Macros
113   * @{
114   */
115
116 /**
117   * @}
118   */
119
120 /* Private variables ---------------------------------------------------------*/
121 /* Private function prototypes -----------------------------------------------*/
122 /** @defgroup NAND_Private_Functions NAND Private Functions
123   * @{
124   */
125 static uint32_t NAND_AddressIncrement(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef* Address);
126 /**
127   * @}
128   */
129
130 /* Exported functions ---------------------------------------------------------*/
131
132 /** @defgroup NAND_Exported_Functions NAND Exported Functions
133   * @{
134   */
135     
136 /** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions 
137   * @brief    Initialization and Configuration functions 
138   *
139   @verbatim    
140   ==============================================================================
141             ##### NAND Initialization and de-initialization functions #####
142   ==============================================================================
143   [..]  
144     This section provides functions allowing to initialize/de-initialize
145     the NAND memory
146   
147 @endverbatim
148   * @{
149   */
150     
151 /**
152   * @brief  Perform NAND memory Initialization sequence
153   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
154   *                the configuration information for NAND module.
155   * @param  ComSpace_Timing: pointer to Common space timing structure
156   * @param  AttSpace_Timing: pointer to Attribute space timing structure
157   * @retval HAL status
158   */
159 HAL_StatusTypeDef  HAL_NAND_Init(NAND_HandleTypeDef *hnand, FSMC_NAND_PCC_TimingTypeDef *ComSpace_Timing, FSMC_NAND_PCC_TimingTypeDef *AttSpace_Timing)
160 {
161   /* Check the NAND handle state */
162   if(hnand == NULL)
163   {
164      return HAL_ERROR;
165   }
166
167   if(hnand->State == HAL_NAND_STATE_RESET)
168   {
169     /* Allocate lock resource and initialize it */
170     hnand-> Lock = HAL_UNLOCKED;
171     
172     /* Initialize the low level hardware (MSP) */
173     HAL_NAND_MspInit(hnand);
174   } 
175
176   /* Initialize NAND control Interface */
177   FSMC_NAND_Init(hnand->Instance, &(hnand->Init));
178   
179   /* Initialize NAND common space timing Interface */  
180   FSMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank);
181   
182   /* Initialize NAND attribute space timing Interface */  
183   FSMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank);
184   
185   /* Enable the NAND device */
186   __FSMC_NAND_ENABLE(hnand->Instance, hnand->Init.NandBank);
187   
188   /* Update the NAND controller state */
189   hnand->State = HAL_NAND_STATE_READY;
190
191   return HAL_OK;
192 }
193
194 /**
195   * @brief  Perform NAND memory De-Initialization sequence
196   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
197   *                the configuration information for NAND module.
198   * @retval HAL status
199   */
200 HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand)  
201 {
202   /* Initialize the low level hardware (MSP) */
203   HAL_NAND_MspDeInit(hnand);
204
205   /* Configure the NAND registers with their reset values */
206   FSMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank);
207
208   /* Reset the NAND controller state */
209   hnand->State = HAL_NAND_STATE_RESET;
210
211   /* Release Lock */
212   __HAL_UNLOCK(hnand);
213
214   return HAL_OK;
215 }
216
217 /**
218   * @brief  NAND MSP Init
219   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
220   *                the configuration information for NAND module.
221   * @retval None
222   */
223 __weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand)
224 {
225   /* NOTE : This function Should not be modified, when the callback is needed,
226             the HAL_NAND_MspInit could be implemented in the user file
227    */ 
228 }
229
230 /**
231   * @brief  NAND MSP DeInit
232   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
233   *                the configuration information for NAND module.
234   * @retval None
235   */
236 __weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand)
237 {
238   /* NOTE : This function Should not be modified, when the callback is needed,
239             the HAL_NAND_MspDeInit could be implemented in the user file
240    */ 
241 }
242
243
244 /**
245   * @brief  This function handles NAND device interrupt request.
246   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
247   *                the configuration information for NAND module.
248   * @retval HAL status
249 */
250 void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand)
251 {
252   /* Check NAND interrupt Rising edge flag */
253   if(__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_RISING_EDGE))
254   {
255     /* NAND interrupt callback*/
256     HAL_NAND_ITCallback(hnand);
257   
258     /* Clear NAND interrupt Rising edge pending bit */
259     __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_RISING_EDGE);
260   }
261   
262   /* Check NAND interrupt Level flag */
263   if(__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_LEVEL))
264   {
265     /* NAND interrupt callback*/
266     HAL_NAND_ITCallback(hnand);
267   
268     /* Clear NAND interrupt Level pending bit */
269     __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_LEVEL);
270   }
271
272   /* Check NAND interrupt Falling edge flag */
273   if(__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FALLING_EDGE))
274   {
275     /* NAND interrupt callback*/
276     HAL_NAND_ITCallback(hnand);
277   
278     /* Clear NAND interrupt Falling edge pending bit */
279     __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FALLING_EDGE);
280   }
281   
282   /* Check NAND interrupt FIFO empty flag */
283   if(__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FEMPT))
284   {
285     /* NAND interrupt callback*/
286     HAL_NAND_ITCallback(hnand);
287   
288     /* Clear NAND interrupt FIFO empty pending bit */
289     __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FEMPT);
290   }  
291
292 }
293
294 /**
295   * @brief  NAND interrupt feature callback
296   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
297   *                the configuration information for NAND module.
298   * @retval None
299   */
300 __weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand)
301 {
302   /* NOTE : This function Should not be modified, when the callback is needed,
303             the HAL_NAND_ITCallback could be implemented in the user file
304    */
305 }
306  
307 /**
308   * @}
309   */
310   
311 /** @defgroup NAND_Exported_Functions_Group2 Input and Output functions 
312   * @brief    Input Output and memory control functions 
313   *
314   @verbatim    
315   ==============================================================================
316                     ##### NAND Input and Output functions #####
317   ==============================================================================
318   [..]  
319     This section provides functions allowing to use and control the NAND 
320     memory
321   
322 @endverbatim
323   * @{
324   */
325
326 /**
327   * @brief  Read the NAND memory electronic signature
328   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
329   *                the configuration information for NAND module.
330   * @param  pNAND_ID: NAND ID structure
331   * @retval HAL status
332   */
333 HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID)
334 {
335   __IO uint32_t data = 0;
336   uint32_t deviceaddress = 0;
337
338   /* Process Locked */
339   __HAL_LOCK(hnand);  
340   
341   /* Check the NAND controller state */
342   if(hnand->State == HAL_NAND_STATE_BUSY)
343   {
344      return HAL_BUSY;
345   }
346   
347   /* Identify the device address */
348   if(hnand->Init.NandBank == FSMC_NAND_BANK2)
349   {
350     deviceaddress = NAND_DEVICE1;
351   }
352   else
353   {
354     deviceaddress = NAND_DEVICE2;
355   }
356   
357   /* Update the NAND controller state */ 
358   hnand->State = HAL_NAND_STATE_BUSY;
359   
360   /* Send Read ID command sequence */   
361   *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA))  = NAND_CMD_READID;
362   *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
363
364   /* Read the electronic signature from NAND flash */  
365   data = *(__IO uint32_t *)deviceaddress;
366   
367   /* Return the data read */
368   pNAND_ID->Maker_Id   = __ADDR_1st_CYCLE(data);
369   pNAND_ID->Device_Id  = __ADDR_2nd_CYCLE(data);
370   pNAND_ID->Third_Id   = __ADDR_3rd_CYCLE(data);
371   pNAND_ID->Fourth_Id  = __ADDR_4th_CYCLE(data);
372   
373   /* Update the NAND controller state */ 
374   hnand->State = HAL_NAND_STATE_READY;
375   
376   /* Process unlocked */
377   __HAL_UNLOCK(hnand);   
378    
379   return HAL_OK;
380 }
381
382 /**
383   * @brief  NAND memory reset
384   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
385   *                the configuration information for NAND module.
386   * @retval HAL status
387   */
388 HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand)
389 {
390   uint32_t deviceaddress = 0;
391   
392   /* Process Locked */
393   __HAL_LOCK(hnand);
394     
395   /* Check the NAND controller state */
396   if(hnand->State == HAL_NAND_STATE_BUSY)
397   {
398      return HAL_BUSY;
399   }
400
401   /* Identify the device address */  
402   if(hnand->Init.NandBank == FSMC_NAND_BANK2)
403   {
404     deviceaddress = NAND_DEVICE1;
405   }
406   else
407   {
408     deviceaddress = NAND_DEVICE2;
409   }  
410   
411   /* Update the NAND controller state */   
412   hnand->State = HAL_NAND_STATE_BUSY; 
413   
414   /* Send NAND reset command */  
415   *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF;
416     
417   
418   /* Update the NAND controller state */   
419   hnand->State = HAL_NAND_STATE_READY;
420   
421   /* Process unlocked */
422   __HAL_UNLOCK(hnand);    
423   
424   return HAL_OK;
425   
426 }
427   
428 /**
429   * @brief  Read Page(s) from NAND memory block 
430   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
431   *                the configuration information for NAND module.
432   * @param  pAddress : pointer to NAND address structure
433   * @param  pBuffer : pointer to destination read buffer
434   * @param  NumPageToRead : number of pages to read from block 
435   * @retval HAL status
436   */
437 HAL_StatusTypeDef HAL_NAND_Read_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead)
438 {   
439   __IO uint32_t index  = 0;
440   uint32_t deviceaddress = 0, size = 0, numpagesread = 0, addressstatus = NAND_VALID_ADDRESS;
441   NAND_AddressTypeDef nandaddress;
442   uint32_t addressoffset = 0;
443   
444   /* Process Locked */
445   __HAL_LOCK(hnand); 
446   
447   /* Check the NAND controller state */
448   if(hnand->State == HAL_NAND_STATE_BUSY)
449   {
450      return HAL_BUSY;
451   }
452   
453   /* Identify the device address */
454   if(hnand->Init.NandBank == FSMC_NAND_BANK2)
455   {
456     deviceaddress = NAND_DEVICE1;
457   }
458   else
459   {
460     deviceaddress = NAND_DEVICE2;
461   }
462
463   /* Update the NAND controller state */ 
464   hnand->State = HAL_NAND_STATE_BUSY;
465   
466   /* Save the content of pAddress as it will be modified */
467   nandaddress.Block     = pAddress->Block;
468   nandaddress.Page      = pAddress->Page;
469   nandaddress.Zone      = pAddress->Zone;
470   
471   /* Page(s) read loop */  
472   while((NumPageToRead != 0) && (addressstatus == NAND_VALID_ADDRESS))  
473   {     
474     /* update the buffer size */
475     size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpagesread);
476     
477     /* Get the address offset */
478     addressoffset = __ARRAY_ADDRESS(&nandaddress, hnand);
479     
480     /* Send read page command sequence */
481     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;  
482    
483     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 
484     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_1st_CYCLE(addressoffset); 
485     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(addressoffset); 
486     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(addressoffset);
487   
488     /* for 512 and 1 GB devices, 4th cycle is required */    
489     if(hnand->Info.BlockNbr >= 1024)
490     {
491       *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_4th_CYCLE(addressoffset);
492     }
493   
494     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA))  = NAND_CMD_AREA_TRUE1;
495       
496     /* Get Data into Buffer */    
497     for(; index < size; index++)
498     {
499       *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress;
500     }
501     
502     /* Increment read pages number */
503     numpagesread++;
504     
505     /* Decrement pages to read */
506     NumPageToRead--;
507     
508     /* Increment the NAND address */
509     addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
510   }
511   
512   /* Update the NAND controller state */ 
513   hnand->State = HAL_NAND_STATE_READY;
514   
515   /* Process unlocked */
516   __HAL_UNLOCK(hnand);  
517     
518   return HAL_OK;
519
520 }
521
522 /**
523   * @brief  Write Page(s) to NAND memory block 
524   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
525   *                the configuration information for NAND module.
526   * @param  pAddress : pointer to NAND address structure
527   * @param  pBuffer : pointer to source buffer to write  
528   * @param  NumPageToWrite  : number of pages to write to block 
529   * @retval HAL status
530   */
531 HAL_StatusTypeDef HAL_NAND_Write_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite)
532 {
533   __IO uint32_t index   = 0;
534   uint32_t tickstart = 0;
535   uint32_t deviceaddress = 0 , size = 0, numpageswritten = 0, addressstatus = NAND_VALID_ADDRESS;
536   NAND_AddressTypeDef nandaddress;
537   uint32_t addressoffset = 0;
538   
539   /* Process Locked */
540   __HAL_LOCK(hnand);  
541
542   /* Check the NAND controller state */
543   if(hnand->State == HAL_NAND_STATE_BUSY)
544   {
545      return HAL_BUSY;
546   }
547   
548   /* Identify the device address */
549   if(hnand->Init.NandBank == FSMC_NAND_BANK2)
550   {
551     deviceaddress = NAND_DEVICE1;
552   }
553   else
554   {
555     deviceaddress = NAND_DEVICE2;
556   }
557   
558   /* Update the NAND controller state */ 
559   hnand->State = HAL_NAND_STATE_BUSY;
560   
561   /* Save the content of pAddress as it will be modified */
562   nandaddress.Block     = pAddress->Block;
563   nandaddress.Page      = pAddress->Page;
564   nandaddress.Zone      = pAddress->Zone;
565     
566   /* Page(s) write loop */
567   while((NumPageToWrite != 0) && (addressstatus == NAND_VALID_ADDRESS))
568   {  
569     /* update the buffer size */
570     size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpageswritten);
571     
572     /* Get the address offset */
573     addressoffset = __ARRAY_ADDRESS(&nandaddress, hnand);
574     
575     /* Send write page command sequence */
576     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
577     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
578
579     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;  
580     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_1st_CYCLE(addressoffset);  
581     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(addressoffset);  
582     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(addressoffset);
583   
584     /* for 512 and 1 GB devices, 4th cycle is required */     
585     if(hnand->Info.BlockNbr >= 1024)
586     {
587       *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_4th_CYCLE(addressoffset);
588     }
589   
590     /* Write data to memory */
591     for(; index < size; index++)
592     {
593       *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++;
594     }
595    
596     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
597     
598     /* Get tick */
599     tickstart = HAL_GetTick();
600     
601     /* Read status until NAND is ready */
602     while(HAL_NAND_Read_Status(hnand) != NAND_READY)
603     {
604       if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
605       {
606         return HAL_TIMEOUT; 
607       } 
608     }    
609  
610     /* Increment written pages number */
611     numpageswritten++;
612     
613     /* Decrement pages to write */
614     NumPageToWrite--;
615     
616     /* Increment the NAND address */
617     addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
618   }
619   
620   /* Update the NAND controller state */ 
621   hnand->State = HAL_NAND_STATE_READY;
622   
623   /* Process unlocked */
624   __HAL_UNLOCK(hnand);      
625   
626   return HAL_OK;
627 }
628
629 /**
630   * @brief  Read Spare area(s) from NAND memory 
631   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
632   *                the configuration information for NAND module.
633   * @param  pAddress : pointer to NAND address structure
634   * @param  pBuffer: pointer to source buffer to write  
635   * @param  NumSpareAreaToRead: Number of spare area to read  
636   * @retval HAL status
637 */
638 HAL_StatusTypeDef HAL_NAND_Read_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead)
639 {
640   __IO uint32_t index   = 0; 
641   uint32_t deviceaddress = 0, size = 0, num_spare_area_read = 0, addressstatus = NAND_VALID_ADDRESS;
642   NAND_AddressTypeDef nandaddress;
643   uint32_t addressoffset = 0;
644   
645   /* Process Locked */
646   __HAL_LOCK(hnand);  
647   
648   /* Check the NAND controller state */
649   if(hnand->State == HAL_NAND_STATE_BUSY)
650   {
651      return HAL_BUSY;
652   }
653   
654   /* Identify the device address */
655   if(hnand->Init.NandBank == FSMC_NAND_BANK2)
656   {
657     deviceaddress = NAND_DEVICE1;
658   }
659   else
660   {
661     deviceaddress = NAND_DEVICE2;
662   }
663   
664   /* Update the NAND controller state */
665   hnand->State = HAL_NAND_STATE_BUSY;
666   
667   /* Save the content of pAddress as it will be modified */
668   nandaddress.Block     = pAddress->Block;
669   nandaddress.Page      = pAddress->Page;
670   nandaddress.Zone      = pAddress->Zone;
671   
672   /* Spare area(s) read loop */ 
673   while((NumSpareAreaToRead != 0) && (addressstatus == NAND_VALID_ADDRESS))
674   {     
675     /* update the buffer size */
676     size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_read);   
677
678     /* Get the address offset */
679     addressoffset = __ARRAY_ADDRESS(&nandaddress, hnand);
680     
681     /* Send read spare area command sequence */     
682     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
683
684     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 
685     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_1st_CYCLE(addressoffset);     
686     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(addressoffset);     
687     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(addressoffset);
688   
689     /* for 512 and 1 GB devices, 4th cycle is required */    
690     if(hnand->Info.BlockNbr >= 1024)
691     {
692       *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_4th_CYCLE(addressoffset);
693     } 
694
695     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;    
696     
697     /* Get Data into Buffer */
698     for ( ;index < size; index++)
699     {
700       *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress;
701     }
702     
703     /* Increment read spare areas number */
704     num_spare_area_read++;
705     
706     /* Decrement spare areas to read */
707     NumSpareAreaToRead--;
708     
709     /* Increment the NAND address */
710     addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
711   }
712   
713   /* Update the NAND controller state */
714   hnand->State = HAL_NAND_STATE_READY;
715   
716   /* Process unlocked */
717   __HAL_UNLOCK(hnand);     
718
719   return HAL_OK;  
720 }
721
722 /**
723   * @brief  Write Spare area(s) to NAND memory 
724   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
725   *                the configuration information for NAND module.
726   * @param  pAddress : pointer to NAND address structure
727   * @param  pBuffer : pointer to source buffer to write  
728   * @param  NumSpareAreaTowrite  : number of spare areas to write to block
729   * @retval HAL status
730   */
731 HAL_StatusTypeDef HAL_NAND_Write_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite)
732 {
733   __IO uint32_t index = 0;
734   uint32_t tickstart = 0;
735   uint32_t deviceaddress = 0, size = 0, num_spare_area_written = 0, addressstatus = NAND_VALID_ADDRESS;
736   NAND_AddressTypeDef nandaddress;
737   uint32_t addressoffset = 0;
738
739   /* Process Locked */
740   __HAL_LOCK(hnand); 
741   
742   /* Check the NAND controller state */
743   if(hnand->State == HAL_NAND_STATE_BUSY)
744   {
745      return HAL_BUSY;
746   }
747   
748   /* Identify the device address */
749   if(hnand->Init.NandBank == FSMC_NAND_BANK2)
750   {
751     deviceaddress = NAND_DEVICE1;
752   }
753   else
754   {
755     deviceaddress = NAND_DEVICE2;
756   }
757   
758   /* Update the FMC_NAND controller state */
759   hnand->State = HAL_NAND_STATE_BUSY;  
760   
761   /* Save the content of pAddress as it will be modified */
762   nandaddress.Block     = pAddress->Block;
763   nandaddress.Page      = pAddress->Page;
764   nandaddress.Zone      = pAddress->Zone;
765   
766   /* Spare area(s) write loop */
767   while((NumSpareAreaTowrite != 0) && (addressstatus == NAND_VALID_ADDRESS))
768   {  
769     /* update the buffer size */
770     size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_written);
771
772     /* Get the address offset */
773     addressoffset = __ARRAY_ADDRESS(&nandaddress, hnand);
774     
775     /* Send write Spare area command sequence */
776     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
777     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
778
779     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;  
780     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_1st_CYCLE(addressoffset);  
781     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(addressoffset);  
782     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(addressoffset); 
783   
784     /* for 512 and 1 GB devices, 4th cycle is required */     
785     if(hnand->Info.BlockNbr >= 1024)
786     {
787       *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_4th_CYCLE(addressoffset);
788     }
789   
790     /* Write data to memory */
791     for(; index < size; index++)
792     {
793       *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++;
794     }
795    
796     *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
797     
798     /* Get tick */
799     tickstart = HAL_GetTick();
800     
801     /* Read status until NAND is ready */
802     while(HAL_NAND_Read_Status(hnand) != NAND_READY)
803     {
804       if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
805       {
806         return HAL_TIMEOUT; 
807       }
808     }
809
810     /* Increment written spare areas number */
811     num_spare_area_written++;
812     
813     /* Decrement spare areas to write */
814     NumSpareAreaTowrite--;
815     
816     /* Increment the NAND address */
817     addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
818   }
819
820   /* Update the NAND controller state */
821   hnand->State = HAL_NAND_STATE_READY;
822
823   /* Process unlocked */
824   __HAL_UNLOCK(hnand);
825     
826   return HAL_OK;  
827 }
828
829 /**
830   * @brief  NAND memory Block erase 
831   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
832   *                the configuration information for NAND module.
833   * @param  pAddress : pointer to NAND address structure
834   * @retval HAL status
835   */
836 HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
837 {
838   uint32_t deviceaddress = 0;
839   uint32_t tickstart = 0;
840   
841   /* Process Locked */
842   __HAL_LOCK(hnand);
843   
844   /* Check the NAND controller state */
845   if(hnand->State == HAL_NAND_STATE_BUSY)
846   {
847      return HAL_BUSY;
848   }
849   
850   /* Identify the device address */
851   if(hnand->Init.NandBank == FSMC_NAND_BANK2)
852   {
853     deviceaddress = NAND_DEVICE1;
854   }
855   else
856   {
857     deviceaddress = NAND_DEVICE2;
858   }
859   
860   /* Update the NAND controller state */
861   hnand->State = HAL_NAND_STATE_BUSY;  
862   
863   /* Send Erase block command sequence */
864   *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0;
865
866   *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_1st_CYCLE(__ARRAY_ADDRESS(pAddress, hnand));
867   *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(__ARRAY_ADDRESS(pAddress, hnand));
868   *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(__ARRAY_ADDRESS(pAddress, hnand));
869   
870   /* for 512 and 1 GB devices, 4th cycle is required */     
871   if(hnand->Info.BlockNbr >= 1024)
872   {
873     *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = __ADDR_4th_CYCLE(__ARRAY_ADDRESS(pAddress, hnand));
874   }  
875     
876   *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1; 
877   
878   /* Update the NAND controller state */
879   hnand->State = HAL_NAND_STATE_READY;
880   
881   /* Get tick */
882   tickstart = HAL_GetTick();
883   
884   /* Read status until NAND is ready */
885   while(HAL_NAND_Read_Status(hnand) != NAND_READY)
886   {
887     if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
888     {
889       /* Process unlocked */
890       __HAL_UNLOCK(hnand);    
891   
892       return HAL_TIMEOUT; 
893     } 
894   }    
895  
896   /* Process unlocked */
897   __HAL_UNLOCK(hnand);    
898   
899   return HAL_OK;  
900 }
901
902 /**
903   * @brief  NAND memory read status 
904   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
905   *                the configuration information for NAND module.
906   * @retval NAND status
907   */
908 uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand)
909 {
910   uint32_t data = 0;
911   uint32_t deviceaddress = 0;
912   
913   /* Identify the device address */
914   if(hnand->Init.NandBank == FSMC_NAND_BANK2)
915   {
916     deviceaddress = NAND_DEVICE1;
917   }
918   else
919   {
920     deviceaddress = NAND_DEVICE2;
921   } 
922
923   /* Send Read status operation command */
924   *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS;
925   
926   /* Read status register data */
927   data = *(__IO uint8_t *)deviceaddress;
928
929   /* Return the status */
930   if((data & NAND_ERROR) == NAND_ERROR)
931   {
932     return NAND_ERROR;
933   } 
934   else if((data & NAND_READY) == NAND_READY)
935   {
936     return NAND_READY;
937   }
938
939   return NAND_BUSY; 
940 }
941
942 /**
943   * @brief  Increment the NAND memory address
944   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
945   *                the configuration information for NAND module.
946   * @param pAddress: pointer to NAND address structure
947   * @retval The new status of the increment address operation. It can be:
948   *           - NAND_VALID_ADDRESS: When the new address is valid address
949   *           - NAND_INVALID_ADDRESS: When the new address is invalid address
950   */
951 uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
952 {
953   uint32_t status = NAND_VALID_ADDRESS;
954  
955   /* Increment page address */
956   pAddress->Page++;
957
958   /* Check NAND address is valid */
959   if(pAddress->Page == hnand->Info.BlockSize)
960   {
961     pAddress->Page = 0;
962     pAddress->Block++;
963     
964     if(pAddress->Block == hnand->Info.ZoneSize)
965     {
966       pAddress->Block = 0;
967       pAddress->Zone++;
968
969       if(pAddress->Zone == (hnand->Info.ZoneSize/ hnand->Info.BlockNbr))
970       {
971         status = NAND_INVALID_ADDRESS;
972       }
973     }
974   } 
975   
976   return (status);
977 }
978 /**
979   * @}
980   */
981
982 /** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions 
983  *  @brief   management functions 
984  *
985 @verbatim   
986   ==============================================================================
987                          ##### NAND Control functions #####
988   ==============================================================================  
989   [..]
990     This subsection provides a set of functions allowing to control dynamically
991     the NAND interface.
992
993 @endverbatim
994   * @{
995   */ 
996
997     
998 /**
999   * @brief  Enables dynamically NAND ECC feature.
1000   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
1001   *                the configuration information for NAND module.
1002   * @retval HAL status
1003   */    
1004 HAL_StatusTypeDef  HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand)
1005 {
1006   /* Check the NAND controller state */
1007   if(hnand->State == HAL_NAND_STATE_BUSY)
1008   {
1009      return HAL_BUSY;
1010   }
1011
1012   /* Update the NAND state */
1013   hnand->State = HAL_NAND_STATE_BUSY;
1014    
1015   /* Enable ECC feature */
1016   FSMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank);
1017   
1018   /* Update the NAND state */
1019   hnand->State = HAL_NAND_STATE_READY;
1020   
1021   return HAL_OK;  
1022 }
1023
1024 /**
1025   * @brief  Disables dynamically FSMC_NAND ECC feature.
1026   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
1027   *                the configuration information for NAND module.
1028   * @retval HAL status
1029   */  
1030 HAL_StatusTypeDef  HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand)  
1031 {
1032   /* Check the NAND controller state */
1033   if(hnand->State == HAL_NAND_STATE_BUSY)
1034   {
1035      return HAL_BUSY;
1036   }
1037
1038   /* Update the NAND state */
1039   hnand->State = HAL_NAND_STATE_BUSY;
1040     
1041   /* Disable ECC feature */
1042   FSMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank);
1043   
1044   /* Update the NAND state */
1045   hnand->State = HAL_NAND_STATE_READY;
1046   
1047   return HAL_OK;  
1048 }
1049
1050 /**
1051   * @brief  Disables dynamically NAND ECC feature.
1052   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
1053   *                the configuration information for NAND module.
1054   * @param  ECCval: pointer to ECC value 
1055   * @param  Timeout: maximum timeout to wait    
1056   * @retval HAL status
1057   */
1058 HAL_StatusTypeDef  HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout)
1059 {
1060   HAL_StatusTypeDef status = HAL_OK;
1061   
1062   /* Check the NAND controller state */
1063   if(hnand->State == HAL_NAND_STATE_BUSY)
1064   {
1065      return HAL_BUSY;
1066   }
1067   
1068   /* Update the NAND state */
1069   hnand->State = HAL_NAND_STATE_BUSY;  
1070    
1071   /* Get NAND ECC value */
1072   status = FSMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout);
1073   
1074   /* Update the NAND state */
1075   hnand->State = HAL_NAND_STATE_READY;
1076
1077   return status;  
1078 }
1079                       
1080 /**
1081   * @}
1082   */
1083   
1084     
1085 /** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions 
1086  *  @brief   Peripheral State functions 
1087  *
1088 @verbatim   
1089   ==============================================================================
1090                          ##### NAND State functions #####
1091   ==============================================================================  
1092   [..]
1093     This subsection permits to get in run-time the status of the NAND controller 
1094     and the data flow.
1095
1096 @endverbatim
1097   * @{
1098   */
1099   
1100 /**
1101   * @brief  return the NAND state
1102   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
1103   *                the configuration information for NAND module.
1104   * @retval HAL state
1105   */
1106 HAL_NAND_StateTypeDef HAL_NAND_GetState(NAND_HandleTypeDef *hnand)
1107 {
1108   return hnand->State;
1109 }
1110
1111 /**
1112   * @}
1113   */  
1114
1115 /**
1116   * @}
1117   */
1118
1119 /** @addtogroup NAND_Private_Functions
1120   * @{
1121   */
1122
1123 /**
1124   * @brief  Increment the NAND memory address. 
1125   * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
1126   *                the configuration information for NAND module.
1127   * @param  Address: address to be incremented.
1128   * @retval The new status of the increment address operation. It can be:
1129   *              - NAND_VALID_ADDRESS: When the new address is valid address
1130   *              - NAND_INVALID_ADDRESS: When the new address is invalid address   
1131   */
1132 static uint32_t NAND_AddressIncrement(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef* Address)
1133 {
1134   uint32_t status = NAND_VALID_ADDRESS;
1135  
1136   Address->Page++;
1137
1138   if(Address->Page == hnand->Info.BlockSize)
1139   {
1140     Address->Page = 0;
1141     Address->Block++;
1142     
1143     if(Address->Block == hnand->Info.ZoneSize)
1144     {
1145       Address->Block = 0;
1146       Address->Zone++;
1147
1148       if(Address->Zone == hnand->Info.BlockNbr)
1149       {
1150         status = NAND_INVALID_ADDRESS;
1151       }
1152     }
1153   } 
1154   
1155   return (status);
1156 }
1157
1158 /**
1159   * @}
1160   */
1161
1162 /**
1163   * @}
1164   */
1165
1166 #endif /* STM32F101xE || STM32F103xE || STM32F101xG || STM32F103xG */
1167 #endif /* HAL_NAND_MODULE_ENABLED  */
1168
1169 /**
1170   * @}
1171   */
1172
1173 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/