Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | mjames | 1 | /** |
2 | ****************************************************************************** |
||
3 | * @file stm32f1xx_hal_nand.c |
||
4 | * @author MCD Application Team |
||
5 | * @brief NAND HAL module driver. |
||
9 | mjames | 6 | * This file provides a generic firmware to drive NAND memories mounted |
2 | mjames | 7 | * as external device. |
9 | mjames | 8 | * |
2 | mjames | 9 | @verbatim |
10 | ============================================================================== |
||
11 | ##### How to use this driver ##### |
||
9 | mjames | 12 | ============================================================================== |
2 | mjames | 13 | [..] |
9 | mjames | 14 | This driver is a generic layered driver which contains a set of APIs used to |
15 | control NAND flash memories. It uses the FSMC layer functions to interface |
||
2 | mjames | 16 | with NAND devices. This driver is used as follows: |
9 | mjames | 17 | |
18 | (+) NAND flash memory configuration sequence using the function HAL_NAND_Init() |
||
2 | mjames | 19 | with control and timing parameters for both common and attribute spaces. |
9 | mjames | 20 | |
2 | mjames | 21 | (+) Read NAND flash memory maker and device IDs using the function |
9 | mjames | 22 | HAL_NAND_Read_ID(). The read information is stored in the NAND_ID_TypeDef |
23 | structure declared by the function caller. |
||
24 | |||
2 | mjames | 25 | (+) Access NAND flash memory by read/write operations using the functions |
9 | mjames | 26 | HAL_NAND_Read_Page_8b()/HAL_NAND_Read_SpareArea_8b(), |
2 | mjames | 27 | HAL_NAND_Write_Page_8b()/HAL_NAND_Write_SpareArea_8b(), |
9 | mjames | 28 | HAL_NAND_Read_Page_16b()/HAL_NAND_Read_SpareArea_16b(), |
2 | mjames | 29 | HAL_NAND_Write_Page_16b()/HAL_NAND_Write_SpareArea_16b() |
9 | mjames | 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 NAND_DeviceConfigTypeDef |
||
2 | mjames | 32 | structure. The read/write address information is contained by the Nand_Address_Typedef |
33 | structure passed as parameter. |
||
9 | mjames | 34 | |
2 | mjames | 35 | (+) Perform NAND flash Reset chip operation using the function HAL_NAND_Reset(). |
9 | mjames | 36 | |
2 | mjames | 37 | (+) Perform NAND flash erase block operation using the function HAL_NAND_Erase_Block(). |
9 | mjames | 38 | The erase block address information is contained in the Nand_Address_Typedef |
2 | mjames | 39 | structure passed as parameter. |
9 | mjames | 40 | |
2 | mjames | 41 | (+) Read the NAND flash status operation using the function HAL_NAND_Read_Status(). |
9 | mjames | 42 | |
2 | mjames | 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 |
||
9 | mjames | 45 | feature or the function HAL_NAND_GetECC() to get the ECC correction code. |
46 | |||
2 | mjames | 47 | (+) You can monitor the NAND device HAL state by calling the function |
9 | mjames | 48 | HAL_NAND_GetState() |
2 | mjames | 49 | |
50 | [..] |
||
51 | (@) This driver is a set of generic APIs which handle standard NAND flash operations. |
||
9 | mjames | 52 | If a NAND flash device contains different operations and/or implementations, |
2 | mjames | 53 | it should be implemented separately. |
54 | |||
9 | mjames | 55 | *** Callback registration *** |
56 | ============================================= |
||
57 | [..] |
||
58 | The compilation define USE_HAL_NAND_REGISTER_CALLBACKS when set to 1 |
||
59 | allows the user to configure dynamically the driver callbacks. |
||
60 | |||
61 | Use Functions @ref HAL_NAND_RegisterCallback() to register a user callback, |
||
62 | it allows to register following callbacks: |
||
63 | (+) MspInitCallback : NAND MspInit. |
||
64 | (+) MspDeInitCallback : NAND MspDeInit. |
||
65 | This function takes as parameters the HAL peripheral handle, the Callback ID |
||
66 | and a pointer to the user callback function. |
||
67 | |||
68 | Use function @ref HAL_NAND_UnRegisterCallback() to reset a callback to the default |
||
69 | weak (surcharged) function. It allows to reset following callbacks: |
||
70 | (+) MspInitCallback : NAND MspInit. |
||
71 | (+) MspDeInitCallback : NAND MspDeInit. |
||
72 | This function) takes as parameters the HAL peripheral handle and the Callback ID. |
||
73 | |||
74 | By default, after the @ref HAL_NAND_Init and if the state is HAL_NAND_STATE_RESET |
||
75 | all callbacks are reset to the corresponding legacy weak (surcharged) functions. |
||
76 | Exception done for MspInit and MspDeInit callbacks that are respectively |
||
77 | reset to the legacy weak (surcharged) functions in the @ref HAL_NAND_Init |
||
78 | and @ref HAL_NAND_DeInit only when these callbacks are null (not registered beforehand). |
||
79 | If not, MspInit or MspDeInit are not null, the @ref HAL_NAND_Init and @ref HAL_NAND_DeInit |
||
80 | keep and use the user MspInit/MspDeInit callbacks (registered beforehand) |
||
81 | |||
82 | Callbacks can be registered/unregistered in READY state only. |
||
83 | Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered |
||
84 | in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used |
||
85 | during the Init/DeInit. |
||
86 | In that case first register the MspInit/MspDeInit user callbacks |
||
87 | using @ref HAL_NAND_RegisterCallback before calling @ref HAL_NAND_DeInit |
||
88 | or @ref HAL_NAND_Init function. |
||
89 | |||
90 | When The compilation define USE_HAL_NAND_REGISTER_CALLBACKS is set to 0 or |
||
91 | not defined, the callback registering feature is not available |
||
92 | and weak (surcharged) callbacks are used. |
||
93 | |||
2 | mjames | 94 | @endverbatim |
95 | ****************************************************************************** |
||
96 | * @attention |
||
97 | * |
||
9 | mjames | 98 | * <h2><center>© Copyright (c) 2016 STMicroelectronics. |
99 | * All rights reserved.</center></h2> |
||
2 | mjames | 100 | * |
9 | mjames | 101 | * This software component is licensed by ST under BSD 3-Clause license, |
102 | * the "License"; You may not use this file except in compliance with the |
||
103 | * License. You may obtain a copy of the License at: |
||
104 | * opensource.org/licenses/BSD-3-Clause |
||
2 | mjames | 105 | * |
106 | ****************************************************************************** |
||
9 | mjames | 107 | */ |
2 | mjames | 108 | |
109 | /* Includes ------------------------------------------------------------------*/ |
||
110 | #include "stm32f1xx_hal.h" |
||
111 | |||
9 | mjames | 112 | #if defined(FSMC_BANK3) |
113 | |||
2 | mjames | 114 | /** @addtogroup STM32F1xx_HAL_Driver |
115 | * @{ |
||
116 | */ |
||
117 | |||
118 | #ifdef HAL_NAND_MODULE_ENABLED |
||
119 | |||
120 | /** @defgroup NAND NAND |
||
121 | * @brief NAND HAL module driver |
||
122 | * @{ |
||
123 | */ |
||
124 | |||
125 | /* Private typedef -----------------------------------------------------------*/ |
||
9 | mjames | 126 | /* Private Constants ------------------------------------------------------------*/ |
127 | /* Private macro -------------------------------------------------------------*/ |
||
2 | mjames | 128 | /* Private variables ---------------------------------------------------------*/ |
129 | /* Private function prototypes -----------------------------------------------*/ |
||
9 | mjames | 130 | /* Exported functions ---------------------------------------------------------*/ |
131 | |||
2 | mjames | 132 | /** @defgroup NAND_Exported_Functions NAND Exported Functions |
133 | * @{ |
||
134 | */ |
||
9 | mjames | 135 | |
136 | /** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions |
||
137 | * @brief Initialization and Configuration functions |
||
2 | mjames | 138 | * |
9 | mjames | 139 | @verbatim |
2 | mjames | 140 | ============================================================================== |
141 | ##### NAND Initialization and de-initialization functions ##### |
||
142 | ============================================================================== |
||
9 | mjames | 143 | [..] |
2 | mjames | 144 | This section provides functions allowing to initialize/de-initialize |
145 | the NAND memory |
||
9 | mjames | 146 | |
2 | mjames | 147 | @endverbatim |
148 | * @{ |
||
149 | */ |
||
9 | mjames | 150 | |
2 | mjames | 151 | /** |
152 | * @brief Perform NAND memory Initialization sequence |
||
9 | mjames | 153 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 154 | * the configuration information for NAND module. |
9 | mjames | 155 | * @param ComSpace_Timing pointer to Common space timing structure |
156 | * @param AttSpace_Timing pointer to Attribute space timing structure |
||
2 | mjames | 157 | * @retval HAL status |
158 | */ |
||
9 | mjames | 159 | HAL_StatusTypeDef HAL_NAND_Init(NAND_HandleTypeDef *hnand, FSMC_NAND_PCC_TimingTypeDef *ComSpace_Timing, |
160 | FSMC_NAND_PCC_TimingTypeDef *AttSpace_Timing) |
||
2 | mjames | 161 | { |
162 | /* Check the NAND handle state */ |
||
9 | mjames | 163 | if (hnand == NULL) |
2 | mjames | 164 | { |
9 | mjames | 165 | return HAL_ERROR; |
2 | mjames | 166 | } |
167 | |||
9 | mjames | 168 | if (hnand->State == HAL_NAND_STATE_RESET) |
2 | mjames | 169 | { |
170 | /* Allocate lock resource and initialize it */ |
||
171 | hnand->Lock = HAL_UNLOCKED; |
||
9 | mjames | 172 | |
173 | #if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) |
||
174 | if (hnand->MspInitCallback == NULL) |
||
175 | { |
||
176 | hnand->MspInitCallback = HAL_NAND_MspInit; |
||
177 | } |
||
178 | hnand->ItCallback = HAL_NAND_ITCallback; |
||
179 | |||
180 | /* Init the low level hardware */ |
||
181 | hnand->MspInitCallback(hnand); |
||
182 | #else |
||
2 | mjames | 183 | /* Initialize the low level hardware (MSP) */ |
184 | HAL_NAND_MspInit(hnand); |
||
9 | mjames | 185 | #endif |
186 | } |
||
2 | mjames | 187 | |
188 | /* Initialize NAND control Interface */ |
||
9 | mjames | 189 | (void)FSMC_NAND_Init(hnand->Instance, &(hnand->Init)); |
190 | |||
191 | /* Initialize NAND common space timing Interface */ |
||
192 | (void)FSMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank); |
||
193 | |||
194 | /* Initialize NAND attribute space timing Interface */ |
||
195 | (void)FSMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank); |
||
196 | |||
2 | mjames | 197 | /* Enable the NAND device */ |
198 | __FSMC_NAND_ENABLE(hnand->Instance, hnand->Init.NandBank); |
||
9 | mjames | 199 | |
2 | mjames | 200 | /* Update the NAND controller state */ |
201 | hnand->State = HAL_NAND_STATE_READY; |
||
202 | |||
203 | return HAL_OK; |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * @brief Perform NAND memory De-Initialization sequence |
||
9 | mjames | 208 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 209 | * the configuration information for NAND module. |
210 | * @retval HAL status |
||
211 | */ |
||
9 | mjames | 212 | HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand) |
2 | mjames | 213 | { |
9 | mjames | 214 | #if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) |
215 | if (hnand->MspDeInitCallback == NULL) |
||
216 | { |
||
217 | hnand->MspDeInitCallback = HAL_NAND_MspDeInit; |
||
218 | } |
||
219 | |||
220 | /* DeInit the low level hardware */ |
||
221 | hnand->MspDeInitCallback(hnand); |
||
222 | #else |
||
2 | mjames | 223 | /* Initialize the low level hardware (MSP) */ |
224 | HAL_NAND_MspDeInit(hnand); |
||
9 | mjames | 225 | #endif |
2 | mjames | 226 | |
227 | /* Configure the NAND registers with their reset values */ |
||
9 | mjames | 228 | (void)FSMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank); |
2 | mjames | 229 | |
230 | /* Reset the NAND controller state */ |
||
231 | hnand->State = HAL_NAND_STATE_RESET; |
||
232 | |||
233 | /* Release Lock */ |
||
234 | __HAL_UNLOCK(hnand); |
||
235 | |||
236 | return HAL_OK; |
||
237 | } |
||
238 | |||
239 | /** |
||
240 | * @brief NAND MSP Init |
||
9 | mjames | 241 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 242 | * the configuration information for NAND module. |
243 | * @retval None |
||
244 | */ |
||
245 | __weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand) |
||
246 | { |
||
247 | /* Prevent unused argument(s) compilation warning */ |
||
248 | UNUSED(hnand); |
||
9 | mjames | 249 | |
2 | mjames | 250 | /* NOTE : This function Should not be modified, when the callback is needed, |
251 | the HAL_NAND_MspInit could be implemented in the user file |
||
9 | mjames | 252 | */ |
2 | mjames | 253 | } |
254 | |||
255 | /** |
||
256 | * @brief NAND MSP DeInit |
||
9 | mjames | 257 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 258 | * the configuration information for NAND module. |
259 | * @retval None |
||
260 | */ |
||
261 | __weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand) |
||
262 | { |
||
263 | /* Prevent unused argument(s) compilation warning */ |
||
264 | UNUSED(hnand); |
||
9 | mjames | 265 | |
2 | mjames | 266 | /* NOTE : This function Should not be modified, when the callback is needed, |
267 | the HAL_NAND_MspDeInit could be implemented in the user file |
||
9 | mjames | 268 | */ |
2 | mjames | 269 | } |
270 | |||
271 | |||
272 | /** |
||
273 | * @brief This function handles NAND device interrupt request. |
||
9 | mjames | 274 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 275 | * the configuration information for NAND module. |
276 | * @retval HAL status |
||
9 | mjames | 277 | */ |
2 | mjames | 278 | void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand) |
279 | { |
||
280 | /* Check NAND interrupt Rising edge flag */ |
||
9 | mjames | 281 | if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_RISING_EDGE)) |
2 | mjames | 282 | { |
283 | /* NAND interrupt callback*/ |
||
9 | mjames | 284 | #if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) |
285 | hnand->ItCallback(hnand); |
||
286 | #else |
||
2 | mjames | 287 | HAL_NAND_ITCallback(hnand); |
9 | mjames | 288 | #endif |
289 | |||
2 | mjames | 290 | /* Clear NAND interrupt Rising edge pending bit */ |
291 | __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_RISING_EDGE); |
||
292 | } |
||
9 | mjames | 293 | |
2 | mjames | 294 | /* Check NAND interrupt Level flag */ |
9 | mjames | 295 | if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_LEVEL)) |
2 | mjames | 296 | { |
297 | /* NAND interrupt callback*/ |
||
9 | mjames | 298 | #if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) |
299 | hnand->ItCallback(hnand); |
||
300 | #else |
||
2 | mjames | 301 | HAL_NAND_ITCallback(hnand); |
9 | mjames | 302 | #endif |
303 | |||
2 | mjames | 304 | /* Clear NAND interrupt Level pending bit */ |
305 | __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_LEVEL); |
||
306 | } |
||
307 | |||
308 | /* Check NAND interrupt Falling edge flag */ |
||
9 | mjames | 309 | if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FALLING_EDGE)) |
2 | mjames | 310 | { |
311 | /* NAND interrupt callback*/ |
||
9 | mjames | 312 | #if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) |
313 | hnand->ItCallback(hnand); |
||
314 | #else |
||
2 | mjames | 315 | HAL_NAND_ITCallback(hnand); |
9 | mjames | 316 | #endif |
317 | |||
2 | mjames | 318 | /* Clear NAND interrupt Falling edge pending bit */ |
319 | __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FALLING_EDGE); |
||
320 | } |
||
9 | mjames | 321 | |
2 | mjames | 322 | /* Check NAND interrupt FIFO empty flag */ |
9 | mjames | 323 | if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FEMPT)) |
2 | mjames | 324 | { |
325 | /* NAND interrupt callback*/ |
||
9 | mjames | 326 | #if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) |
327 | hnand->ItCallback(hnand); |
||
328 | #else |
||
2 | mjames | 329 | HAL_NAND_ITCallback(hnand); |
9 | mjames | 330 | #endif |
331 | |||
2 | mjames | 332 | /* Clear NAND interrupt FIFO empty pending bit */ |
333 | __FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FEMPT); |
||
334 | } |
||
9 | mjames | 335 | |
2 | mjames | 336 | } |
337 | |||
338 | /** |
||
339 | * @brief NAND interrupt feature callback |
||
9 | mjames | 340 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 341 | * the configuration information for NAND module. |
342 | * @retval None |
||
343 | */ |
||
344 | __weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand) |
||
345 | { |
||
346 | /* Prevent unused argument(s) compilation warning */ |
||
347 | UNUSED(hnand); |
||
9 | mjames | 348 | |
2 | mjames | 349 | /* NOTE : This function Should not be modified, when the callback is needed, |
350 | the HAL_NAND_ITCallback could be implemented in the user file |
||
351 | */ |
||
352 | } |
||
9 | mjames | 353 | |
2 | mjames | 354 | /** |
355 | * @} |
||
356 | */ |
||
9 | mjames | 357 | |
358 | /** @defgroup NAND_Exported_Functions_Group2 Input and Output functions |
||
359 | * @brief Input Output and memory control functions |
||
2 | mjames | 360 | * |
9 | mjames | 361 | @verbatim |
2 | mjames | 362 | ============================================================================== |
363 | ##### NAND Input and Output functions ##### |
||
364 | ============================================================================== |
||
9 | mjames | 365 | [..] |
366 | This section provides functions allowing to use and control the NAND |
||
2 | mjames | 367 | memory |
9 | mjames | 368 | |
2 | mjames | 369 | @endverbatim |
370 | * @{ |
||
371 | */ |
||
372 | |||
373 | /** |
||
374 | * @brief Read the NAND memory electronic signature |
||
9 | mjames | 375 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 376 | * the configuration information for NAND module. |
9 | mjames | 377 | * @param pNAND_ID NAND ID structure |
2 | mjames | 378 | * @retval HAL status |
379 | */ |
||
380 | HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID) |
||
381 | { |
||
9 | mjames | 382 | __IO uint32_t data = 0; |
383 | __IO uint32_t data1 = 0; |
||
384 | uint32_t deviceaddress; |
||
2 | mjames | 385 | |
386 | /* Check the NAND controller state */ |
||
9 | mjames | 387 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 388 | { |
9 | mjames | 389 | return HAL_BUSY; |
2 | mjames | 390 | } |
9 | mjames | 391 | else if (hnand->State == HAL_NAND_STATE_READY) |
2 | mjames | 392 | { |
9 | mjames | 393 | /* Process Locked */ |
394 | __HAL_LOCK(hnand); |
||
2 | mjames | 395 | |
9 | mjames | 396 | /* Update the NAND controller state */ |
397 | hnand->State = HAL_NAND_STATE_BUSY; |
||
2 | mjames | 398 | |
9 | mjames | 399 | /* Identify the device address */ |
400 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
401 | { |
||
402 | deviceaddress = NAND_DEVICE1; |
||
403 | } |
||
404 | else |
||
405 | { |
||
406 | deviceaddress = NAND_DEVICE2; |
||
407 | } |
||
408 | |||
409 | /* Send Read ID command sequence */ |
||
410 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_READID; |
||
411 | __DSB(); |
||
412 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; |
||
413 | __DSB(); |
||
414 | |||
415 | /* Read the electronic signature from NAND flash */ |
||
416 | if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8) |
||
417 | { |
||
418 | data = *(__IO uint32_t *)deviceaddress; |
||
419 | |||
420 | /* Return the data read */ |
||
421 | pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data); |
||
422 | pNAND_ID->Device_Id = ADDR_2ND_CYCLE(data); |
||
423 | pNAND_ID->Third_Id = ADDR_3RD_CYCLE(data); |
||
424 | pNAND_ID->Fourth_Id = ADDR_4TH_CYCLE(data); |
||
425 | } |
||
426 | else |
||
427 | { |
||
428 | data = *(__IO uint32_t *)deviceaddress; |
||
429 | data1 = *((__IO uint32_t *)deviceaddress + 4); |
||
430 | |||
431 | /* Return the data read */ |
||
432 | pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data); |
||
433 | pNAND_ID->Device_Id = ADDR_3RD_CYCLE(data); |
||
434 | pNAND_ID->Third_Id = ADDR_1ST_CYCLE(data1); |
||
435 | pNAND_ID->Fourth_Id = ADDR_3RD_CYCLE(data1); |
||
436 | } |
||
437 | |||
438 | /* Update the NAND controller state */ |
||
439 | hnand->State = HAL_NAND_STATE_READY; |
||
440 | |||
441 | /* Process unlocked */ |
||
442 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 443 | } |
444 | else |
||
445 | { |
||
9 | mjames | 446 | return HAL_ERROR; |
2 | mjames | 447 | } |
9 | mjames | 448 | |
2 | mjames | 449 | return HAL_OK; |
450 | } |
||
451 | |||
452 | /** |
||
453 | * @brief NAND memory reset |
||
9 | mjames | 454 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 455 | * the configuration information for NAND module. |
456 | * @retval HAL status |
||
457 | */ |
||
458 | HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand) |
||
459 | { |
||
9 | mjames | 460 | uint32_t deviceaddress; |
2 | mjames | 461 | |
462 | /* Check the NAND controller state */ |
||
9 | mjames | 463 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 464 | { |
9 | mjames | 465 | return HAL_BUSY; |
2 | mjames | 466 | } |
9 | mjames | 467 | else if (hnand->State == HAL_NAND_STATE_READY) |
468 | { |
||
469 | /* Process Locked */ |
||
470 | __HAL_LOCK(hnand); |
||
2 | mjames | 471 | |
9 | mjames | 472 | /* Update the NAND controller state */ |
473 | hnand->State = HAL_NAND_STATE_BUSY; |
||
474 | |||
475 | /* Identify the device address */ |
||
476 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
477 | { |
||
478 | deviceaddress = NAND_DEVICE1; |
||
479 | } |
||
480 | else |
||
481 | { |
||
482 | deviceaddress = NAND_DEVICE2; |
||
483 | } |
||
484 | |||
485 | /* Send NAND reset command */ |
||
486 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF; |
||
487 | |||
488 | /* Update the NAND controller state */ |
||
489 | hnand->State = HAL_NAND_STATE_READY; |
||
490 | |||
491 | /* Process unlocked */ |
||
492 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 493 | } |
494 | else |
||
495 | { |
||
9 | mjames | 496 | return HAL_ERROR; |
497 | } |
||
2 | mjames | 498 | |
499 | return HAL_OK; |
||
500 | |||
501 | } |
||
502 | |||
503 | /** |
||
504 | * @brief Configure the device: Enter the physical parameters of the device |
||
9 | mjames | 505 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 506 | * the configuration information for NAND module. |
9 | mjames | 507 | * @param pDeviceConfig pointer to NAND_DeviceConfigTypeDef structure |
2 | mjames | 508 | * @retval HAL status |
509 | */ |
||
510 | HAL_StatusTypeDef HAL_NAND_ConfigDevice(NAND_HandleTypeDef *hnand, NAND_DeviceConfigTypeDef *pDeviceConfig) |
||
511 | { |
||
512 | hnand->Config.PageSize = pDeviceConfig->PageSize; |
||
513 | hnand->Config.SpareAreaSize = pDeviceConfig->SpareAreaSize; |
||
514 | hnand->Config.BlockSize = pDeviceConfig->BlockSize; |
||
515 | hnand->Config.BlockNbr = pDeviceConfig->BlockNbr; |
||
516 | hnand->Config.PlaneSize = pDeviceConfig->PlaneSize; |
||
517 | hnand->Config.PlaneNbr = pDeviceConfig->PlaneNbr; |
||
518 | hnand->Config.ExtraCommandEnable = pDeviceConfig->ExtraCommandEnable; |
||
9 | mjames | 519 | |
2 | mjames | 520 | return HAL_OK; |
521 | } |
||
9 | mjames | 522 | |
2 | mjames | 523 | /** |
524 | * @brief Read Page(s) from NAND memory block (8-bits addressing) |
||
9 | mjames | 525 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 526 | * the configuration information for NAND module. |
9 | mjames | 527 | * @param pAddress pointer to NAND address structure |
528 | * @param pBuffer pointer to destination read buffer |
||
529 | * @param NumPageToRead number of pages to read from block |
||
2 | mjames | 530 | * @retval HAL status |
531 | */ |
||
9 | mjames | 532 | HAL_StatusTypeDef HAL_NAND_Read_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, |
533 | uint32_t NumPageToRead) |
||
534 | { |
||
535 | uint32_t index; |
||
536 | uint32_t tickstart; |
||
537 | uint32_t deviceaddress; |
||
538 | uint32_t numpagesread = 0U; |
||
539 | uint32_t nandaddress; |
||
540 | uint32_t nbpages = NumPageToRead; |
||
541 | uint8_t *buff = pBuffer; |
||
542 | |||
2 | mjames | 543 | /* Check the NAND controller state */ |
9 | mjames | 544 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 545 | { |
9 | mjames | 546 | return HAL_BUSY; |
2 | mjames | 547 | } |
9 | mjames | 548 | else if (hnand->State == HAL_NAND_STATE_READY) |
2 | mjames | 549 | { |
9 | mjames | 550 | /* Process Locked */ |
551 | __HAL_LOCK(hnand); |
||
2 | mjames | 552 | |
9 | mjames | 553 | /* Update the NAND controller state */ |
554 | hnand->State = HAL_NAND_STATE_BUSY; |
||
2 | mjames | 555 | |
9 | mjames | 556 | /* Identify the device address */ |
557 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
2 | mjames | 558 | { |
9 | mjames | 559 | deviceaddress = NAND_DEVICE1; |
2 | mjames | 560 | } |
9 | mjames | 561 | else |
2 | mjames | 562 | { |
9 | mjames | 563 | deviceaddress = NAND_DEVICE2; |
564 | } |
||
565 | |||
566 | /* NAND raw address calculation */ |
||
567 | nandaddress = ARRAY_ADDRESS(pAddress, hnand); |
||
568 | |||
569 | /* Page(s) read loop */ |
||
570 | while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) |
||
571 | { |
||
572 | /* Send read page command sequence */ |
||
573 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; |
||
574 | __DSB(); |
||
575 | |||
576 | /* Cards with page size <= 512 bytes */ |
||
577 | if ((hnand->Config.PageSize) <= 512U) |
||
2 | mjames | 578 | { |
9 | mjames | 579 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
580 | { |
||
581 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
582 | __DSB(); |
||
583 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
584 | __DSB(); |
||
585 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
586 | __DSB(); |
||
587 | } |
||
588 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
589 | { |
||
590 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
591 | __DSB(); |
||
592 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
593 | __DSB(); |
||
594 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
595 | __DSB(); |
||
596 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
597 | __DSB(); |
||
598 | } |
||
2 | mjames | 599 | } |
9 | mjames | 600 | else /* (hnand->Config.PageSize) > 512 */ |
2 | mjames | 601 | { |
9 | mjames | 602 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
603 | { |
||
604 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
605 | __DSB(); |
||
606 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
607 | __DSB(); |
||
608 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
609 | __DSB(); |
||
610 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
611 | __DSB(); |
||
612 | } |
||
613 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
614 | { |
||
615 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
616 | __DSB(); |
||
617 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
618 | __DSB(); |
||
619 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
620 | __DSB(); |
||
621 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
622 | __DSB(); |
||
623 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
624 | __DSB(); |
||
625 | } |
||
2 | mjames | 626 | } |
627 | |||
9 | mjames | 628 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; |
629 | __DSB(); |
||
630 | |||
631 | |||
632 | if (hnand->Config.ExtraCommandEnable == ENABLE) |
||
2 | mjames | 633 | { |
9 | mjames | 634 | /* Get tick */ |
635 | tickstart = HAL_GetTick(); |
||
636 | |||
637 | /* Read status until NAND is ready */ |
||
638 | while (HAL_NAND_Read_Status(hnand) != NAND_READY) |
||
2 | mjames | 639 | { |
9 | mjames | 640 | if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) |
641 | { |
||
642 | /* Update the NAND controller state */ |
||
643 | hnand->State = HAL_NAND_STATE_ERROR; |
||
644 | |||
645 | /* Process unlocked */ |
||
646 | __HAL_UNLOCK(hnand); |
||
647 | |||
648 | return HAL_TIMEOUT; |
||
649 | } |
||
2 | mjames | 650 | } |
9 | mjames | 651 | |
652 | /* Go back to read mode */ |
||
653 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); |
||
654 | __DSB(); |
||
2 | mjames | 655 | } |
9 | mjames | 656 | |
657 | /* Get Data into Buffer */ |
||
658 | for (index = 0U; index < hnand->Config.PageSize; index++) |
||
659 | { |
||
660 | *buff = *(uint8_t *)deviceaddress; |
||
661 | buff++; |
||
662 | } |
||
663 | |||
664 | /* Increment read pages number */ |
||
665 | numpagesread++; |
||
666 | |||
667 | /* Decrement pages to read */ |
||
668 | nbpages--; |
||
669 | |||
670 | /* Increment the NAND address */ |
||
671 | nandaddress = (uint32_t)(nandaddress + 1U); |
||
2 | mjames | 672 | } |
9 | mjames | 673 | |
674 | /* Update the NAND controller state */ |
||
675 | hnand->State = HAL_NAND_STATE_READY; |
||
676 | |||
677 | /* Process unlocked */ |
||
678 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 679 | } |
9 | mjames | 680 | else |
681 | { |
||
682 | return HAL_ERROR; |
||
683 | } |
||
2 | mjames | 684 | |
685 | return HAL_OK; |
||
686 | } |
||
687 | |||
688 | /** |
||
689 | * @brief Read Page(s) from NAND memory block (16-bits addressing) |
||
9 | mjames | 690 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 691 | * the configuration information for NAND module. |
9 | mjames | 692 | * @param pAddress pointer to NAND address structure |
693 | * @param pBuffer pointer to destination read buffer. pBuffer should be 16bits aligned |
||
694 | * @param NumPageToRead number of pages to read from block |
||
2 | mjames | 695 | * @retval HAL status |
696 | */ |
||
9 | mjames | 697 | HAL_StatusTypeDef HAL_NAND_Read_Page_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, |
698 | uint32_t NumPageToRead) |
||
699 | { |
||
700 | uint32_t index; |
||
701 | uint32_t tickstart; |
||
702 | uint32_t deviceaddress; |
||
703 | uint32_t numpagesread = 0; |
||
704 | uint32_t nandaddress; |
||
705 | uint32_t nbpages = NumPageToRead; |
||
706 | uint16_t *buff = pBuffer; |
||
707 | |||
2 | mjames | 708 | /* Check the NAND controller state */ |
9 | mjames | 709 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 710 | { |
9 | mjames | 711 | return HAL_BUSY; |
2 | mjames | 712 | } |
9 | mjames | 713 | else if (hnand->State == HAL_NAND_STATE_READY) |
2 | mjames | 714 | { |
9 | mjames | 715 | /* Process Locked */ |
716 | __HAL_LOCK(hnand); |
||
2 | mjames | 717 | |
9 | mjames | 718 | /* Update the NAND controller state */ |
719 | hnand->State = HAL_NAND_STATE_BUSY; |
||
720 | |||
721 | /* Identify the device address */ |
||
722 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
2 | mjames | 723 | { |
9 | mjames | 724 | deviceaddress = NAND_DEVICE1; |
2 | mjames | 725 | } |
9 | mjames | 726 | else |
2 | mjames | 727 | { |
9 | mjames | 728 | deviceaddress = NAND_DEVICE2; |
729 | } |
||
730 | |||
731 | /* NAND raw address calculation */ |
||
732 | nandaddress = ARRAY_ADDRESS(pAddress, hnand); |
||
733 | |||
734 | /* Page(s) read loop */ |
||
735 | while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) |
||
736 | { |
||
737 | /* Send read page command sequence */ |
||
738 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; |
||
739 | __DSB(); |
||
740 | |||
741 | /* Cards with page size <= 512 bytes */ |
||
742 | if ((hnand->Config.PageSize) <= 512U) |
||
2 | mjames | 743 | { |
9 | mjames | 744 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
745 | { |
||
746 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
747 | __DSB(); |
||
748 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
749 | __DSB(); |
||
750 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
751 | __DSB(); |
||
752 | } |
||
753 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
754 | { |
||
755 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
756 | __DSB(); |
||
757 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
758 | __DSB(); |
||
759 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
760 | __DSB(); |
||
761 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
762 | __DSB(); |
||
763 | } |
||
2 | mjames | 764 | } |
9 | mjames | 765 | else /* (hnand->Config.PageSize) > 512 */ |
2 | mjames | 766 | { |
9 | mjames | 767 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
768 | { |
||
769 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
770 | __DSB(); |
||
771 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
772 | __DSB(); |
||
773 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
774 | __DSB(); |
||
775 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
776 | __DSB(); |
||
777 | } |
||
778 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
779 | { |
||
780 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
781 | __DSB(); |
||
782 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
783 | __DSB(); |
||
784 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
785 | __DSB(); |
||
786 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
787 | __DSB(); |
||
788 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
789 | __DSB(); |
||
790 | } |
||
2 | mjames | 791 | } |
9 | mjames | 792 | |
793 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; |
||
794 | __DSB(); |
||
795 | |||
796 | if (hnand->Config.ExtraCommandEnable == ENABLE) |
||
2 | mjames | 797 | { |
9 | mjames | 798 | /* Get tick */ |
799 | tickstart = HAL_GetTick(); |
||
800 | |||
801 | /* Read status until NAND is ready */ |
||
802 | while (HAL_NAND_Read_Status(hnand) != NAND_READY) |
||
2 | mjames | 803 | { |
9 | mjames | 804 | if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) |
805 | { |
||
806 | /* Update the NAND controller state */ |
||
807 | hnand->State = HAL_NAND_STATE_ERROR; |
||
808 | |||
809 | /* Process unlocked */ |
||
810 | __HAL_UNLOCK(hnand); |
||
811 | |||
812 | return HAL_TIMEOUT; |
||
813 | } |
||
2 | mjames | 814 | } |
9 | mjames | 815 | |
816 | /* Go back to read mode */ |
||
817 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); |
||
818 | __DSB(); |
||
2 | mjames | 819 | } |
9 | mjames | 820 | |
821 | /* Get Data into Buffer */ |
||
822 | for (index = 0U; index < hnand->Config.PageSize; index++) |
||
823 | { |
||
824 | *buff = *(uint16_t *)deviceaddress; |
||
825 | buff++; |
||
826 | } |
||
827 | |||
828 | /* Increment read pages number */ |
||
829 | numpagesread++; |
||
830 | |||
831 | /* Decrement pages to read */ |
||
832 | nbpages--; |
||
833 | |||
834 | /* Increment the NAND address */ |
||
835 | nandaddress = (uint32_t)(nandaddress + 1U); |
||
2 | mjames | 836 | } |
9 | mjames | 837 | |
838 | /* Update the NAND controller state */ |
||
839 | hnand->State = HAL_NAND_STATE_READY; |
||
840 | |||
841 | /* Process unlocked */ |
||
842 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 843 | } |
9 | mjames | 844 | else |
845 | { |
||
846 | return HAL_ERROR; |
||
847 | } |
||
848 | |||
2 | mjames | 849 | return HAL_OK; |
850 | } |
||
851 | |||
852 | /** |
||
853 | * @brief Write Page(s) to NAND memory block (8-bits addressing) |
||
9 | mjames | 854 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 855 | * the configuration information for NAND module. |
9 | mjames | 856 | * @param pAddress pointer to NAND address structure |
857 | * @param pBuffer pointer to source buffer to write |
||
858 | * @param NumPageToWrite number of pages to write to block |
||
2 | mjames | 859 | * @retval HAL status |
860 | */ |
||
9 | mjames | 861 | HAL_StatusTypeDef HAL_NAND_Write_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, |
862 | uint32_t NumPageToWrite) |
||
2 | mjames | 863 | { |
9 | mjames | 864 | uint32_t index; |
865 | uint32_t tickstart; |
||
866 | uint32_t deviceaddress; |
||
867 | uint32_t numpageswritten = 0; |
||
868 | uint32_t nandaddress; |
||
869 | uint32_t nbpages = NumPageToWrite; |
||
870 | uint8_t *buff = pBuffer; |
||
2 | mjames | 871 | |
872 | /* Check the NAND controller state */ |
||
9 | mjames | 873 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 874 | { |
9 | mjames | 875 | return HAL_BUSY; |
2 | mjames | 876 | } |
9 | mjames | 877 | else if (hnand->State == HAL_NAND_STATE_READY) |
2 | mjames | 878 | { |
9 | mjames | 879 | /* Process Locked */ |
880 | __HAL_LOCK(hnand); |
||
2 | mjames | 881 | |
9 | mjames | 882 | /* Update the NAND controller state */ |
883 | hnand->State = HAL_NAND_STATE_BUSY; |
||
884 | |||
885 | /* Identify the device address */ |
||
886 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
2 | mjames | 887 | { |
9 | mjames | 888 | deviceaddress = NAND_DEVICE1; |
2 | mjames | 889 | } |
9 | mjames | 890 | else |
2 | mjames | 891 | { |
9 | mjames | 892 | deviceaddress = NAND_DEVICE2; |
893 | } |
||
894 | |||
895 | /* NAND raw address calculation */ |
||
896 | nandaddress = ARRAY_ADDRESS(pAddress, hnand); |
||
897 | |||
898 | /* Page(s) write loop */ |
||
899 | while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) |
||
900 | { |
||
901 | /* Send write page command sequence */ |
||
902 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; |
||
903 | __DSB(); |
||
904 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; |
||
905 | __DSB(); |
||
906 | |||
907 | /* Cards with page size <= 512 bytes */ |
||
908 | if ((hnand->Config.PageSize) <= 512U) |
||
2 | mjames | 909 | { |
9 | mjames | 910 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
911 | { |
||
912 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
913 | __DSB(); |
||
914 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
915 | __DSB(); |
||
916 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
917 | __DSB(); |
||
918 | } |
||
919 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
920 | { |
||
921 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
922 | __DSB(); |
||
923 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
924 | __DSB(); |
||
925 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
926 | __DSB(); |
||
927 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
928 | __DSB(); |
||
929 | } |
||
2 | mjames | 930 | } |
9 | mjames | 931 | else /* (hnand->Config.PageSize) > 512 */ |
2 | mjames | 932 | { |
9 | mjames | 933 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
934 | { |
||
935 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
936 | __DSB(); |
||
937 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
938 | __DSB(); |
||
939 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
940 | __DSB(); |
||
941 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
942 | __DSB(); |
||
943 | } |
||
944 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
945 | { |
||
946 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
947 | __DSB(); |
||
948 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
949 | __DSB(); |
||
950 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
951 | __DSB(); |
||
952 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
953 | __DSB(); |
||
954 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
955 | __DSB(); |
||
956 | } |
||
2 | mjames | 957 | } |
958 | |||
9 | mjames | 959 | /* Write data to memory */ |
960 | for (index = 0U; index < hnand->Config.PageSize; index++) |
||
961 | { |
||
962 | *(__IO uint8_t *)deviceaddress = *buff; |
||
963 | buff++; |
||
964 | __DSB(); |
||
965 | } |
||
966 | |||
967 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; |
||
968 | __DSB(); |
||
969 | |||
2 | mjames | 970 | /* Get tick */ |
971 | tickstart = HAL_GetTick(); |
||
9 | mjames | 972 | |
973 | /* Read status until NAND is ready */ |
||
974 | while (HAL_NAND_Read_Status(hnand) != NAND_READY) |
||
2 | mjames | 975 | { |
9 | mjames | 976 | if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) |
977 | { |
||
978 | /* Update the NAND controller state */ |
||
979 | hnand->State = HAL_NAND_STATE_ERROR; |
||
980 | |||
981 | /* Process unlocked */ |
||
982 | __HAL_UNLOCK(hnand); |
||
983 | |||
984 | return HAL_TIMEOUT; |
||
985 | } |
||
2 | mjames | 986 | } |
9 | mjames | 987 | |
988 | /* Increment written pages number */ |
||
989 | numpageswritten++; |
||
990 | |||
991 | /* Decrement pages to write */ |
||
992 | nbpages--; |
||
993 | |||
994 | /* Increment the NAND address */ |
||
995 | nandaddress = (uint32_t)(nandaddress + 1U); |
||
2 | mjames | 996 | } |
9 | mjames | 997 | |
998 | /* Update the NAND controller state */ |
||
999 | hnand->State = HAL_NAND_STATE_READY; |
||
1000 | |||
1001 | /* Process unlocked */ |
||
1002 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 1003 | } |
9 | mjames | 1004 | else |
1005 | { |
||
1006 | return HAL_ERROR; |
||
1007 | } |
||
1008 | |||
2 | mjames | 1009 | return HAL_OK; |
1010 | } |
||
1011 | |||
1012 | /** |
||
1013 | * @brief Write Page(s) to NAND memory block (16-bits addressing) |
||
9 | mjames | 1014 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 1015 | * the configuration information for NAND module. |
9 | mjames | 1016 | * @param pAddress pointer to NAND address structure |
1017 | * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned |
||
1018 | * @param NumPageToWrite number of pages to write to block |
||
2 | mjames | 1019 | * @retval HAL status |
1020 | */ |
||
9 | mjames | 1021 | HAL_StatusTypeDef HAL_NAND_Write_Page_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, |
1022 | uint32_t NumPageToWrite) |
||
2 | mjames | 1023 | { |
9 | mjames | 1024 | uint32_t index; |
1025 | uint32_t tickstart; |
||
1026 | uint32_t deviceaddress; |
||
1027 | uint32_t numpageswritten = 0; |
||
1028 | uint32_t nandaddress; |
||
1029 | uint32_t nbpages = NumPageToWrite; |
||
1030 | uint16_t *buff = pBuffer; |
||
2 | mjames | 1031 | |
1032 | /* Check the NAND controller state */ |
||
9 | mjames | 1033 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 1034 | { |
9 | mjames | 1035 | return HAL_BUSY; |
2 | mjames | 1036 | } |
9 | mjames | 1037 | else if (hnand->State == HAL_NAND_STATE_READY) |
2 | mjames | 1038 | { |
9 | mjames | 1039 | /* Process Locked */ |
1040 | __HAL_LOCK(hnand); |
||
2 | mjames | 1041 | |
9 | mjames | 1042 | /* Update the NAND controller state */ |
1043 | hnand->State = HAL_NAND_STATE_BUSY; |
||
1044 | |||
1045 | /* Identify the device address */ |
||
1046 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
2 | mjames | 1047 | { |
9 | mjames | 1048 | deviceaddress = NAND_DEVICE1; |
1049 | } |
||
1050 | else |
||
1051 | { |
||
1052 | deviceaddress = NAND_DEVICE2; |
||
1053 | } |
||
1054 | |||
1055 | /* NAND raw address calculation */ |
||
1056 | nandaddress = ARRAY_ADDRESS(pAddress, hnand); |
||
1057 | |||
1058 | /* Page(s) write loop */ |
||
1059 | while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) |
||
1060 | { |
||
1061 | /* Send write page command sequence */ |
||
1062 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; |
||
1063 | __DSB(); |
||
1064 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; |
||
1065 | __DSB(); |
||
1066 | |||
1067 | /* Cards with page size <= 512 bytes */ |
||
1068 | if ((hnand->Config.PageSize) <= 512U) |
||
2 | mjames | 1069 | { |
9 | mjames | 1070 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
1071 | { |
||
1072 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1073 | __DSB(); |
||
1074 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1075 | __DSB(); |
||
1076 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1077 | __DSB(); |
||
1078 | } |
||
1079 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
1080 | { |
||
1081 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1082 | __DSB(); |
||
1083 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1084 | __DSB(); |
||
1085 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1086 | __DSB(); |
||
1087 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
1088 | __DSB(); |
||
1089 | } |
||
2 | mjames | 1090 | } |
9 | mjames | 1091 | else /* (hnand->Config.PageSize) > 512 */ |
2 | mjames | 1092 | { |
9 | mjames | 1093 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
1094 | { |
||
1095 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1096 | __DSB(); |
||
1097 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1098 | __DSB(); |
||
1099 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1100 | __DSB(); |
||
1101 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1102 | __DSB(); |
||
1103 | } |
||
1104 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
1105 | { |
||
1106 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1107 | __DSB(); |
||
1108 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1109 | __DSB(); |
||
1110 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1111 | __DSB(); |
||
1112 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1113 | __DSB(); |
||
1114 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
1115 | __DSB(); |
||
1116 | } |
||
2 | mjames | 1117 | } |
9 | mjames | 1118 | |
1119 | /* Write data to memory */ |
||
1120 | for (index = 0U; index < hnand->Config.PageSize; index++) |
||
2 | mjames | 1121 | { |
9 | mjames | 1122 | *(__IO uint16_t *)deviceaddress = *buff; |
1123 | buff++; |
||
1124 | __DSB(); |
||
2 | mjames | 1125 | } |
9 | mjames | 1126 | |
1127 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; |
||
1128 | __DSB(); |
||
1129 | |||
1130 | /* Get tick */ |
||
1131 | tickstart = HAL_GetTick(); |
||
1132 | |||
1133 | /* Read status until NAND is ready */ |
||
1134 | while (HAL_NAND_Read_Status(hnand) != NAND_READY) |
||
2 | mjames | 1135 | { |
9 | mjames | 1136 | if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) |
1137 | { |
||
1138 | /* Update the NAND controller state */ |
||
1139 | hnand->State = HAL_NAND_STATE_ERROR; |
||
1140 | |||
1141 | /* Process unlocked */ |
||
1142 | __HAL_UNLOCK(hnand); |
||
1143 | |||
1144 | return HAL_TIMEOUT; |
||
1145 | } |
||
2 | mjames | 1146 | } |
9 | mjames | 1147 | |
1148 | /* Increment written pages number */ |
||
1149 | numpageswritten++; |
||
1150 | |||
1151 | /* Decrement pages to write */ |
||
1152 | nbpages--; |
||
1153 | |||
1154 | /* Increment the NAND address */ |
||
1155 | nandaddress = (uint32_t)(nandaddress + 1U); |
||
2 | mjames | 1156 | } |
9 | mjames | 1157 | |
1158 | /* Update the NAND controller state */ |
||
1159 | hnand->State = HAL_NAND_STATE_READY; |
||
1160 | |||
1161 | /* Process unlocked */ |
||
1162 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 1163 | } |
9 | mjames | 1164 | else |
1165 | { |
||
1166 | return HAL_ERROR; |
||
1167 | } |
||
1168 | |||
2 | mjames | 1169 | return HAL_OK; |
1170 | } |
||
1171 | |||
1172 | /** |
||
1173 | * @brief Read Spare area(s) from NAND memory (8-bits addressing) |
||
9 | mjames | 1174 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 1175 | * the configuration information for NAND module. |
9 | mjames | 1176 | * @param pAddress pointer to NAND address structure |
1177 | * @param pBuffer pointer to source buffer to write |
||
1178 | * @param NumSpareAreaToRead Number of spare area to read |
||
2 | mjames | 1179 | * @retval HAL status |
9 | mjames | 1180 | */ |
1181 | HAL_StatusTypeDef HAL_NAND_Read_SpareArea_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, |
||
1182 | uint32_t NumSpareAreaToRead) |
||
2 | mjames | 1183 | { |
9 | mjames | 1184 | uint32_t index; |
1185 | uint32_t tickstart; |
||
1186 | uint32_t deviceaddress; |
||
1187 | uint32_t numsparearearead = 0; |
||
1188 | uint32_t nandaddress; |
||
1189 | uint32_t columnaddress; |
||
1190 | uint32_t nbspare = NumSpareAreaToRead; |
||
1191 | uint8_t *buff = pBuffer; |
||
1192 | |||
2 | mjames | 1193 | /* Check the NAND controller state */ |
9 | mjames | 1194 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 1195 | { |
9 | mjames | 1196 | return HAL_BUSY; |
2 | mjames | 1197 | } |
9 | mjames | 1198 | else if (hnand->State == HAL_NAND_STATE_READY) |
2 | mjames | 1199 | { |
9 | mjames | 1200 | /* Process Locked */ |
1201 | __HAL_LOCK(hnand); |
||
2 | mjames | 1202 | |
9 | mjames | 1203 | /* Update the NAND controller state */ |
1204 | hnand->State = HAL_NAND_STATE_BUSY; |
||
1205 | |||
1206 | /* Identify the device address */ |
||
1207 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
2 | mjames | 1208 | { |
9 | mjames | 1209 | deviceaddress = NAND_DEVICE1; |
2 | mjames | 1210 | } |
9 | mjames | 1211 | else |
2 | mjames | 1212 | { |
9 | mjames | 1213 | deviceaddress = NAND_DEVICE2; |
1214 | } |
||
1215 | |||
1216 | /* NAND raw address calculation */ |
||
1217 | nandaddress = ARRAY_ADDRESS(pAddress, hnand); |
||
1218 | |||
1219 | /* Column in page address */ |
||
1220 | columnaddress = COLUMN_ADDRESS(hnand); |
||
1221 | |||
1222 | /* Spare area(s) read loop */ |
||
1223 | while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) |
||
1224 | { |
||
1225 | /* Cards with page size <= 512 bytes */ |
||
1226 | if ((hnand->Config.PageSize) <= 512U) |
||
2 | mjames | 1227 | { |
9 | mjames | 1228 | /* Send read spare area command sequence */ |
1229 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; |
||
1230 | __DSB(); |
||
1231 | |||
1232 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
||
1233 | { |
||
1234 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1235 | __DSB(); |
||
1236 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1237 | __DSB(); |
||
1238 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1239 | __DSB(); |
||
1240 | } |
||
1241 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
1242 | { |
||
1243 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1244 | __DSB(); |
||
1245 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1246 | __DSB(); |
||
1247 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1248 | __DSB(); |
||
1249 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
1250 | __DSB(); |
||
1251 | } |
||
2 | mjames | 1252 | } |
9 | mjames | 1253 | else /* (hnand->Config.PageSize) > 512 */ |
2 | mjames | 1254 | { |
9 | mjames | 1255 | /* Send read spare area command sequence */ |
1256 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; |
||
1257 | __DSB(); |
||
1258 | |||
1259 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
||
1260 | { |
||
1261 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); |
||
1262 | __DSB(); |
||
1263 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); |
||
1264 | __DSB(); |
||
1265 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1266 | __DSB(); |
||
1267 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1268 | __DSB(); |
||
1269 | } |
||
1270 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
1271 | { |
||
1272 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); |
||
1273 | __DSB(); |
||
1274 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); |
||
1275 | __DSB(); |
||
1276 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1277 | __DSB(); |
||
1278 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1279 | __DSB(); |
||
1280 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
1281 | __DSB(); |
||
1282 | } |
||
2 | mjames | 1283 | } |
1284 | |||
9 | mjames | 1285 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; |
1286 | __DSB(); |
||
1287 | |||
1288 | if (hnand->Config.ExtraCommandEnable == ENABLE) |
||
2 | mjames | 1289 | { |
9 | mjames | 1290 | /* Get tick */ |
1291 | tickstart = HAL_GetTick(); |
||
1292 | |||
1293 | /* Read status until NAND is ready */ |
||
1294 | while (HAL_NAND_Read_Status(hnand) != NAND_READY) |
||
2 | mjames | 1295 | { |
9 | mjames | 1296 | if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) |
1297 | { |
||
1298 | /* Update the NAND controller state */ |
||
1299 | hnand->State = HAL_NAND_STATE_ERROR; |
||
1300 | |||
1301 | /* Process unlocked */ |
||
1302 | __HAL_UNLOCK(hnand); |
||
1303 | |||
1304 | return HAL_TIMEOUT; |
||
1305 | } |
||
2 | mjames | 1306 | } |
9 | mjames | 1307 | |
1308 | /* Go back to read mode */ |
||
1309 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); |
||
1310 | __DSB(); |
||
2 | mjames | 1311 | } |
9 | mjames | 1312 | |
1313 | /* Get Data into Buffer */ |
||
1314 | for (index = 0U; index < hnand->Config.SpareAreaSize; index++) |
||
1315 | { |
||
1316 | *buff = *(uint8_t *)deviceaddress; |
||
1317 | buff++; |
||
1318 | } |
||
1319 | |||
1320 | /* Increment read spare areas number */ |
||
1321 | numsparearearead++; |
||
1322 | |||
1323 | /* Decrement spare areas to read */ |
||
1324 | nbspare--; |
||
1325 | |||
1326 | /* Increment the NAND address */ |
||
1327 | nandaddress = (uint32_t)(nandaddress + 1U); |
||
2 | mjames | 1328 | } |
9 | mjames | 1329 | |
1330 | /* Update the NAND controller state */ |
||
1331 | hnand->State = HAL_NAND_STATE_READY; |
||
1332 | |||
1333 | /* Process unlocked */ |
||
1334 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 1335 | } |
9 | mjames | 1336 | else |
1337 | { |
||
1338 | return HAL_ERROR; |
||
1339 | } |
||
2 | mjames | 1340 | |
1341 | return HAL_OK; |
||
1342 | } |
||
1343 | |||
1344 | /** |
||
1345 | * @brief Read Spare area(s) from NAND memory (16-bits addressing) |
||
9 | mjames | 1346 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 1347 | * the configuration information for NAND module. |
9 | mjames | 1348 | * @param pAddress pointer to NAND address structure |
1349 | * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned. |
||
1350 | * @param NumSpareAreaToRead Number of spare area to read |
||
2 | mjames | 1351 | * @retval HAL status |
9 | mjames | 1352 | */ |
1353 | HAL_StatusTypeDef HAL_NAND_Read_SpareArea_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, |
||
1354 | uint16_t *pBuffer, uint32_t NumSpareAreaToRead) |
||
2 | mjames | 1355 | { |
9 | mjames | 1356 | uint32_t index; |
1357 | uint32_t tickstart; |
||
1358 | uint32_t deviceaddress; |
||
1359 | uint32_t numsparearearead = 0; |
||
1360 | uint32_t nandaddress; |
||
1361 | uint32_t columnaddress; |
||
1362 | uint32_t nbspare = NumSpareAreaToRead; |
||
1363 | uint16_t *buff = pBuffer; |
||
1364 | |||
2 | mjames | 1365 | /* Check the NAND controller state */ |
9 | mjames | 1366 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 1367 | { |
9 | mjames | 1368 | return HAL_BUSY; |
2 | mjames | 1369 | } |
9 | mjames | 1370 | else if (hnand->State == HAL_NAND_STATE_READY) |
2 | mjames | 1371 | { |
9 | mjames | 1372 | /* Process Locked */ |
1373 | __HAL_LOCK(hnand); |
||
2 | mjames | 1374 | |
9 | mjames | 1375 | /* Update the NAND controller state */ |
1376 | hnand->State = HAL_NAND_STATE_BUSY; |
||
1377 | |||
1378 | /* Identify the device address */ |
||
1379 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
2 | mjames | 1380 | { |
9 | mjames | 1381 | deviceaddress = NAND_DEVICE1; |
2 | mjames | 1382 | } |
9 | mjames | 1383 | else |
2 | mjames | 1384 | { |
9 | mjames | 1385 | deviceaddress = NAND_DEVICE2; |
1386 | } |
||
1387 | |||
1388 | /* NAND raw address calculation */ |
||
1389 | nandaddress = ARRAY_ADDRESS(pAddress, hnand); |
||
1390 | |||
1391 | /* Column in page address */ |
||
1392 | columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand) * 2U); |
||
1393 | |||
1394 | /* Spare area(s) read loop */ |
||
1395 | while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) |
||
1396 | { |
||
1397 | /* Cards with page size <= 512 bytes */ |
||
1398 | if ((hnand->Config.PageSize) <= 512U) |
||
2 | mjames | 1399 | { |
9 | mjames | 1400 | /* Send read spare area command sequence */ |
1401 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; |
||
1402 | __DSB(); |
||
1403 | |||
1404 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
||
1405 | { |
||
1406 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1407 | __DSB(); |
||
1408 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1409 | __DSB(); |
||
1410 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1411 | __DSB(); |
||
1412 | } |
||
1413 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
1414 | { |
||
1415 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1416 | __DSB(); |
||
1417 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1418 | __DSB(); |
||
1419 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1420 | __DSB(); |
||
1421 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
1422 | __DSB(); |
||
1423 | } |
||
2 | mjames | 1424 | } |
9 | mjames | 1425 | else /* (hnand->Config.PageSize) > 512 */ |
2 | mjames | 1426 | { |
9 | mjames | 1427 | /* Send read spare area command sequence */ |
1428 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; |
||
1429 | __DSB(); |
||
1430 | |||
1431 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
||
1432 | { |
||
1433 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); |
||
1434 | __DSB(); |
||
1435 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); |
||
1436 | __DSB(); |
||
1437 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1438 | __DSB(); |
||
1439 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1440 | __DSB(); |
||
1441 | } |
||
1442 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
1443 | { |
||
1444 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); |
||
1445 | __DSB(); |
||
1446 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); |
||
1447 | __DSB(); |
||
1448 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1449 | __DSB(); |
||
1450 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1451 | __DSB(); |
||
1452 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
1453 | __DSB(); |
||
1454 | } |
||
2 | mjames | 1455 | } |
1456 | |||
9 | mjames | 1457 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; |
1458 | __DSB(); |
||
2 | mjames | 1459 | |
9 | mjames | 1460 | if (hnand->Config.ExtraCommandEnable == ENABLE) |
2 | mjames | 1461 | { |
9 | mjames | 1462 | /* Get tick */ |
1463 | tickstart = HAL_GetTick(); |
||
1464 | |||
1465 | /* Read status until NAND is ready */ |
||
1466 | while (HAL_NAND_Read_Status(hnand) != NAND_READY) |
||
2 | mjames | 1467 | { |
9 | mjames | 1468 | if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) |
1469 | { |
||
1470 | /* Update the NAND controller state */ |
||
1471 | hnand->State = HAL_NAND_STATE_ERROR; |
||
1472 | |||
1473 | /* Process unlocked */ |
||
1474 | __HAL_UNLOCK(hnand); |
||
1475 | |||
1476 | return HAL_TIMEOUT; |
||
1477 | } |
||
2 | mjames | 1478 | } |
9 | mjames | 1479 | |
1480 | /* Go back to read mode */ |
||
1481 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); |
||
1482 | __DSB(); |
||
2 | mjames | 1483 | } |
9 | mjames | 1484 | |
1485 | /* Get Data into Buffer */ |
||
1486 | for (index = 0U; index < hnand->Config.SpareAreaSize; index++) |
||
1487 | { |
||
1488 | *buff = *(uint16_t *)deviceaddress; |
||
1489 | buff++; |
||
1490 | } |
||
1491 | |||
1492 | /* Increment read spare areas number */ |
||
1493 | numsparearearead++; |
||
1494 | |||
1495 | /* Decrement spare areas to read */ |
||
1496 | nbspare--; |
||
1497 | |||
1498 | /* Increment the NAND address */ |
||
1499 | nandaddress = (uint32_t)(nandaddress + 1U); |
||
2 | mjames | 1500 | } |
9 | mjames | 1501 | |
1502 | /* Update the NAND controller state */ |
||
1503 | hnand->State = HAL_NAND_STATE_READY; |
||
1504 | |||
1505 | /* Process unlocked */ |
||
1506 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 1507 | } |
9 | mjames | 1508 | else |
1509 | { |
||
1510 | return HAL_ERROR; |
||
1511 | } |
||
2 | mjames | 1512 | |
9 | mjames | 1513 | return HAL_OK; |
2 | mjames | 1514 | } |
1515 | |||
1516 | /** |
||
1517 | * @brief Write Spare area(s) to NAND memory (8-bits addressing) |
||
9 | mjames | 1518 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 1519 | * the configuration information for NAND module. |
9 | mjames | 1520 | * @param pAddress pointer to NAND address structure |
1521 | * @param pBuffer pointer to source buffer to write |
||
1522 | * @param NumSpareAreaTowrite number of spare areas to write to block |
||
2 | mjames | 1523 | * @retval HAL status |
1524 | */ |
||
9 | mjames | 1525 | HAL_StatusTypeDef HAL_NAND_Write_SpareArea_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, |
1526 | uint8_t *pBuffer, uint32_t NumSpareAreaTowrite) |
||
2 | mjames | 1527 | { |
9 | mjames | 1528 | uint32_t index; |
1529 | uint32_t tickstart; |
||
1530 | uint32_t deviceaddress; |
||
1531 | uint32_t numspareareawritten = 0; |
||
1532 | uint32_t nandaddress; |
||
1533 | uint32_t columnaddress; |
||
1534 | uint32_t nbspare = NumSpareAreaTowrite; |
||
1535 | uint8_t *buff = pBuffer; |
||
2 | mjames | 1536 | |
1537 | /* Check the NAND controller state */ |
||
9 | mjames | 1538 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 1539 | { |
9 | mjames | 1540 | return HAL_BUSY; |
2 | mjames | 1541 | } |
9 | mjames | 1542 | else if (hnand->State == HAL_NAND_STATE_READY) |
2 | mjames | 1543 | { |
9 | mjames | 1544 | /* Process Locked */ |
1545 | __HAL_LOCK(hnand); |
||
2 | mjames | 1546 | |
9 | mjames | 1547 | /* Update the NAND controller state */ |
1548 | hnand->State = HAL_NAND_STATE_BUSY; |
||
1549 | |||
1550 | /* Identify the device address */ |
||
1551 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
2 | mjames | 1552 | { |
9 | mjames | 1553 | deviceaddress = NAND_DEVICE1; |
1554 | } |
||
1555 | else |
||
1556 | { |
||
1557 | deviceaddress = NAND_DEVICE2; |
||
1558 | } |
||
1559 | |||
1560 | /* Page address calculation */ |
||
1561 | nandaddress = ARRAY_ADDRESS(pAddress, hnand); |
||
1562 | |||
1563 | /* Column in page address */ |
||
1564 | columnaddress = COLUMN_ADDRESS(hnand); |
||
1565 | |||
1566 | /* Spare area(s) write loop */ |
||
1567 | while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) |
||
1568 | { |
||
1569 | /* Cards with page size <= 512 bytes */ |
||
1570 | if ((hnand->Config.PageSize) <= 512U) |
||
2 | mjames | 1571 | { |
9 | mjames | 1572 | /* Send write Spare area command sequence */ |
1573 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; |
||
1574 | __DSB(); |
||
1575 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; |
||
1576 | __DSB(); |
||
1577 | |||
1578 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
||
1579 | { |
||
1580 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1581 | __DSB(); |
||
1582 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1583 | __DSB(); |
||
1584 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1585 | __DSB(); |
||
1586 | } |
||
1587 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
1588 | { |
||
1589 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1590 | __DSB(); |
||
1591 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1592 | __DSB(); |
||
1593 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1594 | __DSB(); |
||
1595 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
1596 | __DSB(); |
||
1597 | } |
||
2 | mjames | 1598 | } |
9 | mjames | 1599 | else /* (hnand->Config.PageSize) > 512 */ |
2 | mjames | 1600 | { |
9 | mjames | 1601 | /* Send write Spare area command sequence */ |
1602 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; |
||
1603 | __DSB(); |
||
1604 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; |
||
1605 | __DSB(); |
||
1606 | |||
1607 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
||
1608 | { |
||
1609 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); |
||
1610 | __DSB(); |
||
1611 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); |
||
1612 | __DSB(); |
||
1613 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1614 | __DSB(); |
||
1615 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1616 | __DSB(); |
||
1617 | } |
||
1618 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
1619 | { |
||
1620 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); |
||
1621 | __DSB(); |
||
1622 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); |
||
1623 | __DSB(); |
||
1624 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1625 | __DSB(); |
||
1626 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1627 | __DSB(); |
||
1628 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
1629 | __DSB(); |
||
1630 | } |
||
2 | mjames | 1631 | } |
9 | mjames | 1632 | |
1633 | /* Write data to memory */ |
||
1634 | for (index = 0U; index < hnand->Config.SpareAreaSize; index++) |
||
2 | mjames | 1635 | { |
9 | mjames | 1636 | *(__IO uint8_t *)deviceaddress = *buff; |
1637 | buff++; |
||
1638 | __DSB(); |
||
2 | mjames | 1639 | } |
9 | mjames | 1640 | |
1641 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; |
||
1642 | __DSB(); |
||
1643 | |||
1644 | /* Get tick */ |
||
1645 | tickstart = HAL_GetTick(); |
||
1646 | |||
1647 | /* Read status until NAND is ready */ |
||
1648 | while (HAL_NAND_Read_Status(hnand) != NAND_READY) |
||
2 | mjames | 1649 | { |
9 | mjames | 1650 | if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) |
1651 | { |
||
1652 | /* Update the NAND controller state */ |
||
1653 | hnand->State = HAL_NAND_STATE_ERROR; |
||
1654 | |||
1655 | /* Process unlocked */ |
||
1656 | __HAL_UNLOCK(hnand); |
||
1657 | |||
1658 | return HAL_TIMEOUT; |
||
1659 | } |
||
2 | mjames | 1660 | } |
9 | mjames | 1661 | |
1662 | /* Increment written spare areas number */ |
||
1663 | numspareareawritten++; |
||
1664 | |||
1665 | /* Decrement spare areas to write */ |
||
1666 | nbspare--; |
||
1667 | |||
1668 | /* Increment the NAND address */ |
||
1669 | nandaddress = (uint32_t)(nandaddress + 1U); |
||
2 | mjames | 1670 | } |
1671 | |||
9 | mjames | 1672 | /* Update the NAND controller state */ |
1673 | hnand->State = HAL_NAND_STATE_READY; |
||
1674 | |||
1675 | /* Process unlocked */ |
||
1676 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 1677 | } |
9 | mjames | 1678 | else |
1679 | { |
||
1680 | return HAL_ERROR; |
||
1681 | } |
||
2 | mjames | 1682 | |
1683 | return HAL_OK; |
||
1684 | } |
||
1685 | |||
1686 | /** |
||
1687 | * @brief Write Spare area(s) to NAND memory (16-bits addressing) |
||
9 | mjames | 1688 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 1689 | * the configuration information for NAND module. |
9 | mjames | 1690 | * @param pAddress pointer to NAND address structure |
1691 | * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned. |
||
1692 | * @param NumSpareAreaTowrite number of spare areas to write to block |
||
2 | mjames | 1693 | * @retval HAL status |
1694 | */ |
||
9 | mjames | 1695 | HAL_StatusTypeDef HAL_NAND_Write_SpareArea_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, |
1696 | uint16_t *pBuffer, uint32_t NumSpareAreaTowrite) |
||
2 | mjames | 1697 | { |
9 | mjames | 1698 | uint32_t index; |
1699 | uint32_t tickstart; |
||
1700 | uint32_t deviceaddress; |
||
1701 | uint32_t numspareareawritten = 0; |
||
1702 | uint32_t nandaddress; |
||
1703 | uint32_t columnaddress; |
||
1704 | uint32_t nbspare = NumSpareAreaTowrite; |
||
1705 | uint16_t *buff = pBuffer; |
||
2 | mjames | 1706 | |
1707 | /* Check the NAND controller state */ |
||
9 | mjames | 1708 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 1709 | { |
9 | mjames | 1710 | return HAL_BUSY; |
2 | mjames | 1711 | } |
9 | mjames | 1712 | else if (hnand->State == HAL_NAND_STATE_READY) |
2 | mjames | 1713 | { |
9 | mjames | 1714 | /* Process Locked */ |
1715 | __HAL_LOCK(hnand); |
||
2 | mjames | 1716 | |
9 | mjames | 1717 | /* Update the NAND controller state */ |
1718 | hnand->State = HAL_NAND_STATE_BUSY; |
||
1719 | |||
1720 | /* Identify the device address */ |
||
1721 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
2 | mjames | 1722 | { |
9 | mjames | 1723 | deviceaddress = NAND_DEVICE1; |
1724 | } |
||
1725 | else |
||
1726 | { |
||
1727 | deviceaddress = NAND_DEVICE2; |
||
1728 | } |
||
1729 | |||
1730 | /* NAND raw address calculation */ |
||
1731 | nandaddress = ARRAY_ADDRESS(pAddress, hnand); |
||
1732 | |||
1733 | /* Column in page address */ |
||
1734 | columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand) * 2U); |
||
1735 | |||
1736 | /* Spare area(s) write loop */ |
||
1737 | while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) |
||
1738 | { |
||
1739 | /* Cards with page size <= 512 bytes */ |
||
1740 | if ((hnand->Config.PageSize) <= 512U) |
||
2 | mjames | 1741 | { |
9 | mjames | 1742 | /* Send write Spare area command sequence */ |
1743 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; |
||
1744 | __DSB(); |
||
1745 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; |
||
1746 | __DSB(); |
||
1747 | |||
1748 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
||
1749 | { |
||
1750 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1751 | __DSB(); |
||
1752 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1753 | __DSB(); |
||
1754 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1755 | __DSB(); |
||
1756 | } |
||
1757 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
1758 | { |
||
1759 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; |
||
1760 | __DSB(); |
||
1761 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1762 | __DSB(); |
||
1763 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1764 | __DSB(); |
||
1765 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
1766 | __DSB(); |
||
1767 | } |
||
2 | mjames | 1768 | } |
9 | mjames | 1769 | else /* (hnand->Config.PageSize) > 512 */ |
2 | mjames | 1770 | { |
9 | mjames | 1771 | /* Send write Spare area command sequence */ |
1772 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; |
||
1773 | __DSB(); |
||
1774 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; |
||
1775 | __DSB(); |
||
1776 | |||
1777 | if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) |
||
1778 | { |
||
1779 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); |
||
1780 | __DSB(); |
||
1781 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); |
||
1782 | __DSB(); |
||
1783 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1784 | __DSB(); |
||
1785 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1786 | __DSB(); |
||
1787 | } |
||
1788 | else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ |
||
1789 | { |
||
1790 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); |
||
1791 | __DSB(); |
||
1792 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); |
||
1793 | __DSB(); |
||
1794 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); |
||
1795 | __DSB(); |
||
1796 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); |
||
1797 | __DSB(); |
||
1798 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); |
||
1799 | __DSB(); |
||
1800 | } |
||
2 | mjames | 1801 | } |
9 | mjames | 1802 | |
1803 | /* Write data to memory */ |
||
1804 | for (index = 0U; index < hnand->Config.SpareAreaSize; index++) |
||
2 | mjames | 1805 | { |
9 | mjames | 1806 | *(__IO uint16_t *)deviceaddress = *buff; |
1807 | buff++; |
||
1808 | __DSB(); |
||
2 | mjames | 1809 | } |
9 | mjames | 1810 | |
1811 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; |
||
1812 | __DSB(); |
||
1813 | |||
2 | mjames | 1814 | /* Get tick */ |
1815 | tickstart = HAL_GetTick(); |
||
9 | mjames | 1816 | |
1817 | /* Read status until NAND is ready */ |
||
1818 | while (HAL_NAND_Read_Status(hnand) != NAND_READY) |
||
2 | mjames | 1819 | { |
9 | mjames | 1820 | if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) |
1821 | { |
||
1822 | /* Update the NAND controller state */ |
||
1823 | hnand->State = HAL_NAND_STATE_ERROR; |
||
1824 | |||
1825 | /* Process unlocked */ |
||
1826 | __HAL_UNLOCK(hnand); |
||
1827 | |||
1828 | return HAL_TIMEOUT; |
||
1829 | } |
||
2 | mjames | 1830 | } |
9 | mjames | 1831 | |
1832 | /* Increment written spare areas number */ |
||
1833 | numspareareawritten++; |
||
1834 | |||
1835 | /* Decrement spare areas to write */ |
||
1836 | nbspare--; |
||
1837 | |||
1838 | /* Increment the NAND address */ |
||
1839 | nandaddress = (uint32_t)(nandaddress + 1U); |
||
2 | mjames | 1840 | } |
1841 | |||
9 | mjames | 1842 | /* Update the NAND controller state */ |
1843 | hnand->State = HAL_NAND_STATE_READY; |
||
1844 | |||
1845 | /* Process unlocked */ |
||
1846 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 1847 | } |
9 | mjames | 1848 | else |
1849 | { |
||
1850 | return HAL_ERROR; |
||
1851 | } |
||
2 | mjames | 1852 | |
9 | mjames | 1853 | return HAL_OK; |
2 | mjames | 1854 | } |
1855 | |||
1856 | /** |
||
9 | mjames | 1857 | * @brief NAND memory Block erase |
1858 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
||
2 | mjames | 1859 | * the configuration information for NAND module. |
9 | mjames | 1860 | * @param pAddress pointer to NAND address structure |
2 | mjames | 1861 | * @retval HAL status |
1862 | */ |
||
1863 | HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) |
||
1864 | { |
||
9 | mjames | 1865 | uint32_t deviceaddress; |
1866 | |||
2 | mjames | 1867 | /* Check the NAND controller state */ |
9 | mjames | 1868 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 1869 | { |
9 | mjames | 1870 | return HAL_BUSY; |
2 | mjames | 1871 | } |
9 | mjames | 1872 | else if (hnand->State == HAL_NAND_STATE_READY) |
2 | mjames | 1873 | { |
9 | mjames | 1874 | /* Process Locked */ |
1875 | __HAL_LOCK(hnand); |
||
2 | mjames | 1876 | |
9 | mjames | 1877 | /* Update the NAND controller state */ |
1878 | hnand->State = HAL_NAND_STATE_BUSY; |
||
1879 | |||
1880 | /* Identify the device address */ |
||
1881 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
2 | mjames | 1882 | { |
9 | mjames | 1883 | deviceaddress = NAND_DEVICE1; |
1884 | } |
||
1885 | else |
||
1886 | { |
||
1887 | deviceaddress = NAND_DEVICE2; |
||
1888 | } |
||
2 | mjames | 1889 | |
9 | mjames | 1890 | /* Send Erase block command sequence */ |
1891 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0; |
||
1892 | __DSB(); |
||
1893 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); |
||
1894 | __DSB(); |
||
1895 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); |
||
1896 | __DSB(); |
||
1897 | *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); |
||
1898 | __DSB(); |
||
1899 | |||
1900 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1; |
||
1901 | __DSB(); |
||
1902 | |||
1903 | /* Update the NAND controller state */ |
||
1904 | hnand->State = HAL_NAND_STATE_READY; |
||
1905 | |||
1906 | /* Process unlocked */ |
||
1907 | __HAL_UNLOCK(hnand); |
||
2 | mjames | 1908 | } |
1909 | else |
||
1910 | { |
||
9 | mjames | 1911 | return HAL_ERROR; |
2 | mjames | 1912 | } |
1913 | |||
9 | mjames | 1914 | return HAL_OK; |
2 | mjames | 1915 | } |
1916 | |||
1917 | /** |
||
1918 | * @brief Increment the NAND memory address |
||
9 | mjames | 1919 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 1920 | * the configuration information for NAND module. |
9 | mjames | 1921 | * @param pAddress pointer to NAND address structure |
2 | mjames | 1922 | * @retval The new status of the increment address operation. It can be: |
1923 | * - NAND_VALID_ADDRESS: When the new address is valid address |
||
1924 | * - NAND_INVALID_ADDRESS: When the new address is invalid address |
||
1925 | */ |
||
1926 | uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) |
||
1927 | { |
||
1928 | uint32_t status = NAND_VALID_ADDRESS; |
||
9 | mjames | 1929 | |
2 | mjames | 1930 | /* Increment page address */ |
1931 | pAddress->Page++; |
||
1932 | |||
1933 | /* Check NAND address is valid */ |
||
9 | mjames | 1934 | if (pAddress->Page == hnand->Config.BlockSize) |
2 | mjames | 1935 | { |
9 | mjames | 1936 | pAddress->Page = 0; |
2 | mjames | 1937 | pAddress->Block++; |
9 | mjames | 1938 | |
1939 | if (pAddress->Block == hnand->Config.PlaneSize) |
||
2 | mjames | 1940 | { |
9 | mjames | 1941 | pAddress->Block = 0; |
2 | mjames | 1942 | pAddress->Plane++; |
1943 | |||
9 | mjames | 1944 | if (pAddress->Plane == (hnand->Config.PlaneNbr)) |
2 | mjames | 1945 | { |
1946 | status = NAND_INVALID_ADDRESS; |
||
1947 | } |
||
1948 | } |
||
9 | mjames | 1949 | } |
1950 | |||
2 | mjames | 1951 | return (status); |
1952 | } |
||
9 | mjames | 1953 | |
1954 | #if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) |
||
2 | mjames | 1955 | /** |
9 | mjames | 1956 | * @brief Register a User NAND Callback |
1957 | * To be used instead of the weak (surcharged) predefined callback |
||
1958 | * @param hnand : NAND handle |
||
1959 | * @param CallbackId : ID of the callback to be registered |
||
1960 | * This parameter can be one of the following values: |
||
1961 | * @arg @ref HAL_NAND_MSP_INIT_CB_ID NAND MspInit callback ID |
||
1962 | * @arg @ref HAL_NAND_MSP_DEINIT_CB_ID NAND MspDeInit callback ID |
||
1963 | * @arg @ref HAL_NAND_IT_CB_ID NAND IT callback ID |
||
1964 | * @param pCallback : pointer to the Callback function |
||
1965 | * @retval status |
||
1966 | */ |
||
1967 | HAL_StatusTypeDef HAL_NAND_RegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId, |
||
1968 | pNAND_CallbackTypeDef pCallback) |
||
1969 | { |
||
1970 | HAL_StatusTypeDef status = HAL_OK; |
||
1971 | |||
1972 | if (pCallback == NULL) |
||
1973 | { |
||
1974 | return HAL_ERROR; |
||
1975 | } |
||
1976 | |||
1977 | /* Process locked */ |
||
1978 | __HAL_LOCK(hnand); |
||
1979 | |||
1980 | if (hnand->State == HAL_NAND_STATE_READY) |
||
1981 | { |
||
1982 | switch (CallbackId) |
||
1983 | { |
||
1984 | case HAL_NAND_MSP_INIT_CB_ID : |
||
1985 | hnand->MspInitCallback = pCallback; |
||
1986 | break; |
||
1987 | case HAL_NAND_MSP_DEINIT_CB_ID : |
||
1988 | hnand->MspDeInitCallback = pCallback; |
||
1989 | break; |
||
1990 | case HAL_NAND_IT_CB_ID : |
||
1991 | hnand->ItCallback = pCallback; |
||
1992 | break; |
||
1993 | default : |
||
1994 | /* update return status */ |
||
1995 | status = HAL_ERROR; |
||
1996 | break; |
||
1997 | } |
||
1998 | } |
||
1999 | else if (hnand->State == HAL_NAND_STATE_RESET) |
||
2000 | { |
||
2001 | switch (CallbackId) |
||
2002 | { |
||
2003 | case HAL_NAND_MSP_INIT_CB_ID : |
||
2004 | hnand->MspInitCallback = pCallback; |
||
2005 | break; |
||
2006 | case HAL_NAND_MSP_DEINIT_CB_ID : |
||
2007 | hnand->MspDeInitCallback = pCallback; |
||
2008 | break; |
||
2009 | default : |
||
2010 | /* update return status */ |
||
2011 | status = HAL_ERROR; |
||
2012 | break; |
||
2013 | } |
||
2014 | } |
||
2015 | else |
||
2016 | { |
||
2017 | /* update return status */ |
||
2018 | status = HAL_ERROR; |
||
2019 | } |
||
2020 | |||
2021 | /* Release Lock */ |
||
2022 | __HAL_UNLOCK(hnand); |
||
2023 | return status; |
||
2024 | } |
||
2025 | |||
2026 | /** |
||
2027 | * @brief Unregister a User NAND Callback |
||
2028 | * NAND Callback is redirected to the weak (surcharged) predefined callback |
||
2029 | * @param hnand : NAND handle |
||
2030 | * @param CallbackId : ID of the callback to be unregistered |
||
2031 | * This parameter can be one of the following values: |
||
2032 | * @arg @ref HAL_NAND_MSP_INIT_CB_ID NAND MspInit callback ID |
||
2033 | * @arg @ref HAL_NAND_MSP_DEINIT_CB_ID NAND MspDeInit callback ID |
||
2034 | * @arg @ref HAL_NAND_IT_CB_ID NAND IT callback ID |
||
2035 | * @retval status |
||
2036 | */ |
||
2037 | HAL_StatusTypeDef HAL_NAND_UnRegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId) |
||
2038 | { |
||
2039 | HAL_StatusTypeDef status = HAL_OK; |
||
2040 | |||
2041 | /* Process locked */ |
||
2042 | __HAL_LOCK(hnand); |
||
2043 | |||
2044 | if (hnand->State == HAL_NAND_STATE_READY) |
||
2045 | { |
||
2046 | switch (CallbackId) |
||
2047 | { |
||
2048 | case HAL_NAND_MSP_INIT_CB_ID : |
||
2049 | hnand->MspInitCallback = HAL_NAND_MspInit; |
||
2050 | break; |
||
2051 | case HAL_NAND_MSP_DEINIT_CB_ID : |
||
2052 | hnand->MspDeInitCallback = HAL_NAND_MspDeInit; |
||
2053 | break; |
||
2054 | case HAL_NAND_IT_CB_ID : |
||
2055 | hnand->ItCallback = HAL_NAND_ITCallback; |
||
2056 | break; |
||
2057 | default : |
||
2058 | /* update return status */ |
||
2059 | status = HAL_ERROR; |
||
2060 | break; |
||
2061 | } |
||
2062 | } |
||
2063 | else if (hnand->State == HAL_NAND_STATE_RESET) |
||
2064 | { |
||
2065 | switch (CallbackId) |
||
2066 | { |
||
2067 | case HAL_NAND_MSP_INIT_CB_ID : |
||
2068 | hnand->MspInitCallback = HAL_NAND_MspInit; |
||
2069 | break; |
||
2070 | case HAL_NAND_MSP_DEINIT_CB_ID : |
||
2071 | hnand->MspDeInitCallback = HAL_NAND_MspDeInit; |
||
2072 | break; |
||
2073 | default : |
||
2074 | /* update return status */ |
||
2075 | status = HAL_ERROR; |
||
2076 | break; |
||
2077 | } |
||
2078 | } |
||
2079 | else |
||
2080 | { |
||
2081 | /* update return status */ |
||
2082 | status = HAL_ERROR; |
||
2083 | } |
||
2084 | |||
2085 | /* Release Lock */ |
||
2086 | __HAL_UNLOCK(hnand); |
||
2087 | return status; |
||
2088 | } |
||
2089 | #endif |
||
2090 | |||
2091 | /** |
||
2 | mjames | 2092 | * @} |
2093 | */ |
||
2094 | |||
9 | mjames | 2095 | /** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions |
2096 | * @brief management functions |
||
2097 | * |
||
2098 | @verbatim |
||
2 | mjames | 2099 | ============================================================================== |
2100 | ##### NAND Control functions ##### |
||
9 | mjames | 2101 | ============================================================================== |
2 | mjames | 2102 | [..] |
2103 | This subsection provides a set of functions allowing to control dynamically |
||
2104 | the NAND interface. |
||
2105 | |||
2106 | @endverbatim |
||
2107 | * @{ |
||
9 | mjames | 2108 | */ |
2 | mjames | 2109 | |
9 | mjames | 2110 | |
2 | mjames | 2111 | /** |
2112 | * @brief Enables dynamically NAND ECC feature. |
||
9 | mjames | 2113 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 2114 | * the configuration information for NAND module. |
2115 | * @retval HAL status |
||
9 | mjames | 2116 | */ |
2 | mjames | 2117 | HAL_StatusTypeDef HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand) |
2118 | { |
||
2119 | /* Check the NAND controller state */ |
||
9 | mjames | 2120 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 2121 | { |
9 | mjames | 2122 | return HAL_BUSY; |
2 | mjames | 2123 | } |
9 | mjames | 2124 | else if (hnand->State == HAL_NAND_STATE_READY) |
2125 | { |
||
2126 | /* Update the NAND state */ |
||
2127 | hnand->State = HAL_NAND_STATE_BUSY; |
||
2 | mjames | 2128 | |
9 | mjames | 2129 | /* Enable ECC feature */ |
2130 | (void)FSMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank); |
||
2131 | |||
2132 | /* Update the NAND state */ |
||
2133 | hnand->State = HAL_NAND_STATE_READY; |
||
2134 | } |
||
2135 | else |
||
2136 | { |
||
2137 | return HAL_ERROR; |
||
2138 | } |
||
2139 | |||
2 | mjames | 2140 | return HAL_OK; |
2141 | } |
||
2142 | |||
2143 | /** |
||
2144 | * @brief Disables dynamically FSMC_NAND ECC feature. |
||
9 | mjames | 2145 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 2146 | * the configuration information for NAND module. |
2147 | * @retval HAL status |
||
9 | mjames | 2148 | */ |
2 | mjames | 2149 | HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand) |
2150 | { |
||
2151 | /* Check the NAND controller state */ |
||
9 | mjames | 2152 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 2153 | { |
9 | mjames | 2154 | return HAL_BUSY; |
2 | mjames | 2155 | } |
9 | mjames | 2156 | else if (hnand->State == HAL_NAND_STATE_READY) |
2157 | { |
||
2158 | /* Update the NAND state */ |
||
2159 | hnand->State = HAL_NAND_STATE_BUSY; |
||
2 | mjames | 2160 | |
9 | mjames | 2161 | /* Disable ECC feature */ |
2162 | (void)FSMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank); |
||
2163 | |||
2164 | /* Update the NAND state */ |
||
2165 | hnand->State = HAL_NAND_STATE_READY; |
||
2166 | } |
||
2167 | else |
||
2168 | { |
||
2169 | return HAL_ERROR; |
||
2170 | } |
||
2171 | |||
2172 | return HAL_OK; |
||
2 | mjames | 2173 | } |
2174 | |||
2175 | /** |
||
2176 | * @brief Disables dynamically NAND ECC feature. |
||
9 | mjames | 2177 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 2178 | * the configuration information for NAND module. |
9 | mjames | 2179 | * @param ECCval pointer to ECC value |
2180 | * @param Timeout maximum timeout to wait |
||
2 | mjames | 2181 | * @retval HAL status |
2182 | */ |
||
2183 | HAL_StatusTypeDef HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout) |
||
2184 | { |
||
9 | mjames | 2185 | HAL_StatusTypeDef status; |
2186 | |||
2 | mjames | 2187 | /* Check the NAND controller state */ |
9 | mjames | 2188 | if (hnand->State == HAL_NAND_STATE_BUSY) |
2 | mjames | 2189 | { |
9 | mjames | 2190 | return HAL_BUSY; |
2 | mjames | 2191 | } |
9 | mjames | 2192 | else if (hnand->State == HAL_NAND_STATE_READY) |
2193 | { |
||
2194 | /* Update the NAND state */ |
||
2195 | hnand->State = HAL_NAND_STATE_BUSY; |
||
2 | mjames | 2196 | |
9 | mjames | 2197 | /* Get NAND ECC value */ |
2198 | status = FSMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout); |
||
2199 | |||
2200 | /* Update the NAND state */ |
||
2201 | hnand->State = HAL_NAND_STATE_READY; |
||
2202 | } |
||
2203 | else |
||
2204 | { |
||
2205 | return HAL_ERROR; |
||
2206 | } |
||
2207 | |||
2208 | return status; |
||
2 | mjames | 2209 | } |
2210 | |||
2211 | /** |
||
2212 | * @} |
||
2213 | */ |
||
9 | mjames | 2214 | |
2215 | |||
2216 | /** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions |
||
2217 | * @brief Peripheral State functions |
||
2218 | * |
||
2219 | @verbatim |
||
2 | mjames | 2220 | ============================================================================== |
2221 | ##### NAND State functions ##### |
||
9 | mjames | 2222 | ============================================================================== |
2 | mjames | 2223 | [..] |
9 | mjames | 2224 | This subsection permits to get in run-time the status of the NAND controller |
2 | mjames | 2225 | and the data flow. |
2226 | |||
2227 | @endverbatim |
||
2228 | * @{ |
||
2229 | */ |
||
9 | mjames | 2230 | |
2 | mjames | 2231 | /** |
2232 | * @brief return the NAND state |
||
9 | mjames | 2233 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
2 | mjames | 2234 | * the configuration information for NAND module. |
2235 | * @retval HAL state |
||
2236 | */ |
||
2237 | HAL_NAND_StateTypeDef HAL_NAND_GetState(NAND_HandleTypeDef *hnand) |
||
2238 | { |
||
2239 | return hnand->State; |
||
2240 | } |
||
2241 | |||
2242 | /** |
||
9 | mjames | 2243 | * @brief NAND memory read status |
2244 | * @param hnand pointer to a NAND_HandleTypeDef structure that contains |
||
2245 | * the configuration information for NAND module. |
||
2246 | * @retval NAND status |
||
2247 | */ |
||
2248 | uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand) |
||
2249 | { |
||
2250 | uint32_t data; |
||
2251 | uint32_t deviceaddress; |
||
2252 | UNUSED(hnand); |
||
2253 | |||
2254 | /* Identify the device address */ |
||
2255 | if (hnand->Init.NandBank == FSMC_NAND_BANK2) |
||
2256 | { |
||
2257 | deviceaddress = NAND_DEVICE1; |
||
2258 | } |
||
2259 | else |
||
2260 | { |
||
2261 | deviceaddress = NAND_DEVICE2; |
||
2262 | } |
||
2263 | |||
2264 | /* Send Read status operation command */ |
||
2265 | *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS; |
||
2266 | |||
2267 | /* Read status register data */ |
||
2268 | data = *(__IO uint8_t *)deviceaddress; |
||
2269 | |||
2270 | /* Return the status */ |
||
2271 | if ((data & NAND_ERROR) == NAND_ERROR) |
||
2272 | { |
||
2273 | return NAND_ERROR; |
||
2274 | } |
||
2275 | else if ((data & NAND_READY) == NAND_READY) |
||
2276 | { |
||
2277 | return NAND_READY; |
||
2278 | } |
||
2279 | else |
||
2280 | { |
||
2281 | return NAND_BUSY; |
||
2282 | } |
||
2283 | } |
||
2284 | |||
2285 | /** |
||
2 | mjames | 2286 | * @} |
9 | mjames | 2287 | */ |
2 | mjames | 2288 | |
2289 | /** |
||
2290 | * @} |
||
2291 | */ |
||
2292 | |||
2293 | /** |
||
2294 | * @} |
||
2295 | */ |
||
2296 | |||
2297 | #endif /* HAL_NAND_MODULE_ENABLED */ |
||
2298 | |||
2299 | /** |
||
2300 | * @} |
||
2301 | */ |
||
2302 | |||
9 | mjames | 2303 | #endif /* FSMC_BANK3 */ |
2304 | |||
2 | mjames | 2305 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |