mbed library sources
Fork of mbed-src by
Diff: targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_nand.c
- Revision:
- 532:fe11edbda85c
- Parent:
- 384:ef87175507f1
- Child:
- 613:bc40b8d2aec4
--- a/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_nand.c Thu Apr 30 13:00:08 2015 +0100 +++ b/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_nand.c Thu Apr 30 13:45:11 2015 +0100 @@ -2,8 +2,8 @@ ****************************************************************************** * @file stm32f4xx_hal_nand.c * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 + * @version V1.3.0 + * @date 09-March-2015 * @brief NAND HAL module driver. * This file provides a generic firmware to drive NAND memories mounted * as external device. @@ -55,7 +55,7 @@ ****************************************************************************** * @attention * - * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2> + * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -89,26 +89,44 @@ * @{ */ -/** @defgroup NAND - * @brief NAND driver modules + +#ifdef HAL_NAND_MODULE_ENABLED + +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\ + defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ + defined(STM32F446xx) + +/** @defgroup NAND NAND + * @brief NAND HAL module driver * @{ */ -#ifdef HAL_NAND_MODULE_ENABLED - -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ +/** @defgroup NAND_Private_Constants NAND Private Constants + * @{ + */ + +/** + * @} + */ + /* Private macro -------------------------------------------------------------*/ +/** @defgroup NAND_Private_Macros NAND Private Macros + * @{ + */ + +/** + * @} + */ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/** @defgroup NAND_Private_Functions +/* Exported functions --------------------------------------------------------*/ +/** @defgroup NAND_Exported_Functions NAND Exported Functions * @{ */ -/** @defgroup NAND_Group1 Initialization and de-initialization functions +/** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions * @brief Initialization and Configuration functions * @verbatim @@ -141,6 +159,8 @@ if(hnand->State == HAL_NAND_STATE_RESET) { + /* Allocate lock resource and initialize it */ + hnand->Lock = HAL_UNLOCKED; /* Initialize the low level hardware (MSP) */ HAL_NAND_MspInit(hnand); } @@ -280,7 +300,7 @@ * @} */ -/** @defgroup NAND_Group2 Input and Output functions +/** @defgroup NAND_Exported_Functions_Group2 Input and Output functions * @brief Input Output and memory control functions * @verbatim @@ -305,7 +325,7 @@ HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID) { __IO uint32_t data = 0; - uint32_t deviceAddress = 0; + uint32_t deviceaddress = 0; /* Process Locked */ __HAL_LOCK(hnand); @@ -319,34 +339,34 @@ /* Identify the device address */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { - deviceAddress = NAND_DEVICE1; + deviceaddress = NAND_DEVICE1; } else { - deviceAddress = NAND_DEVICE2; + deviceaddress = NAND_DEVICE2; } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_BUSY; - /* Send Read ID command sequence */ - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_READID; - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00; + /* Send Read ID command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_READID; + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; - /* Read the electronic signature from NAND flash */ - data = *(__IO uint32_t *)deviceAddress; + /* Read the electronic signature from NAND flash */ + data = *(__IO uint32_t *)deviceaddress; /* Return the data read */ - pNAND_ID->Maker_Id = __ADDR_1st_CYCLE(data); - pNAND_ID->Device_Id = __ADDR_2nd_CYCLE(data); - pNAND_ID->Third_Id = __ADDR_3rd_CYCLE(data); - pNAND_ID->Fourth_Id = __ADDR_4th_CYCLE(data); + pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data); + pNAND_ID->Device_Id = ADDR_2ND_CYCLE(data); + pNAND_ID->Third_Id = ADDR_3RD_CYCLE(data); + pNAND_ID->Fourth_Id = ADDR_4TH_CYCLE(data); /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ - __HAL_UNLOCK(hnand); + __HAL_UNLOCK(hnand); return HAL_OK; } @@ -359,44 +379,43 @@ */ HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand) { - uint32_t deviceAddress = 0; - + uint32_t deviceaddress = 0; + /* Process Locked */ __HAL_LOCK(hnand); - + /* Check the NAND controller state */ if(hnand->State == HAL_NAND_STATE_BUSY) { return HAL_BUSY; } - /* Identify the device address */ + /* Identify the device address */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { - deviceAddress = NAND_DEVICE1; + deviceaddress = NAND_DEVICE1; } else { - deviceAddress = NAND_DEVICE2; + deviceaddress = NAND_DEVICE2; } - /* Update the NAND controller state */ + /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_BUSY; /* Send NAND reset command */ - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = 0xFF; - - - /* Update the NAND controller state */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF; + + + /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ - __HAL_UNLOCK(hnand); - + __HAL_UNLOCK(hnand); + return HAL_OK; - + } - /** * @brief Read Page(s) from NAND memory block @@ -407,10 +426,12 @@ * @param NumPageToRead : number of pages to read from block * @retval HAL status */ -HAL_StatusTypeDef HAL_NAND_Read_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead) +HAL_StatusTypeDef HAL_NAND_Read_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead) { __IO uint32_t index = 0; - uint32_t deviceAddress = 0, numPagesRead = 0, nandAddress = 0, addressStatus = NAND_VALID_ADDRESS; + uint32_t deviceaddress = 0, size = 0, numpagesread = 0, addressstatus = NAND_VALID_ADDRESS; + NAND_AddressTypeDef nandaddress; + uint32_t addressoffset = 0; /* Process Locked */ __HAL_LOCK(hnand); @@ -424,61 +445,68 @@ /* Identify the device address */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { - deviceAddress = NAND_DEVICE1; + deviceaddress = NAND_DEVICE1; } else { - deviceAddress = NAND_DEVICE2; + deviceaddress = NAND_DEVICE2; } - /* Update the NAND controller state */ + /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_BUSY; - /* Page(s) read loop */ - while((NumPageToRead != 0) && (addressStatus == NAND_VALID_ADDRESS)) - { - /* NAND raw address calculation */ - nandAddress = __ARRAY_ADDRESS(pAddress, hnand); + /* Save the content of pAddress as it will be modified */ + nandaddress.Block = pAddress->Block; + nandaddress.Page = pAddress->Page; + nandaddress.Zone = pAddress->Zone; + + /* Page(s) read loop */ + while((NumPageToRead != 0) && (addressstatus == NAND_VALID_ADDRESS)) + { + /* update the buffer size */ + size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpagesread); + + /* Get the address offset */ + addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); /* Send read page command sequence */ - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_A; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00; - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_1st_CYCLE(nandAddress); - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(nandAddress); - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(nandAddress); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); - /* for 512 and 1 GB devices, 4th cycle is required */ - if(hnand->Info.BlockNbr > 1024) + /* for 512 and 1 GB devices, 4th cycle is required */ + if(hnand->Info.BlockNbr >= 1024) { - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_4th_CYCLE(nandAddress); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); } - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; /* Get Data into Buffer */ - for(index = 0 ; index < hnand->Info.PageSize; index++) + for(index = size; index != 0; index--) { - *(uint8_t *)pBuffer++ = *(uint8_t *)deviceAddress; + *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress; } /* Increment read pages number */ - numPagesRead++; + numpagesread++; /* Decrement pages to read */ NumPageToRead--; /* Increment the NAND address */ - HAL_NAND_Address_Inc(hnand, pAddress); - + addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress); } - /* Update the NAND controller state */ + /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ - __HAL_UNLOCK(hnand); - + __HAL_UNLOCK(hnand); + return HAL_OK; } @@ -492,11 +520,13 @@ * @param NumPageToWrite : number of pages to write to block * @retval HAL status */ -HAL_StatusTypeDef HAL_NAND_Write_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite) +HAL_StatusTypeDef HAL_NAND_Write_Page(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite) { - __IO uint32_t index = 0; + __IO uint32_t index = 0; uint32_t tickstart = 0; - uint32_t deviceAddress = 0 , numPagesWritten = 0, nandAddress = 0, addressStatus = NAND_VALID_ADDRESS; + uint32_t deviceaddress = 0 , size = 0, numpageswritten = 0, addressstatus = NAND_VALID_ADDRESS; + NAND_AddressTypeDef nandaddress; + uint32_t addressoffset = 0; /* Process Locked */ __HAL_LOCK(hnand); @@ -510,78 +540,84 @@ /* Identify the device address */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { - deviceAddress = NAND_DEVICE1; + deviceaddress = NAND_DEVICE1; } else { - deviceAddress = NAND_DEVICE2; + deviceaddress = NAND_DEVICE2; } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_BUSY; + /* Save the content of pAddress as it will be modified */ + nandaddress.Block = pAddress->Block; + nandaddress.Page = pAddress->Page; + nandaddress.Zone = pAddress->Zone; + /* Page(s) write loop */ - while((NumPageToWrite != 0) && (addressStatus == NAND_VALID_ADDRESS)) - { - /* NAND raw address calculation */ - nandAddress = __ARRAY_ADDRESS(pAddress, hnand); - + while((NumPageToWrite != 0) && (addressstatus == NAND_VALID_ADDRESS)) + { + /* update the buffer size */ + size = hnand->Info.PageSize + ((hnand->Info.PageSize) * numpageswritten); + + /* Get the address offset */ + addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); + /* Send write page command sequence */ - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_A; - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE0; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00; - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_1st_CYCLE(nandAddress); - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(nandAddress); - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(nandAddress); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); /* for 512 and 1 GB devices, 4th cycle is required */ - if(hnand->Info.BlockNbr > 1024) + if(hnand->Info.BlockNbr >= 1024) { - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_4th_CYCLE(nandAddress); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); } /* Write data to memory */ - for(index = 0 ; index < hnand->Info.PageSize; index++) + for(index = size; index != 0; index--) { - *(__IO uint8_t *)deviceAddress = *(uint8_t *)pBuffer++; + *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++; } - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; + + /* Get tick */ + tickstart = HAL_GetTick(); /* Read status until NAND is ready */ while(HAL_NAND_Read_Status(hnand) != NAND_READY) { - /* Get tick */ - tickstart = HAL_GetTick(); - if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) { return HAL_TIMEOUT; - } - } + } + } /* Increment written pages number */ - numPagesWritten++; + numpageswritten++; /* Decrement pages to write */ NumPageToWrite--; /* Increment the NAND address */ - HAL_NAND_Address_Inc(hnand, pAddress); - + addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress); } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ - __HAL_UNLOCK(hnand); + __HAL_UNLOCK(hnand); return HAL_OK; } - /** * @brief Read Spare area(s) from NAND memory * @param hnand: pointer to a NAND_HandleTypeDef structure that contains @@ -591,10 +627,12 @@ * @param NumSpareAreaToRead: Number of spare area to read * @retval HAL status */ -HAL_StatusTypeDef HAL_NAND_Read_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead) +HAL_StatusTypeDef HAL_NAND_Read_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead) { __IO uint32_t index = 0; - uint32_t deviceAddress = 0, numSpareAreaRead = 0, nandAddress = 0, addressStatus = NAND_VALID_ADDRESS; + uint32_t deviceaddress = 0, size = 0, num_spare_area_read = 0, addressstatus = NAND_VALID_ADDRESS; + NAND_AddressTypeDef nandaddress; + uint32_t addressoffset = 0; /* Process Locked */ __HAL_LOCK(hnand); @@ -608,59 +646,67 @@ /* Identify the device address */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { - deviceAddress = NAND_DEVICE1; + deviceaddress = NAND_DEVICE1; } else { - deviceAddress = NAND_DEVICE2; + deviceaddress = NAND_DEVICE2; } /* Update the NAND controller state */ - hnand->State = HAL_NAND_STATE_BUSY; + hnand->State = HAL_NAND_STATE_BUSY; + + /* Save the content of pAddress as it will be modified */ + nandaddress.Block = pAddress->Block; + nandaddress.Page = pAddress->Page; + nandaddress.Zone = pAddress->Zone; /* Spare area(s) read loop */ - while((NumSpareAreaToRead != 0) && (addressStatus == NAND_VALID_ADDRESS)) - { - /* NAND raw address calculation */ - nandAddress = __ARRAY_ADDRESS(pAddress, hnand); + while((NumSpareAreaToRead != 0) && (addressstatus == NAND_VALID_ADDRESS)) + { + /* update the buffer size */ + size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_read); + /* Get the address offset */ + addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); + /* Send read spare area command sequence */ - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_C; - - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00; - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_1st_CYCLE(nandAddress); - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(nandAddress); - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(nandAddress); + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; + + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); /* for 512 and 1 GB devices, 4th cycle is required */ - if(hnand->Info.BlockNbr > 1024) + if(hnand->Info.BlockNbr >= 1024) { - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_4th_CYCLE(nandAddress); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); } - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; /* Get Data into Buffer */ - for(index = 0 ; index < hnand->Info.SpareAreaSize; index++) + for (index = size ;index != 0; index--) { - *(uint8_t *)pBuffer++ = *(uint8_t *)deviceAddress; + *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress; } /* Increment read spare areas number */ - numSpareAreaRead++; + num_spare_area_read++; /* Decrement spare areas to read */ NumSpareAreaToRead--; /* Increment the NAND address */ - HAL_NAND_Address_Inc(hnand, pAddress); + addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress); } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ - __HAL_UNLOCK(hnand); + __HAL_UNLOCK(hnand); return HAL_OK; } @@ -674,11 +720,13 @@ * @param NumSpareAreaTowrite : number of spare areas to write to block * @retval HAL status */ -HAL_StatusTypeDef HAL_NAND_Write_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite) +HAL_StatusTypeDef HAL_NAND_Write_SpareArea(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite) { __IO uint32_t index = 0; uint32_t tickstart = 0; - uint32_t deviceAddress = 0, numSpareAreaWritten = 0, nandAddress = 0, addressStatus = NAND_VALID_ADDRESS; + uint32_t deviceaddress = 0, size = 0, num_spare_area_written = 0, addressstatus = NAND_VALID_ADDRESS; + NAND_AddressTypeDef nandaddress; + uint32_t addressoffset = 0; /* Process Locked */ __HAL_LOCK(hnand); @@ -692,67 +740,73 @@ /* Identify the device address */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { - deviceAddress = NAND_DEVICE1; + deviceaddress = NAND_DEVICE1; } else { - deviceAddress = NAND_DEVICE2; + deviceaddress = NAND_DEVICE2; } /* Update the FMC_NAND controller state */ hnand->State = HAL_NAND_STATE_BUSY; + /* Save the content of pAddress as it will be modified */ + nandaddress.Block = pAddress->Block; + nandaddress.Page = pAddress->Page; + nandaddress.Zone = pAddress->Zone; + /* Spare area(s) write loop */ - while((NumSpareAreaTowrite != 0) && (addressStatus == NAND_VALID_ADDRESS)) - { - /* NAND raw address calculation */ - nandAddress = __ARRAY_ADDRESS(pAddress, hnand); + while((NumSpareAreaTowrite != 0) && (addressstatus == NAND_VALID_ADDRESS)) + { + /* update the buffer size */ + size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * num_spare_area_written); + + /* Get the address offset */ + addressoffset = ARRAY_ADDRESS(&nandaddress, hnand); /* Send write Spare area command sequence */ - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_AREA_C; - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE0; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00; - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_1st_CYCLE(nandAddress); - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(nandAddress); - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(nandAddress); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset); /* for 512 and 1 GB devices, 4th cycle is required */ if(hnand->Info.BlockNbr >= 1024) { - *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = __ADDR_4th_CYCLE(nandAddress); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset); } /* Write data to memory */ - for(index = 0 ; index < hnand->Info.SpareAreaSize; index++) + for(; index < size; index++) { - *(__IO uint8_t *)deviceAddress = *(uint8_t *)pBuffer++; + *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++; } - *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; - + /* Get tick */ + tickstart = HAL_GetTick(); + /* Read status until NAND is ready */ while(HAL_NAND_Read_Status(hnand) != NAND_READY) { - /* Get tick */ - tickstart = HAL_GetTick(); - if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) { return HAL_TIMEOUT; - } + } } /* Increment written spare areas number */ - numSpareAreaWritten++; + num_spare_area_written++; /* Decrement spare areas to write */ NumSpareAreaTowrite--; /* Increment the NAND address */ - HAL_NAND_Address_Inc(hnand, pAddress); - + addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress); } /* Update the NAND controller state */ @@ -761,7 +815,7 @@ /* Process unlocked */ __HAL_UNLOCK(hnand); - return HAL_OK; + return HAL_OK; } /** @@ -771,9 +825,10 @@ * @param pAddress : pointer to NAND address structure * @retval HAL status */ -HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress) +HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) { - uint32_t DeviceAddress = 0; + uint32_t deviceaddress = 0; + uint32_t tickstart = 0; /* Process Locked */ __HAL_LOCK(hnand); @@ -787,41 +842,55 @@ /* Identify the device address */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { - DeviceAddress = NAND_DEVICE1; + deviceaddress = NAND_DEVICE1; } else { - DeviceAddress = NAND_DEVICE2; + deviceaddress = NAND_DEVICE2; } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_BUSY; /* Send Erase block command sequence */ - *(__IO uint8_t *)((uint32_t)(DeviceAddress | CMD_AREA)) = NAND_CMD_ERASE0; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0; - *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = __ADDR_1st_CYCLE(__ARRAY_ADDRESS(pAddress, hnand)); - *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = __ADDR_2nd_CYCLE(__ARRAY_ADDRESS(pAddress, hnand)); - *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = __ADDR_3rd_CYCLE(__ARRAY_ADDRESS(pAddress, hnand)); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); /* for 512 and 1 GB devices, 4th cycle is required */ if(hnand->Info.BlockNbr >= 1024) { - *(__IO uint8_t *)((uint32_t)(DeviceAddress | ADDR_AREA)) = __ADDR_4th_CYCLE(__ARRAY_ADDRESS(pAddress, hnand)); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); } - - *(__IO uint8_t *)((uint32_t)(DeviceAddress | CMD_AREA)) = NAND_CMD_ERASE1; + + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1; /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Read status until NAND is ready */ + while(HAL_NAND_Read_Status(hnand) != NAND_READY) + { + if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) + { + /* Process unlocked */ + __HAL_UNLOCK(hnand); + + return HAL_TIMEOUT; + } + } + /* Process unlocked */ __HAL_UNLOCK(hnand); return HAL_OK; } - /** * @brief NAND memory read status * @param hnand: pointer to a NAND_HandleTypeDef structure that contains @@ -831,23 +900,23 @@ uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand) { uint32_t data = 0; - uint32_t DeviceAddress = 0; + uint32_t deviceaddress = 0; /* Identify the device address */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { - DeviceAddress = NAND_DEVICE1; + deviceaddress = NAND_DEVICE1; } else { - DeviceAddress = NAND_DEVICE2; + deviceaddress = NAND_DEVICE2; } /* Send Read status operation command */ - *(__IO uint8_t *)((uint32_t)(DeviceAddress | CMD_AREA)) = NAND_CMD_STATUS; + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS; /* Read status register data */ - data = *(__IO uint8_t *)DeviceAddress; + data = *(__IO uint8_t *)deviceaddress; /* Return the status */ if((data & NAND_ERROR) == NAND_ERROR) @@ -860,19 +929,18 @@ } return NAND_BUSY; - } /** * @brief Increment the NAND memory address * @param hnand: pointer to a NAND_HandleTypeDef structure that contains * the configuration information for NAND module. - * @param pAddress: pointer to NAND adress structure + * @param pAddress: pointer to NAND address structure * @retval The new status of the increment address operation. It can be: * - NAND_VALID_ADDRESS: When the new address is valid address * - NAND_INVALID_ADDRESS: When the new address is invalid address */ -uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress) +uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) { uint32_t status = NAND_VALID_ADDRESS; @@ -899,13 +967,11 @@ return (status); } - - /** * @} */ -/** @defgroup NAND_Group3 Control functions +/** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions * @brief management functions * @verbatim @@ -944,17 +1010,16 @@ /* Update the NAND state */ hnand->State = HAL_NAND_STATE_READY; - return HAL_OK; + return HAL_OK; } - /** * @brief Disables dynamically FMC_NAND ECC feature. * @param hnand: pointer to a NAND_HandleTypeDef structure that contains * the configuration information for NAND module. * @retval HAL status */ -HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand) +HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand) { /* Check the NAND controller state */ if(hnand->State == HAL_NAND_STATE_BUSY) @@ -1003,13 +1068,13 @@ return status; } - + /** * @} */ -/** @defgroup NAND_Group4 State functions +/** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions * @brief Peripheral State functions * @verbatim @@ -1042,15 +1107,19 @@ /** * @} */ -#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ + +/** + * @} + */ + +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx ||\ + STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx ||\ + STM32F446xx */ + #endif /* HAL_NAND_MODULE_ENABLED */ /** * @} */ -/** - * @} - */ - /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/