Subversion Repositories DashDisplay

Rev

Rev 2 | Details | Compare with Previous | 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 mjames 5
  * @version V1.0.4
6
  * @date    29-April-2016
2 mjames 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
  *
5 mjames 58
  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
2 mjames 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
{
5 mjames 225
  /* Prevent unused argument(s) compilation warning */
226
  UNUSED(hnand);
2 mjames 227
  /* NOTE : This function Should not be modified, when the callback is needed,
228
            the HAL_NAND_MspInit could be implemented in the user file
229
   */
230
}
231
 
232
/**
233
  * @brief  NAND MSP DeInit
234
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
235
  *                the configuration information for NAND module.
236
  * @retval None
237
  */
238
__weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand)
239
{
5 mjames 240
  /* Prevent unused argument(s) compilation warning */
241
  UNUSED(hnand);
2 mjames 242
  /* NOTE : This function Should not be modified, when the callback is needed,
243
            the HAL_NAND_MspDeInit could be implemented in the user file
244
   */
245
}
246
 
247
 
248
/**
249
  * @brief  This function handles NAND device interrupt request.
250
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
251
  *                the configuration information for NAND module.
252
  * @retval HAL status
253
*/
254
void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand)
255
{
256
  /* Check NAND interrupt Rising edge flag */
257
  if(__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_RISING_EDGE))
258
  {
259
    /* NAND interrupt callback*/
260
    HAL_NAND_ITCallback(hnand);
261
 
262
    /* Clear NAND interrupt Rising edge pending bit */
263
    __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_RISING_EDGE);
264
  }
265
 
266
  /* Check NAND interrupt Level flag */
267
  if(__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_LEVEL))
268
  {
269
    /* NAND interrupt callback*/
270
    HAL_NAND_ITCallback(hnand);
271
 
272
    /* Clear NAND interrupt Level pending bit */
273
    __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_LEVEL);
274
  }
275
 
276
  /* Check NAND interrupt Falling edge flag */
277
  if(__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FALLING_EDGE))
278
  {
279
    /* NAND interrupt callback*/
280
    HAL_NAND_ITCallback(hnand);
281
 
282
    /* Clear NAND interrupt Falling edge pending bit */
283
    __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FALLING_EDGE);
284
  }
285
 
286
  /* Check NAND interrupt FIFO empty flag */
287
  if(__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FEMPT))
288
  {
289
    /* NAND interrupt callback*/
290
    HAL_NAND_ITCallback(hnand);
291
 
292
    /* Clear NAND interrupt FIFO empty pending bit */
293
    __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FEMPT);
294
  }  
295
 
296
}
297
 
298
/**
299
  * @brief  NAND interrupt feature callback
300
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
301
  *                the configuration information for NAND module.
302
  * @retval None
303
  */
304
__weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand)
305
{
5 mjames 306
  /* Prevent unused argument(s) compilation warning */
307
  UNUSED(hnand);
2 mjames 308
  /* NOTE : This function Should not be modified, when the callback is needed,
309
            the HAL_NAND_ITCallback could be implemented in the user file
310
   */
311
}
312
 
313
/**
314
  * @}
315
  */
316
 
317
/** @defgroup NAND_Exported_Functions_Group2 Input and Output functions
318
  * @brief    Input Output and memory control functions
319
  *
320
  @verbatim    
321
  ==============================================================================
322
                    ##### NAND Input and Output functions #####
323
  ==============================================================================
324
  [..]  
325
    This section provides functions allowing to use and control the NAND
326
    memory
327
 
328
@endverbatim
329
  * @{
330
  */
331
 
332
/**
333
  * @brief  Read the NAND memory electronic signature
334
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
335
  *                the configuration information for NAND module.
336
  * @param  pNAND_ID: NAND ID structure
337
  * @retval HAL status
338
  */
339
HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID)
340
{
341
  __IO uint32_t data = 0;
342
  uint32_t deviceaddress = 0;
343
 
344
  /* Process Locked */
345
  __HAL_LOCK(hnand);  
346
 
347
  /* Check the NAND controller state */
348
  if(hnand->State == HAL_NAND_STATE_BUSY)
349
  {
350
     return HAL_BUSY;
351
  }
352
 
353
  /* Identify the device address */
354
  if(hnand->Init.NandBank == FSMC_NAND_BANK2)
355
  {
356
    deviceaddress = NAND_DEVICE1;
357
  }
358
  else
359
  {
360
    deviceaddress = NAND_DEVICE2;
361
  }
362
 
363
  /* Update the NAND controller state */
364
  hnand->State = HAL_NAND_STATE_BUSY;
365
 
366
  /* Send Read ID command sequence */  
367
  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA))  = NAND_CMD_READID;
