at26.c
上传用户:xukun0987
上传日期:2022-07-16
资源大小:216k
文件大小:10k
- /* ----------------------------------------------------------------------------
- * 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 "at26.h"
- #include <board.h>
- #include <utility/assert.h>
- //------------------------------------------------------------------------------
- // Internal definitions
- //------------------------------------------------------------------------------
- /// SPI clock frequency used in Hz.
- #define SPCK 1000000
- /// SPI chip select configuration value.
- #define CSR (AT91C_SPI_NCPHA |
- SPID_CSR_DLYBCT(BOARD_MCK, 100) |
- SPID_CSR_DLYBS(BOARD_MCK, 5) |
- SPID_CSR_SCBR(BOARD_MCK, SPCK))
- /// Number of recognized dataflash.
- #define NUMDATAFLASH (sizeof(at26Devices) / sizeof(At26Desc))
- //------------------------------------------------------------------------------
- // Internal variables
- //------------------------------------------------------------------------------
- /// Array of recognized serial firmware dataflash chips.
- static const At26Desc at26Devices[] = {
- // name, Jedec ID, size, page size, block size, block erase command
- {"AT25DF041A" , 0x0001441F, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"AT25DF161" , 0x0002461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"AT26DF081A" , 0x0001451F, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"AT26DF0161" , 0x0000461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"AT26DF161A" , 0x0001461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"AT26DF321 " , 0x0000471F, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- // Manufacturer: ST
- {"M25P05" , 0x00102020, 64 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_64K},
- {"M25P10" , 0x00112020, 128 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_64K},
- {"M25P20" , 0x00122020, 256 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"M25P40" , 0x00132020, 512 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"M25P80" , 0x00142020, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"M25P16" , 0x00152020, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"M25P32" , 0x00162020, 4 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"M25P64" , 0x00172020, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- // Manufacturer: Windbond
- {"W25X10" , 0x001130EF, 128 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"W25X20" , 0x001230EF, 256 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"W25X40" , 0x001330EF, 512 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"W25X80" , 0x001430EF, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- // Manufacturer: Macronix
- {"MX25L512" , 0x001020C2, 64 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"MX25L3205" , 0x001620C2, 4 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- {"MX25L6405" , 0x001720C2, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
- // Other
- {"SST25VF512" , 0x000048BF, 64 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_32K}
- };
- //------------------------------------------------------------------------------
- // Exported functions
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- /// Initializes an AT26 driver instance with the given SPI driver and chip
- /// select value.
- /// param pAt26 Pointer to an AT26 driver instance.
- /// param pSpid Pointer to an SPI driver instance.
- /// param cs Chip select value to communicate with the serial flash.
- //------------------------------------------------------------------------------
- void AT26_Configure(At26 *pAt26, Spid *pSpid, unsigned char cs)
- {
- SpidCmd *pCommand;
- SANITY_CHECK(pAt26);
- SANITY_CHECK(pSpid);
- SANITY_CHECK(cs < 4);
- // Configure the SPI chip select for the serial flash
- SPID_ConfigureCS(pSpid, cs, CSR);
- // Initialize the AT26 fields
- pAt26->pSpid = pSpid;
- pAt26->pDesc = 0;
- // Initialize the command structure
- pCommand = &(pAt26->command);
- pCommand->pCmd = (unsigned char *) pAt26->pCmdBuffer;
- pCommand->callback = 0;
- pCommand->pArgument = 0;
- pCommand->spiCs = cs;
- }
- //------------------------------------------------------------------------------
- /// Returns 1 if the serial flash driver is currently busy executing a command;
- /// otherwise returns 0.
- /// param pAt26 Pointer to an At26 driver instance.
- //------------------------------------------------------------------------------
- unsigned char AT26_IsBusy(At26 *pAt26)
- {
- return SPID_IsBusy(pAt26->pSpid);
- }
-
- //------------------------------------------------------------------------------
- /// Sends a command to the serial flash through the SPI. The command is made up
- /// of two parts: the first is used to transmit the command byte and optionally,
- /// address and dummy bytes. The second part is the data to send or receive.
- /// This function does not block: it returns as soon as the transfer has been
- /// started. An optional callback can be invoked to notify the end of transfer.
- /// Return 0 if successful; otherwise, returns AT26_ERROR_BUSY if the AT26
- /// driver is currently executing a command, or AT26_ERROR_SPI if the command
- /// cannot be sent because of a SPI error.
- /// param pAt26 Pointer to an At26 driver instance.
- /// param cmd Command byte.
- /// param cmdSize Size of command (command byte + address bytes + dummy bytes).
- /// param pData Data buffer.
- /// param dataSize Number of bytes to send/receive.
- /// param address Address to transmit.
- /// param callback Optional user-provided callback to invoke at end of transfer.
- /// param pArgument Optional argument to the callback function.
- //------------------------------------------------------------------------------
- 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)
- {
- SpidCmd *pCommand;
-
- SANITY_CHECK(pAt26);
- // Check if the SPI driver is available
- if (AT26_IsBusy(pAt26)) {
-
- return AT26_ERROR_BUSY;
- }
-
- // Store command and address in command buffer
- pAt26->pCmdBuffer[0] = (cmd & 0x000000FF)
- | ((address & 0x0000FF) << 24)
- | ((address & 0x00FF00) << 8)
- | ((address & 0xFF0000) >> 8);
- // Update the SPI transfer descriptor
- pCommand = &(pAt26->command);
- pCommand->cmdSize = cmdSize;
- pCommand->pData = pData;
- pCommand->dataSize = dataSize;
- pCommand->callback = callback;
- pCommand->pArgument = pArgument;
-
- // Start the SPI transfer
- if (SPID_SendCommand(pAt26->pSpid, pCommand)) {
- return AT26_ERROR_SPI;
- }
-
- return 0;
- }
- //------------------------------------------------------------------------------
- /// Tries to detect a serial firmware flash device given its JEDEC identifier.
- /// The JEDEC id can be retrieved by sending the correct command to the device.
- /// Returns the corresponding AT26 descriptor if found; otherwise returns 0.
- /// param pAt26 Pointer to an AT26 driver instance.
- /// param jedecId JEDEC identifier of device.
- //------------------------------------------------------------------------------
- const At26Desc * AT26_FindDevice(At26 *pAt26, unsigned int jedecId)
- {
- unsigned int i = 0;
- SANITY_CHECK(pAt26);
- // Search if device is recognized
- pAt26->pDesc = 0;
- while ((i < NUMDATAFLASH) && !(pAt26->pDesc)) {
-
- if (jedecId == at26Devices[i].jedecId) {
- pAt26->pDesc = &(at26Devices[i]);
- }
- i++;
- }
- return pAt26->pDesc;
- }