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.
Fork of TUKS-COURSE-TIMER by
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 17:38:49 by