368
  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
369
 
370
  /* Read the electronic signature from NAND flash */  
371
  data = *(__IO uint32_t *)deviceaddress;
372
 
373
  /* Return the data read */
374
  pNAND_ID->Maker_Id   = ADDR_1st_CYCLE(data);
375
  pNAND_ID->Device_Id  = ADDR_2nd_CYCLE(data);
376
  pNAND_ID->Third_Id   = ADDR_3rd_CYCLE(data);
377
  pNAND_ID->Fourth_Id  = ADDR_4th_CYCLE(data);
378
 
379
  /* Update the NAND controller state */
380
  hnand->State = HAL_NAND_STATE_READY;
381
 
382
  /* Process unlocked */
383
  __HAL_UNLOCK(hnand);  
384
 
385
  return HAL_OK;
386
}
387
 
388
/**
389
  * @brief  NAND memory reset
390
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
391
  *                the configuration information for NAND module.
392
  * @retval HAL status
393
  */
394
HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand)
395
{
396
  uint32_t deviceaddress = 0;
397
 
398
  /* Process Locked */
399
  __HAL_LOCK(hnand);
400
 
401
  /* Check the NAND controller state */
402
  if(hnand->State == HAL_NAND_STATE_BUSY)
403
  {
404
     return HAL_BUSY;
405
  }
406
 
407
  /* Identify the device address */  
408
  if(hnand->Init.NandBank == FSMC_NAND_BANK2)
409
  {
410
    deviceaddress = NAND_DEVICE1;
411
  }
412
  else
413
  {
414
    deviceaddress = NAND_DEVICE2;
415
  }  
416
 
417
  /* Update the NAND controller state */  
418
  hnand->State = HAL_NAND_STATE_BUSY;
419
 
420
  /* Send NAND reset command */  
421
  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF;
422
 
423
 
424
  /* Update the NAND controller state */  
425
  hnand->State = HAL_NAND_STATE_READY;
426
 
427
  /* Process unlocked */
428
  __HAL_UNLOCK(hnand);    
429
 
430
  return HAL_OK;
431
 
432
}
433
 
434
/**
435
  * @brief  Read Page(s) from NAND memory block
436
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
437
  *                the configuration information for NAND module.
438
  * @param  pAddress : pointer to NAND address structure
439
  * @param  pBuffer : pointer to destination read buffer
440
  * @param  NumPageToRead : number of pages to read from block
441
  * @retval HAL status
442
  */
443
HAL_StatusTypeDef HAL_NAND_Read_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead)
444
{  
445
  __IO uint32_t index  = 0;
446
  uint32_t deviceaddress = 0, size = 0, numpagesread = 0, addressstatus = NAND_VALID_ADDRESS;
447
  NAND_AddressTypeDef nandaddress;
448
  uint32_t addressoffset = 0;
449
 
450
  /* Process Locked */
451
  __HAL_LOCK(hnand);
452
 
453
  /* Check the NAND controller state */
454
  if(hnand->State == HAL_NAND_STATE_BUSY)
455
  {
456
     return HAL_BUSY;
457
  }
458
 
459
  /* Identify the device address */
460
  if(hnand->Init.NandBank == FSMC_NAND_BANK2)
461
  {
462
    deviceaddress = NAND_DEVICE1;
463
  }
464
  else
465
  {
466
    deviceaddress = NAND_DEVICE2;
467
  }
468
 
469
  /* Update the NAND controller state */
470
  hnand->State = HAL_NAND_STATE_BUSY;
471
 
472
  /* Save the content of pAddress as it will be modified */
473
  nandaddress.Block     = pAddress->Block;
474
  nandaddress.Page      = pAddress->Page;
475
  nandaddress.Zone      = pAddress->Zone;
476
 
477
  /* Page(s) read loop */  
478
  while((NumPageToRead != 0) && (addressstatus == NAND_VALID_ADDRESS))  
479
  {    
480
    /* update the buffer size */
481
    size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpagesread);
482
 
483
    /* Get the address offset */
484
    addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
485
 
486
    /* Send read page command sequence */
487
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;  
488
 
489
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
490
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1st_CYCLE(addressoffset);
491
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2nd_CYCLE(addressoffset);
492
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3rd_CYCLE(addressoffset);
493
 
494
    /* for 512 and 1 GB devices, 4th cycle is required */    
495
    if(hnand->Info.BlockNbr >= 1024)
496
    {
497
      *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4th_CYCLE(addressoffset);
498
    }
499
 
500
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA))  = NAND_CMD_AREA_TRUE1;
501
 
