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