//------------------------------------------------------------------------------ /// Erases all the content of the memory chip. /// \param pAt26 Pointer to an AT26 driver instance. //------------------------------------------------------------------------------ unsigned char AT26D_EraseChip(At26 *pAt26) { unsigned char status; unsigned char error; SANITY_CHECK(pAt26); // Check that the flash is unprotected status = AT26D_ReadStatus(pAt26); if ((status & AT26_STATUS_SWP) != AT26_STATUS_SWP_PROTNONE) { return AT26_ERROR_PROTECTED; } // Enable critical write operation AT26D_EnableWrite(pAt26); // Erase the chip error = AT26_SendCommand(pAt26, AT26_CHIP_ERASE_2, 1, 0, 0, 0, 0, 0); ASSERT(!error, "-F- AT26_ChipErase: Could not issue command.\n\r"); // Wait for transfer to finish AT26D_Wait(pAt26); // Poll the Serial flash status register until the operation is achieved AT26D_WaitReady(pAt26); return 0; }
//------------------------------------------------------------------------------ /// Erases the specified 64KB block of the serial firmware dataflash. /// Returns 0 if successful; otherwise returns AT26_ERROR_PROTECTED if the /// device is protected or AT26_ERROR_BUSY if it is busy executing a command. /// \param pAt26 Pointer to an AT26 driver instance. /// \param address Address of the block to erase. //------------------------------------------------------------------------------ unsigned char AT26D_EraseBlock(At26 *pAt26, unsigned int address) { unsigned char status; unsigned char error; SANITY_CHECK(pAt26); // Check that the flash is ready and unprotected status = AT26D_ReadStatus(pAt26); if ((status & AT26_STATUS_RDYBSY) != AT26_STATUS_RDYBSY_READY) { TRACE_ERROR("AT26D_EraseBlock : Flash busy\n\r"); return AT26_ERROR_BUSY; } else if ((status & AT26_STATUS_SWP) != AT26_STATUS_SWP_PROTNONE) { TRACE_ERROR("AT26D_EraseBlock : Flash protected\n\r"); return AT26_ERROR_PROTECTED; } // Enable critical write operation AT26D_EnableWrite(pAt26); // Start the block erase command error = AT26_SendCommand(pAt26, AT26_BlockEraseCmd(pAt26), 4, 0, 0, address, 0, 0); ASSERT(!error, "-F- AT26_EraseBlock: Could not issue command.\n\r"); // Wait for transfer to finish AT26D_Wait(pAt26); // Poll the Serial flash status register until the operation is achieved AT26D_WaitReady(pAt26); return 0; }
//------------------------------------------------------------------------------ /// Reads data from the specified address on the serial flash. /// \param pAt26 Pointer to an AT26 driver instance. /// \param pData Data buffer. /// \param size Number of bytes to read. /// \param address Read address. //------------------------------------------------------------------------------ unsigned char AT26D_Read( At26 *pAt26, unsigned char *pData, unsigned int size, unsigned int address) { unsigned char error; unsigned int read_len; while (size > 0) { read_len = min(size, 0xffff); // Start a read operation error = AT26_SendCommand(pAt26, AT26_READ_ARRAY_LF, 4, pData, read_len, address, 0, 0); ASSERT(!error, "-F- AT26_Read: Could not issue command.\n\r"); if (error) { break; } // Wait for transfer to finish AT26D_Wait(pAt26); size -= read_len; address += read_len; pData += read_len; } return error; }
//------------------------------------------------------------------------------ // Reads and returns the status register of the serial flash. // \param pAt26 Pointer to an AT26 driver instance. //------------------------------------------------------------------------------ unsigned char AT26F004_Unprotect(At26 *pAt26) { unsigned char error; unsigned int sector, sectorAddress = 0; for (sector = 0 ; sector < 11 ; sector ++) { sectorAddress = 0x0; if (sector == 10) sectorAddress = 0x7C000; else if (sector == 9) sectorAddress = 0x7A000; else if (sector == 8) sectorAddress = 0x78000; else if (sector == 7) sectorAddress = 0x70000; else sectorAddress = sectorAddress + (0x10000 * sector); // Write Enable AT26D_EnableWrite(pAt26); error = AT26_SendCommand(pAt26, AT26_UNPROTECT_SECTOR, 4, 0, 0, sectorAddress, 0, 0); ASSERT(!error, "-F- AT26_SectorUnprotect: Failed to issue command.\n\r"); // Wait for transfer to finish AT26D_Wait(pAt26); } return 0; }
//------------------------------------------------------------------------------ /// Writes the given value in the status register of the serial flash device. /// \param pAt26 Pointer to an AT26 driver instance. /// \param status Status to write. //------------------------------------------------------------------------------ static void AT26D_WriteStatus(At26 *pAt26, unsigned char status) { unsigned char error; SANITY_CHECK(pAt26); // Issue a write status command error = AT26_SendCommand(pAt26, AT26_WRITE_STATUS, 1, &status, 1, 0, 0, 0); ASSERT(!error, "-F- AT26_WriteStatus: Failed to issue command.\n\r"); // Wait for transfer to finish AT26D_Wait(pAt26); }
//------------------------------------------------------------------------------ /// Enables critical writes operation on a serial flash device, such as sector /// protection, status register, etc. /// \para pAt26 Pointer to an AT26 driver instance. //------------------------------------------------------------------------------ void AT26D_EnableWrite(At26 *pAt26) { unsigned char error; SANITY_CHECK(pAt26); // Issue a write enable command error = AT26_SendCommand(pAt26, AT26_WRITE_ENABLE, 1, 0, 0, 0, 0, 0); ASSERT(!error, "-F- AT26_EnableWrite: Could not issue command.\n\r"); // Wait for transfer to finish AT26D_Wait(pAt26); }
//------------------------------------------------------------------------------ /// Reads and returns the status register of the serial flash. /// \param pAt26 Pointer to an AT26 driver instance. //------------------------------------------------------------------------------ static unsigned char AT26D_ReadStatus(At26 *pAt26) { unsigned char error, status; SANITY_CHECK(pAt26); // Issue a status read command error = AT26_SendCommand(pAt26, AT26_READ_STATUS, 1, &status, 1, 0, 0, 0); ASSERT(!error, "-F- AT26_GetStatus: Failed to issue command.\n\r"); // Wait for transfer to finish AT26D_Wait(pAt26); return status; }
//------------------------------------------------------------------------------ /// Reads data from the specified address on the serial flash. /// \param pAt26 Pointer to an AT26 driver instance. /// \param pData Data buffer. /// \param size Number of bytes to read. /// \param address Read address. //------------------------------------------------------------------------------ unsigned char AT26D_Read( At26 *pAt26, unsigned char *pData, unsigned int size, unsigned int address) { unsigned char error; // Start a read operation error = AT26_SendCommand(pAt26, AT26_READ_ARRAY_LF, 4, pData, size, address, 0, 0); ASSERT(!error, "-F- AT26_Read: Could not issue command.\n\r"); // Wait for transfer to finish AT26D_Wait(pAt26); return error; }
//------------------------------------------------------------------------------ /// 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. /// Returns 0 if successful; otherwise, returns AT26_ERROR_PROGRAM is there has /// been an error during the data programming. /// \param pAt26 Pointer to an AT26 driver instance. /// \param pData Data buffer. /// \param size Number of bytes in buffer. /// \param address Write address. //------------------------------------------------------------------------------ unsigned char AT26D_Write( At26 *pAt26, unsigned char *pData, unsigned int size, unsigned int address) { unsigned int pageSize; unsigned int writeSize; unsigned char error; unsigned char status; SANITY_CHECK(pAt26); SANITY_CHECK(pData); // Retrieve device page size pageSize = AT26_PageSize(pAt26); // 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 AT26D_EnableWrite(pAt26); // Program page error = AT26_SendCommand(pAt26, AT26_BYTE_PAGE_PROGRAM, 4, pData, writeSize, address, 0, 0); ASSERT(!error, "-F- AT26_WritePage: Failed to issue command.\n\r"); // Wait for transfer to finish AT26D_Wait(pAt26); // Poll the Serial flash status register until the operation is achieved AT26D_WaitReady(pAt26); // Make sure that write was without error status = AT26D_ReadStatus(pAt26); if ((status & AT26_STATUS_EPE) == AT26_STATUS_EPE_ERROR) { return AT26_ERROR_PROGRAM; } pData += writeSize; size -= writeSize; address += writeSize; } return 0; }
//------------------------------------------------------------------------------ /// Reads and returns the serial flash device ID. /// \param pAt26 Pointer to an AT26 driver instance. //------------------------------------------------------------------------------ unsigned int AT26D_ReadJedecId(At26 *pAt26) { unsigned char error; unsigned int id = 0; SANITY_CHECK(pAt26); // Issue a read ID command error = AT26_SendCommand(pAt26, AT26_READ_JEDEC_ID, 1, (unsigned char *) &id, 3, 0, 0, 0); ASSERT(!error, "-F- AT26_GetJedecId: Could not issue command.\n\r"); // Wait for transfer to finish AT26D_Wait(pAt26); return id; }
//------------------------------------------------------------------------------ /// 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. /// Returns 0 if successful; otherwise, returns AT26_ERROR_PROGRAM is there has /// been an error during the data programming. /// \param pAt26 Pointer to an AT26 driver instance. /// \param pData Data buffer. /// \param size Number of bytes in buffer. /// \param address Write address. //------------------------------------------------------------------------------ unsigned char AT26D_Write( At26 *pAt26, unsigned char *pData, unsigned int size, unsigned int address) { unsigned int pageSize; unsigned int writeSize; unsigned char error; #if !defined(BOARD_AT26F004) unsigned char status; #endif unsigned int i = 0; SANITY_CHECK(pAt26); SANITY_CHECK(pData); // Retrieve device page size pageSize = AT26_PageSize(pAt26); // Program one page after the other while (size > 0) { // Compute number of bytes to program in page #if defined(BOARD_AT26F004) writeSize = 1; #else writeSize = min(size, pageSize - (address % pageSize)); #endif // Enable critical write operation AT26D_EnableWrite(pAt26); if (AT26_ManId(pAt26) == SST_SPI_FLASH) { error = AT26_SendCommand(pAt26, AT26_SEQUENTIAL_PROGRAM_1, 4, pData, 2, address, 0, 0); ASSERT(!error, "-F- AT26_WritePage: Failed to issue command.\n\r"); /* Wait for transfer to finish */ AT26D_Wait(pAt26); /* Poll the Serial flash status register until the operation is achieved */ AT26D_WaitReady(pAt26); for (i = 2; i < pageSize; i += 2) { error = AT26_SendCommand(pAt26, AT26_SEQUENTIAL_PROGRAM_1, 1, pData + i, 2, 0, 0, 0); ASSERT(!error, "-F- AT26_WritePage: Failed to issue command.\n\r"); /* Wait for transfer to finish */ AT26D_Wait(pAt26); /* Poll the Serial flash status register until the operation is achieved */ AT26D_WaitReady(pAt26); } } else { // Program page error = AT26_SendCommand(pAt26, AT26_BYTE_PAGE_PROGRAM, 4, pData, writeSize, address, 0, 0); ASSERT(!error, "-F- AT26_WritePage: Failed to issue command.\n\r"); // Wait for transfer to finish AT26D_Wait(pAt26); // Poll the Serial flash status register until the operation is achieved AT26D_WaitReady(pAt26); } #if !defined(AT26F004) // Make sure that write was without error status = AT26D_ReadStatus(pAt26); if ((status & AT26_STATUS_EPE) == AT26_STATUS_EPE_ERROR) { return AT26_ERROR_PROGRAM; } #endif pData += writeSize; size -= writeSize; address += writeSize; } return 0; }