502
    /* Get Data into Buffer */    
503
    for(; index < size; index++)
504
    {
505
      *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress;
506
    }
507
 
508
    /* Increment read pages number */
509
    numpagesread++;
510
 
511
    /* Decrement pages to read */
512
    NumPageToRead--;
513
 
514
    /* Increment the NAND address */
515
    addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
516
  }
517
 
518
  /* Update the NAND controller state */
519
  hnand->State = HAL_NAND_STATE_READY;
520
 
521
  /* Process unlocked */
522
  __HAL_UNLOCK(hnand);  
523
 
524
  return HAL_OK;
525
 
526
}
527
 
528
/**
529
  * @brief  Write Page(s) to NAND memory block
530
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
531
  *                the configuration information for NAND module.
532
  * @param  pAddress : pointer to NAND address structure
533
  * @param  pBuffer : pointer to source buffer to write  
534
  * @param  NumPageToWrite  : number of pages to write to block
535
  * @retval HAL status
536
  */
537
HAL_StatusTypeDef HAL_NAND_Write_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite)
538
{
539
  __IO uint32_t index   = 0;
540
  uint32_t tickstart = 0;
541
  uint32_t deviceaddress = 0 , size = 0, numpageswritten = 0, addressstatus = NAND_VALID_ADDRESS;
542
  NAND_AddressTypeDef nandaddress;
543
  uint32_t addressoffset = 0;
544
 
545
  /* Process Locked */
546
  __HAL_LOCK(hnand);  
547
 
548
  /* Check the NAND controller state */
549
  if(hnand->State == HAL_NAND_STATE_BUSY)
550
  {
551
     return HAL_BUSY;
552
  }
553
 
554
  /* Identify the device address */
555
  if(hnand->Init.NandBank == FSMC_NAND_BANK2)
556
  {
557
    deviceaddress = NAND_DEVICE1;
558
  }
559
  else
560
  {
561
    deviceaddress = NAND_DEVICE2;
562
  }
563
 
564
  /* Update the NAND controller state */
565
  hnand->State = HAL_NAND_STATE_BUSY;
566
 
567
  /* Save the content of pAddress as it will be modified */
568
  nandaddress.Block     = pAddress->Block;
569
  nandaddress.Page      = pAddress->Page;
570
  nandaddress.Zone      = pAddress->Zone;
571
 
572
  /* Page(s) write loop */
573
  while((NumPageToWrite != 0) && (addressstatus == NAND_VALID_ADDRESS))
574
  {  
575
    /* update the buffer size */
576
    size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpageswritten);
577
 
578
    /* Get the address offset */
579
    addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
580
 
581
    /* Send write page command sequence */
582
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
583
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
584
 
585
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;  
586
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1st_CYCLE(addressoffset);  
587
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2nd_CYCLE(addressoffset);  
588
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3rd_CYCLE(addressoffset);
589
 
590
    /* for 512 and 1 GB devices, 4th cycle is required */    
591
    if(hnand->Info.BlockNbr >= 1024)
592
    {
593
      *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4th_CYCLE(addressoffset);
594
    }
595
 
596
    /* Write data to memory */
597
    for(; index < size; index++)
598
    {
599
      *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++;
600
    }
601
 
602
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
603
 
604
    /* Get tick */
605
    tickstart = HAL_GetTick();
606
 
607
    /* Read status until NAND is ready */
608
    while(HAL_NAND_Read_Status(hnand) != NAND_READY)
609
    {
610
      if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
611
      {
612
        return HAL_TIMEOUT;
613
      }
614
    }    
615
 
616
    /* Increment written pages number */
617
    numpageswritten++;
618
 
619
    /* Decrement pages to write */
620
    NumPageToWrite--;
621
 
622
    /* Increment the NAND address */
623
    addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
624
  }
