Mercurial > public > ostc4
comparison Common/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c @ 128:c78bcbd5deda FlipDisplay
Added current STM32 standandard libraries in version independend folder structure
author | Ideenmodellierer |
---|---|
date | Sun, 17 Feb 2019 21:12:22 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
127:1369f8660eaa | 128:c78bcbd5deda |
---|---|
1 /** | |
2 ****************************************************************************** | |
3 * @file stm32f4xx_hal_nand.c | |
4 * @author MCD Application Team | |
5 * @brief NAND HAL module driver. | |
6 * This file provides a generic firmware to drive NAND memories mounted | |
7 * as external device. | |
8 * | |
9 @verbatim | |
10 ============================================================================== | |
11 ##### How to use this driver ##### | |
12 ============================================================================== | |
13 [..] | |
14 This driver is a generic layered driver which contains a set of APIs used to | |
15 control NAND flash memories. It uses the FMC/FSMC layer functions to interface | |
16 with NAND devices. This driver is used as follows: | |
17 | |
18 (+) NAND flash memory configuration sequence using the function HAL_NAND_Init() | |
19 with control and timing parameters for both common and attribute spaces. | |
20 | |
21 (+) Read NAND flash memory maker and device IDs using the function | |
22 HAL_NAND_Read_ID(). The read information is stored in the NAND_ID_TypeDef | |
23 structure declared by the function caller. | |
24 | |
25 (+) Access NAND flash memory by read/write operations using the functions | |
26 HAL_NAND_Read_Page_8b()/HAL_NAND_Read_SpareArea_8b(), | |
27 HAL_NAND_Write_Page_8b()/HAL_NAND_Write_SpareArea_8b(), | |
28 HAL_NAND_Read_Page_16b()/HAL_NAND_Read_SpareArea_16b(), | |
29 HAL_NAND_Write_Page_16b()/HAL_NAND_Write_SpareArea_16b() | |
30 to read/write page(s)/spare area(s). These functions use specific device | |
31 information (Block, page size..) predefined by the user in the HAL_NAND_Info_TypeDef | |
32 structure. The read/write address information is contained by the Nand_Address_Typedef | |
33 structure passed as parameter. | |
34 | |
35 (+) Perform NAND flash Reset chip operation using the function HAL_NAND_Reset(). | |
36 | |
37 (+) Perform NAND flash erase block operation using the function HAL_NAND_Erase_Block(). | |
38 The erase block address information is contained in the Nand_Address_Typedef | |
39 structure passed as parameter. | |
40 | |
41 (+) Read the NAND flash status operation using the function HAL_NAND_Read_Status(). | |
42 | |
43 (+) You can also control the NAND device by calling the control APIs HAL_NAND_ECC_Enable()/ | |
44 HAL_NAND_ECC_Disable() to respectively enable/disable the ECC code correction | |
45 feature or the function HAL_NAND_GetECC() to get the ECC correction code. | |
46 | |
47 (+) You can monitor the NAND device HAL state by calling the function | |
48 HAL_NAND_GetState() | |
49 | |
50 [..] | |
51 (@) This driver is a set of generic APIs which handle standard NAND flash operations. | |
52 If a NAND flash device contains different operations and/or implementations, | |
53 it should be implemented separately. | |
54 | |
55 @endverbatim | |
56 ****************************************************************************** | |
57 * @attention | |
58 * | |
59 * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> | |
60 * | |
61 * Redistribution and use in source and binary forms, with or without modification, | |
62 * are permitted provided that the following conditions are met: | |
63 * 1. Redistributions of source code must retain the above copyright notice, | |
64 * this list of conditions and the following disclaimer. | |
65 * 2. Redistributions in binary form must reproduce the above copyright notice, | |
66 * this list of conditions and the following disclaimer in the documentation | |
67 * and/or other materials provided with the distribution. | |
68 * 3. Neither the name of STMicroelectronics nor the names of its contributors | |
69 * may be used to endorse or promote products derived from this software | |
70 * without specific prior written permission. | |
71 * | |
72 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
73 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
74 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
75 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
76 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
77 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
78 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
79 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
80 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
81 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
82 * | |
83 ****************************************************************************** | |
84 */ | |
85 | |
86 /* Includes ------------------------------------------------------------------*/ | |
87 #include "stm32f4xx_hal.h" | |
88 | |
89 /** @addtogroup STM32F4xx_HAL_Driver | |
90 * @{ | |
91 */ | |
92 | |
93 | |
94 #ifdef HAL_NAND_MODULE_ENABLED | |
95 | |
96 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\ | |
97 defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ | |
98 defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) | |
99 | |
100 /** @defgroup NAND NAND | |
101 * @brief NAND HAL module driver | |
102 * @{ | |
103 */ | |
104 | |
105 /* Private typedef -----------------------------------------------------------*/ | |
106 /* Private define ------------------------------------------------------------*/ | |
107 /** @defgroup NAND_Private_Constants NAND Private Constants | |
108 * @{ | |
109 */ | |
110 | |
111 /** | |
112 * @} | |
113 */ | |
114 | |
115 /* Private macro -------------------------------------------------------------*/ | |
116 /** @defgroup NAND_Private_Macros NAND Private Macros | |
117 * @{ | |
118 */ | |
119 | |
120 /** | |
121 * @} | |
122 */ | |
123 /* Private variables ---------------------------------------------------------*/ | |
124 /* Private function prototypes -----------------------------------------------*/ | |
125 /* Exported functions --------------------------------------------------------*/ | |
126 /** @defgroup NAND_Exported_Functions NAND Exported Functions | |
127 * @{ | |
128 */ | |
129 | |
130 /** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions | |
131 * @brief Initialization and Configuration functions | |
132 * | |
133 @verbatim | |
134 ============================================================================== | |
135 ##### NAND Initialization and de-initialization functions ##### | |
136 ============================================================================== | |
137 [..] | |
138 This section provides functions allowing to initialize/de-initialize | |
139 the NAND memory | |
140 | |
141 @endverbatim | |
142 * @{ | |
143 */ | |
144 | |
145 /** | |
146 * @brief Perform NAND memory Initialization sequence | |
147 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
148 * the configuration information for NAND module. | |
149 * @param ComSpace_Timing pointer to Common space timing structure | |
150 * @param AttSpace_Timing pointer to Attribute space timing structure | |
151 * @retval HAL status | |
152 */ | |
153 HAL_StatusTypeDef HAL_NAND_Init(NAND_HandleTypeDef *hnand, FMC_NAND_PCC_TimingTypeDef *ComSpace_Timing, FMC_NAND_PCC_TimingTypeDef *AttSpace_Timing) | |
154 { | |
155 /* Check the NAND handle state */ | |
156 if(hnand == NULL) | |
157 { | |
158 return HAL_ERROR; | |
159 } | |
160 | |
161 if(hnand->State == HAL_NAND_STATE_RESET) | |
162 { | |
163 /* Allocate lock resource and initialize it */ | |
164 hnand->Lock = HAL_UNLOCKED; | |
165 /* Initialize the low level hardware (MSP) */ | |
166 HAL_NAND_MspInit(hnand); | |
167 } | |
168 | |
169 /* Initialize NAND control Interface */ | |
170 FMC_NAND_Init(hnand->Instance, &(hnand->Init)); | |
171 | |
172 /* Initialize NAND common space timing Interface */ | |
173 FMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank); | |
174 | |
175 /* Initialize NAND attribute space timing Interface */ | |
176 FMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank); | |
177 | |
178 /* Enable the NAND device */ | |
179 __FMC_NAND_ENABLE(hnand->Instance, hnand->Init.NandBank); | |
180 | |
181 /* Update the NAND controller state */ | |
182 hnand->State = HAL_NAND_STATE_READY; | |
183 | |
184 return HAL_OK; | |
185 } | |
186 | |
187 /** | |
188 * @brief Perform NAND memory De-Initialization sequence | |
189 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
190 * the configuration information for NAND module. | |
191 * @retval HAL status | |
192 */ | |
193 HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand) | |
194 { | |
195 /* Initialize the low level hardware (MSP) */ | |
196 HAL_NAND_MspDeInit(hnand); | |
197 | |
198 /* Configure the NAND registers with their reset values */ | |
199 FMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank); | |
200 | |
201 /* Reset the NAND controller state */ | |
202 hnand->State = HAL_NAND_STATE_RESET; | |
203 | |
204 /* Release Lock */ | |
205 __HAL_UNLOCK(hnand); | |
206 | |
207 return HAL_OK; | |
208 } | |
209 | |
210 /** | |
211 * @brief NAND MSP Init | |
212 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
213 * the configuration information for NAND module. | |
214 * @retval None | |
215 */ | |
216 __weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand) | |
217 { | |
218 /* Prevent unused argument(s) compilation warning */ | |
219 UNUSED(hnand); | |
220 /* NOTE : This function Should not be modified, when the callback is needed, | |
221 the HAL_NAND_MspInit could be implemented in the user file | |
222 */ | |
223 } | |
224 | |
225 /** | |
226 * @brief NAND MSP DeInit | |
227 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
228 * the configuration information for NAND module. | |
229 * @retval None | |
230 */ | |
231 __weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand) | |
232 { | |
233 /* Prevent unused argument(s) compilation warning */ | |
234 UNUSED(hnand); | |
235 /* NOTE : This function Should not be modified, when the callback is needed, | |
236 the HAL_NAND_MspDeInit could be implemented in the user file | |
237 */ | |
238 } | |
239 | |
240 | |
241 /** | |
242 * @brief This function handles NAND device interrupt request. | |
243 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
244 * the configuration information for NAND module. | |
245 * @retval HAL status | |
246 */ | |
247 void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand) | |
248 { | |
249 /* Check NAND interrupt Rising edge flag */ | |
250 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE)) | |
251 { | |
252 /* NAND interrupt callback*/ | |
253 HAL_NAND_ITCallback(hnand); | |
254 | |
255 /* Clear NAND interrupt Rising edge pending bit */ | |
256 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE); | |
257 } | |
258 | |
259 /* Check NAND interrupt Level flag */ | |
260 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL)) | |
261 { | |
262 /* NAND interrupt callback*/ | |
263 HAL_NAND_ITCallback(hnand); | |
264 | |
265 /* Clear NAND interrupt Level pending bit */ | |
266 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL); | |
267 } | |
268 | |
269 /* Check NAND interrupt Falling edge flag */ | |
270 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE)) | |
271 { | |
272 /* NAND interrupt callback*/ | |
273 HAL_NAND_ITCallback(hnand); | |
274 | |
275 /* Clear NAND interrupt Falling edge pending bit */ | |
276 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE); | |
277 } | |
278 | |
279 /* Check NAND interrupt FIFO empty flag */ | |
280 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT)) | |
281 { | |
282 /* NAND interrupt callback*/ | |
283 HAL_NAND_ITCallback(hnand); | |
284 | |
285 /* Clear NAND interrupt FIFO empty pending bit */ | |
286 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT); | |
287 } | |
288 } | |
289 | |
290 /** | |
291 * @brief NAND interrupt feature callback | |
292 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
293 * the configuration information for NAND module. | |
294 * @retval None | |
295 */ | |
296 __weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand) | |
297 { | |
298 /* Prevent unused argument(s) compilation warning */ | |
299 UNUSED(hnand); | |
300 /* NOTE : This function Should not be modified, when the callback is needed, | |
301 the HAL_NAND_ITCallback could be implemented in the user file | |
302 */ | |
303 } | |
304 | |
305 /** | |
306 * @} | |
307 */ | |
308 | |
309 /** @defgroup NAND_Exported_Functions_Group2 Input and Output functions | |
310 * @brief Input Output and memory control functions | |
311 * | |
312 @verbatim | |
313 ============================================================================== | |
314 ##### NAND Input and Output functions ##### | |
315 ============================================================================== | |
316 [..] | |
317 This section provides functions allowing to use and control the NAND | |
318 memory | |
319 | |
320 @endverbatim | |
321 * @{ | |
322 */ | |
323 | |
324 /** | |
325 * @brief Read the NAND memory electronic signature | |
326 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
327 * the configuration information for NAND module. | |
328 * @param pNAND_ID NAND ID structure | |
329 * @retval HAL status | |
330 */ | |
331 HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID) | |
332 { | |
333 __IO uint32_t data = 0U; | |
334 __IO uint32_t data1 = 0U; | |
335 uint32_t deviceaddress = 0U; | |
336 | |
337 /* Process Locked */ | |
338 __HAL_LOCK(hnand); | |
339 | |
340 /* Check the NAND controller state */ | |
341 if(hnand->State == HAL_NAND_STATE_BUSY) | |
342 { | |
343 return HAL_BUSY; | |
344 } | |
345 | |
346 /* Identify the device address */ | |
347 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
348 { | |
349 deviceaddress = NAND_DEVICE1; | |
350 } | |
351 else | |
352 { | |
353 deviceaddress = NAND_DEVICE2; | |
354 } | |
355 | |
356 /* Update the NAND controller state */ | |
357 hnand->State = HAL_NAND_STATE_BUSY; | |
358 | |
359 /* Send Read ID command sequence */ | |
360 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_READID; | |
361 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
362 | |
363 /* Read the electronic signature from NAND flash */ | |
364 #ifdef FSMC_PCR2_PWID | |
365 if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8) | |
366 #else /* FMC_PCR2_PWID is defined */ | |
367 if (hnand->Init.MemoryDataWidth == FMC_NAND_PCC_MEM_BUS_WIDTH_8) | |
368 #endif | |
369 { | |
370 data = *(__IO uint32_t *)deviceaddress; | |
371 | |
372 /* Return the data read */ | |
373 pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data); | |
374 pNAND_ID->Device_Id = ADDR_2ND_CYCLE(data); | |
375 pNAND_ID->Third_Id = ADDR_3RD_CYCLE(data); | |
376 pNAND_ID->Fourth_Id = ADDR_4TH_CYCLE(data); | |
377 } | |
378 else | |
379 { | |
380 data = *(__IO uint32_t *)deviceaddress; | |
381 data1 = *((__IO uint32_t *)deviceaddress + 4U); | |
382 | |
383 /* Return the data read */ | |
384 pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data); | |
385 pNAND_ID->Device_Id = ADDR_3RD_CYCLE(data); | |
386 pNAND_ID->Third_Id = ADDR_1ST_CYCLE(data1); | |
387 pNAND_ID->Fourth_Id = ADDR_3RD_CYCLE(data1); | |
388 } | |
389 | |
390 /* Update the NAND controller state */ | |
391 hnand->State = HAL_NAND_STATE_READY; | |
392 | |
393 /* Process unlocked */ | |
394 __HAL_UNLOCK(hnand); | |
395 | |
396 return HAL_OK; | |
397 } | |
398 | |
399 /** | |
400 * @brief NAND memory reset | |
401 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
402 * the configuration information for NAND module. | |
403 * @retval HAL status | |
404 */ | |
405 HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand) | |
406 { | |
407 uint32_t deviceaddress = 0U; | |
408 | |
409 /* Process Locked */ | |
410 __HAL_LOCK(hnand); | |
411 | |
412 /* Check the NAND controller state */ | |
413 if(hnand->State == HAL_NAND_STATE_BUSY) | |
414 { | |
415 return HAL_BUSY; | |
416 } | |
417 | |
418 /* Identify the device address */ | |
419 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
420 { | |
421 deviceaddress = NAND_DEVICE1; | |
422 } | |
423 else | |
424 { | |
425 deviceaddress = NAND_DEVICE2; | |
426 } | |
427 | |
428 /* Update the NAND controller state */ | |
429 hnand->State = HAL_NAND_STATE_BUSY; | |
430 | |
431 /* Send NAND reset command */ | |
432 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF; | |
433 | |
434 | |
435 /* Update the NAND controller state */ | |
436 hnand->State = HAL_NAND_STATE_READY; | |
437 | |
438 /* Process unlocked */ | |
439 __HAL_UNLOCK(hnand); | |
440 | |
441 return HAL_OK; | |
442 | |
443 } | |
444 | |
445 /** | |
446 * @brief Configure the device: Enter the physical parameters of the device | |
447 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
448 * the configuration information for NAND module. | |
449 * @param pDeviceConfig pointer to NAND_DeviceConfigTypeDef structure | |
450 * @retval HAL status | |
451 */ | |
452 HAL_StatusTypeDef HAL_NAND_ConfigDevice(NAND_HandleTypeDef *hnand, NAND_DeviceConfigTypeDef *pDeviceConfig) | |
453 { | |
454 hnand->Config.PageSize = pDeviceConfig->PageSize; | |
455 hnand->Config.SpareAreaSize = pDeviceConfig->SpareAreaSize; | |
456 hnand->Config.BlockSize = pDeviceConfig->BlockSize; | |
457 hnand->Config.BlockNbr = pDeviceConfig->BlockNbr; | |
458 hnand->Config.PlaneSize = pDeviceConfig->PlaneSize; | |
459 hnand->Config.PlaneNbr = pDeviceConfig->PlaneNbr; | |
460 hnand->Config.ExtraCommandEnable = pDeviceConfig->ExtraCommandEnable; | |
461 | |
462 return HAL_OK; | |
463 } | |
464 | |
465 /** | |
466 * @brief Read Page(s) from NAND memory block (8-bits addressing) | |
467 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
468 * the configuration information for NAND module. | |
469 * @param pAddress pointer to NAND address structure | |
470 * @param pBuffer pointer to destination read buffer | |
471 * @param NumPageToRead number of pages to read from block | |
472 * @retval HAL status | |
473 */ | |
474 HAL_StatusTypeDef HAL_NAND_Read_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead) | |
475 { | |
476 __IO uint32_t index = 0U; | |
477 uint32_t tickstart = 0U; | |
478 uint32_t deviceaddress = 0U, size = 0U, numPagesRead = 0U, nandaddress = 0U; | |
479 | |
480 /* Process Locked */ | |
481 __HAL_LOCK(hnand); | |
482 | |
483 /* Check the NAND controller state */ | |
484 if(hnand->State == HAL_NAND_STATE_BUSY) | |
485 { | |
486 return HAL_BUSY; | |
487 } | |
488 | |
489 /* Identify the device address */ | |
490 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
491 { | |
492 deviceaddress = NAND_DEVICE1; | |
493 } | |
494 else | |
495 { | |
496 deviceaddress = NAND_DEVICE2; | |
497 } | |
498 | |
499 /* Update the NAND controller state */ | |
500 hnand->State = HAL_NAND_STATE_BUSY; | |
501 | |
502 /* NAND raw address calculation */ | |
503 nandaddress = ARRAY_ADDRESS(pAddress, hnand); | |
504 | |
505 /* Page(s) read loop */ | |
506 while((NumPageToRead != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) | |
507 { | |
508 /* update the buffer size */ | |
509 size = (hnand->Config.PageSize) + ((hnand->Config.PageSize) * numPagesRead); | |
510 | |
511 /* Send read page command sequence */ | |
512 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; | |
513 | |
514 /* Cards with page size <= 512 bytes */ | |
515 if((hnand->Config.PageSize) <= 512U) | |
516 { | |
517 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
518 { | |
519 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
520 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
521 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
522 } | |
523 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
524 { | |
525 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
526 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
527 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
528 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
529 } | |
530 } | |
531 else /* (hnand->Config.PageSize) > 512 */ | |
532 { | |
533 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
534 { | |
535 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
536 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
537 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
538 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
539 } | |
540 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
541 { | |
542 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
543 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
544 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
545 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
546 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
547 } | |
548 } | |
549 | |
550 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; | |
551 | |
552 /* Check if an extra command is needed for reading pages */ | |
553 if(hnand->Config.ExtraCommandEnable == ENABLE) | |
554 { | |
555 /* Get tick */ | |
556 tickstart = HAL_GetTick(); | |
557 | |
558 /* Read status until NAND is ready */ | |
559 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
560 { | |
561 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
562 { | |
563 return HAL_TIMEOUT; | |
564 } | |
565 } | |
566 | |
567 /* Go back to read mode */ | |
568 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); | |
569 __DSB(); | |
570 } | |
571 | |
572 /* Get Data into Buffer */ | |
573 for(; index < size; index++) | |
574 { | |
575 *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress; | |
576 } | |
577 | |
578 /* Increment read pages number */ | |
579 numPagesRead++; | |
580 | |
581 /* Decrement pages to read */ | |
582 NumPageToRead--; | |
583 | |
584 /* Increment the NAND address */ | |
585 nandaddress = (uint32_t)(nandaddress + 1U); | |
586 } | |
587 | |
588 /* Update the NAND controller state */ | |
589 hnand->State = HAL_NAND_STATE_READY; | |
590 | |
591 /* Process unlocked */ | |
592 __HAL_UNLOCK(hnand); | |
593 | |
594 return HAL_OK; | |
595 } | |
596 | |
597 /** | |
598 * @brief Read Page(s) from NAND memory block (16-bits addressing) | |
599 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
600 * the configuration information for NAND module. | |
601 * @param pAddress pointer to NAND address structure | |
602 * @param pBuffer pointer to destination read buffer. pBuffer should be 16bits aligned | |
603 * @param NumPageToRead number of pages to read from block | |
604 * @retval HAL status | |
605 */ | |
606 HAL_StatusTypeDef HAL_NAND_Read_Page_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumPageToRead) | |
607 { | |
608 __IO uint32_t index = 0U; | |
609 uint32_t tickstart = 0U; | |
610 uint32_t deviceaddress = 0U, size = 0U, numPagesRead = 0U, nandaddress = 0U; | |
611 | |
612 /* Process Locked */ | |
613 __HAL_LOCK(hnand); | |
614 | |
615 /* Check the NAND controller state */ | |
616 if(hnand->State == HAL_NAND_STATE_BUSY) | |
617 { | |
618 return HAL_BUSY; | |
619 } | |
620 | |
621 /* Identify the device address */ | |
622 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
623 { | |
624 deviceaddress = NAND_DEVICE1; | |
625 } | |
626 else | |
627 { | |
628 deviceaddress = NAND_DEVICE2; | |
629 } | |
630 | |
631 /* Update the NAND controller state */ | |
632 hnand->State = HAL_NAND_STATE_BUSY; | |
633 | |
634 /* NAND raw address calculation */ | |
635 nandaddress = ARRAY_ADDRESS(pAddress, hnand); | |
636 | |
637 /* Page(s) read loop */ | |
638 while((NumPageToRead != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) | |
639 { | |
640 /* update the buffer size */ | |
641 size = (hnand->Config.PageSize) + ((hnand->Config.PageSize) * numPagesRead); | |
642 | |
643 /* Send read page command sequence */ | |
644 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; | |
645 __DSB(); | |
646 | |
647 /* Cards with page size <= 512 bytes */ | |
648 if((hnand->Config.PageSize) <= 512U) | |
649 { | |
650 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
651 { | |
652 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
653 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
654 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
655 } | |
656 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
657 { | |
658 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
659 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
660 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
661 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
662 } | |
663 } | |
664 else /* (hnand->Config.PageSize) > 512 */ | |
665 { | |
666 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
667 { | |
668 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
669 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
670 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
671 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
672 } | |
673 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
674 { | |
675 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
676 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
677 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
678 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
679 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
680 } | |
681 } | |
682 | |
683 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; | |
684 | |
685 if(hnand->Config.ExtraCommandEnable == ENABLE) | |
686 { | |
687 /* Get tick */ | |
688 tickstart = HAL_GetTick(); | |
689 | |
690 /* Read status until NAND is ready */ | |
691 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
692 { | |
693 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
694 { | |
695 return HAL_TIMEOUT; | |
696 } | |
697 } | |
698 | |
699 /* Go back to read mode */ | |
700 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); | |
701 } | |
702 | |
703 /* Get Data into Buffer */ | |
704 for(; index < size; index++) | |
705 { | |
706 *(uint16_t *)pBuffer++ = *(uint16_t *)deviceaddress; | |
707 } | |
708 | |
709 /* Increment read pages number */ | |
710 numPagesRead++; | |
711 | |
712 /* Decrement pages to read */ | |
713 NumPageToRead--; | |
714 | |
715 /* Increment the NAND address */ | |
716 nandaddress = (uint32_t)(nandaddress + 1U); | |
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 Page(s) to NAND memory block (8-bits addressing) | |
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 NumPageToWrite number of pages to write to block | |
735 * @retval HAL status | |
736 */ | |
737 HAL_StatusTypeDef HAL_NAND_Write_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite) | |
738 { | |
739 __IO uint32_t index = 0U; | |
740 uint32_t tickstart = 0U; | |
741 uint32_t deviceaddress = 0U, size = 0U, numPagesWritten = 0U, nandaddress = 0U; | |
742 | |
743 /* Process Locked */ | |
744 __HAL_LOCK(hnand); | |
745 | |
746 /* Check the NAND controller state */ | |
747 if(hnand->State == HAL_NAND_STATE_BUSY) | |
748 { | |
749 return HAL_BUSY; | |
750 } | |
751 | |
752 /* Identify the device address */ | |
753 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
754 { | |
755 deviceaddress = NAND_DEVICE1; | |
756 } | |
757 else | |
758 { | |
759 deviceaddress = NAND_DEVICE2; | |
760 } | |
761 | |
762 /* Update the NAND controller state */ | |
763 hnand->State = HAL_NAND_STATE_BUSY; | |
764 | |
765 /* NAND raw address calculation */ | |
766 nandaddress = ARRAY_ADDRESS(pAddress, hnand); | |
767 | |
768 /* Page(s) write loop */ | |
769 while((NumPageToWrite != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) | |
770 { | |
771 /* update the buffer size */ | |
772 size = hnand->Config.PageSize + ((hnand->Config.PageSize) * numPagesWritten); | |
773 | |
774 /* Send write page command sequence */ | |
775 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; | |
776 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; | |
777 | |
778 /* Cards with page size <= 512 bytes */ | |
779 if((hnand->Config.PageSize) <= 512U) | |
780 { | |
781 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
782 { | |
783 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
784 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
785 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
786 } | |
787 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
788 { | |
789 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
790 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
791 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
792 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
793 } | |
794 } | |
795 else /* (hnand->Config.PageSize) > 512 */ | |
796 { | |
797 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
798 { | |
799 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
800 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
801 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
802 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
803 } | |
804 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
805 { | |
806 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
807 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
808 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
809 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
810 __DSB(); | |
811 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
812 __DSB(); | |
813 } | |
814 } | |
815 | |
816 | |
817 /* Write data to memory */ | |
818 for(; index < size; index++) | |
819 { | |
820 *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++; | |
821 } | |
822 | |
823 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; | |
824 | |
825 /* Read status until NAND is ready */ | |
826 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
827 { | |
828 /* Get tick */ | |
829 tickstart = HAL_GetTick(); | |
830 | |
831 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
832 { | |
833 return HAL_TIMEOUT; | |
834 } | |
835 } | |
836 | |
837 /* Increment written pages number */ | |
838 numPagesWritten++; | |
839 | |
840 /* Decrement pages to write */ | |
841 NumPageToWrite--; | |
842 | |
843 /* Increment the NAND address */ | |
844 nandaddress = (uint32_t)(nandaddress + 1U); | |
845 } | |
846 | |
847 /* Update the NAND controller state */ | |
848 hnand->State = HAL_NAND_STATE_READY; | |
849 | |
850 /* Process unlocked */ | |
851 __HAL_UNLOCK(hnand); | |
852 | |
853 return HAL_OK; | |
854 } | |
855 | |
856 /** | |
857 * @brief Write Page(s) to NAND memory block (16-bits addressing) | |
858 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
859 * the configuration information for NAND module. | |
860 * @param pAddress pointer to NAND address structure | |
861 * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned | |
862 * @param NumPageToWrite number of pages to write to block | |
863 * @retval HAL status | |
864 */ | |
865 HAL_StatusTypeDef HAL_NAND_Write_Page_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumPageToWrite) | |
866 { | |
867 __IO uint32_t index = 0U; | |
868 uint32_t tickstart = 0U; | |
869 uint32_t deviceaddress = 0U, size = 0U, numPagesWritten = 0U, nandaddress = 0U; | |
870 | |
871 /* Process Locked */ | |
872 __HAL_LOCK(hnand); | |
873 | |
874 /* Check the NAND controller state */ | |
875 if(hnand->State == HAL_NAND_STATE_BUSY) | |
876 { | |
877 return HAL_BUSY; | |
878 } | |
879 | |
880 /* Identify the device address */ | |
881 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
882 { | |
883 deviceaddress = NAND_DEVICE1; | |
884 } | |
885 else | |
886 { | |
887 deviceaddress = NAND_DEVICE2; | |
888 } | |
889 | |
890 /* Update the NAND controller state */ | |
891 hnand->State = HAL_NAND_STATE_BUSY; | |
892 | |
893 /* NAND raw address calculation */ | |
894 nandaddress = ARRAY_ADDRESS(pAddress, hnand); | |
895 | |
896 /* Page(s) write loop */ | |
897 while((NumPageToWrite != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) | |
898 { | |
899 /* update the buffer size */ | |
900 size = (hnand->Config.PageSize) + ((hnand->Config.PageSize) * numPagesWritten); | |
901 | |
902 /* Send write page command sequence */ | |
903 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; | |
904 __DSB(); | |
905 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; | |
906 __DSB(); | |
907 | |
908 /* Cards with page size <= 512 bytes */ | |
909 if((hnand->Config.PageSize) <= 512U) | |
910 { | |
911 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
912 { | |
913 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
914 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
915 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
916 } | |
917 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
918 { | |
919 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
920 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
921 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
922 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
923 } | |
924 } | |
925 else /* (hnand->Config.PageSize) > 512 */ | |
926 { | |
927 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
928 { | |
929 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
930 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
931 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
932 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
933 } | |
934 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
935 { | |
936 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
937 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
938 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
939 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
940 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
941 } | |
942 } | |
943 | |
944 /* Write data to memory */ | |
945 for(; index < size; index++) | |
946 { | |
947 *(__IO uint16_t *)deviceaddress = *(uint16_t *)pBuffer++; | |
948 } | |
949 | |
950 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; | |
951 | |
952 /* Read status until NAND is ready */ | |
953 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
954 { | |
955 /* Get tick */ | |
956 tickstart = HAL_GetTick(); | |
957 | |
958 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
959 { | |
960 return HAL_TIMEOUT; | |
961 } | |
962 } | |
963 | |
964 /* Increment written pages number */ | |
965 numPagesWritten++; | |
966 | |
967 /* Decrement pages to write */ | |
968 NumPageToWrite--; | |
969 | |
970 /* Increment the NAND address */ | |
971 nandaddress = (uint32_t)(nandaddress + 1U); | |
972 } | |
973 | |
974 /* Update the NAND controller state */ | |
975 hnand->State = HAL_NAND_STATE_READY; | |
976 | |
977 /* Process unlocked */ | |
978 __HAL_UNLOCK(hnand); | |
979 | |
980 return HAL_OK; | |
981 } | |
982 | |
983 /** | |
984 * @brief Read Spare area(s) from NAND memory | |
985 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
986 * the configuration information for NAND module. | |
987 * @param pAddress pointer to NAND address structure | |
988 * @param pBuffer pointer to source buffer to write | |
989 * @param NumSpareAreaToRead Number of spare area to read | |
990 * @retval HAL status | |
991 */ | |
992 HAL_StatusTypeDef HAL_NAND_Read_SpareArea_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead) | |
993 { | |
994 __IO uint32_t index = 0U; | |
995 uint32_t tickstart = 0U; | |
996 uint32_t deviceaddress = 0U, size = 0U, numSpareAreaRead = 0U, nandaddress = 0U, columnaddress = 0U; | |
997 | |
998 /* Process Locked */ | |
999 __HAL_LOCK(hnand); | |
1000 | |
1001 /* Check the NAND controller state */ | |
1002 if(hnand->State == HAL_NAND_STATE_BUSY) | |
1003 { | |
1004 return HAL_BUSY; | |
1005 } | |
1006 | |
1007 /* Identify the device address */ | |
1008 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
1009 { | |
1010 deviceaddress = NAND_DEVICE1; | |
1011 } | |
1012 else | |
1013 { | |
1014 deviceaddress = NAND_DEVICE2; | |
1015 } | |
1016 | |
1017 /* Update the NAND controller state */ | |
1018 hnand->State = HAL_NAND_STATE_BUSY; | |
1019 | |
1020 /* NAND raw address calculation */ | |
1021 nandaddress = ARRAY_ADDRESS(pAddress, hnand); | |
1022 | |
1023 /* Column in page address */ | |
1024 columnaddress = COLUMN_ADDRESS(hnand); | |
1025 | |
1026 /* Spare area(s) read loop */ | |
1027 while((NumSpareAreaToRead != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) | |
1028 { | |
1029 /* update the buffer size */ | |
1030 size = (hnand->Config.SpareAreaSize) + ((hnand->Config.SpareAreaSize) * numSpareAreaRead); | |
1031 | |
1032 /* Cards with page size <= 512 bytes */ | |
1033 if((hnand->Config.PageSize) <= 512U) | |
1034 { | |
1035 /* Send read spare area command sequence */ | |
1036 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; | |
1037 | |
1038 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
1039 { | |
1040 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
1041 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1042 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1043 } | |
1044 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
1045 { | |
1046 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
1047 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1048 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1049 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
1050 } | |
1051 } | |
1052 else /* (hnand->Config.PageSize) > 512 */ | |
1053 { | |
1054 /* Send read spare area command sequence */ | |
1055 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; | |
1056 | |
1057 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
1058 { | |
1059 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); | |
1060 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); | |
1061 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1062 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1063 } | |
1064 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
1065 { | |
1066 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); | |
1067 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); | |
1068 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1069 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1070 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
1071 } | |
1072 } | |
1073 | |
1074 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; | |
1075 | |
1076 if(hnand->Config.ExtraCommandEnable == ENABLE) | |
1077 { | |
1078 /* Get tick */ | |
1079 tickstart = HAL_GetTick(); | |
1080 | |
1081 /* Read status until NAND is ready */ | |
1082 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
1083 { | |
1084 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
1085 { | |
1086 return HAL_TIMEOUT; | |
1087 } | |
1088 } | |
1089 | |
1090 /* Go back to read mode */ | |
1091 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); | |
1092 } | |
1093 | |
1094 /* Get Data into Buffer */ | |
1095 for(; index < size; index++) | |
1096 { | |
1097 *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress; | |
1098 } | |
1099 | |
1100 /* Increment read spare areas number */ | |
1101 numSpareAreaRead++; | |
1102 | |
1103 /* Decrement spare areas to read */ | |
1104 NumSpareAreaToRead--; | |
1105 | |
1106 /* Increment the NAND address */ | |
1107 nandaddress = (uint32_t)(nandaddress + 1U); | |
1108 } | |
1109 | |
1110 /* Update the NAND controller state */ | |
1111 hnand->State = HAL_NAND_STATE_READY; | |
1112 | |
1113 /* Process unlocked */ | |
1114 __HAL_UNLOCK(hnand); | |
1115 | |
1116 return HAL_OK; | |
1117 } | |
1118 | |
1119 /** | |
1120 * @brief Read Spare area(s) from NAND memory (16-bits addressing) | |
1121 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
1122 * the configuration information for NAND module. | |
1123 * @param pAddress pointer to NAND address structure | |
1124 * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned. | |
1125 * @param NumSpareAreaToRead Number of spare area to read | |
1126 * @retval HAL status | |
1127 */ | |
1128 HAL_StatusTypeDef HAL_NAND_Read_SpareArea_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumSpareAreaToRead) | |
1129 { | |
1130 __IO uint32_t index = 0U; | |
1131 uint32_t tickstart = 0U; | |
1132 uint32_t deviceaddress = 0U, size = 0U, numSpareAreaRead = 0U, nandaddress = 0U, columnaddress = 0U; | |
1133 | |
1134 /* Process Locked */ | |
1135 __HAL_LOCK(hnand); | |
1136 | |
1137 /* Check the NAND controller state */ | |
1138 if(hnand->State == HAL_NAND_STATE_BUSY) | |
1139 { | |
1140 return HAL_BUSY; | |
1141 } | |
1142 | |
1143 /* Identify the device address */ | |
1144 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
1145 { | |
1146 deviceaddress = NAND_DEVICE1; | |
1147 } | |
1148 else | |
1149 { | |
1150 deviceaddress = NAND_DEVICE2; | |
1151 } | |
1152 | |
1153 /* Update the NAND controller state */ | |
1154 hnand->State = HAL_NAND_STATE_BUSY; | |
1155 | |
1156 /* NAND raw address calculation */ | |
1157 nandaddress = ARRAY_ADDRESS(pAddress, hnand); | |
1158 | |
1159 /* Column in page address */ | |
1160 columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand) * 2U); | |
1161 | |
1162 /* Spare area(s) read loop */ | |
1163 while((NumSpareAreaToRead != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) | |
1164 { | |
1165 /* update the buffer size */ | |
1166 size = (hnand->Config.SpareAreaSize) + ((hnand->Config.SpareAreaSize) * numSpareAreaRead); | |
1167 | |
1168 /* Cards with page size <= 512 bytes */ | |
1169 if((hnand->Config.PageSize) <= 512U) | |
1170 { | |
1171 /* Send read spare area command sequence */ | |
1172 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; | |
1173 | |
1174 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
1175 { | |
1176 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
1177 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1178 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1179 } | |
1180 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
1181 { | |
1182 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
1183 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1184 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1185 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
1186 } | |
1187 } | |
1188 else /* (hnand->Config.PageSize) > 512 */ | |
1189 { | |
1190 /* Send read spare area command sequence */ | |
1191 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; | |
1192 | |
1193 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
1194 { | |
1195 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); | |
1196 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); | |
1197 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1198 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1199 } | |
1200 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
1201 { | |
1202 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); | |
1203 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); | |
1204 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1205 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1206 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
1207 } | |
1208 } | |
1209 | |
1210 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; | |
1211 | |
1212 if(hnand->Config.ExtraCommandEnable == ENABLE) | |
1213 { | |
1214 /* Get tick */ | |
1215 tickstart = HAL_GetTick(); | |
1216 | |
1217 /* Read status until NAND is ready */ | |
1218 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
1219 { | |
1220 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
1221 { | |
1222 return HAL_TIMEOUT; | |
1223 } | |
1224 } | |
1225 | |
1226 /* Go back to read mode */ | |
1227 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); | |
1228 } | |
1229 | |
1230 /* Get Data into Buffer */ | |
1231 for(; index < size; index++) | |
1232 { | |
1233 *(uint16_t *)pBuffer++ = *(uint16_t *)deviceaddress; | |
1234 } | |
1235 | |
1236 /* Increment read spare areas number */ | |
1237 numSpareAreaRead++; | |
1238 | |
1239 /* Decrement spare areas to read */ | |
1240 NumSpareAreaToRead--; | |
1241 | |
1242 /* Increment the NAND address */ | |
1243 nandaddress = (uint32_t)(nandaddress + 1U); | |
1244 } | |
1245 | |
1246 /* Update the NAND controller state */ | |
1247 hnand->State = HAL_NAND_STATE_READY; | |
1248 | |
1249 /* Process unlocked */ | |
1250 __HAL_UNLOCK(hnand); | |
1251 | |
1252 return HAL_OK; | |
1253 } | |
1254 | |
1255 /** | |
1256 * @brief Write Spare area(s) to NAND memory | |
1257 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
1258 * the configuration information for NAND module. | |
1259 * @param pAddress pointer to NAND address structure | |
1260 * @param pBuffer pointer to source buffer to write | |
1261 * @param NumSpareAreaTowrite number of spare areas to write to block | |
1262 * @retval HAL status | |
1263 */ | |
1264 HAL_StatusTypeDef HAL_NAND_Write_SpareArea_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite) | |
1265 { | |
1266 __IO uint32_t index = 0U; | |
1267 uint32_t tickstart = 0U; | |
1268 uint32_t deviceaddress = 0U, size = 0U, numSpareAreaWritten = 0U, nandaddress = 0U, columnaddress = 0U; | |
1269 | |
1270 /* Process Locked */ | |
1271 __HAL_LOCK(hnand); | |
1272 | |
1273 /* Check the NAND controller state */ | |
1274 if(hnand->State == HAL_NAND_STATE_BUSY) | |
1275 { | |
1276 return HAL_BUSY; | |
1277 } | |
1278 | |
1279 /* Identify the device address */ | |
1280 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
1281 { | |
1282 deviceaddress = NAND_DEVICE1; | |
1283 } | |
1284 else | |
1285 { | |
1286 deviceaddress = NAND_DEVICE2; | |
1287 } | |
1288 | |
1289 /* Update the FMC_NAND controller state */ | |
1290 hnand->State = HAL_NAND_STATE_BUSY; | |
1291 | |
1292 /* Page address calculation */ | |
1293 nandaddress = ARRAY_ADDRESS(pAddress, hnand); | |
1294 | |
1295 /* Column in page address */ | |
1296 columnaddress = COLUMN_ADDRESS(hnand); | |
1297 | |
1298 /* Spare area(s) write loop */ | |
1299 while((NumSpareAreaTowrite != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) | |
1300 { | |
1301 /* update the buffer size */ | |
1302 size = (hnand->Config.SpareAreaSize) + ((hnand->Config.SpareAreaSize) * numSpareAreaWritten); | |
1303 | |
1304 /* Cards with page size <= 512 bytes */ | |
1305 if((hnand->Config.PageSize) <= 512U) | |
1306 { | |
1307 /* Send write Spare area command sequence */ | |
1308 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; | |
1309 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; | |
1310 | |
1311 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
1312 { | |
1313 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
1314 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1315 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1316 } | |
1317 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
1318 { | |
1319 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
1320 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1321 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1322 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
1323 } | |
1324 } | |
1325 else /* (hnand->Config.PageSize) > 512 */ | |
1326 { | |
1327 /* Send write Spare area command sequence */ | |
1328 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; | |
1329 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; | |
1330 | |
1331 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
1332 { | |
1333 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); | |
1334 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); | |
1335 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1336 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1337 } | |
1338 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
1339 { | |
1340 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); | |
1341 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); | |
1342 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1343 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1344 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
1345 } | |
1346 } | |
1347 | |
1348 /* Write data to memory */ | |
1349 for(; index < size; index++) | |
1350 { | |
1351 *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++; | |
1352 } | |
1353 | |
1354 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; | |
1355 | |
1356 /* Get tick */ | |
1357 tickstart = HAL_GetTick(); | |
1358 | |
1359 /* Read status until NAND is ready */ | |
1360 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
1361 { | |
1362 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
1363 { | |
1364 return HAL_TIMEOUT; | |
1365 } | |
1366 } | |
1367 | |
1368 /* Increment written spare areas number */ | |
1369 numSpareAreaWritten++; | |
1370 | |
1371 /* Decrement spare areas to write */ | |
1372 NumSpareAreaTowrite--; | |
1373 | |
1374 /* Increment the NAND address */ | |
1375 nandaddress = (uint32_t)(nandaddress + 1U); | |
1376 } | |
1377 | |
1378 /* Update the NAND controller state */ | |
1379 hnand->State = HAL_NAND_STATE_READY; | |
1380 | |
1381 /* Process unlocked */ | |
1382 __HAL_UNLOCK(hnand); | |
1383 | |
1384 return HAL_OK; | |
1385 } | |
1386 | |
1387 /** | |
1388 * @brief Write Spare area(s) to NAND memory (16-bits addressing) | |
1389 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
1390 * the configuration information for NAND module. | |
1391 * @param pAddress pointer to NAND address structure | |
1392 * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned. | |
1393 * @param NumSpareAreaTowrite number of spare areas to write to block | |
1394 * @retval HAL status | |
1395 */ | |
1396 HAL_StatusTypeDef HAL_NAND_Write_SpareArea_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumSpareAreaTowrite) | |
1397 { | |
1398 __IO uint32_t index = 0U; | |
1399 uint32_t tickstart = 0U; | |
1400 uint32_t deviceaddress = 0U, size = 0U, numSpareAreaWritten = 0U, nandaddress = 0U, columnaddress = 0U; | |
1401 | |
1402 /* Process Locked */ | |
1403 __HAL_LOCK(hnand); | |
1404 | |
1405 /* Check the NAND controller state */ | |
1406 if(hnand->State == HAL_NAND_STATE_BUSY) | |
1407 { | |
1408 return HAL_BUSY; | |
1409 } | |
1410 | |
1411 /* Identify the device address */ | |
1412 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
1413 { | |
1414 deviceaddress = NAND_DEVICE1; | |
1415 } | |
1416 else | |
1417 { | |
1418 deviceaddress = NAND_DEVICE2; | |
1419 } | |
1420 | |
1421 /* Update the FMC_NAND controller state */ | |
1422 hnand->State = HAL_NAND_STATE_BUSY; | |
1423 | |
1424 /* NAND raw address calculation */ | |
1425 nandaddress = ARRAY_ADDRESS(pAddress, hnand); | |
1426 | |
1427 /* Column in page address */ | |
1428 columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand) * 2U); | |
1429 | |
1430 /* Spare area(s) write loop */ | |
1431 while((NumSpareAreaTowrite != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) | |
1432 { | |
1433 /* update the buffer size */ | |
1434 size = (hnand->Config.SpareAreaSize) + ((hnand->Config.SpareAreaSize) * numSpareAreaWritten); | |
1435 | |
1436 /* Cards with page size <= 512 bytes */ | |
1437 if((hnand->Config.PageSize) <= 512U) | |
1438 { | |
1439 /* Send write Spare area command sequence */ | |
1440 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; | |
1441 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; | |
1442 | |
1443 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
1444 { | |
1445 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
1446 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1447 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1448 } | |
1449 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
1450 { | |
1451 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; | |
1452 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1453 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1454 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
1455 } | |
1456 } | |
1457 else /* (hnand->Config.PageSize) > 512 */ | |
1458 { | |
1459 /* Send write Spare area command sequence */ | |
1460 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; | |
1461 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; | |
1462 | |
1463 if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U) | |
1464 { | |
1465 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); | |
1466 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); | |
1467 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1468 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1469 } | |
1470 else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ | |
1471 { | |
1472 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); | |
1473 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); | |
1474 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); | |
1475 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); | |
1476 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); | |
1477 } | |
1478 } | |
1479 | |
1480 /* Write data to memory */ | |
1481 for(; index < size; index++) | |
1482 { | |
1483 *(__IO uint16_t *)deviceaddress = *(uint16_t *)pBuffer++; | |
1484 } | |
1485 | |
1486 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; | |
1487 | |
1488 /* Read status until NAND is ready */ | |
1489 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
1490 { | |
1491 /* Get tick */ | |
1492 tickstart = HAL_GetTick(); | |
1493 | |
1494 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
1495 { | |
1496 return HAL_TIMEOUT; | |
1497 } | |
1498 } | |
1499 | |
1500 /* Increment written spare areas number */ | |
1501 numSpareAreaWritten++; | |
1502 | |
1503 /* Decrement spare areas to write */ | |
1504 NumSpareAreaTowrite--; | |
1505 | |
1506 /* Increment the NAND address */ | |
1507 nandaddress = (uint32_t)(nandaddress + 1U); | |
1508 } | |
1509 | |
1510 /* Update the NAND controller state */ | |
1511 hnand->State = HAL_NAND_STATE_READY; | |
1512 | |
1513 /* Process unlocked */ | |
1514 __HAL_UNLOCK(hnand); | |
1515 | |
1516 return HAL_OK; | |
1517 } | |
1518 | |
1519 /** | |
1520 * @brief NAND memory Block erase | |
1521 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
1522 * the configuration information for NAND module. | |
1523 * @param pAddress pointer to NAND address structure | |
1524 * @retval HAL status | |
1525 */ | |
1526 HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) | |
1527 { | |
1528 uint32_t deviceaddress = 0U; | |
1529 uint32_t tickstart = 0U; | |
1530 | |
1531 /* Process Locked */ | |
1532 __HAL_LOCK(hnand); | |
1533 | |
1534 /* Check the NAND controller state */ | |
1535 if(hnand->State == HAL_NAND_STATE_BUSY) | |
1536 { | |
1537 return HAL_BUSY; | |
1538 } | |
1539 | |
1540 /* Identify the device address */ | |
1541 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
1542 { | |
1543 deviceaddress = NAND_DEVICE1; | |
1544 } | |
1545 else | |
1546 { | |
1547 deviceaddress = NAND_DEVICE2; | |
1548 } | |
1549 | |
1550 /* Update the NAND controller state */ | |
1551 hnand->State = HAL_NAND_STATE_BUSY; | |
1552 | |
1553 /* Send Erase block command sequence */ | |
1554 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0; | |
1555 | |
1556 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); | |
1557 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); | |
1558 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); | |
1559 | |
1560 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1; | |
1561 | |
1562 /* Update the NAND controller state */ | |
1563 hnand->State = HAL_NAND_STATE_READY; | |
1564 | |
1565 /* Get tick */ | |
1566 tickstart = HAL_GetTick(); | |
1567 | |
1568 /* Read status until NAND is ready */ | |
1569 while(HAL_NAND_Read_Status(hnand) != NAND_READY) | |
1570 { | |
1571 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) | |
1572 { | |
1573 /* Process unlocked */ | |
1574 __HAL_UNLOCK(hnand); | |
1575 | |
1576 return HAL_TIMEOUT; | |
1577 } | |
1578 } | |
1579 | |
1580 /* Process unlocked */ | |
1581 __HAL_UNLOCK(hnand); | |
1582 | |
1583 return HAL_OK; | |
1584 } | |
1585 | |
1586 /** | |
1587 * @brief NAND memory read status | |
1588 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
1589 * the configuration information for NAND module. | |
1590 * @retval NAND status | |
1591 */ | |
1592 uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand) | |
1593 { | |
1594 uint32_t data = 0U; | |
1595 uint32_t deviceaddress = 0U; | |
1596 | |
1597 /* Identify the device address */ | |
1598 if(hnand->Init.NandBank == FMC_NAND_BANK2) | |
1599 { | |
1600 deviceaddress = NAND_DEVICE1; | |
1601 } | |
1602 else | |
1603 { | |
1604 deviceaddress = NAND_DEVICE2; | |
1605 } | |
1606 | |
1607 /* Send Read status operation command */ | |
1608 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS; | |
1609 | |
1610 /* Read status register data */ | |
1611 data = *(__IO uint8_t *)deviceaddress; | |
1612 | |
1613 /* Return the status */ | |
1614 if((data & NAND_ERROR) == NAND_ERROR) | |
1615 { | |
1616 return NAND_ERROR; | |
1617 } | |
1618 else if((data & NAND_READY) == NAND_READY) | |
1619 { | |
1620 return NAND_READY; | |
1621 } | |
1622 | |
1623 return NAND_BUSY; | |
1624 } | |
1625 | |
1626 /** | |
1627 * @brief Increment the NAND memory address | |
1628 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
1629 * the configuration information for NAND module. | |
1630 * @param pAddress pointer to NAND address structure | |
1631 * @retval The new status of the increment address operation. It can be: | |
1632 * - NAND_VALID_ADDRESS: When the new address is valid address | |
1633 * - NAND_INVALID_ADDRESS: When the new address is invalid address | |
1634 */ | |
1635 uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) | |
1636 { | |
1637 uint32_t status = NAND_VALID_ADDRESS; | |
1638 | |
1639 /* Increment page address */ | |
1640 pAddress->Page++; | |
1641 | |
1642 /* Check NAND address is valid */ | |
1643 if(pAddress->Page == hnand->Config.BlockSize) | |
1644 { | |
1645 pAddress->Page = 0U; | |
1646 pAddress->Block++; | |
1647 | |
1648 if(pAddress->Block == hnand->Config.PlaneSize) | |
1649 { | |
1650 pAddress->Block = 0U; | |
1651 pAddress->Plane++; | |
1652 | |
1653 if(pAddress->Plane == (hnand->Config.PlaneNbr)) | |
1654 { | |
1655 status = NAND_INVALID_ADDRESS; | |
1656 } | |
1657 } | |
1658 } | |
1659 | |
1660 return (status); | |
1661 } | |
1662 /** | |
1663 * @} | |
1664 */ | |
1665 | |
1666 /** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions | |
1667 * @brief management functions | |
1668 * | |
1669 @verbatim | |
1670 ============================================================================== | |
1671 ##### NAND Control functions ##### | |
1672 ============================================================================== | |
1673 [..] | |
1674 This subsection provides a set of functions allowing to control dynamically | |
1675 the NAND interface. | |
1676 | |
1677 @endverbatim | |
1678 * @{ | |
1679 */ | |
1680 | |
1681 | |
1682 /** | |
1683 * @brief Enables dynamically NAND ECC feature. | |
1684 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
1685 * the configuration information for NAND module. | |
1686 * @retval HAL status | |
1687 */ | |
1688 HAL_StatusTypeDef HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand) | |
1689 { | |
1690 /* Check the NAND controller state */ | |
1691 if(hnand->State == HAL_NAND_STATE_BUSY) | |
1692 { | |
1693 return HAL_BUSY; | |
1694 } | |
1695 | |
1696 /* Update the NAND state */ | |
1697 hnand->State = HAL_NAND_STATE_BUSY; | |
1698 | |
1699 /* Enable ECC feature */ | |
1700 FMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank); | |
1701 | |
1702 /* Update the NAND state */ | |
1703 hnand->State = HAL_NAND_STATE_READY; | |
1704 | |
1705 return HAL_OK; | |
1706 } | |
1707 | |
1708 /** | |
1709 * @brief Disables dynamically FMC_NAND ECC feature. | |
1710 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
1711 * the configuration information for NAND module. | |
1712 * @retval HAL status | |
1713 */ | |
1714 HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand) | |
1715 { | |
1716 /* Check the NAND controller state */ | |
1717 if(hnand->State == HAL_NAND_STATE_BUSY) | |
1718 { | |
1719 return HAL_BUSY; | |
1720 } | |
1721 | |
1722 /* Update the NAND state */ | |
1723 hnand->State = HAL_NAND_STATE_BUSY; | |
1724 | |
1725 /* Disable ECC feature */ | |
1726 FMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank); | |
1727 | |
1728 /* Update the NAND state */ | |
1729 hnand->State = HAL_NAND_STATE_READY; | |
1730 | |
1731 return HAL_OK; | |
1732 } | |
1733 | |
1734 /** | |
1735 * @brief Disables dynamically NAND ECC feature. | |
1736 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
1737 * the configuration information for NAND module. | |
1738 * @param ECCval pointer to ECC value | |
1739 * @param Timeout maximum timeout to wait | |
1740 * @retval HAL status | |
1741 */ | |
1742 HAL_StatusTypeDef HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout) | |
1743 { | |
1744 HAL_StatusTypeDef status = HAL_OK; | |
1745 | |
1746 /* Check the NAND controller state */ | |
1747 if(hnand->State == HAL_NAND_STATE_BUSY) | |
1748 { | |
1749 return HAL_BUSY; | |
1750 } | |
1751 | |
1752 /* Update the NAND state */ | |
1753 hnand->State = HAL_NAND_STATE_BUSY; | |
1754 | |
1755 /* Get NAND ECC value */ | |
1756 status = FMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout); | |
1757 | |
1758 /* Update the NAND state */ | |
1759 hnand->State = HAL_NAND_STATE_READY; | |
1760 | |
1761 return status; | |
1762 } | |
1763 | |
1764 /** | |
1765 * @} | |
1766 */ | |
1767 | |
1768 | |
1769 /** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions | |
1770 * @brief Peripheral State functions | |
1771 * | |
1772 @verbatim | |
1773 ============================================================================== | |
1774 ##### NAND State functions ##### | |
1775 ============================================================================== | |
1776 [..] | |
1777 This subsection permits to get in run-time the status of the NAND controller | |
1778 and the data flow. | |
1779 | |
1780 @endverbatim | |
1781 * @{ | |
1782 */ | |
1783 | |
1784 /** | |
1785 * @brief return the NAND state | |
1786 * @param hnand pointer to a NAND_HandleTypeDef structure that contains | |
1787 * the configuration information for NAND module. | |
1788 * @retval HAL state | |
1789 */ | |
1790 HAL_NAND_StateTypeDef HAL_NAND_GetState(NAND_HandleTypeDef *hnand) | |
1791 { | |
1792 return hnand->State; | |
1793 } | |
1794 | |
1795 /** | |
1796 * @} | |
1797 */ | |
1798 | |
1799 /** | |
1800 * @} | |
1801 */ | |
1802 | |
1803 /** | |
1804 * @} | |
1805 */ | |
1806 | |
1807 #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx ||\ | |
1808 STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx ||\ | |
1809 STM32F446xx || STM32F469xx || STM32F479xx */ | |
1810 #endif /* HAL_NAND_MODULE_ENABLED */ | |
1811 | |
1812 /** | |
1813 * @} | |
1814 */ | |
1815 | |
1816 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |