First commit
authorKevin Townsend <kevin@ktownsend.com>
Tue, 13 Sep 2011 05:59:52 +0000 (07:59 +0200)
committerKevin Townsend <kevin@ktownsend.com>
Tue, 13 Sep 2011 05:59:52 +0000 (07:59 +0200)
drivers/spiflash/spiflash.h [new file with mode: 0644]
drivers/spiflash/w25q16bv/w25q16bv.c [new file with mode: 0644]
drivers/spiflash/w25q16bv/w25q16bv.h [new file with mode: 0644]

diff --git a/drivers/spiflash/spiflash.h b/drivers/spiflash/spiflash.h
new file mode 100644 (file)
index 0000000..7bb14ae
--- /dev/null
@@ -0,0 +1,232 @@
+/**************************************************************************/
+/*! 
+    @file     spiflash.h
+    @author   K. Townsend (microBuilder.eu)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2010, microBuilder SARL
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#ifndef _SPIFLASH_H_
+#define _SPIFLASH_H_
+
+#include "projectconfig.h"
+
+/**************************************************************************/
+/*! 
+    @brief  Error messages
+*/
+/**************************************************************************/
+typedef enum
+{
+  SPIFLASH_ERROR_OK = 0,                // Everything executed normally
+  SPIFLASH_ERROR_ADDROUTOFRANGE = 1,    // Address out of range
+  SPIFLASH_ERROR_TIMEOUT_READY = 2,     // Timeout waiting for ready status
+  SPIFLASH_ERROR_WRITEERR = 3,          // Write Error
+  SPIFLASH_ERROR_PROTECTIONERR = 4,     // Write Protection Error
+  SPIFLASH_ERROR_ADDROVERFLOW = 5,      // Address overflow during read/write
+  SPIFLASH_ERROR_UNEXPECTEDID = 6,      // The manufacturer and/or device ID are different than expected
+  SPIFLASH_ERROR_LAST
+}
+spiflashError_e;
+
+/**************************************************************************/
+/*! 
+    @brief  Describes the storage capacity of the SPI flash, including the
+            size of the minimum HW write (page) and erase (sector) units.
+*/
+/**************************************************************************/
+typedef struct
+{
+  uint32_t pageSize;                    // Page size to write data (in bytes)
+  uint32_t pageCount;                   // Number of pages
+  uint32_t sectorSize;                  // Sector size to erase data (in bytes)
+  uint32_t sectorCount;                 // Number of sectors
+}
+spiflashSizeInfo_t;
+
+/**************************************************************************/
+/*! 
+    @brief Tries to initialise the flash device, and setups any HW
+           required by the SPI flash
+*/
+/**************************************************************************/
+void spiflashInit (void);
+
+/**************************************************************************/
+/*! 
+    @brief Gets an instance of spiflashSizeInfo_t that describes the
+           storage limits of the SPI flash like page size (minimum write
+           size) and sector size (minimum erase size).
+*/
+/**************************************************************************/
+spiflashSizeInfo_t spiflashGetSizeInfo(void);
+
+/**************************************************************************/
+/*! 
+    @brief Gets the 8-bit manufacturer ID and device ID for the flash
+
+    @param[out] *manufID
+                Pointer to the uint8_t that will store the manufacturer ID
+    @param[out] *deviceID
+                Pointer to the uint8_t that will store the device ID
+*/
+/**************************************************************************/
+void spiflashGetManufacturerInfo (uint8_t *manufID, uint8_t *deviceID);
+
+/**************************************************************************/
+/*! 
+    @brief Sets the write flag on the SPI flash, and if required puts the
+           WP pin in an appropriate state
+
+    @param[in]  enable
+                True (1) to enable writing, false (0) to disable it
+*/
+/**************************************************************************/
+void spiflashWriteEnable (bool enable);
+
+/**************************************************************************/
+/*! 
+    @brief Reads the specified number of bytes from the supplied address.
+
+    This function will read one or more bytes starting at the supplied
+    address. Please note that bufferLength is zero-based, meaning you
+    should  supply '0' to read a single byte, '3' to read 4 bytes of data,
+    etc.
+
+    @param[in]  address
+                The 24-bit address where the read will start.
+    @param[out] *buffer
+                Pointer to the buffer that will store the read results
+    @param[in]  len
+                Length of the buffer (zero-based).
+
+    @section EXAMPLE
+
+    @code
+    uint8_t buffer[64];
+    spiflashError_e error;
+    error = spiflashReadBuffer (0, buffer, 64);
+    if (error)
+    {
+      // Check what went wrong
+      switch (error)
+      {
+        case SPIFLASH_ERROR_ADDROUTOFRANGE:
+          // Specified starting address is out of range
+          break;
+        case SPIFLASH_ERROR_TIMEOUT_READY:
+          // Timed out waiting for flash to return ready state
+          break;
+        case SPIFLASH_ERROR_ADDROVERFLOW:
+          // Ran over the upper address during read
+          break;
+      }
+    }
+    @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashReadBuffer (uint32_t address, uint8_t *buffer, uint32_t len);
+
+/**************************************************************************/
+/*! 
+    @brief Writes a single byte to the SPI flash
+
+    @param[in]  address
+                The 24-bit address where the read will start.
+    @param[out] *buffer
+                Pointer to the buffer that will store the read results
+    @param[in]  len
+                Length of the buffer (zero-based).
+*/
+/**************************************************************************/
+spiflashError_e spiflashWriteBuffer (uint32_t address, uint8_t *buffer, uint32_t len);
+
+/**************************************************************************/
+/*! 
+    @brief Erases the contents of a single sector
+
+    @param[in]  sectorNumber
+                The sector number to erase (zero-based).
+
+    @section  EXAMPLE
+
+    @code
+    spiflashError_e error;
+    error = spiflashEraseSector(0);
+    if (error)
+    {
+      // Check what went wrong
+      switch (error)
+      {
+        case SPIFLASH_ERROR_ADDROUTOFRANGE:
+          // Specified starting address is out of range
+          break;
+        case SPIFLASH_ERROR_PROTECTIONERR:
+          // Couldn't set the write enable bit
+          break;
+        case SPIFLASH_ERROR_TIMEOUT_READY:
+          // Timed out waiting for flash to return ready state
+          break;
+      }
+    }
+    @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashEraseSector (uint32_t sectorNumber);
+
+/**************************************************************************/
+/*! 
+    @brief Erases the entire flash chip
+
+    @section  EXAMPLE
+
+    @code
+    spiflashError_e error;
+    error = spiflashEraseChip();
+    if (error)
+    {
+      // Check what went wrong
+      switch (error)
+      {
+        case SPIFLASH_ERROR_PROTECTIONERR:
+          // Couldn't set the write enable bit
+          break;
+        case SPIFLASH_ERROR_TIMEOUT_READY:
+          // Timed out waiting for flash to return ready state
+          break;
+      }
+    }
+    @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashEraseChip (void);
+
+#endif
diff --git a/drivers/spiflash/w25q16bv/w25q16bv.c b/drivers/spiflash/w25q16bv/w25q16bv.c
new file mode 100644 (file)
index 0000000..7fcfef4
--- /dev/null
@@ -0,0 +1,548 @@
+/**************************************************************************/
+/*! 
+    @file     w25q16bv.c
+    @author   K. Townsend (microBuilder.eu)
+
+    @section DESCRIPTION
+
+    Driver for Winbond's 16 MBit SPI/Quad-SPI Flash (W25Q16BV)
+    
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2010, microBuilder SARL
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#include "w25q16bv.h"
+#include "../spiflash.h"
+#include "core/ssp/ssp.h"
+#include "core/gpio/gpio.h"
+
+// Macros to toggle the CS/SSEL line on the SPI bus
+#define W25Q16BV_SELECT()       gpioSetValue(0, 2, 0)
+#define W25Q16BV_DESELECT()     gpioSetValue(0, 2, 1)
+
+// Flag to indicate whether the SPI flash has been initialised or not
+static bool _w25q16bvInitialised = false;
+
+/**************************************************************************/
+/*   HW Specific Functions                                                */
+/*   -------------------------------------------------------------------  */
+/*   These functions are specific to the chip being used, and are         */
+/*   seperate from the 'generic' functions defined in spiflash.h          */
+/*                                                                        */
+/**************************************************************************/
+
+/**************************************************************************/
+/*!
+    This function both reads and writes data. For write operations, include data
+    to be written as argument. For read ops, use dummy data as arg. Returned
+    data is read byte val.
+*/
+/**************************************************************************/
+uint8_t w25q16bv_TransferByte(uint8_t data)
+{
+    /* Move on only if NOT busy and TX FIFO not full */
+    while ((SSP_SSP0SR & (SSP_SSP0SR_TNF_MASK | SSP_SSP0SR_BSY_MASK)) != SSP_SSP0SR_TNF_NOTFULL);
+    SSP_SSP0DR = data;
+  
+    /* Wait until the busy bit is cleared and receive buffer is not empty */
+    while ((SSP_SSP0SR & (SSP_SSP0SR_BSY_MASK | SSP_SSP0SR_RNE_MASK)) != SSP_SSP0SR_RNE_NOTEMPTY);
+
+    // Read the queue
+    return SSP_SSP0DR;
+}
+
+/**************************************************************************/
+/*! 
+    @brief Gets the value of the Read Status Register (0x05)
+
+    @return     The 8-bit value returned by the Read Status Register
+*/
+/**************************************************************************/
+uint8_t w25q16bvGetStatus()
+{
+  uint8_t status;
+
+  W25Q16BV_SELECT();
+  w25q16bv_TransferByte(W25Q16BV_CMD_READSTAT1);  // Send read status 1 cmd
+  status = w25q16bv_TransferByte(0xFF);           // Dummy write
+  W25Q16BV_DESELECT();
+
+  return status & (W25Q16BV_STAT1_BUSY | W25Q16BV_STAT1_WRTEN);
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Waits for the SPI flash to indicate that it is ready (not
+            busy) or until a timeout occurs.
+
+    @return An error message indicating that a timeoout occured
+            (SPIFLASH_ERROR_TIMEOUT_READY) or an OK signal to indicate that
+            the SPI flash is ready (SPIFLASH_ERROR_OK)
+*/
+/**************************************************************************/
+spiflashError_e w25q16bvWaitForReady()
+{
+  uint32_t timeout = 0;
+  uint8_t status;
+
+  while ( timeout < SSP_MAX_TIMEOUT )
+  {
+    status = w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY;
+    if (status == 0)
+    {
+      break;
+    }
+    timeout++;
+  }
+  if ( timeout == SSP_MAX_TIMEOUT )
+  {
+    return SPIFLASH_ERROR_TIMEOUT_READY;
+  }
+
+  return SPIFLASH_ERROR_OK;
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Gets the unique 64-bit ID assigned to this IC (useful for
+            security purposes to detect if the flash was changed, etc.)
+
+    @param[out] *buffer
+                Pointer to the uint8_t buffer that will store the 8 byte
+                long unique ID
+
+    @note   The unique ID is return in bit order 63..0
+*/
+/**************************************************************************/
+void w25q16bvGetUniqueID(uint8_t *buffer)
+{
+  uint8_t i;
+
+  W25Q16BV_SELECT();
+  w25q16bv_TransferByte(W25Q16BV_CMD_READUNIQUEID); // Unique ID cmd
+  w25q16bv_TransferByte(0xFF);                      // Dummy write
+  w25q16bv_TransferByte(0xFF);                      // Dummy write
+  w25q16bv_TransferByte(0xFF);                      // Dummy write
+  w25q16bv_TransferByte(0xFF);                      // Dummy write
+  // Read 8 bytes worth of data
+  for (i = 0; i < 8; i++)
+  {
+    buffer[i] = w25q16bv_TransferByte(0xFF);
+  }
+  W25Q16BV_DESELECT();
+}
+
+/**************************************************************************/
+/*   Generic spiflash.h Functions                                         */
+/*   -------------------------------------------------------------------  */
+/*   These functions are part of the common interface defined in          */
+/*   spiflash.h and must be implemented by any spi flash device           */
+/*                                                                        */
+/**************************************************************************/
+
+/**************************************************************************/
+/*! 
+    @brief Tries to initialise the flash device, and setups any HW
+           required by the SPI flash
+*/
+/**************************************************************************/
+void spiflashInit (void)
+{
+  // Initialise the SPI bus
+  sspInit(0, sspClockPolarity_Low, sspClockPhase_RisingEdge);
+
+  // ToDo: Set the WP, Hold, etc. pins to an appropriate state
+
+  _w25q16bvInitialised = TRUE;
+}
+
+/**************************************************************************/
+/*! 
+    @brief Gets an instance of spiflashSizeInfo_t that describes the
+           storage limits of the SPI flash like page size (minimum write
+           size) and sector size (minimum erase size).
+*/
+/**************************************************************************/
+spiflashSizeInfo_t spiflashGetSizeInfo(void)
+{
+  spiflashSizeInfo_t size;
+  size.pageSize = W25Q16BV_PAGESIZE;
+  size.pageCount = W25Q16BV_PAGES;
+  size.sectorSize = W25Q16BV_SECTORSIZE;
+  size.sectorCount = W25Q16BV_SECTORS;
+  return size;
+}
+
+/**************************************************************************/
+/*! 
+    @brief Gets the 8-bit manufacturer ID and device ID for the flash
+
+    @param[out] *manufID
+                Pointer to the uint8_t that will store the manufacturer ID
+    @param[out] *deviceID
+                Pointer to the uint8_t that will store the device ID
+*/
+/**************************************************************************/
+void spiflashGetManufacturerInfo (uint8_t *manufID, uint8_t *deviceID)
+{
+  if (!_w25q16bvInitialised) spiflashInit();
+
+  // W25Q16BV_CMD_MANUFDEVID (0x90) provides both the JEDEC manufacturer
+  // ID and the device ID
+
+  W25Q16BV_SELECT();
+  w25q16bv_TransferByte(W25Q16BV_CMD_MANUFDEVID); 
+  w25q16bv_TransferByte(0x00);            // Dummy write
+  w25q16bv_TransferByte(0x00);            // Dummy write
+  w25q16bv_TransferByte(0x00);            // Dummy write
+  *manufID = w25q16bv_TransferByte(0xFF);
+  *deviceID = w25q16bv_TransferByte(0xFF);
+  W25Q16BV_DESELECT();
+}
+
+/**************************************************************************/
+/*! 
+    @brief Sets the write flag on the SPI flash, and if required puts the
+           WP pin in an appropriate state
+
+    @param[in]  enable
+                True (1) to enable writing, false (0) to disable it
+*/
+/**************************************************************************/
+void spiflashWriteEnable (bool enable)
+{
+  if (!_w25q16bvInitialised) spiflashInit();
+
+  uint32_t i;
+  
+  // ToDo: Put the WP pin in an appropriate state if required
+
+  W25Q16BV_SELECT();
+  w25q16bv_TransferByte(enable ? W25Q16BV_CMD_WRITEENABLE : W25Q16BV_CMD_WRITEDISABLE);
+  W25Q16BV_DESELECT();
+}
+
+/**************************************************************************/
+/*! 
+    @brief Reads the specified number of bytes from the supplied address.
+
+    This function will read one or more bytes starting at the supplied
+    address. Please note that bufferLength is zero-based, meaning you
+    should  supply '0' to read a single byte, '3' to read 4 bytes of data,
+    etc.
+
+    @param[in]  address
+                The 24-bit address where the read will start.
+    @param[out] *buffer
+                Pointer to the buffer that will store the read results
+    @param[in]  len
+                Length of the buffer (zero-based).
+
+    @section EXAMPLE
+
+    @code
+    uint8_t buffer[64];
+    spiflashError_e error;
+    error = spiflashReadBuffer (0, buffer, 64);
+    if (error)
+    {
+      // Check what went wrong
+      switch (error)
+      {
+        case SPIFLASH_ERROR_ADDROUTOFRANGE:
+          // Specified starting address is out of range
+          break;
+        case SPIFLASH_ERROR_TIMEOUT_READY:
+          // Timed out waiting for flash to return ready state
+          break;
+        case SPIFLASH_ERROR_ADDROVERFLOW:
+          // Ran over the upper address during read
+          break;
+      }
+    }
+    @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashReadBuffer (uint32_t address, uint8_t *buffer, uint32_t len)
+{
+  if (!_w25q16bvInitialised) spiflashInit();
+
+  uint32_t a, i;
+  a = i = 0;
+
+  // Make sure the address is valid
+  if (address >= W25Q16BV_MAXADDRESS)
+  {
+    return SPIFLASH_ERROR_ADDROUTOFRANGE;
+  }
+
+  // Wait until the device is ready or a timeout occurs
+  if (w25q16bvWaitForReady())
+    return SPIFLASH_ERROR_TIMEOUT_READY;
+
+  // Send the read data command
+  W25Q16BV_SELECT();
+  w25q16bv_TransferByte(W25Q16BV_CMD_READDATA);      // 0x03
+  w25q16bv_TransferByte((address >> 16) & 0xFF);     // address upper 8
+  w25q16bv_TransferByte((address >> 8) & 0xFF);      // address mid 8
+  w25q16bv_TransferByte(address & 0xFF);             // address lower 8
+  // Fill response buffer
+  for (a = address; a < address + len; a++, i++)
+  {
+    if (a > W25Q16BV_MAXADDRESS)
+    {
+      // Oops ... we're at the end of the flash memory
+      return SPIFLASH_ERROR_ADDROVERFLOW;
+    }
+    buffer[i] = w25q16bv_TransferByte(0xFF);
+  }
+  W25Q16BV_DESELECT();
+
+  return SPIFLASH_ERROR_OK;
+}
+
+/**************************************************************************/
+/*! 
+    @brief Erases the contents of a single sector
+
+    @param[in]  sectorNumber
+                The sector number to erase (zero-based).
+
+    @section  EXAMPLE
+
+    @code
+    spiflashError_e error;
+    error = spiflashEraseSector(0);
+    if (error)
+    {
+      // Check what went wrong
+      switch (error)
+      {
+        case SPIFLASH_ERROR_ADDROUTOFRANGE:
+          // Specified starting address is out of range
+          break;
+        case SPIFLASH_ERROR_PROTECTIONERR:
+          // Couldn't set the write enable bit
+          break;
+        case SPIFLASH_ERROR_TIMEOUT_READY:
+          // Timed out waiting for flash to return ready state
+          break;
+      }
+    }
+    @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashEraseSector (uint32_t sectorNumber)
+{
+  if (!_w25q16bvInitialised) spiflashInit();
+
+  // Make sure the address is valid
+  if (sectorNumber >= W25Q16BV_SECTORS)
+  {
+    return SPIFLASH_ERROR_ADDROUTOFRANGE;
+  }  
+
+  // Wait until the device is ready or a timeout occurs
+  if (w25q16bvWaitForReady())
+    return SPIFLASH_ERROR_TIMEOUT_READY;
+
+  // Make sure the chip is write enabled
+  spiflashWriteEnable (TRUE);
+
+  // Make sure the write enable latch is actually set
+  uint8_t status;
+  status = w25q16bvGetStatus();
+  if (!(status & W25Q16BV_STAT1_WRTEN))
+  {
+    // Throw a write protection error (write enable latch not set)
+    return SPIFLASH_ERROR_PROTECTIONERR;
+  }
+
+  // Send the erase sector command
+  uint32_t address = sectorNumber * W25Q16BV_SECTORSIZE;
+  W25Q16BV_SELECT();
+  w25q16bv_TransferByte(W25Q16BV_CMD_SECTERASE4); 
+  w25q16bv_TransferByte((address >> 16) & 0xFF);     // address upper 8
+  w25q16bv_TransferByte((address >> 8) & 0xFF);      // address mid 8
+  w25q16bv_TransferByte(address & 0xFF);             // address lower 8
+  W25Q16BV_DESELECT();
+
+  // Wait until the busy bit is cleared before exiting
+  // This can take up to 10 seconds according to the datasheet!
+  while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY);
+
+  return SPIFLASH_ERROR_OK;
+}
+
+/**************************************************************************/
+/*! 
+    @brief Erases the entire flash chip
+
+    @section  EXAMPLE
+
+    @code
+    spiflashError_e error;
+    error = spiflashEraseChip();
+    if (error)
+    {
+      // Check what went wrong
+      switch (error)
+      {
+        case SPIFLASH_ERROR_PROTECTIONERR:
+          // Couldn't set the write enable bit
+          break;
+        case SPIFLASH_ERROR_TIMEOUT_READY:
+          // Timed out waiting for flash to return ready state
+          break;
+      }
+    }
+    @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashEraseChip (void)
+{
+  if (!_w25q16bvInitialised) spiflashInit();
+
+  // Wait until the device is ready or a timeout occurs
+  if (w25q16bvWaitForReady())
+    return SPIFLASH_ERROR_TIMEOUT_READY;
+
+  // Make sure the chip is write enabled
+  spiflashWriteEnable (TRUE);
+
+  // Make sure the write enable latch is actually set
+  uint8_t status;
+  status = w25q16bvGetStatus();
+  if (!(status & W25Q16BV_STAT1_WRTEN))
+  {
+    // Throw a write protection error (write enable latch not set)
+    return SPIFLASH_ERROR_PROTECTIONERR;
+  }
+
+  // Send the erase chip command
+  W25Q16BV_SELECT();
+  w25q16bv_TransferByte(W25Q16BV_CMD_CHIPERASE); 
+  W25Q16BV_DESELECT();
+
+  // Wait until the busy bit is cleared before exiting
+  // This can take up to 10 seconds according to the datasheet!
+  while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY);
+
+  return SPIFLASH_ERROR_OK;
+}
+
+///**************************************************************************/
+///*! 
+//    @brief Writes the supplied bytes at a specified address.
+//
+//    This function will write one or more bytes starting at the supplied
+//    address.
+//
+//    @param[in]  address
+//                The 16-bit address where the write will start.  The
+//                maximum value for the address depends on the size of the
+//                EEPROM
+//    @param[in]  *buffer
+//                Pointer to the buffer that contains the values to write.
+//    @param[in]  bufferLength
+//                Length of the buffer
+//*/
+///**************************************************************************/
+//at25Error_e at25Write (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
+//{
+//  if (address >= AT25_MAXADDRESS)
+//  {
+//    return AT25_ERROR_ADDRERR;
+//  }
+//
+//  if (bufferLength > 6)
+//  {
+//    return AT25_ERROR_BUFFEROVERFLOW;
+//  }
+//
+//  // Set write enable latch
+//  at25WriteEnable();
+//
+//  timeout = 0;
+//  while ( timeout < SSP_MAX_TIMEOUT )
+//  {
+//    // Wait until the device is write enabled
+//    if (at25GetRSR() == AT25_RDSR_WEN)
+//    {
+//      break;
+//    }
+//    timeout++;
+//  }
+//  if ( timeout == SSP_MAX_TIMEOUT )
+//  {
+//    return AT25_ERROR_TIMEOUT_WE;
+//  }
+//
+//  for (i = 0; i < bufferLength; i++)        // Init RD and WR buffer
+//  {
+//    src_addr[i+2] = buffer[i];              // leave two bytes for cmd and offset(8 bits)
+//    dest_addr[i] = 0;
+//  }
+//
+//  W25Q16BV_SELECT();
+//  // Write command (0x02), append A8 if addr > 256 bytes
+//  src_addr[0] = address > 0xFF ? AT25_WRITE | AT25_A8 : AT25_WRITE;
+//  src_addr[1] = (address);
+//  sspSend(0, (uint8_t *)src_addr, bufferLength + 2);
+//  W25Q16BV_DESELECT();
+//
+//  // Wait at least 3ms
+//  for (i = 0; i < ((CFG_CPU_CCLK / 1000) * 3); i++);
+//  
+//  timeout = 0;
+//  while ( timeout < SSP_MAX_TIMEOUT )
+//  {
+//    // Check status to see if write cycle is done or not
+//    W25Q16BV_SELECT();
+//    src_addr[0] = AT25_RDSR;
+//    sspSend(0, (uint8_t *)src_addr, 1);
+//    sspReceive(0, (uint8_t *)dest_addr, 1);
+//    W25Q16BV_DESELECT();
+//    // Wait until device is ready
+//    if ((dest_addr[0] & AT25_RDSR_RDY) == 0x00)
+//    {
+//      break;
+//    }
+//    timeout++;
+//  }
+//  if ( timeout == SSP_MAX_TIMEOUT )
+//  {
+//    return AT25_ERROR_TIMEOUT_WFINISH;
+//  }
+//
+//  for (i = 0; i < 300; i++);                // Wait at least 250ns
+//
+//  return AT25_ERROR_OK;
+//}
diff --git a/drivers/spiflash/w25q16bv/w25q16bv.h b/drivers/spiflash/w25q16bv/w25q16bv.h
new file mode 100644 (file)
index 0000000..15e296d
--- /dev/null
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*! 
+    @file     w25q16bv.h
+    @author   K. Townsend (microBuilder.eu)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2010, microBuilder SARL
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#ifndef _W25Q16BV_H_
+#define _W25Q16BV_H_
+
+#include "projectconfig.h"
+
+#define W25Q16BV_MAXADDRESS      0x1FFFFF
+#define W25Q16BV_PAGESIZE        256    // 256 bytes per programmable page
+#define W25Q16BV_PAGES           8192   // 2,097,152 Bytes / 256 bytes per page
+#define W25Q16BV_SECTORSIZE      4096   // 1 erase sector = 4096 bytes
+#define W25Q16BV_SECTORS         512    // 2,097,152 Bytes / 4096 bytes per sector
+#define W25Q16BV_MANUFACTURERID  0xEF   // Used to validate read data
+#define W25Q16BV_DEVICEID        0x14   // Used to validate read data
+
+#define W25Q16BV_STAT1_BUSY      0x01   // Erase/Write in Progress
+#define W25Q16BV_STAT1_WRTEN     0x02   // Write Enable Latch
+#define W25Q16BV_STAT2_QUADENBL  0x02   // Quad Enable
+#define W25Q16BV_STAT2_SSPNDSTAT 0x80   // Suspend Status
+
+/**************************************************************************/
+/*! 
+    W25Q16BV Commands
+*/
+/**************************************************************************/
+typedef enum
+{
+  // Erase/Program Instructions
+  W25Q16BV_CMD_WRITEENABLE    = 0x06,   // Write Enabled
+  W25Q16BV_CMD_WRITEDISABLE   = 0x04,   // Write Disabled
+  W25Q16BV_CMD_READSTAT1      = 0x05,   // Read Status Register 1
+  W25Q16BV_CMD_READSTAT2      = 0x35,   // Read Status Register 2
+  W25Q16BV_CMD_WRITESTAT      = 0x01,   // Write Status Register
+  W25Q16BV_CMD_PAGEPROG       = 0x02,   // Page Program
+  W25Q16BV_CMD_QUADPAGEPROG   = 0x32,   // Quad Page Program
+  W25Q16BV_CMD_SECTERASE4     = 0x20,   // Sector Erase (4KB)
+  W25Q16BV_CMD_BLOCKERASE32   = 0x52,   // Block Erase (32KB)
+  W25Q16BV_CMD_BLOCKERASE64   = 0xD8,   // Block Erase (64KB)
+  W25Q16BV_CMD_CHIPERASE      = 0x60,   // Chip Erase
+  W25Q16BV_CMD_ERASESUSPEND   = 0x75,   // Erase Suspend
+  W25Q16BV_CMD_ERASERESUME    = 0x7A,   // Erase Resume
+  W25Q16BV_CMD_POWERDOWN      = 0xB9,   // Power Down
+  W25Q16BV_CMD_CRMR           = 0xFF,   // Continuous Read Mode Reset
+  // Read Instructions
+  W25Q16BV_CMD_READDATA       = 0x03,   // Read Data
+  W25Q16BV_CMD_FREAD          = 0x0B,   // Fast Read
+  W25Q16BV_CMD_FREADDUALOUT   = 0x3B,   // Fast Read Dual Output
+  W25Q16BV_CMD_FREADDUALIO    = 0xBB,   // Fast Read Dual I/O
+  W25Q16BV_CMD_FREADQUADOUT   = 0x6B,   // Fast Read Quad Output
+  W25Q16BV_CMD_FREADQUADIO    = 0xEB,   // Fast Read Quad I/O
+  W25Q16BV_CMD_WREADQUADIO    = 0xE7,   // Word Read Quad I/O
+  W25Q16BV_CMD_OWREADQUADIO   = 0xE3,   // Octal Word Read Quad I/O
+  // ID/Security Instructions
+  W25Q16BV_CMD_RPWRDDEVID     = 0xAB,   // Release Power Down/Device ID
+  W25Q16BV_CMD_MANUFDEVID     = 0x90,   // Manufacturer/Device ID
+  W25Q16BV_CMD_MANUFDEVID2    = 0x92,   // Manufacturer/Device ID by Dual I/O
+  W25Q16BV_CMD_MANUFDEVID4    = 0x94,   // Manufacturer/Device ID by Quad I/O
+  W25Q16BV_CMD_JEDECID        = 0x9F,   // JEDEC ID
+  W25Q16BV_CMD_READUNIQUEID   = 0x4B    // Read Unique ID
+} w25q16bv_Commands_e;
+
+#endif
This page took 0.037009 seconds and 4 git commands to generate.