625
 
626
  /* Update the NAND controller state */
627
  hnand->State = HAL_NAND_STATE_READY;
628
 
629
  /* Process unlocked */
630
  __HAL_UNLOCK(hnand);      
631
 
632
  return HAL_OK;
633
}
634
 
635
/**
636
  * @brief  Read Spare area(s) from NAND memory
637
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
638
  *                the configuration information for NAND module.
639
  * @param  pAddress : pointer to NAND address structure
640
  * @param  pBuffer: pointer to source buffer to write  
641
  * @param  NumSpareAreaToRead: Number of spare area to read  
642
  * @retval HAL status
643
*/
644
HAL_StatusTypeDef HAL_NAND_Read_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead)
645
{
646
  __IO uint32_t index   = 0;
647
  uint32_t deviceaddress = 0, size = 0, num_spare_area_read = 0, addressstatus = NAND_VALID_ADDRESS;
648
  NAND_AddressTypeDef nandaddress;
649
  uint32_t addressoffset = 0;
650
 
651
  /* Process Locked */
652
  __HAL_LOCK(hnand);  
653
 
654
  /* Check the NAND controller state */
655
  if(hnand->State == HAL_NAND_STATE_BUSY)
656
  {
657
     return HAL_BUSY;
658
  }
659
 
660
  /* Identify the device address */
661
  if(hnand->Init.NandBank == FSMC_NAND_BANK2)
662
  {
663
    deviceaddress = NAND_DEVICE1;
664
  }
665
  else
666
  {
667
    deviceaddress = NAND_DEVICE2;
668
  }
669
 
670
  /* Update the NAND controller state */
671
  hnand->State = HAL_NAND_STATE_BUSY;
672
 
673
  /* Save the content of pAddress as it will be modified */
674
  nandaddress.Block     = pAddress->Block;
675
  nandaddress.Page      = pAddress->Page;
676
  nandaddress.Zone      = pAddress->Zone;
677
 
678
  /* Spare area(s) read loop */
679
  while((NumSpareAreaToRead != 0) && (addressstatus == NAND_VALID_ADDRESS))
680
  {    
681
    /* update the buffer size */
682
    size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_read);  
683
 
684
    /* Get the address offset */
685
    addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
686
 
687
    /* Send read spare area command sequence */    
688
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
689
 
690
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
691
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1st_CYCLE(addressoffset);    
692
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2nd_CYCLE(addressoffset);    
693
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3rd_CYCLE(addressoffset);
694
 
695
    /* for 512 and 1 GB devices, 4th cycle is required */    
696
    if(hnand->Info.BlockNbr >= 1024)
697
    {
698
      *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4th_CYCLE(addressoffset);
699
    }
700
 
701
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;    
702
 
703
    /* Get Data into Buffer */
704
    for ( ;index < size; index++)
705
    {
706
      *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress;
707
    }
708
 
709
    /* Increment read spare areas number */
710
    num_spare_area_read++;
711
 
712
    /* Decrement spare areas to read */
713
    NumSpareAreaToRead--;
714
 
715
    /* Increment the NAND address */
716
    addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
717
  }
718
 
719
  /* Update the NAND controller state */
720
  hnand->State = HAL_NAND_STATE_READY;
721
 
722
  /* Process unlocked */
723
  __HAL_UNLOCK(hnand);    
724
 
725
  return HAL_OK;  
726
}
727
 
728
/**
729
  * @brief  Write Spare area(s) to NAND memory
730
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
731
  *                the configuration information for NAND module.
732
  * @param  pAddress : pointer to NAND address structure
733
  * @param  pBuffer : pointer to source buffer to write  
734
  * @param  NumSpareAreaTowrite  : number of spare areas to write to block
735
  * @retval HAL status
736
  */
