From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011 it's sad to see that atmel doesn't publish their svn repo or has a centralized location or even puts proper version/release info into the library itself --- memories/spi-flash/at45.c | 257 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 memories/spi-flash/at45.c (limited to 'memories/spi-flash/at45.c') diff --git a/memories/spi-flash/at45.c b/memories/spi-flash/at45.c new file mode 100644 index 0000000..142e7ed --- /dev/null +++ b/memories/spi-flash/at45.c @@ -0,0 +1,257 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "at45.h" +#include +#include + +#include + +//------------------------------------------------------------------------------ +// Internal definitions +//------------------------------------------------------------------------------ + +/// Number of dataflash which can be recognized. +#define NUMDATAFLASH (sizeof(at45Devices) / sizeof(At45Desc)) + +//------------------------------------------------------------------------------ +// Local variables +//------------------------------------------------------------------------------ + +/// indicate if the device is configured as binary page or not. +static unsigned char configuredBinaryPage; + +//------------------------------------------------------------------------------ +// Internal variables +//------------------------------------------------------------------------------ + +static const At45Desc at45Devices[] = { + { 512, 1, 264, 9, 0x0C, "AT45DB011D"}, + { 1024, 1, 264, 9, 0x14, "AT45DB021D"}, + { 2048, 1, 264, 9, 0x1C, "AT45DB041D"}, + { 4096, 1, 264, 9, 0x24, "AT45DB081D"}, + { 4096, 1, 528, 10, 0x2C, "AT45DB161D"}, + { 8192, 1, 528, 10, 0x34, "AT45DB321D"}, + { 8192, 1, 1056, 11, 0x3C, "AT45DB642D"}, + {16384, 1, 1056, 11, 0x10, "AT45DB1282"}, + {16384, 1, 2112, 12, 0x18, "AT45DB2562"}, + {32768, 1, 2112, 12, 0x20, "AT45DB5122"} +}; + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes an AT45 instance and configures SPI chip select register. +/// Always returns 0. +/// \param pAt45 Pointer to the At45 instance to initialize. +/// \param pSpid Pointer to the underlying SPI driver. +/// \param spiCs Chip select value to connect to the At45. +//------------------------------------------------------------------------------ +unsigned char AT45_Configure(At45 *pAt45, Spid *pSpid, unsigned char spiCs) +{ + SpidCmd *pCommand; + + // Sanity checks + ASSERT(pSpid, "AT45_Configure: pSpid is 0.\n\r"); + ASSERT(pAt45, "AT45_Configure: pAt45 is 0.\n\r"); + + // Initialize the At45 instance + pAt45->pSpid = pSpid; + pAt45->pDesc = 0; + memset(pAt45->pCmdBuffer, 0, 8); + + // Initialize the spidCmd structure + pCommand = &(pAt45->command); + pCommand->pCmd = pAt45->pCmdBuffer; + pCommand->callback = 0; + pCommand->pArgument = 0; + pCommand->spiCs = spiCs; + + return 0; +} + +//------------------------------------------------------------------------------ +/// This function returns 1 if the At45 driver is not executing any command; +/// otherwise it returns 0. +/// \param pAt45 Pointer to an At45 instance. +//------------------------------------------------------------------------------ +unsigned char AT45_IsBusy(At45 *pAt45) +{ + return SPID_IsBusy(pAt45->pSpid); +} + +//------------------------------------------------------------------------------ +/// Sends a command to the dataflash through the SPI. The command is identified +/// by its command code and the number of bytes to transfer (1 + number of +/// address bytes + number of dummy bytes). If data needs to be received, then +/// a data buffer must be provided. +/// This function does not block; its optional callback will be invoked when +/// the transfer completes. +/// \param pAt45 Pointer to an At45 driver instance. +/// \param cmd Command code. +/// \param cmdSize Size of command code + address bytes + dummy bytes. +/// \param pData Data buffer. +/// \param dataSize Number of data bytes to send/receive. +/// \param address Address at which the command is performed if meaningful. +/// \param callback Optional callback to invoke at end of transfer. +/// \param pArgument Optional parameter to the callback function. +//------------------------------------------------------------------------------ +unsigned char AT45_SendCommand( + At45 *pAt45, + unsigned char cmd, + unsigned char cmdSize, + unsigned char *pData, + unsigned int dataSize, + unsigned int address, + SpidCallback callback, + void *pArgument) +{ + SpidCmd *pCommand; + const At45Desc *pDesc = pAt45->pDesc; + unsigned int dfAddress = 0; + + // Sanity checks + ASSERT(pAt45, "AT45_Command: pAt45 is 0.\n\r"); + ASSERT(pDesc || (cmd == AT45_STATUS_READ), + "AT45_Command: Device has no descriptor, only STATUS_READ command allowed\n\r"); + + // Check if the SPI driver is available + if (AT45_IsBusy(pAt45)) { + + return AT45_ERROR_LOCK; + } + + // Compute command pattern + pAt45->pCmdBuffer[0] = cmd; + + // Add address bytes if necessary + if (cmdSize > 1) { + + ASSERT(pDesc, "AT45_Command: No descriptor for dataflash.\n\r"); + if (!configuredBinaryPage) { + dfAddress = + ((address / (pDesc->pageSize)) << pDesc->pageOffset) + + (address % (pDesc->pageSize)); + } + else { + dfAddress = address; + } + // Write address bytes + if (pDesc->pageNumber >= 16384) { + + pAt45->pCmdBuffer[1] = ((dfAddress & 0x0F000000) >> 24); + pAt45->pCmdBuffer[2] = ((dfAddress & 0x00FF0000) >> 16); + pAt45->pCmdBuffer[3] = ((dfAddress & 0x0000FF00) >> 8); + pAt45->pCmdBuffer[4] = ((dfAddress & 0x000000FF) >> 0); + + if ((cmd != AT45_CONTINUOUS_READ) && (cmd != AT45_PAGE_READ)) { + + cmdSize++; + } + } + else { + + pAt45->pCmdBuffer[1] = ((dfAddress & 0x00FF0000) >> 16); + pAt45->pCmdBuffer[2] = ((dfAddress & 0x0000FF00) >> 8); + pAt45->pCmdBuffer[3] = ((dfAddress & 0x000000FF) >> 0); + } + } + + // Update the SPI Transfer descriptors + pCommand = &(pAt45->command); + pCommand->cmdSize = cmdSize; + pCommand->pData = pData; + pCommand->dataSize = dataSize; + pCommand->callback = callback; + pCommand->pArgument = pArgument; + + // Send Command and data through the SPI + if (SPID_SendCommand(pAt45->pSpid, pCommand)) { + + return AT45_ERROR_SPI; + } + + return 0; +} + +//------------------------------------------------------------------------------ +/// This function returns the At45Desc structure corresponding to the device +/// connected +/// It automatically initializes pAt45->pDesc field structure. +/// This function shall be called by the application before AT45_SendCommand. +/// Returns 0 if successful; Otherwise, returns AT45_ERROR_LOCK if the At45 +/// driver is in use or AT45_ERROR_SPI if there was an error with the SPI driver. +/// \param pAt45 Pointer to an AT45 driver instance. +/// \param status Device status register value. +//------------------------------------------------------------------------------ +const At45Desc * AT45_FindDevice(At45 *pAt45, unsigned char status) +{ + unsigned int i; + unsigned char id = AT45_STATUS_ID(status); + + // Check if status is all one; in which case, it is assumed that no device + // is connected + if (status == 0xFF) { + + return 0; + } + + // Look in device array + i = 0; + pAt45->pDesc = 0; + while ((i < NUMDATAFLASH) && !(pAt45->pDesc)) { + + if (at45Devices[i].id == id) { + + pAt45->pDesc = &(at45Devices[i]); + } + i++; + } + configuredBinaryPage = AT45_STATUS_BINARY(status); + return pAt45->pDesc; +} + +//------------------------------------------------------------------------------ +/// This function returns the pagesize corresponding to the device connected +/// \param pAt45 Pointer to an AT45 driver instance. +//------------------------------------------------------------------------------ +unsigned int AT45_PageSize(At45 *pAt45) +{ + unsigned int pagesize = pAt45->pDesc->pageSize; + if(((pAt45->pDesc->hasBinaryPage) == 0) || !configuredBinaryPage){ + return pagesize; + } + return ((pagesize >> 8) << 8); +} -- cgit v1.2.3