/** * @brief This routine erase complete block from NAND FLASH * @param Address: Any address into block to be erased * @retval New status of the NAND operation. This parameter can be: * - NAND_TIMEOUT_ERROR: when the previous operation generate * a Timeout error * - NAND_READY: when memory is ready for the next operation */ uint32_t NAND_EraseBlock(NAND_ADDRESS Address) { *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE0; *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE1; return (NAND_GetStatus()); }
/** * @brief This routine write the spare area information for the specified * pages addresses. * @param pBuffer: pointer on the Buffer containing data to be written * @param Address: First page address * @param NumSpareAreaTowrite: Number of Spare Area to write * @retval New status of the NAND operation. This parameter can be: * - NAND_TIMEOUT_ERROR: when the previous operation generate * a Timeout error * - NAND_READY: when memory is ready for the next operation * And 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 NAND_WriteSpareArea(uint8_t * pBuffer, NAND_ADDRESS Address, uint32_t NumSpareAreaTowrite) { uint32_t index = 0x00, numsparesreawritten = 0x00, addressstatus = NAND_VALID_ADDRESS; uint32_t status = NAND_READY, size = 0x00; while ((NumSpareAreaTowrite != 0x00) && (addressstatus == NAND_VALID_ADDRESS) && (status == NAND_READY)) { /*!< Page write Spare area command and address */ *(__IO uint8_t *) (Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_C; *(__IO uint8_t *) (Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE0; *(__IO uint8_t *) (Bank_NAND_ADDR | ADDR_AREA) = 0x00; *(__IO uint8_t *) (Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(__IO uint8_t *) (Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); *(__IO uint8_t *) (Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); /*!< Calculate the size */ size = NAND_SPARE_AREA_SIZE + (NAND_SPARE_AREA_SIZE * numsparesreawritten); /*!< Write the data */ for (; index < size; index++) { *(__IO uint8_t *) (Bank_NAND_ADDR | DATA_AREA) = pBuffer[index]; } *(__IO uint8_t *) (Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE_TRUE1; /*!< Check status for successful operation */ status = NAND_GetStatus(); if (status == NAND_READY) { numsparesreawritten++; NumSpareAreaTowrite--; /*!< Calculate Next page Address */ addressstatus = NAND_AddressIncrement(&Address); } } return (status | addressstatus); }
/****************************************************************************** * Function Name : FSMC_NAND_EraseBlock * Description : This routine erase complete block from NAND FLASH * Input : - Address: Any address into block to be erased * Output : None * Return : New status of the NAND operation. This parameter can be: * - NAND_TIMEOUT_ERROR: when the previous operation generate * a Timeout error * - NAND_READY: when memory is ready for the next operation *******************************************************************************/ u32 FSMC_NAND_EraseBlock(NAND_ADDRESS Address) { *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE0; *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_5fh_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE1; return (FSMC_NAND_GetStatus()); }
/** * @brief NAND memory Block erase * @param hnand: pointer to a NAND_HandleTypeDef structure that contains * the configuration information for NAND module. * @param pAddress : pointer to NAND address structure * @retval HAL status */ HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypedef *pAddress) { 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 */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { DeviceAddress = NAND_DEVICE1; } else { 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)) = 0x60; *(__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 | CMD_AREA)) = 0xD0; /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hnand); return HAL_OK; }
/****************************************************************************** * Function Name : FSMC_NAND_ReadID * Description : Reads NAND memory's ID. * Input : - NAND_ID: pointer to a NAND_IDTypeDef structure which will hold * the Manufacturer and Device ID. * Output : None * Return : None * Attention : None *******************************************************************************/ void FSMC_NAND_ReadID(NAND_IDTypeDef* NAND_ID) { uint32_t data = 0; /* Send Command to the command area */ *(vu8 *)(NAND_FLASH_START_ADDR | CMD_AREA) = 0x90; *(vu8 *)(NAND_FLASH_START_ADDR | ADDR_AREA) = 0x00; /* Sequence to read ID from NAND flash */ data = *(vu32 *)(NAND_FLASH_START_ADDR | DATA_AREA); NAND_ID->Maker_ID = ADDR_1st_CYCLE (data); NAND_ID->Device_ID = ADDR_2nd_CYCLE (data); NAND_ID->Third_ID = ADDR_3rd_CYCLE (data); NAND_ID->Fourth_ID = ADDR_4th_CYCLE (data); }
/** * @brief Read the NAND memory electronic signature * @param hnand: pointer to a NAND_HandleTypeDef structure that contains * the configuration information for NAND module. * @param pNAND_ID: NAND ID structure * @retval HAL status */ HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID) { __IO uint32_t data = 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 */ if(hnand->Init.NandBank == FSMC_NAND_BANK2) { deviceaddress = NAND_DEVICE1; } else { 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; /* 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); /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hnand); return HAL_OK; }
/** * @brief Reads NAND memory's ID. * @param NAND_ID: pointer to a NAND_IDTypeDef structure which will hold * the Manufacturer and Device ID. * @retval None */ void NAND_ReadID(NAND_IDTypeDef* NAND_ID) { uint32_t data = 0; /*!< Send Command to the command area */ *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = 0x90; *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00; /*!< Sequence to read ID from NAND flash */ data = *(__IO uint32_t *)(Bank_NAND_ADDR | DATA_AREA); NAND_ID->Maker_ID = ADDR_1st_CYCLE (data); NAND_ID->Device_ID = ADDR_2nd_CYCLE (data); NAND_ID->Third_ID = ADDR_3rd_CYCLE (data); NAND_ID->Fourth_ID = ADDR_4th_CYCLE (data); }
/****************************************************************************** * Function Name : FSMC_NAND_WriteSmallPage * Description : This routine is for writing one or several 512 Bytes Page size. * Input : - pBuffer: pointer on the Buffer containing data to be written * - Address: First page address * - NumPageToWrite: Number of page to write * Output : None * Return : New status of the NAND operation. This parameter can be: * - NAND_TIMEOUT_ERROR: when the previous operation generate * a Timeout error * - NAND_READY: when memory is ready for the next operation * And 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 *******************************************************************************/ u32 FSMC_NAND_WriteSmallPage(u8 *pBuffer, NAND_ADDRESS Address, u32 NumPageToWrite) { u32 index = 0x00, numpagewritten = 0x00, addressstatus = NAND_VALID_ADDRESS; u32 status = NAND_READY, size = 2048; while((NumPageToWrite != 0x00) && (addressstatus == NAND_VALID_ADDRESS) && (status == NAND_READY)) { /* Page write command and address */ *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_A; *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE0; *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_5fh_CYCLE(ROW_ADDRESS); /* Calculate the size */ size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpagewritten); /* Write data */ for(; index < size; index++) { *(vu8 *)(Bank_NAND_ADDR | DATA_AREA) = pBuffer[index]; } *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE_TRUE1; /* Check status for successful operation */ status = FSMC_NAND_GetStatus(); if(status == NAND_READY) { numpagewritten++; NumPageToWrite--; /* Calculate Next small page Address */ addressstatus = FSMC_NAND_AddressIncrement(&Address); } } return (status | addressstatus); }
/** * @brief This routine read the spare area information from the specified * pages addresses. * @param pBuffer: pointer on the Buffer to fill * @param Address: First page address * @param NumSpareAreaToRead: Number of Spare Area to read * @retval New status of the NAND operation. This parameter can be: * - NAND_TIMEOUT_ERROR: when the previous operation generate * a Timeout error * - NAND_READY: when memory is ready for the next operation * And 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 NAND_ReadSpareArea(uint8_t * pBuffer, NAND_ADDRESS Address, uint32_t NumSpareAreaToRead) { uint32_t numsparearearead = 0x00, index = 0x00, addressstatus = NAND_VALID_ADDRESS; uint32_t status = NAND_READY, size = 0x00; while ((NumSpareAreaToRead != 0x0) && (addressstatus == NAND_VALID_ADDRESS)) { /*!< Page Read command and page address */ *(__IO uint8_t *) (Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_C; *(__IO uint8_t *) (Bank_NAND_ADDR | ADDR_AREA) = 0x00; *(__IO uint8_t *) (Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(__IO uint8_t *) (Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); *(__IO uint8_t *) (Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); /*!< Data Read */ size = NAND_SPARE_AREA_SIZE + (NAND_SPARE_AREA_SIZE * numsparearearead); /*!< Get Data into Buffer */ for (; index < size; index++) { pBuffer[index] = *(__IO uint8_t *) (Bank_NAND_ADDR | DATA_AREA); } numsparearearead++; NumSpareAreaToRead--; /*!< Calculate page address */ addressstatus = NAND_AddressIncrement(&Address); } status = NAND_GetStatus(); return (status | addressstatus); }
/****************************************************************************** * Function Name : FSMC_NAND_ReadSmallPage * Description : This routine is for sequential read from one or several * 512 Bytes Page size. * Input : - pBuffer: pointer on the Buffer to fill * - Address: First page address * - NumPageToRead: Number of page to read * Output : None * Return : New status of the NAND operation. This parameter can be: * - NAND_TIMEOUT_ERROR: when the previous operation generate * a Timeout error * - NAND_READY: when memory is ready for the next operation * And 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 *******************************************************************************/ u32 FSMC_NAND_ReadSmallPage(u8 *pBuffer, NAND_ADDRESS Address, u32 NumPageToRead) { u32 index = 0x00, numpageread = 0x00, addressstatus = NAND_VALID_ADDRESS; u32 status = NAND_READY, size = 2048, i = 0; /* Calculate the size */ size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpageread); while((NumPageToRead != 0x0) && (addressstatus == NAND_VALID_ADDRESS)) { /* Page Read command and page address */ *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_A; *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_5fh_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_TRUE1; for(i = 0; i <= 10000; i++); /* Get Data into Buffer */ for(; index < size; index++) { pBuffer[index]= *(vu8 *)(Bank_NAND_ADDR | DATA_AREA); } numpageread++; NumPageToRead--; /* Calculate page address */ addressstatus = FSMC_NAND_AddressIncrement(&Address); } status = FSMC_NAND_GetStatus(); return (status | addressstatus); }
/****************************************************************************** * Function Name : FSMC_NAND_ReadSpareArea * Description : This routine read the spare area information from the specified * pages addresses. * Input : - pBuffer: pointer on the Buffer to fill * - Address: First page address * - NumSpareAreaToRead: Number of Spare Area to read * Output : None * Return : New status of the NAND operation. This parameter can be: * - NAND_TIMEOUT_ERROR: when the previous operation generate * a Timeout error * - NAND_READY: when memory is ready for the next operation * And 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 *******************************************************************************/ u32 FSMC_NAND_ReadSpareArea(u8 *pBuffer, NAND_ADDRESS Address, u32 NumSpareAreaToRead) { u32 numsparearearead = 0x00, index = 0x00, addressstatus = NAND_VALID_ADDRESS; u32 status = NAND_READY, size = 0x00; while((NumSpareAreaToRead != 0x0) && (addressstatus == NAND_VALID_ADDRESS)) { /* Page Read command and page address */ *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_C; *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_5fh_CYCLE(ROW_ADDRESS); *(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_TRUE1; /* Data Read */ size = NAND_SPARE_AREA_SIZE + (NAND_SPARE_AREA_SIZE * numsparearearead); /* Get Data into Buffer */ for ( ;index < size; index++) { pBuffer[index] = *(vu8 *)(Bank_NAND_ADDR | DATA_AREA); } numsparearearead++; NumSpareAreaToRead--; /* Calculate page address */ addressstatus = FSMC_NAND_AddressIncrement(&Address); } status = FSMC_NAND_GetStatus(); return (status | addressstatus); }
/****************************************************************************** * Function Name : FSMC_NAND_ReadSmallPage * Description : This routine is for sequential read from one or several * 512 Bytes Page size. * Input : - pBuffer: pointer on the Buffer to fill * - Address: First page address * - NumPageToRead: Number of page to read * Output : None * Return : New status of the NAND operation. This parameter can be: * - NAND_TIMEOUT_ERROR: when the previous operation generate * a Timeout error * - NAND_READY: when memory is ready for the next operation * And 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 FSMC_NAND_ReadSmallPage(uint8_t *pBuffer, NAND_ADDRESS Address, uint32_t NumPageToRead) { uint32_t index = 0x00, numpageread = 0x00, addressstatus = NAND_VALID_ADDRESS; uint32_t status = NAND_READY, size = 0x00; while((NumPageToRead != 0x0) && (addressstatus == NAND_VALID_ADDRESS)) { /* Page Read command and page address */ *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_A; *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00; *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS); *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS); *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS); *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_AREA_TRUE1; delay_nus(20); /* Calculate the size */ size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpageread); /* Get Data into Buffer */ for(; index < size; index++) { pBuffer[index]= *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA); } numpageread++; NumPageToRead--; /* Calculate page address */ addressstatus = FSMC_NAND_AddressIncrement(&Address); } status = FSMC_NAND_GetStatus(); return (status | addressstatus); }
/** * @brief Write Spare area(s) to NAND memory * @param hnand: pointer to a NAND_HandleTypeDef structure that contains * the configuration information for NAND module. * @param pAddress : pointer to NAND address structure * @param pBuffer : pointer to source buffer to write * @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) { __IO uint32_t index = 0; uint32_t timeout = 0; uint32_t deviceAddress = 0, size = 0, numSpareAreaWritten = 0, nandAddress = 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 */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { deviceAddress = NAND_DEVICE1; } else { deviceAddress = NAND_DEVICE2; } /* Update the FMC_NAND controller state */ hnand->State = HAL_NAND_STATE_BUSY; /* NAND raw address calculation */ nandAddress = ARRAY_ADDRESS(pAddress, hnand); /* Spare area(s) write loop */ while((NumSpareAreaTowrite != 0) && (nandAddress < ((hnand->Info.BlockSize) * (hnand->Info.SpareAreaSize) * (hnand->Info.ZoneSize)))) { /* update the buffer size */ size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * numSpareAreaWritten); /* 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)) = 0x80; *(__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); /* 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); } /* Write data to memory */ for(; index < size; index++) { *(__IO uint8_t *)deviceAddress = *(uint8_t *)pBuffer++; } *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = 0x10; /* Read status until NAND is ready */ while(HAL_NAND_Read_Status(hnand) != NAND_READY) { /* Check for timeout value */ timeout = HAL_GetTick() + NAND_WRITE_TIMEOUT; if(HAL_GetTick() >= timeout) { return HAL_TIMEOUT; } } /* Increment written spare areas number */ numSpareAreaWritten++; /* Decrement spare areas to write */ NumSpareAreaTowrite--; /* Increment the NAND address */ nandAddress = (uint32_t)(nandAddress + (hnand->Info.PageSize)); } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hnand); return HAL_OK; }
/** * @brief Read Spare area(s) from NAND memory * @param hnand: pointer to a NAND_HandleTypeDef structure that contains * the configuration information for NAND module. * @param pAddress : pointer to NAND address structure * @param pBuffer: pointer to source buffer to write * @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) { __IO uint32_t index = 0; uint32_t deviceAddress = 0, size = 0, numSpareAreaRead = 0, nandAddress = 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 */ if(hnand->Init.NandBank == FMC_NAND_BANK2) { deviceAddress = NAND_DEVICE1; } else { deviceAddress = NAND_DEVICE2; } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_BUSY; /* NAND raw address calculation */ nandAddress = ARRAY_ADDRESS(pAddress, hnand); /* Spare area(s) read loop */ while((NumSpareAreaToRead != 0) && (nandAddress < ((hnand->Info.BlockSize) * (hnand->Info.SpareAreaSize) * (hnand->Info.ZoneSize)))) { /* update the buffer size */ size = (hnand->Info.SpareAreaSize) + ((hnand->Info.SpareAreaSize) * numSpareAreaRead); /* 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); /* 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 | CMD_AREA)) = 0x30; /* Get Data into Buffer */ for ( ;index < size; index++) { *(uint8_t *)pBuffer++ = *(uint8_t *)deviceAddress; } /* Increment read spare areas number */ numSpareAreaRead++; /* Decrement spare areas to read */ NumSpareAreaToRead--; /* Increment the NAND address */ nandAddress = (uint32_t)(nandAddress + (hnand->Info.SpareAreaSize)); } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hnand); return HAL_OK; }
/** * @brief NAND memory Block erase * @param hnand: pointer to a NAND_HandleTypeDef structure that contains * the configuration information for NAND module. * @param pAddress : pointer to NAND address structure * @retval HAL status */ HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) { uint32_t deviceaddress = 0; uint32_t tickstart = 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 */ if(hnand->Init.NandBank == FSMC_NAND_BANK2) { deviceaddress = NAND_DEVICE1; } else { 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 | 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 | 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 Read Page(s) from NAND memory block * @param hnand: pointer to a NAND_HandleTypeDef structure that contains * the configuration information for NAND module. * @param pAddress : pointer to NAND address structure * @param pBuffer : pointer to destination read buffer * @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) { __IO uint32_t index = 0; uint32_t deviceaddress = 0, size = 0, numpagesread = 0, addressstatus = NAND_VALID_ADDRESS; NAND_AddressTypeDef nandaddress; uint32_t addressoffset = 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 */ if(hnand->Init.NandBank == FSMC_NAND_BANK2) { deviceaddress = NAND_DEVICE1; } else { 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) 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 | 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(addressoffset); } *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; /* Get Data into Buffer */ for(; index < size; index++) { *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress; } /* Increment read pages number */ numpagesread++; /* Decrement pages to read */ NumPageToRead--; /* Increment the NAND address */ addressstatus = NAND_AddressIncrement(hnand, &nandaddress); } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hnand); return HAL_OK; }
/** * @brief Write Spare area(s) to NAND memory * @param hnand: pointer to a NAND_HandleTypeDef structure that contains * the configuration information for NAND module. * @param pAddress : pointer to NAND address structure * @param pBuffer : pointer to source buffer to write * @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) { __IO uint32_t index = 0; uint32_t tickstart = 0; 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); /* Check the NAND controller state */ if(hnand->State == HAL_NAND_STATE_BUSY) { return HAL_BUSY; } /* Identify the device address */ if(hnand->Init.NandBank == FSMC_NAND_BANK2) { deviceaddress = NAND_DEVICE1; } else { deviceaddress = NAND_DEVICE2; } /* Update the FSMC_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)) { /* 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 | 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(addressoffset); } /* Write data to memory */ for(; index < size; index++) { *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++; } *(__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) { if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT) { return HAL_TIMEOUT; } } /* Increment written spare areas number */ num_spare_area_written++; /* Decrement spare areas to write */ NumSpareAreaTowrite--; /* Increment the NAND address */ addressstatus = NAND_AddressIncrement(hnand, &nandaddress); } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hnand); return HAL_OK; }