Mercurial > public > ostc4
comparison Common/Drivers/STM32F4xx_HAL_DRIVER_v120/Src/stm32f4xx_hal_nand.c @ 38:5f11787b4f42
include in ostc4 repository
author | heinrichsweikamp |
---|---|
date | Sat, 28 Apr 2018 11:52:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
37:ccc45c0e1ea2 | 38:5f11787b4f42 |
---|---|
1 /** | |
2 ****************************************************************************** | |
3 * @file stm32f4xx_hal_nand.c | |
4 * @author MCD Application Team | |
5 * @version V1.2.0 | |
6 * @date 26-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 FMC/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>© 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 "stm32f4xx_hal.h" | |
87 | |
88 /** @addtogroup STM32F4xx_HAL_Driver | |
89 * @{ | |
90 */ | |
91 | |
92 | |
93 #ifdef HAL_NAND_MODULE_ENABLED | |
94 | |
95 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) | |
96 | |
97 /** @defgroup NAND NAND | |
98 * @brief NAND HAL module driver | |
99 * @{ | |
100 */ | |
101 | |
102 /* Private typedef -----------------------------------------------------------*/ | |
103 /* Private define ------------------------------------------------------------*/ | |
104 /** @defgroup NAND_Private_Constants NAND Private Constants | |
105 * @{ | |
106 */ | |
107 | |
108 /** | |
109 * @} | |
110 */ | |
111 | |
112 /* Private macro -------------------------------------------------------------*/ | |
113 /** @defgroup NAND_Private_Macros NAND Private Macros | |
114 * @{ | |
115 */ | |
116 | |
117 /** | |
118 * @} | |
119 */ | |
120 /* Private variables ---------------------------------------------------------*/ | |
121 /* Private function prototypes -----------------------------------------------*/ | |
122 /* Exported functions --------------------------------------------------------*/ | |
123 /** @defgroup NAND_Exported_Functions NAND Exported Functions | |
124 * @{ | |
125 */ | |
126 | |
127 /** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions | |
128 * @brief Initialization and Configuration functions | |
129 * | |
130 @verbatim | |
131 ============================================================================== | |
132 ##### NAND Initialization and de-initialization functions ##### | |
133 ============================================================================== | |
134 [..] | |
135 This section provides functions allowing to initialize/de-initialize | |
136 the NAND memory | |
137 | |
138 @endverbatim | |
139 * @{ | |
140 */ | |
141 | |
142 /** | |
143 * @brief Perform NAND memory Initialization sequence | |
144 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
145 * the configuration information for NAND module. | |
146 * @param ComSpace_Timing: pointer to Common space timing structure | |
147 * @param AttSpace_Timing: pointer to Attribute space timing structure | |
148 * @retval HAL status | |
149 */ | |
150 HAL_StatusTypeDef HAL_NAND_Init(NAND_HandleTypeDef *hnand, FMC_NAND_PCC_TimingTypeDef *ComSpace_Timing, FMC_NAND_PCC_TimingTypeDef *AttSpace_Timing) | |
151 { | |
152 /* Check the NAND handle state */ | |
153 if(hnand == NULL) | |
154 { | |
155 return HAL_ERROR; | |
156 } | |
157 | |
158 if(hnand->State == HAL_NAND_STATE_RESET) | |
159 { | |
160 /* Initialize the low level hardware (MSP) */ | |
161 HAL_NAND_MspInit(hnand); | |
162 } | |
163 | |
164 /* Initialize NAND control Interface */ | |
165 FMC_NAND_Init(hnand->Instance, &(hnand->Init)); | |
166 | |
167 /* Initialize NAND common space timing Interface */ | |
168 FMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank); | |
169 | |
170 /* Initialize NAND attribute space timing Interface */ | |
171 FMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank); | |
172 | |
173 /* Enable the NAND device */ | |
174 __FMC_NAND_ENABLE(hnand->Instance, hnand->Init.NandBank); | |
175 | |
176 /* Update the NAND controller state */ | |
177 hnand->State = HAL_NAND_STATE_READY; | |
178 | |
179 return HAL_OK; | |
180 } | |
181 | |
182 /** | |
183 * @brief Perform NAND memory De-Initialization sequence | |
184 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
185 * the configuration information for NAND module. | |
186 * @retval HAL status | |
187 */ | |
188 HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand) | |
189 { | |
190 /* Initialize the low level hardware (MSP) */ | |
191 HAL_NAND_MspDeInit(hnand); | |
192 | |
193 /* Configure the NAND registers with their reset values */ | |
194 FMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank); | |
195 | |
196 /* Reset the NAND controller state */ | |
197 hnand->State = HAL_NAND_STATE_RESET; | |
198 | |
199 /* Release Lock */ | |
200 __HAL_UNLOCK(hnand); | |
201 | |
202 return HAL_OK; | |
203 } | |
204 | |
205 /** | |
206 * @brief NAND MSP Init | |
207 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
208 * the configuration information for NAND module. | |
209 * @retval None | |
210 */ | |
211 __weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand) | |
212 { | |
213 /* NOTE : This function Should not be modified, when the callback is needed, | |
214 the HAL_NAND_MspInit could be implemented in the user file | |
215 */ | |
216 } | |
217 | |
218 /** | |
219 * @brief NAND MSP DeInit | |
220 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
221 * the configuration information for NAND module. | |
222 * @retval None | |
223 */ | |
224 __weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand) | |
225 { | |
226 /* NOTE : This function Should not be modified, when the callback is needed, | |
227 the HAL_NAND_MspDeInit could be implemented in the user file | |
228 */ | |
229 } | |
230 | |
231 | |
232 /** | |
233 * @brief This function handles NAND device interrupt request. | |
234 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
235 * the configuration information for NAND module. | |
236 * @retval HAL status | |
237 */ | |
238 void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand) | |
239 { | |
240 /* Check NAND interrupt Rising edge flag */ | |
241 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE)) | |
242 { | |
243 /* NAND interrupt callback*/ | |
244 HAL_NAND_ITCallback(hnand); | |
245 | |
246 /* Clear NAND interrupt Rising edge pending bit */ | |
247 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE); | |
248 } | |
249 | |
250 /* Check NAND interrupt Level flag */ | |
251 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL)) | |
252 { | |
253 /* NAND interrupt callback*/ | |
254 HAL_NAND_ITCallback(hnand); | |
255 | |
256 /* Clear NAND interrupt Level pending bit */ | |
257 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL); | |
258 } | |
259 | |
260 /* Check NAND interrupt Falling edge flag */ | |
261 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE)) | |
262 { | |
263 /* NAND interrupt callback*/ | |
264 HAL_NAND_ITCallback(hnand); | |
265 | |
266 /* Clear NAND interrupt Falling edge pending bit */ | |
267 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE); | |
268 } | |
269 | |
270 /* Check NAND interrupt FIFO empty flag */ | |
271 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT)) | |
272 { | |
273 /* NAND interrupt callback*/ | |
274 HAL_NAND_ITCallback(hnand); | |
275 | |
276 /* Clear NAND interrupt FIFO empty pending bit */ | |
277 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT); | |
278 } | |
279 | |
280 } | |
281 | |
282 /** | |
283 * @brief NAND interrupt feature callback | |
284 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
285 * the configuration information for NAND module. | |
286 * @retval None | |
287 */ | |
288 __weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand) | |
289 { | |
290 /* NOTE : This function Should not be modified, when the callback is needed, | |
291 the HAL_NAND_ITCallback could be implemented in the user file | |
292 */ | |
293 } | |
294 | |
295 /** | |
296 * @} | |
297 */ | |
298 | |
299 /** @defgroup NAND_Exported_Functions_Group2 Input and Output functions | |
300 * @brief Input Output and memory control functions | |
301 * | |
302 @verbatim | |
303 ============================================================================== | |
304 ##### NAND Input and Output functions ##### | |
305 ============================================================================== | |
306 [..] | |
307 This section provides functions allowing to use and control the NAND | |
308 memory | |
309 | |
310 @endverbatim | |
311 * @{ | |
312 */ | |
313 | |
314 /** | |
315 * @brief Read the NAND memory electronic signature | |
316 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
317 * the configuration information for NAND module. | |
318 * @param pNAND_ID: NAND ID structure | |
319 * @retval HAL status | |
320 */ | |
321 HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID) | |
322 { | |
323 __IO uint32_t data = 0; | |
324 uint32_t deviceaddress = 0; | |
325 | |
326 /* Process Locked */ | |
327 __HAL_LOCK(hnand); | |
328 | |
329 /* Check the NAND controller state */ | |
330 if(hnand->State == HAL_NAND_STATE_BUSY) | |
331 { | |
332 return HAL_BUSY; | |
333 } | |
334 | |
335 /* Identify the device address */ | |
336 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
337 { | |
338 deviceaddress = NAND_DEVICE1; | |
339 } | |
340 else | |
341 { | |
342 deviceaddress = NAND_DEVICE2; | |
343 } | |
344 | |
345 /* Update the NAND controller state */ | |
346 hnand->State = HAL_NAND_STATE_BUSY; | |
347 | |
348 /* Send Read ID command sequence */ | |
349 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_READID; | |
350 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
351 | |
352 /* Read the electronic signature from NAND flash */ | |
353 data = *(__IO uint32_t *)deviceaddress; | |
354 | |
355 /* Return the data read */ | |
356 pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data); | |
357 pNAND_ID->Device_Id = ADDR_2ND_CYCLE(data); | |
358 pNAND_ID->Third_Id = ADDR_3RD_CYCLE(data); | |
359 pNAND_ID->Fourth_Id = ADDR_4TH_CYCLE(data); | |
360 | |
361 /* Update the NAND controller state */ | |
362 hnand->State = HAL_NAND_STATE_READY; | |
363 | |
364 /* Process unlocked */ | |
365 __HAL_UNLOCK(hnand); | |
366 | |
367 return HAL_OK; | |
368 } | |
369 | |
370 /** | |
371 * @brief NAND memory reset | |
372 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
373 * the configuration information for NAND module. | |
374 * @retval HAL status | |
375 */ | |
376 HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand) | |
377 { | |
378 uint32_t deviceaddress = 0; | |
379 | |
380 /* Process Locked */ | |
381 __HAL_LOCK(hnand); | |
382 | |
383 /* Check the NAND controller state */ | |
384 if(hnand->State == HAL_NAND_STATE_BUSY) | |
385 { | |
386 return HAL_BUSY; | |
387 } | |
388 | |
389 /* Identify the device address */ | |
390 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
391 { | |
392 deviceaddress = NAND_DEVICE1; | |
393 } | |
394 else | |
395 { | |
396 deviceaddress = NAND_DEVICE2; | |
397 } | |
398 | |
399 /* Update the NAND controller state */ | |
400 hnand->State = HAL_NAND_STATE_BUSY; | |
401 | |
402 /* Send NAND reset command */ | |
403 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF; | |
404 | |
405 | |
406 /* Update the NAND controller state */ | |
407 hnand->State = HAL_NAND_STATE_READY; | |
408 | |
409 /* Process unlocked */ | |
410 __HAL_UNLOCK(hnand); | |
411 | |
412 return HAL_OK; | |
413 | |
414 } | |
415 | |
416 /** | |
417 * @brief Read Page(s) from NAND memory block | |
418 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
419 * the configuration information for NAND module. | |
420 * @param pAddress : pointer to NAND address structure | |
421 * @param pBuffer : pointer to destination read buffer | |
422 * @param NumPageToRead : number of pages to read from block | |
423 * @retval HAL status | |
424 */ | |
425 HAL_StatusTypeDef HAL_NAND_Read_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead) | |
426 { | |
427 __IO uint32_t index = 0; | |
428 uint32_t deviceaddress = 0, size = 0, numpagesread = 0, addressstatus = NAND_VALID_ADDRESS; | |
429 NAND_AddressTypeDef nandaddress; | |
430 uint32_t addressoffset = 0; | |
431 | |
432 /* Process Locked */ | |
433 __HAL_LOCK(hnand); | |
434 | |
435 /* Check the NAND controller state */ | |
436 if(hnand->State == HAL_NAND_STATE_BUSY) | |
437 { | |
438 return HAL_BUSY; | |
439 } | |
440 | |
441 /* Identify the device address */ | |
442 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
443 { | |
444 deviceaddress = NAND_DEVICE1; | |
445 } | |
446 else | |
447 { | |
448 deviceaddress = NAND_DEVICE2; | |
449 } | |
450 | |
451 /* Update the NAND controller state */ | |
452 hnand->State = HAL_NAND_STATE_BUSY; | |
453 | |
454 /* Save the content of pAddress as it will be modified */ | |
455 nandaddress.Block = pAddress->Block; | |
456 nandaddress.Page = pAddress->Page; | |
457 nandaddress.Zone = pAddress->Zone; | |
458 | |
459 /* Page(s) read loop */ | |
460 while((NumPageToRead != 0) && (addressstatus == NAND_VALID_ADDRESS)) | |
461 { | |
462 /* update the buffer size */ | |
463 size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpagesread); | |
464 | |
465 /* Get the address offset */ | |
466 addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); | |
467 | |
468 /* Send read page command sequence */ | |
469 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; | |
470 | |
471 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
472 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); | |
473 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); | |
474 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); | |
475 | |
476 /* for 512 and 1 GB devices, 4th cycle is required */ | |
477 if(hnand->Info.BlockNbr >= 1024) | |
478 { | |
479 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); | |
480 } | |
481 | |
482 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; | |
483 | |
484 /* Get Data into Buffer */ | |
485 for(; index < size; index++) | |
486 { | |
487 *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress; | |
488 } | |
489 | |
490 /* Increment read pages number */ | |
491 numpagesread++; | |
492 | |
493 /* Decrement pages to read */ | |
494 NumPageToRead--; | |
495 | |
496 /* Increment the NAND address */ | |
497 addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress); | |
498 } | |
499 | |
500 /* Update the NAND controller state */ | |
501 hnand->State = HAL_NAND_STATE_READY; | |
502 | |
503 /* Process unlocked */ | |
504 __HAL_UNLOCK(hnand); | |
505 | |
506 return HAL_OK; | |
507 | |
508 } | |
509 | |
510 /** | |
511 * @brief Write Page(s) to NAND memory block | |
512 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
513 * the configuration information for NAND module. | |
514 * @param pAddress : pointer to NAND address structure | |
515 * @param pBuffer : pointer to source buffer to write | |
516 * @param NumPageToWrite : number of pages to write to block | |
517 * @retval HAL status | |
518 */ | |
519 HAL_StatusTypeDef HAL_NAND_Write_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite) | |
520 { | |
521 __IO uint32_t index = 0; | |
522 uint32_t tickstart = 0; | |
523 uint32_t deviceaddress = 0 , size = 0, numpageswritten = 0, addressstatus = NAND_VALID_ADDRESS; | |
524 NAND_AddressTypeDef nandaddress; | |
525 uint32_t addressoffset = 0; | |
526 | |
527 /* Process Locked */ | |
528 __HAL_LOCK(hnand); | |
529 | |
530 /* Check the NAND controller state */ | |
531 if(hnand->State == HAL_NAND_STATE_BUSY) | |
532 { | |
533 return HAL_BUSY; | |
534 } | |
535 | |
536 /* Identify the device address */ | |
537 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
538 { | |
539 deviceaddress = NAND_DEVICE1; | |
540 } | |
541 else | |
542 { | |
543 deviceaddress = NAND_DEVICE2; | |
544 } | |
545 | |
546 /* Update the NAND controller state */ | |
547 hnand->State = HAL_NAND_STATE_BUSY; | |
548 | |
549 /* Save the content of pAddress as it will be modified */ | |
550 nandaddress.Block = pAddress->Block; | |
551 nandaddress.Page = pAddress->Page; | |
552 nandaddress.Zone = pAddress->Zone; | |
553 | |
554 /* Page(s) write loop */ | |
555 while((NumPageToWrite != 0) && (addressstatus == NAND_VALID_ADDRESS)) | |
556 { | |
557 /* update the buffer size */ | |
558 size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpageswritten); | |
559 | |
560 /* Get the address offset */ | |
561 addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); | |
562 | |
563 /* Send write page command sequence */ | |
564 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; | |
565 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; | |
566 | |
567 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
568 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); | |
569 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); | |
570 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); | |
571 | |
572 /* for 512 and 1 GB devices, 4th cycle is required */ | |
573 if(hnand->Info.BlockNbr >= 1024) | |
574 { | |
575 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); | |
576 } | |
577 | |
578 /* Write data to memory */ | |
579 for(; index < size; index++) | |
580 { | |
581 *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++; | |
582 } | |
583 | |
584 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; | |
585 | |
586 /* Get tick */ | |
587 tickstart = HAL_GetTick(); | |
588 | |
589 /* Read status until NAND is ready */ | |
590 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
591 { | |
592 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
593 { | |
594 return HAL_TIMEOUT; | |
595 } | |
596 } | |
597 | |
598 /* Increment written pages number */ | |
599 numpageswritten++; | |
600 | |
601 /* Decrement pages to write */ | |
602 NumPageToWrite--; | |
603 | |
604 /* Increment the NAND address */ | |
605 addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress); | |
606 } | |
607 | |
608 /* Update the NAND controller state */ | |
609 hnand->State = HAL_NAND_STATE_READY; | |
610 | |
611 /* Process unlocked */ | |
612 __HAL_UNLOCK(hnand); | |
613 | |
614 return HAL_OK; | |
615 } | |
616 | |
617 /** | |
618 * @brief Read Spare area(s) from NAND memory | |
619 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
620 * the configuration information for NAND module. | |
621 * @param pAddress : pointer to NAND address structure | |
622 * @param pBuffer: pointer to source buffer to write | |
623 * @param NumSpareAreaToRead: Number of spare area to read | |
624 * @retval HAL status | |
625 */ | |
626 HAL_StatusTypeDef HAL_NAND_Read_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead) | |
627 { | |
628 __IO uint32_t index = 0; | |
629 uint32_t deviceaddress = 0, size = 0, num_spare_area_read = 0, addressstatus = NAND_VALID_ADDRESS; | |
630 NAND_AddressTypeDef nandaddress; | |
631 uint32_t addressoffset = 0; | |
632 | |
633 /* Process Locked */ | |
634 __HAL_LOCK(hnand); | |
635 | |
636 /* Check the NAND controller state */ | |
637 if(hnand->State == HAL_NAND_STATE_BUSY) | |
638 { | |
639 return HAL_BUSY; | |
640 } | |
641 | |
642 /* Identify the device address */ | |
643 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
644 { | |
645 deviceaddress = NAND_DEVICE1; | |
646 } | |
647 else | |
648 { | |
649 deviceaddress = NAND_DEVICE2; | |
650 } | |
651 | |
652 /* Update the NAND controller state */ | |
653 hnand->State = HAL_NAND_STATE_BUSY; | |
654 | |
655 /* Save the content of pAddress as it will be modified */ | |
656 nandaddress.Block = pAddress->Block; | |
657 nandaddress.Page = pAddress->Page; | |
658 nandaddress.Zone = pAddress->Zone; | |
659 | |
660 /* Spare area(s) read loop */ | |
661 while((NumSpareAreaToRead != 0) && (addressstatus == NAND_VALID_ADDRESS)) | |
662 { | |
663 /* update the buffer size */ | |
664 size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_read); | |
665 | |
666 /* Get the address offset */ | |
667 addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); | |
668 | |
669 /* Send read spare area command sequence */ | |
670 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; | |
671 | |
672 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
673 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); | |
674 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); | |
675 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); | |
676 | |
677 /* for 512 and 1 GB devices, 4th cycle is required */ | |
678 if(hnand->Info.BlockNbr >= 1024) | |
679 { | |
680 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); | |
681 } | |
682 | |
683 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; | |
684 | |
685 /* Get Data into Buffer */ | |
686 for ( ;index < size; index++) | |
687 { | |
688 *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress; | |
689 } | |
690 | |
691 /* Increment read spare areas number */ | |
692 num_spare_area_read++; | |
693 | |
694 /* Decrement spare areas to read */ | |
695 NumSpareAreaToRead--; | |
696 | |
697 /* Increment the NAND address */ | |
698 addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress); | |
699 } | |
700 | |
701 /* Update the NAND controller state */ | |
702 hnand->State = HAL_NAND_STATE_READY; | |
703 | |
704 /* Process unlocked */ | |
705 __HAL_UNLOCK(hnand); | |
706 | |
707 return HAL_OK; | |
708 } | |
709 | |
710 /** | |
711 * @brief Write Spare area(s) to NAND memory | |
712 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
713 * the configuration information for NAND module. | |
714 * @param pAddress : pointer to NAND address structure | |
715 * @param pBuffer : pointer to source buffer to write | |
716 * @param NumSpareAreaTowrite : number of spare areas to write to block | |
717 * @retval HAL status | |
718 */ | |
719 HAL_StatusTypeDef HAL_NAND_Write_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite) | |
720 { | |
721 __IO uint32_t index = 0; | |
722 uint32_t tickstart = 0; | |
723 uint32_t deviceaddress = 0, size = 0, num_spare_area_written = 0, addressstatus = NAND_VALID_ADDRESS; | |
724 NAND_AddressTypeDef nandaddress; | |
725 uint32_t addressoffset = 0; | |
726 | |
727 /* Process Locked */ | |
728 __HAL_LOCK(hnand); | |
729 | |
730 /* Check the NAND controller state */ | |
731 if(hnand->State == HAL_NAND_STATE_BUSY) | |
732 { | |
733 return HAL_BUSY; | |
734 } | |
735 | |
736 /* Identify the device address */ | |
737 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
738 { | |
739 deviceaddress = NAND_DEVICE1; | |
740 } | |
741 else | |
742 { | |
743 deviceaddress = NAND_DEVICE2; | |
744 } | |
745 | |
746 /* Update the FMC_NAND controller state */ | |
747 hnand->State = HAL_NAND_STATE_BUSY; | |
748 | |
749 /* Save the content of pAddress as it will be modified */ | |
750 nandaddress.Block = pAddress->Block; | |
751 nandaddress.Page = pAddress->Page; | |
752 nandaddress.Zone = pAddress->Zone; | |
753 | |
754 /* Spare area(s) write loop */ | |
755 while((NumSpareAreaTowrite != 0) && (addressstatus == NAND_VALID_ADDRESS)) | |
756 { | |
757 /* update the buffer size */ | |
758 size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_written); | |
759 | |
760 /* Get the address offset */ | |
761 addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); | |
762 | |
763 /* Send write Spare area command sequence */ | |
764 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; | |
765 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; | |
766 | |
767 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
768 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); | |
769 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); | |
770 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); | |
771 | |
772 /* for 512 and 1 GB devices, 4th cycle is required */ | |
773 if(hnand->Info.BlockNbr >= 1024) | |
774 { | |
775 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); | |
776 } | |
777 | |
778 /* Write data to memory */ | |
779 for(; index < size; index++) | |
780 { | |
781 *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++; | |
782 } | |
783 | |
784 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; | |
785 | |
786 /* Get tick */ | |
787 tickstart = HAL_GetTick(); | |
788 | |
789 /* Read status until NAND is ready */ | |
790 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
791 { | |
792 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
793 { | |
794 return HAL_TIMEOUT; | |
795 } | |
796 } | |
797 | |
798 /* Increment written spare areas number */ | |
799 num_spare_area_written++; | |
800 | |
801 /* Decrement spare areas to write */ | |
802 NumSpareAreaTowrite--; | |
803 | |
804 /* Increment the NAND address */ | |
805 addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress); | |
806 } | |
807 | |
808 /* Update the NAND controller state */ | |
809 hnand->State = HAL_NAND_STATE_READY; | |
810 | |
811 /* Process unlocked */ | |
812 __HAL_UNLOCK(hnand); | |
813 | |
814 return HAL_OK; | |
815 } | |
816 | |
817 /** | |
818 * @brief NAND memory Block erase | |
819 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
820 * the configuration information for NAND module. | |
821 * @param pAddress : pointer to NAND address structure | |
822 * @retval HAL status | |
823 */ | |
824 HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) | |
825 { | |
826 uint32_t deviceaddress = 0; | |
827 uint32_t tickstart = 0; | |
828 | |
829 /* Process Locked */ | |
830 __HAL_LOCK(hnand); | |
831 | |
832 /* Check the NAND controller state */ | |
833 if(hnand->State == HAL_NAND_STATE_BUSY) | |
834 { | |
835 return HAL_BUSY; | |
836 } | |
837 | |
838 /* Identify the device address */ | |
839 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
840 { | |
841 deviceaddress = NAND_DEVICE1; | |
842 } | |
843 else | |
844 { | |
845 deviceaddress = NAND_DEVICE2; | |
846 } | |
847 | |
848 /* Update the NAND controller state */ | |
849 hnand->State = HAL_NAND_STATE_BUSY; | |
850 | |
851 /* Send Erase block command sequence */ | |
852 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0; | |
853 | |
854 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); | |
855 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); | |
856 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); | |
857 | |
858 /* for 512 and 1 GB devices, 4th cycle is required */ | |
859 if(hnand->Info.BlockNbr >= 1024) | |
860 { | |
861 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); | |
862 } | |
863 | |
864 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1; | |
865 | |
866 /* Update the NAND controller state */ | |
867 hnand->State = HAL_NAND_STATE_READY; | |
868 | |
869 /* Get tick */ | |
870 tickstart = HAL_GetTick(); | |
871 | |
872 /* Read status until NAND is ready */ | |
873 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
874 { | |
875 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
876 { | |
877 /* Process unlocked */ | |
878 __HAL_UNLOCK(hnand); | |
879 | |
880 return HAL_TIMEOUT; | |
881 } | |
882 } | |
883 | |
884 /* Process unlocked */ | |
885 __HAL_UNLOCK(hnand); | |
886 | |
887 return HAL_OK; | |
888 } | |
889 | |
890 /** | |
891 * @brief NAND memory read status | |
892 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
893 * the configuration information for NAND module. | |
894 * @retval NAND status | |
895 */ | |
896 uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand) | |
897 { | |
898 uint32_t data = 0; | |
899 uint32_t deviceaddress = 0; | |
900 | |
901 /* Identify the device address */ | |
902 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
903 { | |
904 deviceaddress = NAND_DEVICE1; | |
905 } | |
906 else | |
907 { | |
908 deviceaddress = NAND_DEVICE2; | |
909 } | |
910 | |
911 /* Send Read status operation command */ | |
912 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS; | |
913 | |
914 /* Read status register data */ | |
915 data = *(__IO uint8_t *)deviceaddress; | |
916 | |
917 /* Return the status */ | |
918 if((data & NAND_ERROR) == NAND_ERROR) | |
919 { | |
920 return NAND_ERROR; | |
921 } | |
922 else if((data & NAND_READY) == NAND_READY) | |
923 { | |
924 return NAND_READY; | |
925 } | |
926 | |
927 return NAND_BUSY; | |
928 } | |
929 | |
930 /** | |
931 * @brief Increment the NAND memory address | |
932 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
933 * the configuration information for NAND module. | |
934 * @param pAddress: pointer to NAND address structure | |
935 * @retval The new status of the increment address operation. It can be: | |
936 * - NAND_VALID_ADDRESS: When the new address is valid address | |
937 * - NAND_INVALID_ADDRESS: When the new address is invalid address | |
938 */ | |
939 uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) | |
940 { | |
941 uint32_t status = NAND_VALID_ADDRESS; | |
942 | |
943 /* Increment page address */ | |
944 pAddress->Page++; | |
945 | |
946 /* Check NAND address is valid */ | |
947 if(pAddress->Page == hnand->Info.BlockSize) | |
948 { | |
949 pAddress->Page = 0; | |
950 pAddress->Block++; | |
951 | |
952 if(pAddress->Block == hnand->Info.ZoneSize) | |
953 { | |
954 pAddress->Block = 0; | |
955 pAddress->Zone++; | |
956 | |
957 if(pAddress->Zone == (hnand->Info.ZoneSize/ hnand->Info.BlockNbr)) | |
958 { | |
959 status = NAND_INVALID_ADDRESS; | |
960 } | |
961 } | |
962 } | |
963 | |
964 return (status); | |
965 } | |
966 /** | |
967 * @} | |
968 */ | |
969 | |
970 /** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions | |
971 * @brief management functions | |
972 * | |
973 @verbatim | |
974 ============================================================================== | |
975 ##### NAND Control functions ##### | |
976 ============================================================================== | |
977 [..] | |
978 This subsection provides a set of functions allowing to control dynamically | |
979 the NAND interface. | |
980 | |
981 @endverbatim | |
982 * @{ | |
983 */ | |
984 | |
985 | |
986 /** | |
987 * @brief Enables dynamically NAND ECC feature. | |
988 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
989 * the configuration information for NAND module. | |
990 * @retval HAL status | |
991 */ | |
992 HAL_StatusTypeDef HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand) | |
993 { | |
994 /* Check the NAND controller state */ | |
995 if(hnand->State == HAL_NAND_STATE_BUSY) | |
996 { | |
997 return HAL_BUSY; | |
998 } | |
999 | |
1000 /* Update the NAND state */ | |
1001 hnand->State = HAL_NAND_STATE_BUSY; | |
1002 | |
1003 /* Enable ECC feature */ | |
1004 FMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank); | |
1005 | |
1006 /* Update the NAND state */ | |
1007 hnand->State = HAL_NAND_STATE_READY; | |
1008 | |
1009 return HAL_OK; | |
1010 } | |
1011 | |
1012 /** | |
1013 * @brief Disables dynamically FMC_NAND ECC feature. | |
1014 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
1015 * the configuration information for NAND module. | |
1016 * @retval HAL status | |
1017 */ | |
1018 HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand) | |
1019 { | |
1020 /* Check the NAND controller state */ | |
1021 if(hnand->State == HAL_NAND_STATE_BUSY) | |
1022 { | |
1023 return HAL_BUSY; | |
1024 } | |
1025 | |
1026 /* Update the NAND state */ | |
1027 hnand->State = HAL_NAND_STATE_BUSY; | |
1028 | |
1029 /* Disable ECC feature */ | |
1030 FMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank); | |
1031 | |
1032 /* Update the NAND state */ | |
1033 hnand->State = HAL_NAND_STATE_READY; | |
1034 | |
1035 return HAL_OK; | |
1036 } | |
1037 | |
1038 /** | |
1039 * @brief Disables dynamically NAND ECC feature. | |
1040 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
1041 * the configuration information for NAND module. | |
1042 * @param ECCval: pointer to ECC value | |
1043 * @param Timeout: maximum timeout to wait | |
1044 * @retval HAL status | |
1045 */ | |
1046 HAL_StatusTypeDef HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout) | |
1047 { | |
1048 HAL_StatusTypeDef status = HAL_OK; | |
1049 | |
1050 /* Check the NAND controller state */ | |
1051 if(hnand->State == HAL_NAND_STATE_BUSY) | |
1052 { | |
1053 return HAL_BUSY; | |
1054 } | |
1055 | |
1056 /* Update the NAND state */ | |
1057 hnand->State = HAL_NAND_STATE_BUSY; | |
1058 | |
1059 /* Get NAND ECC value */ | |
1060 status = FMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout); | |
1061 | |
1062 /* Update the NAND state */ | |
1063 hnand->State = HAL_NAND_STATE_READY; | |
1064 | |
1065 return status; | |
1066 } | |
1067 | |
1068 /** | |
1069 * @} | |
1070 */ | |
1071 | |
1072 | |
1073 /** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions | |
1074 * @brief Peripheral State functions | |
1075 * | |
1076 @verbatim | |
1077 ============================================================================== | |
1078 ##### NAND State functions ##### | |
1079 ============================================================================== | |
1080 [..] | |
1081 This subsection permits to get in run-time the status of the NAND controller | |
1082 and the data flow. | |
1083 | |
1084 @endverbatim | |
1085 * @{ | |
1086 */ | |
1087 | |
1088 /** | |
1089 * @brief return the NAND state | |
1090 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains | |
1091 * the configuration information for NAND module. | |
1092 * @retval HAL state | |
1093 */ | |
1094 HAL_NAND_StateTypeDef HAL_NAND_GetState(NAND_HandleTypeDef *hnand) | |
1095 { | |
1096 return hnand->State; | |
1097 } | |
1098 | |
1099 /** | |
1100 * @} | |
1101 */ | |
1102 | |
1103 /** | |
1104 * @} | |
1105 */ | |
1106 | |
1107 /** | |
1108 * @} | |
1109 */ | |
1110 | |
1111 #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ | |
1112 #endif /* HAL_NAND_MODULE_ENABLED */ | |
1113 | |
1114 /** | |
1115 * @} | |
1116 */ | |
1117 | |
1118 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |