From e1db5f6d346ead1dc7c32493cdf3b66b9f734b5b Mon Sep 17 00:00:00 2001 From: Kevin Townsend Date: Tue, 13 Sep 2011 07:59:52 +0200 Subject: [PATCH] First commit --- drivers/spiflash/spiflash.h | 232 ++++++++++++ drivers/spiflash/w25q16bv/w25q16bv.c | 548 +++++++++++++++++++++++++++ drivers/spiflash/w25q16bv/w25q16bv.h | 96 +++++ 3 files changed, 876 insertions(+) create mode 100644 drivers/spiflash/spiflash.h create mode 100644 drivers/spiflash/w25q16bv/w25q16bv.c create mode 100644 drivers/spiflash/w25q16bv/w25q16bv.h diff --git a/drivers/spiflash/spiflash.h b/drivers/spiflash/spiflash.h new file mode 100644 index 0000000..7bb14ae --- /dev/null +++ b/drivers/spiflash/spiflash.h @@ -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 index 0000000..7fcfef4 --- /dev/null +++ b/drivers/spiflash/w25q16bv/w25q16bv.c @@ -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 index 0000000..15e296d --- /dev/null +++ b/drivers/spiflash/w25q16bv/w25q16bv.h @@ -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 -- 2.20.1