737
HAL_StatusTypeDef HAL_NAND_Write_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite)
738
{
739
  __IO uint32_t index = 0;
740
  uint32_t tickstart = 0;
741
  uint32_t deviceaddress = 0, size = 0, num_spare_area_written = 0, addressstatus = NAND_VALID_ADDRESS;
742
  NAND_AddressTypeDef nandaddress;
743
  uint32_t addressoffset = 0;
744
 
745
  /* Process Locked */
746
  __HAL_LOCK(hnand);
747
 
748
  /* Check the NAND controller state */
749
  if(hnand->State == HAL_NAND_STATE_BUSY)
750
  {
751
     return HAL_BUSY;
752
  }
753
 
754
  /* Identify the device address */
755
  if(hnand->Init.NandBank == FSMC_NAND_BANK2)
756
  {
757
    deviceaddress = NAND_DEVICE1;
758
  }
759
  else
760
  {
761
    deviceaddress = NAND_DEVICE2;
762
  }
763
 
764
  /* Update the FSMC_NAND controller state */
765
  hnand->State = HAL_NAND_STATE_BUSY;  
766
 
767
  /* Save the content of pAddress as it will be modified */
768
  nandaddress.Block     = pAddress->Block;
769
  nandaddress.Page      = pAddress->Page;
770
  nandaddress.Zone      = pAddress->Zone;
771
 
772
  /* Spare area(s) write loop */
773
  while((NumSpareAreaTowrite != 0) && (addressstatus == NAND_VALID_ADDRESS))
774
  {  
775
    /* update the buffer size */
776
    size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_written);
777
 
778
    /* Get the address offset */
779
    addressoffset = ARRAY_ADDRESS(&nandaddress, hnand);
780
 
781
    /* Send write Spare area command sequence */
782
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
783
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
784
 
785
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;  
786
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1st_CYCLE(addressoffset);  
787
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2nd_CYCLE(addressoffset);  
788
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3rd_CYCLE(addressoffset);
789
 
790
    /* for 512 and 1 GB devices, 4th cycle is required */    
791
    if(hnand->Info.BlockNbr >= 1024)
792
    {
793
      *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4th_CYCLE(addressoffset);
794
    }
795
 
796
    /* Write data to memory */
797
    for(; index < size; index++)
798
    {
799
      *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++;
800
    }
801
 
802
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
803
 
804
    /* Get tick */
805
    tickstart = HAL_GetTick();
806
 
807
    /* Read status until NAND is ready */
808
    while(HAL_NAND_Read_Status(hnand) != NAND_READY)
809
    {
810
      if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
811
      {
812
        return HAL_TIMEOUT;
813
      }
814
    }
815
 
816
    /* Increment written spare areas number */
817
    num_spare_area_written++;
818
 
819
    /* Decrement spare areas to write */
820
    NumSpareAreaTowrite--;
821
 
822
    /* Increment the NAND address */
823
    addressstatus = NAND_AddressIncrement(hnand, &nandaddress);
824
  }
825
 
826
  /* Update the NAND controller state */
827
  hnand->State = HAL_NAND_STATE_READY;
828
 
829
  /* Process unlocked */
830
  __HAL_UNLOCK(hnand);
831
 
832
  return HAL_OK;  
833
}
834
 
835
/**
836
  * @brief  NAND memory Block erase
837
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
838
  *                the configuration information for NAND module.
839
  * @param  pAddress : pointer to NAND address structure
840
  * @retval HAL status
841
  */
842
HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
843
{
844
  uint32_t deviceaddress = 0;
845
  uint32_t tickstart = 0;
846
 
847
  /* Process Locked */
848
  __HAL_LOCK(hnand);
849
 
850
  /* Check the NAND controller state */
851
  if(hnand->State == HAL_NAND_STATE_BUSY)
852
  {
853
     return HAL_BUSY;
854
  }
855
 
856
  /* Identify the device address */
857
  if(hnand->Init.NandBank == FSMC_NAND_BANK2)
858
  {
859
    deviceaddress = NAND_DEVICE1;
860
  }
861
  else
862
  {
863
    deviceaddress = NAND_DEVICE2;
864
  }
865
 
866
  /* Update the NAND controller state */
867
  hnand->State = HAL_NAND_STATE_BUSY;  
868
 
869
  /* Send Erase block command sequence */
870
  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0;
871
 
872
  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1st_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
873
  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2nd_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
874
  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3rd_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
875
 
876
  /* for 512 and 1 GB devices, 4th cycle is required */    
877
  if(hnand->Info.BlockNbr >= 1024)
878
  {
879
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4th_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
880
  }  
881
 
882
  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1;
883
 
884
  /* Update the NAND controller state */
885
  hnand->State = HAL_NAND_STATE_READY;
886
 
887
  /* Get tick */
888
  tickstart = HAL_GetTick();
889
 
890
  /* Read status until NAND is ready */
891
  while(HAL_NAND_Read_Status(hnand) != NAND_READY)
892
  {
893
    if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
894
    {
895
      /* Process unlocked */
896
      __HAL_UNLOCK(hnand);    
897
 
898
      return HAL_TIMEOUT;
899
    }
900
  }    
901
 
902
  /* Process unlocked */
903
  __HAL_UNLOCK(hnand);    
904
 
905
  return HAL_OK;  
906
}
907
 
