at26.c
上传用户:xukun0987
上传日期:2022-07-16
资源大小:216k
文件大小:10k
源码类别:

微处理器开发

开发平台:

C/C++

  1. /* ----------------------------------------------------------------------------
  2.  *         ATMEL Microcontroller Software Support 
  3.  * ----------------------------------------------------------------------------
  4.  * Copyright (c) 2008, Atmel Corporation
  5.  *
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions are met:
  10.  *
  11.  * - Redistributions of source code must retain the above copyright notice,
  12.  * this list of conditions and the disclaimer below.
  13.  *
  14.  * Atmel's name may not be used to endorse or promote products derived from
  15.  * this software without specific prior written permission.
  16.  *
  17.  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  20.  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  23.  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  24.  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  25.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  26.  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  * ----------------------------------------------------------------------------
  28.  */
  29. //------------------------------------------------------------------------------
  30. //         Headers
  31. //------------------------------------------------------------------------------
  32. #include "at26.h"
  33. #include <board.h>
  34. #include <utility/assert.h>
  35. //------------------------------------------------------------------------------
  36. //         Internal definitions
  37. //------------------------------------------------------------------------------
  38. /// SPI clock frequency used in Hz.
  39. #define SPCK            1000000
  40. /// SPI chip select configuration value.
  41. #define CSR             (AT91C_SPI_NCPHA | 
  42.                          SPID_CSR_DLYBCT(BOARD_MCK, 100) | 
  43.                          SPID_CSR_DLYBS(BOARD_MCK, 5) | 
  44.                          SPID_CSR_SCBR(BOARD_MCK, SPCK))
  45. /// Number of recognized dataflash.
  46. #define NUMDATAFLASH    (sizeof(at26Devices) / sizeof(At26Desc))
  47. //------------------------------------------------------------------------------
  48. //         Internal variables
  49. //------------------------------------------------------------------------------
  50. /// Array of recognized serial firmware dataflash chips.
  51. static const At26Desc at26Devices[] = {
  52.     // name, Jedec ID, size, page size, block size, block erase command
  53.     {"AT25DF041A" , 0x0001441F, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  54.     {"AT25DF161"  , 0x0002461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  55.     {"AT26DF081A" , 0x0001451F, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  56.     {"AT26DF0161" , 0x0000461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  57.     {"AT26DF161A" , 0x0001461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  58.     {"AT26DF321 " , 0x0000471F, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  59.     // Manufacturer: ST
  60.     {"M25P05"     , 0x00102020,       64 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_64K},
  61.     {"M25P10"     , 0x00112020,      128 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_64K},
  62.     {"M25P20"     , 0x00122020,      256 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  63.     {"M25P40"     , 0x00132020,      512 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  64.     {"M25P80"     , 0x00142020, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  65.     {"M25P16"     , 0x00152020, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  66.     {"M25P32"     , 0x00162020, 4 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  67.     {"M25P64"     , 0x00172020, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  68.     // Manufacturer: Windbond
  69.     {"W25X10"     , 0x001130EF,      128 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  70.     {"W25X20"     , 0x001230EF,      256 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  71.     {"W25X40"     , 0x001330EF,      512 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  72.     {"W25X80"     , 0x001430EF, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  73.     // Manufacturer: Macronix
  74.     {"MX25L512"   , 0x001020C2,       64 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  75.     {"MX25L3205"  , 0x001620C2, 4 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  76.     {"MX25L6405"  , 0x001720C2, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
  77.     // Other
  78.     {"SST25VF512" , 0x000048BF,       64 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_32K}
  79. };
  80. //------------------------------------------------------------------------------
  81. //         Exported functions
  82. //------------------------------------------------------------------------------
  83. //------------------------------------------------------------------------------
  84. /// Initializes an AT26 driver instance with the given SPI driver and chip 
  85. /// select value.
  86. /// param pAt26  Pointer to an AT26 driver instance.
  87. /// param pSpid  Pointer to an SPI driver instance.
  88. /// param cs  Chip select value to communicate with the serial flash.
  89. //------------------------------------------------------------------------------
  90. void AT26_Configure(At26 *pAt26, Spid *pSpid, unsigned char cs)
  91. {
  92.     SpidCmd *pCommand;
  93.     SANITY_CHECK(pAt26);
  94.     SANITY_CHECK(pSpid);
  95.     SANITY_CHECK(cs < 4);
  96.     // Configure the SPI chip select for the serial flash
  97.     SPID_ConfigureCS(pSpid, cs, CSR);
  98.     // Initialize the AT26 fields
  99.     pAt26->pSpid = pSpid;
  100.     pAt26->pDesc = 0;
  101.     // Initialize the command structure
  102.     pCommand = &(pAt26->command);
  103.     pCommand->pCmd = (unsigned char *) pAt26->pCmdBuffer;
  104.     pCommand->callback = 0;
  105.     pCommand->pArgument = 0;
  106.     pCommand->spiCs = cs;    
  107. }
  108. //------------------------------------------------------------------------------
  109. /// Returns 1 if the serial flash driver is currently busy executing a command;
  110. /// otherwise returns 0.
  111. /// param pAt26  Pointer to an At26 driver instance.
  112. //------------------------------------------------------------------------------
  113. unsigned char AT26_IsBusy(At26 *pAt26)
  114. {
  115.     return SPID_IsBusy(pAt26->pSpid);
  116. }
  117.     
  118. //------------------------------------------------------------------------------
  119. /// Sends a command to the serial flash through the SPI. The command is made up
  120. /// of two parts: the first is used to transmit the command byte and optionally,
  121. /// address and dummy bytes. The second part is the data to send or receive.
  122. /// This function does not block: it returns as soon as the transfer has been
  123. /// started. An optional callback can be invoked to notify the end of transfer.
  124. /// Return 0 if successful; otherwise, returns AT26_ERROR_BUSY if the AT26
  125. /// driver is currently executing a command, or AT26_ERROR_SPI if the command
  126. /// cannot be sent because of a SPI error.
  127. /// param pAt26  Pointer to an At26 driver instance.
  128. /// param cmd  Command byte.
  129. /// param cmdSize  Size of command (command byte + address bytes + dummy bytes).
  130. /// param pData Data buffer.
  131. /// param dataSize  Number of bytes to send/receive.
  132. /// param address  Address to transmit.
  133. /// param callback  Optional user-provided callback to invoke at end of transfer.
  134. /// param pArgument  Optional argument to the callback function.
  135. //------------------------------------------------------------------------------
  136. unsigned char AT26_SendCommand(
  137.     At26 *pAt26,
  138.     unsigned char cmd,
  139.     unsigned char cmdSize,
  140.     unsigned char *pData,
  141.     unsigned int dataSize,
  142.     unsigned int address,
  143.     SpidCallback callback,
  144.     void *pArgument)
  145. {
  146.     SpidCmd *pCommand;
  147.     
  148.     SANITY_CHECK(pAt26);
  149.     // Check if the SPI driver is available
  150.     if (AT26_IsBusy(pAt26)) {
  151.     
  152.         return AT26_ERROR_BUSY;
  153.     }
  154.     
  155.     // Store command and address in command buffer
  156.     pAt26->pCmdBuffer[0] = (cmd & 0x000000FF)
  157.                            | ((address & 0x0000FF) << 24)
  158.                            | ((address & 0x00FF00) << 8)
  159.                            | ((address & 0xFF0000) >> 8);
  160.     // Update the SPI transfer descriptor
  161.     pCommand = &(pAt26->command);
  162.      pCommand->cmdSize = cmdSize;
  163.      pCommand->pData = pData;
  164.      pCommand->dataSize = dataSize;
  165.      pCommand->callback = callback;
  166.      pCommand->pArgument = pArgument;
  167.     
  168.      // Start the SPI transfer
  169.      if (SPID_SendCommand(pAt26->pSpid, pCommand)) {
  170.          return AT26_ERROR_SPI;
  171.      }
  172.  
  173.      return 0;
  174. }
  175. //------------------------------------------------------------------------------
  176. /// Tries to detect a serial firmware flash device given its JEDEC identifier.
  177. /// The JEDEC id can be retrieved by sending the correct command to the device.
  178. /// Returns the corresponding AT26 descriptor if found; otherwise returns 0.
  179. /// param pAt26  Pointer to an AT26 driver instance.
  180. /// param jedecId  JEDEC identifier of device.
  181. //------------------------------------------------------------------------------
  182. const At26Desc * AT26_FindDevice(At26 *pAt26, unsigned int jedecId)
  183. {
  184.     unsigned int i = 0;
  185.     SANITY_CHECK(pAt26);
  186.     // Search if device is recognized
  187.     pAt26->pDesc = 0;
  188.     while ((i < NUMDATAFLASH) && !(pAt26->pDesc)) {
  189.     
  190.         if (jedecId == at26Devices[i].jedecId) {
  191.             pAt26->pDesc = &(at26Devices[i]);
  192.         }
  193.         i++;
  194.     }
  195.     return pAt26->pDesc;
  196. }