/** * @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 == FMC_NAND_BANK2) { deviceaddress = NAND_DEVICE1; } else { 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)) { /* 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 = HAL_NAND_Address_Inc(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, numSpareAreaWritten = 0, nandAddress = 0, addressStatus = NAND_VALID_ADDRESS; /* 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; /* Spare area(s) write loop */ while((NumSpareAreaTowrite != 0) && (addressStatus == NAND_VALID_ADDRESS)) { /* NAND raw address calculation */ nandAddress = __ARRAY_ADDRESS(pAddress, 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(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 = 0 ; index < hnand->Info.SpareAreaSize; index++) { *(__IO uint8_t *)deviceAddress = *(uint8_t *)pBuffer++; } *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; /* 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++; /* Decrement spare areas to write */ NumSpareAreaTowrite--; /* Increment the NAND address */ HAL_NAND_Address_Inc(hnand, pAddress); } /* 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, num_spare_area_read = 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 == FMC_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; /* Spare area(s) read loop */ 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(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 != 0; index--) { *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress; } /* Increment read spare areas number */ num_spare_area_read++; /* Decrement spare areas to read */ NumSpareAreaToRead--; /* Increment the NAND address */ addressstatus = HAL_NAND_Address_Inc(hnand, &nandaddress); } /* 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, numSpareAreaRead = 0, nandAddress = 0, addressStatus = NAND_VALID_ADDRESS; /* 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; /* Spare area(s) read loop */ while((NumSpareAreaToRead != 0) && (addressStatus == NAND_VALID_ADDRESS)) { /* NAND raw address calculation */ nandAddress = __ARRAY_ADDRESS(pAddress, 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); /* 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)) = NAND_CMD_AREA_TRUE1; /* Get Data into Buffer */ for(index = 0 ; index < hnand->Info.SpareAreaSize; index++) { *(uint8_t *)pBuffer++ = *(uint8_t *)deviceAddress; } /* Increment read spare areas number */ numSpareAreaRead++; /* Decrement spare areas to read */ NumSpareAreaToRead--; /* Increment the NAND address */ HAL_NAND_Address_Inc(hnand, pAddress); } /* Update the NAND controller state */ hnand->State = HAL_NAND_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hnand); return HAL_OK; }