908
/**
909
  * @brief  NAND memory read status
910
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
911
  *                the configuration information for NAND module.
912
  * @retval NAND status
913
  */
914
uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand)
915
{
916
  uint32_t data = 0;
917
  uint32_t deviceaddress = 0;
918
 
919
  /* Identify the device address */
920
  if(hnand->Init.NandBank == FSMC_NAND_BANK2)
921
  {
922
    deviceaddress = NAND_DEVICE1;
923
  }
924
  else
925
  {
926
    deviceaddress = NAND_DEVICE2;
927
  }
928
 
929
  /* Send Read status operation command */
930
  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS;
931
 
932
  /* Read status register data */
933
  data = *(__IO uint8_t *)deviceaddress;
934
 
935
  /* Return the status */
936
  if((data & NAND_ERROR) == NAND_ERROR)
937
  {
938
    return NAND_ERROR;
939
  }
940
  else if((data & NAND_READY) == NAND_READY)
941
  {
942
    return NAND_READY;
943
  }
944
 
945
  return NAND_BUSY;
946
}
947
 
948
/**
949
  * @brief  Increment the NAND memory address
950
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
951
  *                the configuration information for NAND module.
952
  * @param pAddress: pointer to NAND address structure
953
  * @retval The new status of the increment address operation. It can be:
954
  *           - NAND_VALID_ADDRESS: When the new address is valid address
955
  *           - NAND_INVALID_ADDRESS: When the new address is invalid address
956
  */
957
uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
958
{
959
  uint32_t status = NAND_VALID_ADDRESS;
960
 
961
  /* Increment page address */
962
  pAddress->Page++;
963
 
964
  /* Check NAND address is valid */
965
  if(pAddress->Page == hnand->Info.BlockSize)
966
  {
967
    pAddress->Page = 0;
968
    pAddress->Block++;
969
 
970
    if(pAddress->Block == hnand->Info.ZoneSize)
971
    {
972
      pAddress->Block = 0;
973
      pAddress->Zone++;
974
 
975
      if(pAddress->Zone == (hnand->Info.ZoneSize/ hnand->Info.BlockNbr))
976
      {
977
        status = NAND_INVALID_ADDRESS;
978
      }
979
    }
980
  }
981
 
982
  return (status);
983
}
984
/**
985
  * @}
986
  */
987
 
988
/** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions
989
 *  @brief   management functions
990
 *
991
@verbatim  
992
  ==============================================================================
993
                         ##### NAND Control functions #####
994
  ==============================================================================  
995
  [..]
996
    This subsection provides a set of functions allowing to control dynamically
997
    the NAND interface.
998
 
999
@endverbatim
1000
  * @{
1001
  */
1002
 
1003
 
1004
/**
1005
  * @brief  Enables dynamically NAND ECC feature.
1006
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
1007
  *                the configuration information for NAND module.
1008
  * @retval HAL status
1009
  */    
1010
HAL_StatusTypeDef  HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand)
1011
{
1012
  /* Check the NAND controller state */
1013
  if(hnand->State == HAL_NAND_STATE_BUSY)
1014
  {
1015
     return HAL_BUSY;
1016
  }
1017
 
1018
  /* Update the NAND state */
1019
  hnand->State = HAL_NAND_STATE_BUSY;
1020
 
1021
  /* Enable ECC feature */
1022
  FSMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank);
1023
 
1024
  /* Update the NAND state */
1025
  hnand->State = HAL_NAND_STATE_READY;
1026
 
1027
  return HAL_OK;  
1028
}
1029
 
1030
/**
1031
  * @brief  Disables dynamically FSMC_NAND ECC feature.
1032
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
1033
  *                the configuration information for NAND module.
1034
  * @retval HAL status
1035
  */  
