1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
8 Driver for Winbond's 16 MBit SPI/Quad-SPI Flash (W25Q16BV)
12 Software License Agreement (BSD License)
14 Copyright (c) 2010, microBuilder SARL
17 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions are met:
19 1. Redistributions of source code must retain the above copyright
20 notice, this list of conditions and the following disclaimer.
21 2. Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in the
23 documentation and/or other materials provided with the distribution.
24 3. Neither the name of the copyright holders nor the
25 names of its contributors may be used to endorse or promote products
26 derived from this software without specific prior written permission.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
29 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
32 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 /**************************************************************************/
42 #include "../spiflash.h"
43 #include "core/ssp/ssp.h"
44 #include "core/gpio/gpio.h"
46 // Macros to toggle the CS/SSEL line on the SPI bus
47 #define W25Q16BV_SELECT() gpioSetValue(0, 2, 0)
48 #define W25Q16BV_DESELECT() gpioSetValue(0, 2, 1)
50 // Flag to indicate whether the SPI flash has been initialised or not
51 static bool _w25q16bvInitialised
= false;
53 /**************************************************************************/
54 /* HW Specific Functions */
55 /* ------------------------------------------------------------------- */
56 /* These functions are specific to the chip being used, and are */
57 /* seperate from the 'generic' functions defined in spiflash.h */
59 /**************************************************************************/
61 /**************************************************************************/
63 This function both reads and writes data. For write operations, include data
64 to be written as argument. For read ops, use dummy data as arg. Returned
65 data is read byte val.
67 /**************************************************************************/
68 uint8_t w25q16bv_TransferByte(uint8_t data
)
70 /* Move on only if NOT busy and TX FIFO not full */
71 while ((SSP_SSP0SR
& (SSP_SSP0SR_TNF_MASK
| SSP_SSP0SR_BSY_MASK
)) != SSP_SSP0SR_TNF_NOTFULL
);
74 /* Wait until the busy bit is cleared and receive buffer is not empty */
75 while ((SSP_SSP0SR
& (SSP_SSP0SR_BSY_MASK
| SSP_SSP0SR_RNE_MASK
)) != SSP_SSP0SR_RNE_NOTEMPTY
);
81 /**************************************************************************/
83 @brief Gets the value of the Read Status Register (0x05)
85 @return The 8-bit value returned by the Read Status Register
87 /**************************************************************************/
88 uint8_t w25q16bvGetStatus()
93 w25q16bv_TransferByte(W25Q16BV_CMD_READSTAT1
); // Send read status 1 cmd
94 status
= w25q16bv_TransferByte(0xFF); // Dummy write
97 return status
& (W25Q16BV_STAT1_BUSY
| W25Q16BV_STAT1_WRTEN
);
100 /**************************************************************************/
102 @brief Waits for the SPI flash to indicate that it is ready (not
103 busy) or until a timeout occurs.
105 @return An error message indicating that a timeoout occured
106 (SPIFLASH_ERROR_TIMEOUT_READY) or an OK signal to indicate that
107 the SPI flash is ready (SPIFLASH_ERROR_OK)
109 /**************************************************************************/
110 spiflashError_e
w25q16bvWaitForReady()
112 uint32_t timeout
= 0;
115 while ( timeout
< SSP_MAX_TIMEOUT
)
117 status
= w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY
;
124 if ( timeout
== SSP_MAX_TIMEOUT
)
126 return SPIFLASH_ERROR_TIMEOUT_READY
;
129 return SPIFLASH_ERROR_OK
;
132 /**************************************************************************/
134 @brief Gets the unique 64-bit ID assigned to this IC (useful for
135 security purposes to detect if the flash was changed, etc.)
138 Pointer to the uint8_t buffer that will store the 8 byte
141 @note The unique ID is return in bit order 63..0
143 /**************************************************************************/
144 void w25q16bvGetUniqueID(uint8_t *buffer
)
149 w25q16bv_TransferByte(W25Q16BV_CMD_READUNIQUEID
); // Unique ID cmd
150 w25q16bv_TransferByte(0xFF); // Dummy write
151 w25q16bv_TransferByte(0xFF); // Dummy write
152 w25q16bv_TransferByte(0xFF); // Dummy write
153 w25q16bv_TransferByte(0xFF); // Dummy write
154 // Read 8 bytes worth of data
155 for (i
= 0; i
< 8; i
++)
157 buffer
[i
] = w25q16bv_TransferByte(0xFF);
162 /**************************************************************************/
163 /* Generic spiflash.h Functions */
164 /* ------------------------------------------------------------------- */
165 /* These functions are part of the common interface defined in */
166 /* spiflash.h and must be implemented by any spi flash device */
168 /**************************************************************************/
170 /**************************************************************************/
172 @brief Tries to initialise the flash device, and setups any HW
173 required by the SPI flash
175 /**************************************************************************/
176 void spiflashInit (void)
178 // Initialise the SPI bus
179 sspInit(0, sspClockPolarity_Low
, sspClockPhase_RisingEdge
);
181 // ToDo: Set the WP, Hold, etc. pins to an appropriate state
183 _w25q16bvInitialised
= TRUE
;
186 /**************************************************************************/
188 @brief Gets an instance of spiflashSizeInfo_t that describes the
189 storage limits of the SPI flash like page size (minimum write
190 size) and sector size (minimum erase size).
192 /**************************************************************************/
193 spiflashSizeInfo_t
spiflashGetSizeInfo(void)
195 spiflashSizeInfo_t size
;
196 size
.pageSize
= W25Q16BV_PAGESIZE
;
197 size
.pageCount
= W25Q16BV_PAGES
;
198 size
.sectorSize
= W25Q16BV_SECTORSIZE
;
199 size
.sectorCount
= W25Q16BV_SECTORS
;
203 /**************************************************************************/
205 @brief Gets the 8-bit manufacturer ID and device ID for the flash
208 Pointer to the uint8_t that will store the manufacturer ID
209 @param[out] *deviceID
210 Pointer to the uint8_t that will store the device ID
212 /**************************************************************************/
213 void spiflashGetManufacturerInfo (uint8_t *manufID
, uint8_t *deviceID
)
215 if (!_w25q16bvInitialised
) spiflashInit();
217 // W25Q16BV_CMD_MANUFDEVID (0x90) provides both the JEDEC manufacturer
218 // ID and the device ID
221 w25q16bv_TransferByte(W25Q16BV_CMD_MANUFDEVID
);
222 w25q16bv_TransferByte(0x00); // Dummy write
223 w25q16bv_TransferByte(0x00); // Dummy write
224 w25q16bv_TransferByte(0x00); // Dummy write
225 *manufID
= w25q16bv_TransferByte(0xFF);
226 *deviceID
= w25q16bv_TransferByte(0xFF);
230 /**************************************************************************/
232 @brief Sets the write flag on the SPI flash, and if required puts the
233 WP pin in an appropriate state
236 True (1) to enable writing, false (0) to disable it
238 /**************************************************************************/
239 void spiflashWriteEnable (bool enable
)
241 if (!_w25q16bvInitialised
) spiflashInit();
245 // ToDo: Put the WP pin in an appropriate state if required
248 w25q16bv_TransferByte(enable
? W25Q16BV_CMD_WRITEENABLE
: W25Q16BV_CMD_WRITEDISABLE
);
252 /**************************************************************************/
254 @brief Reads the specified number of bytes from the supplied address.
256 This function will read one or more bytes starting at the supplied
257 address. Please note that bufferLength is zero-based, meaning you
258 should supply '0' to read a single byte, '3' to read 4 bytes of data,
262 The 24-bit address where the read will start.
264 Pointer to the buffer that will store the read results
266 Length of the buffer (zero-based).
272 spiflashError_e error;
273 error = spiflashReadBuffer (0, buffer, 64);
276 // Check what went wrong
279 case SPIFLASH_ERROR_ADDROUTOFRANGE:
280 // Specified starting address is out of range
282 case SPIFLASH_ERROR_TIMEOUT_READY:
283 // Timed out waiting for flash to return ready state
285 case SPIFLASH_ERROR_ADDROVERFLOW:
286 // Ran over the upper address during read
292 /**************************************************************************/
293 spiflashError_e
spiflashReadBuffer (uint32_t address
, uint8_t *buffer
, uint32_t len
)
295 if (!_w25q16bvInitialised
) spiflashInit();
300 // Make sure the address is valid
301 if (address
>= W25Q16BV_MAXADDRESS
)
303 return SPIFLASH_ERROR_ADDROUTOFRANGE
;
306 // Wait until the device is ready or a timeout occurs
307 if (w25q16bvWaitForReady())
308 return SPIFLASH_ERROR_TIMEOUT_READY
;
310 // Send the read data command
312 w25q16bv_TransferByte(W25Q16BV_CMD_READDATA
); // 0x03
313 w25q16bv_TransferByte((address
>> 16) & 0xFF); // address upper 8
314 w25q16bv_TransferByte((address
>> 8) & 0xFF); // address mid 8
315 w25q16bv_TransferByte(address
& 0xFF); // address lower 8
316 // Fill response buffer
317 for (a
= address
; a
< address
+ len
; a
++, i
++)
319 if (a
> W25Q16BV_MAXADDRESS
)
321 // Oops ... we're at the end of the flash memory
322 return SPIFLASH_ERROR_ADDROVERFLOW
;
324 buffer
[i
] = w25q16bv_TransferByte(0xFF);
328 return SPIFLASH_ERROR_OK
;
331 /**************************************************************************/
333 @brief Erases the contents of a single sector
335 @param[in] sectorNumber
336 The sector number to erase (zero-based).
341 spiflashError_e error;
342 error = spiflashEraseSector(0);
345 // Check what went wrong
348 case SPIFLASH_ERROR_ADDROUTOFRANGE:
349 // Specified starting address is out of range
351 case SPIFLASH_ERROR_PROTECTIONERR:
352 // Couldn't set the write enable bit
354 case SPIFLASH_ERROR_TIMEOUT_READY:
355 // Timed out waiting for flash to return ready state
361 /**************************************************************************/
362 spiflashError_e
spiflashEraseSector (uint32_t sectorNumber
)
364 if (!_w25q16bvInitialised
) spiflashInit();
366 // Make sure the address is valid
367 if (sectorNumber
>= W25Q16BV_SECTORS
)
369 return SPIFLASH_ERROR_ADDROUTOFRANGE
;
372 // Wait until the device is ready or a timeout occurs
373 if (w25q16bvWaitForReady())
374 return SPIFLASH_ERROR_TIMEOUT_READY
;
376 // Make sure the chip is write enabled
377 spiflashWriteEnable (TRUE
);
379 // Make sure the write enable latch is actually set
381 status
= w25q16bvGetStatus();
382 if (!(status
& W25Q16BV_STAT1_WRTEN
))
384 // Throw a write protection error (write enable latch not set)
385 return SPIFLASH_ERROR_PROTECTIONERR
;
388 // Send the erase sector command
389 uint32_t address
= sectorNumber
* W25Q16BV_SECTORSIZE
;
391 w25q16bv_TransferByte(W25Q16BV_CMD_SECTERASE4
);
392 w25q16bv_TransferByte((address
>> 16) & 0xFF); // address upper 8
393 w25q16bv_TransferByte((address
>> 8) & 0xFF); // address mid 8
394 w25q16bv_TransferByte(address
& 0xFF); // address lower 8
397 // Wait until the busy bit is cleared before exiting
398 // This can take up to 10 seconds according to the datasheet!
399 while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY
);
401 return SPIFLASH_ERROR_OK
;
404 /**************************************************************************/
406 @brief Erases the entire flash chip
411 spiflashError_e error;
412 error = spiflashEraseChip();
415 // Check what went wrong
418 case SPIFLASH_ERROR_PROTECTIONERR:
419 // Couldn't set the write enable bit
421 case SPIFLASH_ERROR_TIMEOUT_READY:
422 // Timed out waiting for flash to return ready state
428 /**************************************************************************/
429 spiflashError_e
spiflashEraseChip (void)
431 if (!_w25q16bvInitialised
) spiflashInit();
433 // Wait until the device is ready or a timeout occurs
434 if (w25q16bvWaitForReady())
435 return SPIFLASH_ERROR_TIMEOUT_READY
;
437 // Make sure the chip is write enabled
438 spiflashWriteEnable (TRUE
);
440 // Make sure the write enable latch is actually set
442 status
= w25q16bvGetStatus();
443 if (!(status
& W25Q16BV_STAT1_WRTEN
))
445 // Throw a write protection error (write enable latch not set)
446 return SPIFLASH_ERROR_PROTECTIONERR
;
449 // Send the erase chip command
451 w25q16bv_TransferByte(W25Q16BV_CMD_CHIPERASE
);
454 // Wait until the busy bit is cleared before exiting
455 // This can take up to 10 seconds according to the datasheet!
456 while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY
);
458 return SPIFLASH_ERROR_OK
;
461 ///**************************************************************************/
463 // @brief Writes the supplied bytes at a specified address.
465 // This function will write one or more bytes starting at the supplied
468 // @param[in] address
469 // The 16-bit address where the write will start. The
470 // maximum value for the address depends on the size of the
472 // @param[in] *buffer
473 // Pointer to the buffer that contains the values to write.
474 // @param[in] bufferLength
475 // Length of the buffer
477 ///**************************************************************************/
478 //at25Error_e at25Write (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
480 // if (address >= AT25_MAXADDRESS)
482 // return AT25_ERROR_ADDRERR;
485 // if (bufferLength > 6)
487 // return AT25_ERROR_BUFFEROVERFLOW;
490 // // Set write enable latch
491 // at25WriteEnable();
494 // while ( timeout < SSP_MAX_TIMEOUT )
496 // // Wait until the device is write enabled
497 // if (at25GetRSR() == AT25_RDSR_WEN)
503 // if ( timeout == SSP_MAX_TIMEOUT )
505 // return AT25_ERROR_TIMEOUT_WE;
508 // for (i = 0; i < bufferLength; i++) // Init RD and WR buffer
510 // src_addr[i+2] = buffer[i]; // leave two bytes for cmd and offset(8 bits)
514 // W25Q16BV_SELECT();
515 // // Write command (0x02), append A8 if addr > 256 bytes
516 // src_addr[0] = address > 0xFF ? AT25_WRITE | AT25_A8 : AT25_WRITE;
517 // src_addr[1] = (address);
518 // sspSend(0, (uint8_t *)src_addr, bufferLength + 2);
519 // W25Q16BV_DESELECT();
521 // // Wait at least 3ms
522 // for (i = 0; i < ((CFG_CPU_CCLK / 1000) * 3); i++);
525 // while ( timeout < SSP_MAX_TIMEOUT )
527 // // Check status to see if write cycle is done or not
528 // W25Q16BV_SELECT();
529 // src_addr[0] = AT25_RDSR;
530 // sspSend(0, (uint8_t *)src_addr, 1);
531 // sspReceive(0, (uint8_t *)dest_addr, 1);
532 // W25Q16BV_DESELECT();
533 // // Wait until device is ready
534 // if ((dest_addr[0] & AT25_RDSR_RDY) == 0x00)
540 // if ( timeout == SSP_MAX_TIMEOUT )
542 // return AT25_ERROR_TIMEOUT_WFINISH;
545 // for (i = 0; i < 300; i++); // Wait at least 250ns
547 // return AT25_ERROR_OK;