Subversion Repositories DashDisplay

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/**
2
  ******************************************************************************
3
  * @file    stm32f1xx_hal_nand.c
4
  * @author  MCD Application Team
5
  * @version V1.0.1
6
  * @date    31-July-2015
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) 2015 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 FSMC_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****/