1036
HAL_StatusTypeDef  HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand)  
1037
{
1038
  /* Check the NAND controller state */
1039
  if(hnand->State == HAL_NAND_STATE_BUSY)
1040
  {
1041
     return HAL_BUSY;
1042
  }
1043
 
1044
  /* Update the NAND state */
1045
  hnand->State = HAL_NAND_STATE_BUSY;
1046
 
1047
  /* Disable ECC feature */
1048
  FSMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank);
1049
 
1050
  /* Update the NAND state */
1051
  hnand->State = HAL_NAND_STATE_READY;
1052
 
1053
  return HAL_OK;  
1054
}
1055
 
1056
/**
1057
  * @brief  Disables dynamically NAND ECC feature.
1058
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
1059
  *                the configuration information for NAND module.
1060
  * @param  ECCval: pointer to ECC value
1061
  * @param  Timeout: maximum timeout to wait    
1062
  * @retval HAL status
1063
  */
1064
HAL_StatusTypeDef  HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout)
1065
{
1066
  HAL_StatusTypeDef status = HAL_OK;
1067
 
1068
  /* Check the NAND controller state */
1069
  if(hnand->State == HAL_NAND_STATE_BUSY)
1070
  {
1071
     return HAL_BUSY;
1072
  }
1073
 
1074
  /* Update the NAND state */
1075
  hnand->State = HAL_NAND_STATE_BUSY;  
1076
 
1077
  /* Get NAND ECC value */
1078
  status = FSMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout);
1079
 
1080
  /* Update the NAND state */
1081
  hnand->State = HAL_NAND_STATE_READY;
1082
 
1083
  return status;  
1084
}
1085
 
1086
/**
1087
  * @}
1088
  */
1089
 
1090
 
1091
/** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions
1092
 *  @brief   Peripheral State functions
1093
 *
1094
@verbatim  
1095
  ==============================================================================
1096
                         ##### NAND State functions #####
1097
  ==============================================================================  
1098
  [..]
1099
    This subsection permits to get in run-time the status of the NAND controller
1100
    and the data flow.
1101
 
1102
@endverbatim
1103
  * @{
1104
  */
1105
 
1106
/**
1107
  * @brief  return the NAND state
1108
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
1109
  *                the configuration information for NAND module.
1110
  * @retval HAL state
1111
  */
1112
HAL_NAND_StateTypeDef HAL_NAND_GetState(NAND_HandleTypeDef *hnand)
1113
{
1114
  return hnand->State;
1115
}
1116
 
1117
/**
1118
  * @}
1119
  */  
1120
 
1121
/**
1122
  * @}
1123
  */
1124
 
1125
/** @addtogroup NAND_Private_Functions
1126
  * @{
1127
  */
1128
 
1129
/**
1130
  * @brief  Increment the NAND memory address.
1131
  * @param  hnand: pointer to a NAND_HandleTypeDef structure that contains
1132
  *                the configuration information for NAND module.
1133
  * @param  Address: address to be incremented.
1134
  * @retval The new status of the increment address operation. It can be:
1135
  *              - NAND_VALID_ADDRESS: When the new address is valid address
1136
  *              - NAND_INVALID_ADDRESS: When the new address is invalid address  
1137
  */
1138
static uint32_t NAND_AddressIncrement(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef* Address)
1139
{
1140
  uint32_t status = NAND_VALID_ADDRESS;
1141
 
1142
  Address->Page++;
1143
 
1144
  if(Address->Page == hnand->Info.BlockSize)
1145
  {
1146
    Address->Page = 0;
1147
    Address->Block++;
1148
 
1149
    if(Address->Block == hnand->Info.ZoneSize)
1150
    {
1151
      Address->Block = 0;
1152
      Address->Zone++;
1153
 
1154
      if(Address->Zone == hnand->Info.BlockNbr)
1155
      {
1156
        status = NAND_INVALID_ADDRESS;
1157
      }
1158
    }
1159
  }
1160
 
1161
  return (status);
1162
}
1163
 
1164
/**
1165
  * @}
1166
  */
1167
 
1168
/**
1169
  * @}
1170
  */
1171
 
1172
#endif /* STM32F101xE || STM32F103xE || STM32F101xG || STM32F103xG */
1173
#endif /* HAL_NAND_MODULE_ENABLED  */
1174
 
1175
/**
1176
  * @}
1177
  */
1178
 
1179
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/