Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
stm32l4xx_hal_nand.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32l4xx_hal_nand.c 00004 * @author MCD Application Team 00005 * @version V1.5.1 00006 * @date 31-May-2016 00007 * @brief NAND HAL module driver. 00008 * This file provides a generic firmware to drive NAND memories mounted 00009 * as external device. 00010 * 00011 @verbatim 00012 ============================================================================== 00013 ##### How to use this driver ##### 00014 ============================================================================== 00015 [..] 00016 This driver is a generic layered driver which contains a set of APIs used to 00017 control NAND flash memories. It uses the FMC layer functions to interface 00018 with NAND devices. This driver is used as follows: 00019 00020 (+) NAND flash memory configuration sequence using the function HAL_NAND_Init() 00021 with control and timing parameters for both common and attribute spaces. 00022 00023 (+) Read NAND flash memory maker and device IDs using the function 00024 HAL_NAND_Read_ID(). The read information is stored in the NAND_ID_TypeDef 00025 structure declared by the function caller. 00026 00027 (+) Access NAND flash memory by read/write operations using the functions 00028 HAL_NAND_Read_Page()/HAL_NAND_Read_SpareArea(), HAL_NAND_Write_Page()/HAL_NAND_Write_SpareArea() 00029 to read/write page(s)/spare area(s). These functions use specific device 00030 information (Block, page size..) predefined by the user in the HAL_NAND_Info_TypeDef 00031 structure. The read/write address information is contained by the Nand_Address_Typedef 00032 structure passed as parameter. 00033 00034 (+) Perform NAND flash Reset chip operation using the function HAL_NAND_Reset(). 00035 00036 (+) Perform NAND flash erase block operation using the function HAL_NAND_Erase_Block(). 00037 The erase block address information is contained in the Nand_Address_Typedef 00038 structure passed as parameter. 00039 00040 (+) Read the NAND flash status operation using the function HAL_NAND_Read_Status(). 00041 00042 (+) You can also control the NAND device by calling the control APIs HAL_NAND_ECC_Enable()/ 00043 HAL_NAND_ECC_Disable() to respectively enable/disable the ECC code correction 00044 feature or the function HAL_NAND_GetECC() to get the ECC correction code. 00045 00046 (+) You can monitor the NAND device HAL state by calling the function 00047 HAL_NAND_GetState() 00048 00049 [..] 00050 (@) This driver is a set of generic APIs which handle standard NAND flash operations. 00051 If a NAND flash device contains different operations and/or implementations, 00052 it should be implemented separately. 00053 00054 @endverbatim 00055 ****************************************************************************** 00056 * @attention 00057 * 00058 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00059 * 00060 * Redistribution and use in source and binary forms, with or without modification, 00061 * are permitted provided that the following conditions are met: 00062 * 1. Redistributions of source code must retain the above copyright notice, 00063 * this list of conditions and the following disclaimer. 00064 * 2. Redistributions in binary form must reproduce the above copyright notice, 00065 * this list of conditions and the following disclaimer in the documentation 00066 * and/or other materials provided with the distribution. 00067 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00068 * may be used to endorse or promote products derived from this software 00069 * without specific prior written permission. 00070 * 00071 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00072 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00073 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00074 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00075 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00076 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00077 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00078 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00079 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00080 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00081 * 00082 ****************************************************************************** 00083 */ 00084 00085 /* Includes ------------------------------------------------------------------*/ 00086 #include "stm32l4xx_hal.h" 00087 00088 #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) 00089 00090 /** @addtogroup STM32L4xx_HAL_Driver 00091 * @{ 00092 */ 00093 00094 #ifdef HAL_NAND_MODULE_ENABLED 00095 00096 /** @defgroup NAND NAND 00097 * @brief NAND HAL module driver 00098 * @{ 00099 */ 00100 00101 /* Private typedef -----------------------------------------------------------*/ 00102 /* Private define ------------------------------------------------------------*/ 00103 /** @defgroup NAND_Private_Constants NAND Private Constants 00104 * @{ 00105 */ 00106 00107 /** 00108 * @} 00109 */ 00110 00111 /* Private macro -------------------------------------------------------------*/ 00112 /** @defgroup NAND_Private_Macros NAND Private Macros 00113 * @{ 00114 */ 00115 00116 /** 00117 * @} 00118 */ 00119 00120 /* Private variables ---------------------------------------------------------*/ 00121 /* Private function prototypes -----------------------------------------------*/ 00122 /** @defgroup NAND_Private_Functions NAND Private Functions 00123 * @{ 00124 */ 00125 static uint32_t NAND_AddressIncrement(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef* Address); 00126 /** 00127 * @} 00128 */ 00129 00130 /* Exported functions ---------------------------------------------------------*/ 00131 00132 /** @defgroup NAND_Exported_Functions NAND Exported Functions 00133 * @{ 00134 */ 00135 00136 /** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions 00137 * @brief Initialization and Configuration functions 00138 * 00139 @verbatim 00140 ============================================================================== 00141 ##### NAND Initialization and de-initialization functions ##### 00142 ============================================================================== 00143 [..] 00144 This section provides functions allowing to initialize/de-initialize 00145 the NAND memory 00146 00147 @endverbatim 00148 * @{ 00149 */ 00150 00151 /** 00152 * @brief Perform NAND memory Initialization sequence. 00153 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00154 * the configuration information for NAND module. 00155 * @param ComSpace_Timing: pointer to Common space timing structure 00156 * @param AttSpace_Timing: pointer to Attribute space timing structure 00157 * @retval HAL status 00158 */ 00159 HAL_StatusTypeDef HAL_NAND_Init(NAND_HandleTypeDef *hnand, FMC_NAND_PCC_TimingTypeDef *ComSpace_Timing, FMC_NAND_PCC_TimingTypeDef *AttSpace_Timing) 00160 { 00161 /* Check the NAND handle state */ 00162 if(hnand == NULL) 00163 { 00164 return HAL_ERROR; 00165 } 00166 00167 if(hnand->State == HAL_NAND_STATE_RESET) 00168 { 00169 /* Allocate lock resource and initialize it */ 00170 hnand->Lock = HAL_UNLOCKED; 00171 00172 /* Initialize the low level hardware (MSP) */ 00173 HAL_NAND_MspInit(hnand); 00174 } 00175 00176 /* Initialize NAND control Interface */ 00177 FMC_NAND_Init(hnand->Instance, &(hnand->Init)); 00178 00179 /* Initialize NAND common space timing Interface */ 00180 FMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank); 00181 00182 /* Initialize NAND attribute space timing Interface */ 00183 FMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank); 00184 00185 /* Enable the NAND device */ 00186 __FMC_NAND_ENABLE(hnand->Instance, hnand->Init.NandBank); 00187 00188 /* Update the NAND controller state */ 00189 hnand->State = HAL_NAND_STATE_READY; 00190 00191 return HAL_OK; 00192 } 00193 00194 /** 00195 * @brief Perform NAND memory De-Initialization sequence. 00196 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00197 * the configuration information for NAND module. 00198 * @retval HAL status 00199 */ 00200 HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand) 00201 { 00202 /* Initialize the low level hardware (MSP) */ 00203 HAL_NAND_MspDeInit(hnand); 00204 00205 /* Configure the NAND registers with their reset values */ 00206 FMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank); 00207 00208 /* Reset the NAND controller state */ 00209 hnand->State = HAL_NAND_STATE_RESET; 00210 00211 /* Release Lock */ 00212 __HAL_UNLOCK(hnand); 00213 00214 return HAL_OK; 00215 } 00216 00217 /** 00218 * @brief Initialize the NAND MSP. 00219 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00220 * the configuration information for NAND module. 00221 * @retval None 00222 */ 00223 __weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand) 00224 { 00225 /* Prevent unused argument(s) compilation warning */ 00226 UNUSED(hnand); 00227 00228 /* NOTE : This function should not be modified, when the callback is needed, 00229 the HAL_NAND_MspInit could be implemented in the user file 00230 */ 00231 } 00232 00233 /** 00234 * @brief DeInitialize the NAND MSP. 00235 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00236 * the configuration information for NAND module. 00237 * @retval None 00238 */ 00239 __weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand) 00240 { 00241 /* Prevent unused argument(s) compilation warning */ 00242 UNUSED(hnand); 00243 00244 /* NOTE : This function should not be modified, when the callback is needed, 00245 the HAL_NAND_MspDeInit could be implemented in the user file 00246 */ 00247 } 00248 00249 00250 /** 00251 * @brief This function handles NAND device interrupt request. 00252 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00253 * the configuration information for NAND module. 00254 * @retval HAL status 00255 */ 00256 void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand) 00257 { 00258 /* Check NAND interrupt Rising edge flag */ 00259 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE)) 00260 { 00261 /* NAND interrupt callback*/ 00262 HAL_NAND_ITCallback(hnand); 00263 00264 /* Clear NAND interrupt Rising edge pending bit */ 00265 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE); 00266 } 00267 00268 /* Check NAND interrupt Level flag */ 00269 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL)) 00270 { 00271 /* NAND interrupt callback*/ 00272 HAL_NAND_ITCallback(hnand); 00273 00274 /* Clear NAND interrupt Level pending bit */ 00275 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL); 00276 } 00277 00278 /* Check NAND interrupt Falling edge flag */ 00279 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE)) 00280 { 00281 /* NAND interrupt callback*/ 00282 HAL_NAND_ITCallback(hnand); 00283 00284 /* Clear NAND interrupt Falling edge pending bit */ 00285 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE); 00286 } 00287 00288 /* Check NAND interrupt FIFO empty flag */ 00289 if(__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT)) 00290 { 00291 /* NAND interrupt callback*/ 00292 HAL_NAND_ITCallback(hnand); 00293 00294 /* Clear NAND interrupt FIFO empty pending bit */ 00295 __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT); 00296 } 00297 } 00298 00299 /** 00300 * @brief NAND interrupt feature callback. 00301 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00302 * the configuration information for NAND module. 00303 * @retval None 00304 */ 00305 __weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand) 00306 { 00307 /* Prevent unused argument(s) compilation warning */ 00308 UNUSED(hnand); 00309 00310 /* NOTE : This function should not be modified, when the callback is needed, 00311 the HAL_NAND_ITCallback could be implemented in the user file 00312 */ 00313 } 00314 00315 /** 00316 * @} 00317 */ 00318 00319 /** @defgroup NAND_Exported_Functions_Group2 Input and Output functions 00320 * @brief Input Output and memory control functions 00321 * 00322 @verbatim 00323 ============================================================================== 00324 ##### NAND Input and Output functions ##### 00325 ============================================================================== 00326 [..] 00327 This section provides functions allowing to use and control the NAND 00328 memory 00329 00330 @endverbatim 00331 * @{ 00332 */ 00333 00334 /** 00335 * @brief Read the NAND memory electronic signature. 00336 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00337 * the configuration information for NAND module. 00338 * @param pNAND_ID: NAND ID structure 00339 * @retval HAL status 00340 */ 00341 HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID) 00342 { 00343 __IO uint32_t data = 0; 00344 uint32_t deviceaddress = 0; 00345 00346 /* Process Locked */ 00347 __HAL_LOCK(hnand); 00348 00349 /* Check the NAND controller state */ 00350 if(hnand->State == HAL_NAND_STATE_BUSY) 00351 { 00352 return HAL_BUSY; 00353 } 00354 00355 /* Identify the device address */ 00356 deviceaddress = NAND_DEVICE; 00357 00358 /* Update the NAND controller state */ 00359 hnand->State = HAL_NAND_STATE_BUSY; 00360 00361 /* Send Read ID command sequence */ 00362 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_READID; 00363 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 00364 00365 /* Read the electronic signature from NAND flash */ 00366 data = *(__IO uint32_t *)deviceaddress; 00367 00368 /* Return the data read */ 00369 pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data); 00370 pNAND_ID->Device_Id = ADDR_2ND_CYCLE(data); 00371 pNAND_ID->Third_Id = ADDR_3RD_CYCLE(data); 00372 pNAND_ID->Fourth_Id = ADDR_4TH_CYCLE(data); 00373 00374 /* Update the NAND controller state */ 00375 hnand->State = HAL_NAND_STATE_READY; 00376 00377 /* Process unlocked */ 00378 __HAL_UNLOCK(hnand); 00379 00380 return HAL_OK; 00381 } 00382 00383 /** 00384 * @brief NAND memory reset. 00385 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00386 * the configuration information for NAND module. 00387 * @retval HAL status 00388 */ 00389 HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand) 00390 { 00391 uint32_t deviceaddress = 0; 00392 00393 /* Process Locked */ 00394 __HAL_LOCK(hnand); 00395 00396 /* Check the NAND controller state */ 00397 if(hnand->State == HAL_NAND_STATE_BUSY) 00398 { 00399 return HAL_BUSY; 00400 } 00401 00402 /* Identify the device address */ 00403 deviceaddress = NAND_DEVICE; 00404 00405 /* Update the NAND controller state */ 00406 hnand->State = HAL_NAND_STATE_BUSY; 00407 00408 /* Send NAND reset command */ 00409 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF; 00410 00411 00412 /* Update the NAND controller state */ 00413 hnand->State = HAL_NAND_STATE_READY; 00414 00415 /* Process unlocked */ 00416 __HAL_UNLOCK(hnand); 00417 00418 return HAL_OK; 00419 00420 } 00421 00422 /** 00423 * @brief Read Page(s) from NAND memory block. 00424 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00425 * the configuration information for NAND module. 00426 * @param pAddress: pointer to NAND address structure 00427 * @param pBuffer: pointer to destination read buffer 00428 * @param NumPageToRead: number of pages to read from block 00429 * @retval HAL status 00430 */ 00431 HAL_StatusTypeDef HAL_NAND_Read_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead) 00432 { 00433 __IO uint32_t index = 0; 00434 uint32_t deviceaddress = 0, size = 0, numpagesread = 0, addressstatus = NAND_VALID_ADDRESS; 00435 NAND_AddressTypeDef nandaddress; 00436 uint32_t addressoffset = 0; 00437 00438 /* Process Locked */ 00439 __HAL_LOCK(hnand); 00440 00441 /* Check the NAND controller state */ 00442 if(hnand->State == HAL_NAND_STATE_BUSY) 00443 { 00444 return HAL_BUSY; 00445 } 00446 00447 /* Identify the device address */ 00448 deviceaddress = NAND_DEVICE; 00449 00450 /* Update the NAND controller state */ 00451 hnand->State = HAL_NAND_STATE_BUSY; 00452 00453 /* Save the content of pAddress as it will be modified */ 00454 nandaddress.Block = pAddress->Block; 00455 nandaddress.Page = pAddress->Page; 00456 nandaddress.Zone = pAddress->Zone; 00457 00458 /* Page(s) read loop */ 00459 while((NumPageToRead != 0) && (addressstatus == NAND_VALID_ADDRESS)) 00460 { 00461 /* update the buffer size */ 00462 size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpagesread); 00463 00464 /* Get the address offset */ 00465 addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); 00466 00467 /* Send read page command sequence */ 00468 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; 00469 00470 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 00471 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); 00472 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); 00473 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); 00474 00475 /* for 512 and 1 GB devices, 4th cycle is required */ 00476 if(hnand->Info.BlockNbr >= 1024) 00477 { 00478 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); 00479 } 00480 00481 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; 00482 00483 /* Get Data into Buffer */ 00484 for(; index < size; index++) 00485 { 00486 *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress; 00487 } 00488 00489 /* Increment read pages number */ 00490 numpagesread++; 00491 00492 /* Decrement pages to read */ 00493 NumPageToRead--; 00494 00495 /* Increment the NAND address */ 00496 addressstatus = NAND_AddressIncrement(hnand, &nandaddress); 00497 } 00498 00499 /* Update the NAND controller state */ 00500 hnand->State = HAL_NAND_STATE_READY; 00501 00502 /* Process unlocked */ 00503 __HAL_UNLOCK(hnand); 00504 00505 return HAL_OK; 00506 00507 } 00508 00509 /** 00510 * @brief Write Page(s) to NAND memory block. 00511 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00512 * the configuration information for NAND module. 00513 * @param pAddress: pointer to NAND address structure 00514 * @param pBuffer: pointer to source buffer to write 00515 * @param NumPageToWrite: number of pages to write to block 00516 * @retval HAL status 00517 */ 00518 HAL_StatusTypeDef HAL_NAND_Write_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite) 00519 { 00520 __IO uint32_t index = 0; 00521 uint32_t tickstart = 0; 00522 uint32_t deviceaddress = 0 , size = 0, numpageswritten = 0, addressstatus = NAND_VALID_ADDRESS; 00523 NAND_AddressTypeDef nandaddress; 00524 uint32_t addressoffset = 0; 00525 00526 /* Process Locked */ 00527 __HAL_LOCK(hnand); 00528 00529 /* Check the NAND controller state */ 00530 if(hnand->State == HAL_NAND_STATE_BUSY) 00531 { 00532 return HAL_BUSY; 00533 } 00534 00535 /* Identify the device address */ 00536 deviceaddress = NAND_DEVICE; 00537 00538 /* Update the NAND controller state */ 00539 hnand->State = HAL_NAND_STATE_BUSY; 00540 00541 /* Save the content of pAddress as it will be modified */ 00542 nandaddress.Block = pAddress->Block; 00543 nandaddress.Page = pAddress->Page; 00544 nandaddress.Zone = pAddress->Zone; 00545 00546 /* Page(s) write loop */ 00547 while((NumPageToWrite != 0) && (addressstatus == NAND_VALID_ADDRESS)) 00548 { 00549 /* update the buffer size */ 00550 size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpageswritten); 00551 00552 /* Get the address offset */ 00553 addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); 00554 00555 /* Send write page command sequence */ 00556 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; 00557 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; 00558 00559 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 00560 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); 00561 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); 00562 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); 00563 00564 /* for 512 and 1 GB devices, 4th cycle is required */ 00565 if(hnand->Info.BlockNbr >= 1024) 00566 { 00567 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); 00568 } 00569 00570 /* Write data to memory */ 00571 for(; index < size; index++) 00572 { 00573 *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++; 00574 } 00575 00576 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; 00577 00578 /* Get tick */ 00579 tickstart = HAL_GetTick(); 00580 00581 /* Read status until NAND is ready */ 00582 while(HAL_NAND_Read_Status(hnand) != NAND_READY) 00583 { 00584 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) 00585 { 00586 return HAL_TIMEOUT; 00587 } 00588 } 00589 00590 /* Increment written pages number */ 00591 numpageswritten++; 00592 00593 /* Decrement pages to write */ 00594 NumPageToWrite--; 00595 00596 /* Increment the NAND address */ 00597 addressstatus = NAND_AddressIncrement(hnand, &nandaddress); 00598 } 00599 00600 /* Update the NAND controller state */ 00601 hnand->State = HAL_NAND_STATE_READY; 00602 00603 /* Process unlocked */ 00604 __HAL_UNLOCK(hnand); 00605 00606 return HAL_OK; 00607 } 00608 00609 /** 00610 * @brief Read Spare area(s) from NAND memory. 00611 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00612 * the configuration information for NAND module. 00613 * @param pAddress: pointer to NAND address structure 00614 * @param pBuffer: pointer to source buffer to write 00615 * @param NumSpareAreaToRead: Number of spare area to read 00616 * @retval HAL status 00617 */ 00618 HAL_StatusTypeDef HAL_NAND_Read_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead) 00619 { 00620 __IO uint32_t index = 0; 00621 uint32_t deviceaddress = 0, size = 0, num_spare_area_read = 0, addressstatus = NAND_VALID_ADDRESS; 00622 NAND_AddressTypeDef nandaddress; 00623 uint32_t addressoffset = 0; 00624 00625 /* Process Locked */ 00626 __HAL_LOCK(hnand); 00627 00628 /* Check the NAND controller state */ 00629 if(hnand->State == HAL_NAND_STATE_BUSY) 00630 { 00631 return HAL_BUSY; 00632 } 00633 00634 /* Identify the device address */ 00635 deviceaddress = NAND_DEVICE; 00636 00637 /* Update the NAND controller state */ 00638 hnand->State = HAL_NAND_STATE_BUSY; 00639 00640 /* Save the content of pAddress as it will be modified */ 00641 nandaddress.Block = pAddress->Block; 00642 nandaddress.Page = pAddress->Page; 00643 nandaddress.Zone = pAddress->Zone; 00644 00645 /* Spare area(s) read loop */ 00646 while((NumSpareAreaToRead != 0) && (addressstatus == NAND_VALID_ADDRESS)) 00647 { 00648 /* update the buffer size */ 00649 size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_read); 00650 00651 /* Get the address offset */ 00652 addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); 00653 00654 /* Send read spare area command sequence */ 00655 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; 00656 00657 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 00658 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); 00659 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); 00660 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); 00661 00662 /* for 512 and 1 GB devices, 4th cycle is required */ 00663 if(hnand->Info.BlockNbr >= 1024) 00664 { 00665 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); 00666 } 00667 00668 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; 00669 00670 /* Get Data into Buffer */ 00671 for ( ;index < size; index++) 00672 { 00673 *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress; 00674 } 00675 00676 /* Increment read spare areas number */ 00677 num_spare_area_read++; 00678 00679 /* Decrement spare areas to read */ 00680 NumSpareAreaToRead--; 00681 00682 /* Increment the NAND address */ 00683 addressstatus = NAND_AddressIncrement(hnand, &nandaddress); 00684 } 00685 00686 /* Update the NAND controller state */ 00687 hnand->State = HAL_NAND_STATE_READY; 00688 00689 /* Process unlocked */ 00690 __HAL_UNLOCK(hnand); 00691 00692 return HAL_OK; 00693 } 00694 00695 /** 00696 * @brief Write Spare area(s) to NAND memory. 00697 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00698 * the configuration information for NAND module. 00699 * @param pAddress: pointer to NAND address structure 00700 * @param pBuffer: pointer to source buffer to write 00701 * @param NumSpareAreaTowrite: number of spare areas to write to block 00702 * @retval HAL status 00703 */ 00704 HAL_StatusTypeDef HAL_NAND_Write_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite) 00705 { 00706 __IO uint32_t index = 0; 00707 uint32_t tickstart = 0; 00708 uint32_t deviceaddress = 0, size = 0, num_spare_area_written = 0, addressstatus = NAND_VALID_ADDRESS; 00709 NAND_AddressTypeDef nandaddress; 00710 uint32_t addressoffset = 0; 00711 00712 /* Process Locked */ 00713 __HAL_LOCK(hnand); 00714 00715 /* Check the NAND controller state */ 00716 if(hnand->State == HAL_NAND_STATE_BUSY) 00717 { 00718 return HAL_BUSY; 00719 } 00720 00721 /* Identify the device address */ 00722 deviceaddress = NAND_DEVICE; 00723 00724 /* Update the FMC_NAND controller state */ 00725 hnand->State = HAL_NAND_STATE_BUSY; 00726 00727 /* Save the content of pAddress as it will be modified */ 00728 nandaddress.Block = pAddress->Block; 00729 nandaddress.Page = pAddress->Page; 00730 nandaddress.Zone = pAddress->Zone; 00731 00732 /* Spare area(s) write loop */ 00733 while((NumSpareAreaTowrite != 0) && (addressstatus == NAND_VALID_ADDRESS)) 00734 { 00735 /* update the buffer size */ 00736 size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_written); 00737 00738 /* Get the address offset */ 00739 addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); 00740 00741 /* Send write Spare area command sequence */ 00742 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; 00743 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; 00744 00745 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; 00746 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); 00747 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); 00748 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); 00749 00750 /* for 512 and 1 GB devices, 4th cycle is required */ 00751 if(hnand->Info.BlockNbr >= 1024) 00752 { 00753 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); 00754 } 00755 00756 /* Write data to memory */ 00757 for(; index < size; index++) 00758 { 00759 *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++; 00760 } 00761 00762 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; 00763 00764 /* Get tick */ 00765 tickstart = HAL_GetTick(); 00766 00767 /* Read status until NAND is ready */ 00768 while(HAL_NAND_Read_Status(hnand) != NAND_READY) 00769 { 00770 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) 00771 { 00772 return HAL_TIMEOUT; 00773 } 00774 } 00775 00776 /* Increment written spare areas number */ 00777 num_spare_area_written++; 00778 00779 /* Decrement spare areas to write */ 00780 NumSpareAreaTowrite--; 00781 00782 /* Increment the NAND address */ 00783 addressstatus = NAND_AddressIncrement(hnand, &nandaddress); 00784 } 00785 00786 /* Update the NAND controller state */ 00787 hnand->State = HAL_NAND_STATE_READY; 00788 00789 /* Process unlocked */ 00790 __HAL_UNLOCK(hnand); 00791 00792 return HAL_OK; 00793 } 00794 00795 /** 00796 * @brief NAND memory Block erase. 00797 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00798 * the configuration information for NAND module. 00799 * @param pAddress: pointer to NAND address structure 00800 * @retval HAL status 00801 */ 00802 HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) 00803 { 00804 uint32_t deviceaddress = 0; 00805 uint32_t tickstart = 0; 00806 00807 /* Process Locked */ 00808 __HAL_LOCK(hnand); 00809 00810 /* Check the NAND controller state */ 00811 if(hnand->State == HAL_NAND_STATE_BUSY) 00812 { 00813 return HAL_BUSY; 00814 } 00815 00816 /* Identify the device address */ 00817 deviceaddress = NAND_DEVICE; 00818 00819 /* Update the NAND controller state */ 00820 hnand->State = HAL_NAND_STATE_BUSY; 00821 00822 /* Send Erase block command sequence */ 00823 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0; 00824 00825 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); 00826 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); 00827 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); 00828 00829 /* for 512 and 1 GB devices, 4th cycle is required */ 00830 if(hnand->Info.BlockNbr >= 1024) 00831 { 00832 *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); 00833 } 00834 00835 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1; 00836 00837 /* Update the NAND controller state */ 00838 hnand->State = HAL_NAND_STATE_READY; 00839 00840 /* Get tick */ 00841 tickstart = HAL_GetTick(); 00842 00843 /* Read status until NAND is ready */ 00844 while(HAL_NAND_Read_Status(hnand) != NAND_READY) 00845 { 00846 if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) 00847 { 00848 /* Process unlocked */ 00849 __HAL_UNLOCK(hnand); 00850 00851 return HAL_TIMEOUT; 00852 } 00853 } 00854 00855 /* Process unlocked */ 00856 __HAL_UNLOCK(hnand); 00857 00858 return HAL_OK; 00859 } 00860 00861 /** 00862 * @brief NAND memory read status. 00863 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00864 * the configuration information for NAND module. 00865 * @retval NAND status 00866 */ 00867 uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand) 00868 { 00869 uint32_t data = 0; 00870 uint32_t deviceaddress = 0; 00871 00872 /* Prevent unused argument(s) compilation warning */ 00873 UNUSED(hnand); 00874 00875 /* Identify the device address */ 00876 deviceaddress = NAND_DEVICE; 00877 00878 /* Send Read status operation command */ 00879 *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS; 00880 00881 /* Read status register data */ 00882 data = *(__IO uint8_t *)deviceaddress; 00883 00884 /* Return the status */ 00885 if((data & NAND_ERROR) == NAND_ERROR) 00886 { 00887 return NAND_ERROR; 00888 } 00889 else if((data & NAND_READY) == NAND_READY) 00890 { 00891 return NAND_READY; 00892 } 00893 00894 return NAND_BUSY; 00895 } 00896 00897 /** 00898 * @brief Increment the NAND memory address. 00899 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00900 * the configuration information for NAND module. 00901 * @param pAddress: pointer to NAND address structure 00902 * @retval The new status of the increment address operation. It can be: 00903 * - NAND_VALID_ADDRESS: When the new address is valid address 00904 * - NAND_INVALID_ADDRESS: When the new address is invalid address 00905 */ 00906 uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) 00907 { 00908 uint32_t status = NAND_VALID_ADDRESS; 00909 00910 /* Increment page address */ 00911 pAddress->Page++; 00912 00913 /* Check NAND address is valid */ 00914 if(pAddress->Page == hnand->Info.BlockSize) 00915 { 00916 pAddress->Page = 0; 00917 pAddress->Block++; 00918 00919 if(pAddress->Block == hnand->Info.ZoneSize) 00920 { 00921 pAddress->Block = 0; 00922 pAddress->Zone++; 00923 00924 if(pAddress->Zone == (hnand->Info.ZoneSize/ hnand->Info.BlockNbr)) 00925 { 00926 status = NAND_INVALID_ADDRESS; 00927 } 00928 } 00929 } 00930 00931 return (status); 00932 } 00933 /** 00934 * @} 00935 */ 00936 00937 /** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions 00938 * @brief management functions 00939 * 00940 @verbatim 00941 ============================================================================== 00942 ##### NAND Control functions ##### 00943 ============================================================================== 00944 [..] 00945 This subsection provides a set of functions allowing to control dynamically 00946 the NAND interface. 00947 00948 @endverbatim 00949 * @{ 00950 */ 00951 00952 00953 /** 00954 * @brief Enable dynamically NAND ECC feature. 00955 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00956 * the configuration information for NAND module. 00957 * @retval HAL status 00958 */ 00959 HAL_StatusTypeDef HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand) 00960 { 00961 /* Check the NAND controller state */ 00962 if(hnand->State == HAL_NAND_STATE_BUSY) 00963 { 00964 return HAL_BUSY; 00965 } 00966 00967 /* Update the NAND state */ 00968 hnand->State = HAL_NAND_STATE_BUSY; 00969 00970 /* Enable ECC feature */ 00971 FMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank); 00972 00973 /* Update the NAND state */ 00974 hnand->State = HAL_NAND_STATE_READY; 00975 00976 return HAL_OK; 00977 } 00978 00979 /** 00980 * @brief Disable dynamically NAND ECC feature. 00981 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 00982 * the configuration information for NAND module. 00983 * @retval HAL status 00984 */ 00985 HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand) 00986 { 00987 /* Check the NAND controller state */ 00988 if(hnand->State == HAL_NAND_STATE_BUSY) 00989 { 00990 return HAL_BUSY; 00991 } 00992 00993 /* Update the NAND state */ 00994 hnand->State = HAL_NAND_STATE_BUSY; 00995 00996 /* Disable ECC feature */ 00997 FMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank); 00998 00999 /* Update the NAND state */ 01000 hnand->State = HAL_NAND_STATE_READY; 01001 01002 return HAL_OK; 01003 } 01004 01005 /** 01006 * @brief Disable dynamically NAND ECC feature. 01007 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 01008 * the configuration information for NAND module. 01009 * @param ECCval: pointer to ECC value 01010 * @param Timeout: maximum timeout to wait 01011 * @retval HAL status 01012 */ 01013 HAL_StatusTypeDef HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout) 01014 { 01015 HAL_StatusTypeDef status = HAL_OK; 01016 01017 /* Check the NAND controller state */ 01018 if(hnand->State == HAL_NAND_STATE_BUSY) 01019 { 01020 return HAL_BUSY; 01021 } 01022 01023 /* Update the NAND state */ 01024 hnand->State = HAL_NAND_STATE_BUSY; 01025 01026 /* Get NAND ECC value */ 01027 status = FMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout); 01028 01029 /* Update the NAND state */ 01030 hnand->State = HAL_NAND_STATE_READY; 01031 01032 return status; 01033 } 01034 01035 /** 01036 * @} 01037 */ 01038 01039 01040 /** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions 01041 * @brief Peripheral State functions 01042 * 01043 @verbatim 01044 ============================================================================== 01045 ##### NAND State functions ##### 01046 ============================================================================== 01047 [..] 01048 This subsection permits to get in run-time the status of the NAND controller 01049 and the data flow. 01050 01051 @endverbatim 01052 * @{ 01053 */ 01054 01055 /** 01056 * @brief Return the NAND handle state. 01057 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 01058 * the configuration information for NAND module. 01059 * @retval HAL state 01060 */ 01061 HAL_NAND_StateTypeDef HAL_NAND_GetState(NAND_HandleTypeDef *hnand) 01062 { 01063 /* Return NAND handle state */ 01064 return hnand->State; 01065 } 01066 01067 /** 01068 * @} 01069 */ 01070 01071 /** 01072 * @} 01073 */ 01074 01075 /** @addtogroup NAND_Private_Functions 01076 * @{ 01077 */ 01078 01079 /** 01080 * @brief Increment the NAND memory address. 01081 * @param hnand: pointer to a NAND_HandleTypeDef structure that contains 01082 * the configuration information for NAND module. 01083 * @param Address: address to be incremented. 01084 * @retval The new status of the increment address operation. It can be: 01085 * - NAND_VALID_ADDRESS: When the new address is valid address 01086 * - NAND_INVALID_ADDRESS: When the new address is invalid address 01087 */ 01088 static uint32_t NAND_AddressIncrement(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef* Address) 01089 { 01090 uint32_t status = NAND_VALID_ADDRESS; 01091 01092 Address->Page++; 01093 01094 if(Address->Page == hnand->Info.BlockSize) 01095 { 01096 Address->Page = 0; 01097 Address->Block++; 01098 01099 if(Address->Block == hnand->Info.ZoneSize) 01100 { 01101 Address->Block = 0; 01102 Address->Zone++; 01103 01104 if(Address->Zone == hnand->Info.BlockNbr) 01105 { 01106 status = NAND_INVALID_ADDRESS; 01107 } 01108 } 01109 } 01110 01111 return (status); 01112 } 01113 01114 /** 01115 * @} 01116 */ 01117 01118 /** 01119 * @} 01120 */ 01121 01122 #endif /* HAL_NAND_MODULE_ENABLED */ 01123 01124 /** 01125 * @} 01126 */ 01127 01128 #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ 01129 01130 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 10:59:58 by
