blob: 6d4ce95cc434e2193dcfef47828887d846bb9424 [file] [log] [blame]
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// The AT26 serial firmware Dataflash driver is based on top of the
/// corresponding Spi driver. A Dataflash structure instance has to be
/// initialized using the DF_Init function. Then basic dataflash
/// operations can be launched using macros such as DF_continuous_read.
/// These macros invoke the DF_Command() function which invokes the
/// DPI low driver using the SPI_SendCommand() function.
/// Beware to compute the dataflash internal address, the dataflash sector
/// description must be known (DataflashDesc). Dataflash can be automatically
/// detected using the DF_Scan() function.
///
/// !Usage
///
/// -# Initializes an AT26 instance and configures SPI chip select pin
/// using AT26_Configure().
/// -# Detect DF and returns DF description corresponding to the device
/// connected using AT26_FindDevice().This function shall be called by
/// the application before AT26_SendCommand().
/// -# Sends a command to the DF through the SPI using AT26_SendCommand().
/// The command is identified by its command code and the number of
/// bytes to transfer.
/// -# Example code for sending command to write a page to DF.
/// \code
/// // Program page
/// error = AT26_SendCommand(pAt26, AT26_BYTE_PAGE_PROGRAM, 4,
/// pData, writeSize, address, 0, 0);
/// \endcode
/// -# Example code for sending command to read a page from DF.
/// If data needs to be received, then a data buffer must be
/// provided.
/// \code
/// // Start a read operation
/// error = AT26_SendCommand(pAt26, AT26_READ_ARRAY_LF,
/// 4, pData, size, address, 0, 0);
/// \endcode
/// -# This function does not block; its optional callback will
/// be invoked when the transfer completes.
/// -# Check the AT26 driver is ready or not by polling AT26_IsBusy().
///
//------------------------------------------------------------------------------
#ifndef AT26_H
#define AT26_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
//#include "chip.h"
//------------------------------------------------------------------------------
// Macros
//------------------------------------------------------------------------------
#define AT26_Size(pAt26) ((pAt26)->pDesc->size)
#define AT26_PageSize(pAt26) ((pAt26)->pDesc->pageSize)
#define AT26_BlockSize(pAt26) ((pAt26)->pDesc->blockSize)
#define AT26_Name(pAt26) ((pAt26)->pDesc->name)
#define AT26_PageNumber(pAt26) (AT26_Size(pAt26) / AT26_PageSize(pAt26))
#define AT26_BlockNumber(pAt26) (AT26_Size(pAt26) / AT26_BlockSize(pAt26))
#define AT26_PagePerBlock(pAt26) (AT26_BlockSize(pAt26) / AT26_PageSize(pAt26))
#define AT26_BlockEraseCmd(pAt26) ((pAt26)->pDesc->blockEraseCmd)
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
/// Device is protected, operation cannot be carried out.
#define AT26_ERROR_PROTECTED 1
/// Device is busy executing a command.
#define AT26_ERROR_BUSY 2
/// There was a problem while trying to program page data.
#define AT26_ERROR_PROGRAM 3
/// There was an SPI communication error.
#define AT26_ERROR_SPI 4
/// Device ready/busy status bit.
#define AT26_STATUS_RDYBSY (1 << 0)
/// Device is ready.
#define AT26_STATUS_RDYBSY_READY (0 << 0)
/// Device is busy with internal operations.
#define AT26_STATUS_RDYBSY_BUSY (1 << 0)
/// Write enable latch status bit.
#define AT26_STATUS_WEL (1 << 1)
/// Device is not write enabled.
#define AT26_STATUS_WEL_DISABLED (0 << 1)
/// Device is write enabled.
#define AT26_STATUS_WEL_ENABLED (1 << 1)
/// Software protection status bitfield.
#define AT26_STATUS_SWP (3 << 2)
/// All sectors are software protected.
#define AT26_STATUS_SWP_PROTALL (3 << 2)
/// Some sectors are software protected.
#define AT26_STATUS_SWP_PROTSOME (1 << 2)
/// No sector is software protected.
#define AT26_STATUS_SWP_PROTNONE (0 << 2)
/// Write protect pin status bit.
#define AT26_STATUS_WPP (1 << 4)
/// Write protect signal is not asserted.
#define AT26_STATUS_WPP_NOTASSERTED (0 << 4)
/// Write protect signal is asserted.
#define AT26_STATUS_WPP_ASSERTED (1 << 4)
/// Erase/program error bit.
#define AT26_STATUS_EPE (1 << 5)
/// Erase or program operation was successful.
#define AT26_STATUS_EPE_SUCCESS (0 << 5)
/// Erase or program error detected.
#define AT26_STATUS_EPE_ERROR (1 << 5)
/// Sector protection registers locked bit.
#define AT26_STATUS_SPRL (1 << 7)
/// Sector protection registers are unlocked.
#define AT26_STATUS_SPRL_UNLOCKED (0 << 7)
/// Sector protection registers are locked.
#define AT26_STATUS_SPRL_LOCKED (1 << 7)
/// Read array command code.
#define AT26_READ_ARRAY 0x0B
/// Read array (low frequency) command code.
#define AT26_READ_ARRAY_LF 0x03
/// Block erase command code (4K block).
#define AT26_BLOCK_ERASE_4K 0x20
/// Block erase command code (32K block).
#define AT26_BLOCK_ERASE_32K 0x52
/// Block erase command code (64K block).
#define AT26_BLOCK_ERASE_64K 0xD8
/// Chip erase command code 1.
#define AT26_CHIP_ERASE_1 0x60
/// Chip erase command code 2.
#define AT26_CHIP_ERASE_2 0xC7
/// Byte/page program command code.
#define AT26_BYTE_PAGE_PROGRAM 0x02
/// Sequential program mode command code 1.
#define AT26_SEQUENTIAL_PROGRAM_1 0xAD
/// Sequential program mode command code 2.
#define AT26_SEQUENTIAL_PROGRAM_2 0xAF
/// Write enable command code.
#define AT26_WRITE_ENABLE 0x06
/// Write disable command code.
#define AT26_WRITE_DISABLE 0x04
/// Protect sector command code.
#define AT26_PROTECT_SECTOR 0x36
/// Unprotect sector command code.
#define AT26_UNPROTECT_SECTOR 0x39
/// Read sector protection registers command code.
#define AT26_READ_SECTOR_PROT 0x3C
/// Read status register command code.
#define AT26_READ_STATUS 0x05
/// Write status register command code.
#define AT26_WRITE_STATUS 0x01
/// Read manufacturer and device ID command code.
#define AT26_READ_JEDEC_ID 0x9F
/// Deep power-down command code.
#define AT26_DEEP_PDOWN 0xB9
/// Resume from deep power-down command code.
#define AT26_RES_DEEP_PDOWN 0xAB
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Describes a serial firmware flash device parameters.
//------------------------------------------------------------------------------
typedef struct _At26Desc {
/// Device string name.
const char *name;
/// JEDEC ID of device.
unsigned int jedecId;
/// Size of device in bytes.
unsigned int size;
/// Size of one page in bytes.
unsigned int pageSize;
/// Block erase size in bytes.
unsigned int blockSize;
/// Block erase command.
unsigned int blockEraseCmd;
} At26Desc;
//------------------------------------------------------------------------------
/// Serial flash driver structure. Holds the current state of the driver,
/// including the current command and the descriptor for the underlying device.
//------------------------------------------------------------------------------
typedef struct _At26 {
/// Pointer to the underlying SPI driver.
Spid *pSpid;
/// Current SPI command sent to the SPI driver.
SpidCmd command;
/// Pointer to a descriptor for the serial firmware flash device.
const At26Desc *pDesc;
/// Command buffer.
unsigned int pCmdBuffer[2];
} At26;
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void AT26_Configure(At26 *pAt26, Spid *pSpid, unsigned char cs);
extern unsigned char AT26_SendCommand(
At26 *pAt26,
unsigned char cmd,
unsigned char cmdSize,
unsigned char *pData,
unsigned int dataSize,
unsigned int address,
SpidCallback callback,
void *pArgument);
extern unsigned char AT26_IsBusy(At26 *pAt26);
extern const At26Desc * AT26_FindDevice(
At26 *pAt26,
unsigned int jedecId);
#endif //#ifndef AT26_H