]> git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F1/stm32f1xx_hal_nand.c
Merge commit '22b6e15a179031afb7c3534cf7b109b0668b602c'
[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****/
Imprint / Impressum