/** *\brief Erases the specified 64KB block of the serial firmware dataflash. * * \param pAt25 Pointer to an AT25 driver instance. * \param address Address of the block to erase. * * \return 0 if successful; otherwise returns AT25_ERROR_PROTECTED if the * device is protected or AT25_ERROR_BUSY if it is busy executing a command. */ unsigned char AT25D_EraseBlock(At25 *pAt25, unsigned int address) { unsigned char status; unsigned char error; assert(pAt25); /* Check that the flash is ready and unprotected */ status = AT25D_ReadStatus(pAt25); if ((status & AT25_STATUS_RDYBSY) != AT25_STATUS_RDYBSY_READY) { TRACE_ERROR("AT25D_EraseBlock : Flash busy\n\r"); return AT25_ERROR_BUSY; } else if ((status & AT25_STATUS_SWP) != AT25_STATUS_SWP_PROTNONE) { TRACE_ERROR("AT25D_EraseBlock : Flash protected\n\r"); return AT25_ERROR_PROTECTED; } /* Enable critical write operation */ AT25D_EnableWrite(pAt25); /* Start the block erase command */ error = AT25_SendCommand(pAt25, AT25_BlockEraseCmd(pAt25), 4, 0, 0, address, 0, 0); assert(!error); /* Wait for transfer to finish */ AT25D_Wait(pAt25); /* Poll the Serial flash status register until the operation is achieved */ AT25D_WaitReady(pAt25); return 0; }
/** * \brief Erases all the content of the memory chip. * * \param pAt25 Pointer to an AT25 driver instance. * * \return 0 if the device has been unprotected; otherwise returns * AT25_ERROR_PROTECTED. */ unsigned char AT25D_EraseChip(At25 *pAt25) { unsigned char status; unsigned char error; assert(pAt25); /* Check that the flash is unprotected */ status = AT25D_ReadStatus(pAt25); if ((status & AT25_STATUS_SWP) != AT25_STATUS_SWP_PROTNONE) { return AT25_ERROR_PROTECTED; } /* Enable critical write operation */ AT25D_EnableWrite(pAt25); /* Erase the chip */ error = AT25_SendCommand(pAt25, AT25_CHIP_ERASE_2, 1, 0, 0, 0, 0, 0); assert(!error); /* Wait for transfer to finish */ AT25D_Wait(pAt25); /* Poll the Serial flash status register until the operation is achieved */ AT25D_WaitReady(pAt25); return 0; }
/** * \brief Disables write operation on a serial flash device. * * \para pAt25 Pointer to an AT25 driver instance. */ void AT25D_DisableWrite(At25 *pAt25) { unsigned char error; assert(pAt25); /* Issue a write enable command */ error = AT25_SendCommand(pAt25, AT25_WRITE_DISABLE, 1, 0, 0, 0, 0, 0); assert(!error); /* Wait for transfer to finish */ AT25D_Wait(pAt25); }
/** * \brief Writes the given value in the status register of the serial flash device. * * \param pAt25 Pointer to an AT25 driver instance. * \param status Status to write. */ static void AT25D_WriteStatus(At25 *pAt25, unsigned char status) { unsigned char error; assert(pAt25); /* Issue a write status command */ error = AT25_SendCommand(pAt25, AT25_WRITE_STATUS, 1, &status, 1, 0, 0, 0); assert(!error); /* Wait for transfer to finish */ AT25D_Wait(pAt25); }
/** * \brief Writes data at the specified address on the serial firmware dataflash. The * page(s) to program must have been erased prior to writing. This function * handles page boundary crossing automatically. * * \param pAt25 Pointer to an AT25 driver instance. * \param pData Data buffer. * \param size Number of bytes in buffer. * \param address Write address. * * \return 0 if successful; otherwise, returns AT25_ERROR_PROGRAM is there has * been an error during the data programming. */ unsigned char AT25D_Write( At25 *pAt25, unsigned char *pData, unsigned int size, unsigned int address) { unsigned int pageSize; unsigned int writeSize; unsigned char error; unsigned char status; assert(pAt25); assert(pData); /* Retrieve device page size */ pageSize = AT25_PageSize(pAt25); /* Program one page after the other */ while (size > 0) { /* Compute number of bytes to program in page */ writeSize = min(size, pageSize - (address % pageSize)); /* Enable critical write operation */ AT25D_EnableWrite(pAt25); /* Program page */ error = AT25_SendCommand(pAt25, AT25_BYTE_PAGE_PROGRAM, 4, pData, writeSize, address, 0, 0); assert(!error); /* Wait for transfer to finish */ AT25D_Wait(pAt25); /* Poll the Serial flash status register until the operation is achieved */ AT25D_WaitReady(pAt25); /* Make sure that write was without error */ status = AT25D_ReadStatus(pAt25); if ((status & AT25_STATUS_EPE) == AT25_STATUS_EPE_ERROR) { return AT25_ERROR_PROGRAM; } pData += writeSize; size -= writeSize; address += writeSize; } return 0; }
/** * \brief Reads and returns the status register of the serial flash. * * \param pAt25 Pointer to an AT25 driver instance. */ static unsigned char AT25D_ReadStatus(At25 *pAt25) { unsigned char error, status; assert(pAt25); /* Issue a status read command */ error = AT25_SendCommand(pAt25, AT25_READ_STATUS, 1, &status, 1, 0, 0, 0); assert(!error); /* Wait for transfer to finish */ AT25D_Wait(pAt25); return status; }
/** * \brief Reads data from the specified address on the serial flash. * * \param pAt25 Pointer to an AT25 driver instance. * \param pData Data buffer. * \param size Number of bytes to read. * \param address Read address. * * \return 0 if successful; otherwise, fail. */ unsigned char AT25D_Read( At25 *pAt25, unsigned char *pData, unsigned int size, unsigned int address) { unsigned char error; /* Start a read operation */ error = AT25_SendCommand(pAt25, AT25_READ_ARRAY_LF, 4, pData, size, address, 0, 0); assert(!error); /* Wait for transfer to finish */ AT25D_Wait(pAt25); return error; }
/** * \brief Reads and returns the serial flash device ID. * * \param pAt25 Pointer to an AT25 driver instance. */ unsigned int AT25D_ReadJedecId(At25 *pAt25) { unsigned char error; unsigned int id = 0; assert(pAt25); /* Issue a read ID command */ error = AT25_SendCommand(pAt25, AT25_READ_JEDEC_ID, 1, (unsigned char *) &id, 3, 0, 0, 0); assert(!error); /* Wait for transfer to finish */ AT25D_Wait(pAt25); return id; }