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"
45 #include "core/systick/systick.h"
47 // Macros to toggle the CS/SSEL line on the SPI bus
48 #define W25Q16BV_SELECT() gpioSetValue(0, 2, 0)
49 #define W25Q16BV_DESELECT() gpioSetValue(0, 2, 1)
51 // Flag to indicate whether the SPI flash has been initialised or not
52 static bool _w25q16bvInitialised
= false;
54 /**************************************************************************/
55 /* HW Specific Functions */
56 /* ------------------------------------------------------------------- */
57 /* These functions are specific to the chip being used, and are */
58 /* seperate from the 'generic' functions defined in spiflash.h */
60 /**************************************************************************/
62 /**************************************************************************/
64 This function both reads and writes data. For write operations, include data
65 to be written as argument. For read ops, use dummy data as arg. Returned
66 data is read byte val.
68 /**************************************************************************/
69 uint8_t w25q16bv_TransferByte(uint8_t data
)
71 /* Move on only if NOT busy and TX FIFO not full */
72 while ((SSP_SSP0SR
& (SSP_SSP0SR_TNF_MASK
| SSP_SSP0SR_BSY_MASK
)) != SSP_SSP0SR_TNF_NOTFULL
);
75 /* Wait until the busy bit is cleared and receive buffer is not empty */
76 while ((SSP_SSP0SR
& (SSP_SSP0SR_BSY_MASK
| SSP_SSP0SR_RNE_MASK
)) != SSP_SSP0SR_RNE_NOTEMPTY
);
82 /**************************************************************************/
84 @brief Gets the value of the Read Status Register (0x05)
86 @return The 8-bit value returned by the Read Status Register
88 /**************************************************************************/
89 uint8_t w25q16bvGetStatus()
94 w25q16bv_TransferByte(W25Q16BV_CMD_READSTAT1
); // Send read status 1 cmd
95 status
= w25q16bv_TransferByte(0xFF); // Dummy write
98 return status
& (W25Q16BV_STAT1_BUSY
| W25Q16BV_STAT1_WRTEN
);
101 /**************************************************************************/
103 @brief Waits for the SPI flash to indicate that it is ready (not
104 busy) or until a timeout occurs.
106 @return An error message indicating that a timeoout occured
107 (SPIFLASH_ERROR_TIMEOUT_READY) or an OK signal to indicate that
108 the SPI flash is ready (SPIFLASH_ERROR_OK)
110 /**************************************************************************/
111 spiflashError_e
w25q16bvWaitForReady()
113 uint32_t timeout
= 0;
116 while ( timeout
< SSP_MAX_TIMEOUT
)
118 status
= w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY
;
125 if ( timeout
== SSP_MAX_TIMEOUT
)
127 return SPIFLASH_ERROR_TIMEOUT_READY
;
130 return SPIFLASH_ERROR_OK
;
133 /**************************************************************************/
135 @brief Gets the unique 64-bit ID assigned to this IC (useful for
136 security purposes to detect if the flash was changed, etc.)
139 Pointer to the uint8_t buffer that will store the 8 byte
142 @note The unique ID is return in bit order 63..0
144 /**************************************************************************/
145 void w25q16bvGetUniqueID(uint8_t *buffer
)
150 w25q16bv_TransferByte(W25Q16BV_CMD_READUNIQUEID
); // Unique ID cmd
151 w25q16bv_TransferByte(0xFF); // Dummy write
152 w25q16bv_TransferByte(0xFF); // Dummy write
153 w25q16bv_TransferByte(0xFF); // Dummy write
154 w25q16bv_TransferByte(0xFF); // Dummy write
155 // Read 8 bytes worth of data
156 for (i
= 0; i
< 8; i
++)
158 buffer
[i
] = w25q16bv_TransferByte(0xFF);
163 /**************************************************************************/
164 /* Generic spiflash.h Functions */
165 /* ------------------------------------------------------------------- */
166 /* These functions are part of the common interface defined in */
167 /* spiflash.h and must be implemented by any spi flash device */
169 /**************************************************************************/
171 /**************************************************************************/
173 @brief Tries to initialise the flash device, and setups any HW
174 required by the SPI flash
176 /**************************************************************************/
177 void spiflashInit (void)
179 // Initialise the SPI bus
180 sspInit(0, sspClockPolarity_Low
, sspClockPhase_RisingEdge
);
182 // ToDo: Set the WP, Hold, etc. pins to an appropriate state
184 _w25q16bvInitialised
= TRUE
;
187 /**************************************************************************/
189 @brief Gets an instance of spiflashSizeInfo_t that describes the
190 storage limits of the SPI flash like page size (minimum write
191 size) and sector size (minimum erase size).
193 /**************************************************************************/
194 spiflashSizeInfo_t
spiflashGetSizeInfo(void)
196 spiflashSizeInfo_t size
;
197 size
.pageSize
= W25Q16BV_PAGESIZE
;
198 size
.pageCount
= W25Q16BV_PAGES
;
199 size
.sectorSize
= W25Q16BV_SECTORSIZE
;
200 size
.sectorCount
= W25Q16BV_SECTORS
;
204 /**************************************************************************/
206 @brief Gets the 8-bit manufacturer ID and device ID for the flash
209 Pointer to the uint8_t that will store the manufacturer ID
210 @param[out] *deviceID
211 Pointer to the uint8_t that will store the device ID
213 /**************************************************************************/
214 void spiflashGetManufacturerInfo (uint8_t *manufID
, uint8_t *deviceID
)
216 if (!_w25q16bvInitialised
) spiflashInit();
218 // W25Q16BV_CMD_MANUFDEVID (0x90) provides both the JEDEC manufacturer
219 // ID and the device ID
222 w25q16bv_TransferByte(W25Q16BV_CMD_MANUFDEVID
);
223 w25q16bv_TransferByte(0x00); // Dummy write
224 w25q16bv_TransferByte(0x00); // Dummy write
225 w25q16bv_TransferByte(0x00); // Dummy write
226 *manufID
= w25q16bv_TransferByte(0xFF);
227 *deviceID
= w25q16bv_TransferByte(0xFF);
231 /**************************************************************************/
233 @brief Sets the write flag on the SPI flash, and if required puts the
234 WP pin in an appropriate state
237 True (1) to enable writing, false (0) to disable it
239 /**************************************************************************/
240 void spiflashWriteEnable (bool enable
)
242 if (!_w25q16bvInitialised
) spiflashInit();
244 // ToDo: Put the WP pin in an appropriate state if required
247 w25q16bv_TransferByte(enable
? W25Q16BV_CMD_WRITEENABLE
: W25Q16BV_CMD_WRITEDISABLE
);
251 /**************************************************************************/
253 @brief Reads the specified number of bytes from the supplied address.
255 This function will read one or more bytes starting at the supplied
256 address. Please note that bufferLength is zero-based, meaning you
257 should supply '0' to read a single byte, '3' to read 4 bytes of data,
261 The 24-bit address where the read will start.
263 Pointer to the buffer that will store the read results
265 Length of the buffer.
271 spiflashError_e error;
272 error = spiflashReadBuffer (0, buffer, 64);
275 // Check what went wrong
278 case SPIFLASH_ERROR_ADDROUTOFRANGE:
279 // Specified starting address is out of range
281 case SPIFLASH_ERROR_TIMEOUT_READY:
282 // Timed out waiting for flash to return ready state
284 case SPIFLASH_ERROR_ADDROVERFLOW:
285 // Ran over the upper address during read
291 /**************************************************************************/
292 spiflashError_e
spiflashReadBuffer (uint32_t address
, uint8_t *buffer
, uint32_t len
)
294 if (!_w25q16bvInitialised
) spiflashInit();
299 // Make sure the address is valid
300 if (address
>= W25Q16BV_MAXADDRESS
)
302 return SPIFLASH_ERROR_ADDROUTOFRANGE
;
305 // Wait until the device is ready or a timeout occurs
306 if (w25q16bvWaitForReady())
307 return SPIFLASH_ERROR_TIMEOUT_READY
;
309 // Send the read data command
311 w25q16bv_TransferByte(W25Q16BV_CMD_READDATA
); // 0x03
312 w25q16bv_TransferByte((address
>> 16) & 0xFF); // address upper 8
313 w25q16bv_TransferByte((address
>> 8) & 0xFF); // address mid 8
314 w25q16bv_TransferByte(address
& 0xFF); // address lower 8
315 // Fill response buffer
316 for (a
= address
; a
< address
+ len
; a
++, i
++)
318 if (a
> W25Q16BV_MAXADDRESS
)
320 // Oops ... we're at the end of the flash memory
321 return SPIFLASH_ERROR_ADDROVERFLOW
;
323 buffer
[i
] = w25q16bv_TransferByte(0xFF);
327 return SPIFLASH_ERROR_OK
;
330 /**************************************************************************/
332 @brief Erases the contents of a single sector
334 @param[in] sectorNumber
335 The sector number to erase (zero-based).
340 spiflashError_e error;
341 error = spiflashEraseSector(0);
344 // Check what went wrong
347 case SPIFLASH_ERROR_ADDROUTOFRANGE:
348 // Specified starting address is out of range
350 case SPIFLASH_ERROR_PROTECTIONERR:
351 // Couldn't set the write enable bit
353 case SPIFLASH_ERROR_TIMEOUT_READY:
354 // Timed out waiting for flash to return ready state
360 /**************************************************************************/
361 spiflashError_e
spiflashEraseSector (uint32_t sectorNumber
)
363 if (!_w25q16bvInitialised
) spiflashInit();
365 // Make sure the address is valid
366 if (sectorNumber
>= W25Q16BV_SECTORS
)
368 return SPIFLASH_ERROR_ADDROUTOFRANGE
;
371 // Wait until the device is ready or a timeout occurs
372 if (w25q16bvWaitForReady())
373 return SPIFLASH_ERROR_TIMEOUT_READY
;
375 // Make sure the chip is write enabled
376 spiflashWriteEnable (TRUE
);
378 // Make sure the write enable latch is actually set
380 status
= w25q16bvGetStatus();
381 if (!(status
& W25Q16BV_STAT1_WRTEN
))
383 // Throw a write protection error (write enable latch not set)
384 return SPIFLASH_ERROR_PROTECTIONERR
;
387 // Send the erase sector command
388 uint32_t address
= sectorNumber
* W25Q16BV_SECTORSIZE
;
390 w25q16bv_TransferByte(W25Q16BV_CMD_SECTERASE4
);
391 w25q16bv_TransferByte((address
>> 16) & 0xFF); // address upper 8
392 w25q16bv_TransferByte((address
>> 8) & 0xFF); // address mid 8
393 w25q16bv_TransferByte(address
& 0xFF); // address lower 8
396 // Wait until the busy bit is cleared before exiting
397 // This can take up to 400ms according to the datasheet
398 while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY
);
400 return SPIFLASH_ERROR_OK
;
403 /**************************************************************************/
405 @brief Erases the entire flash chip
410 spiflashError_e error;
411 error = spiflashEraseChip();
414 // Check what went wrong
417 case SPIFLASH_ERROR_PROTECTIONERR:
418 // Couldn't set the write enable bit
420 case SPIFLASH_ERROR_TIMEOUT_READY:
421 // Timed out waiting for flash to return ready state
427 /**************************************************************************/
428 spiflashError_e
spiflashEraseChip (void)
430 if (!_w25q16bvInitialised
) spiflashInit();
432 // Wait until the device is ready or a timeout occurs
433 if (w25q16bvWaitForReady())
434 return SPIFLASH_ERROR_TIMEOUT_READY
;
436 // Make sure the chip is write enabled
437 spiflashWriteEnable (TRUE
);
439 // Make sure the write enable latch is actually set
441 status
= w25q16bvGetStatus();
442 if (!(status
& W25Q16BV_STAT1_WRTEN
))
444 // Throw a write protection error (write enable latch not set)
445 return SPIFLASH_ERROR_PROTECTIONERR
;
448 // Send the erase chip command
450 w25q16bv_TransferByte(W25Q16BV_CMD_CHIPERASE
);
453 // Wait until the busy bit is cleared before exiting
454 // This can take up to 10 seconds according to the datasheet!
455 while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY
);
457 return SPIFLASH_ERROR_OK
;
460 /**************************************************************************/
462 @brief Writes up to 256 bytes of data to the specified page.
464 @note Before writing data to a page, make sure that the 4K sector
465 containing the specific page has been erased, otherwise the
466 data will be meaningless.
469 The 24-bit address where the write will start.
471 Pointer to the buffer that will store the read results
473 Length of the buffer. Valid values are from 1 to 256,
474 within the limits of the starting address and page length.
479 spiflashError_e error;
491 error = spiflashWritePage (0, buffer, 8);
494 // Check what went wrong
497 case SPIFLASH_ERROR_ADDROUTOFRANGE:
498 // Specified starting address is out of range
500 case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
501 // Supplied data exceeds max page size
503 case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
504 // The data length plus the start address offset exceeeds page limits
506 case SPIFLASH_ERROR_TIMEOUT_READY:
507 // Timeout waiting for ready status (can be pre or post write)
509 case SPIFLASH_ERROR_PROTECTIONERR:
510 // Unable to set write latch
516 /**************************************************************************/
517 spiflashError_e
spiflashWritePage (uint32_t address
, uint8_t *buffer
, uint32_t len
)
522 if (!_w25q16bvInitialised
) spiflashInit();
524 // Make sure the address is valid
525 if (address
>= W25Q16BV_MAXADDRESS
)
527 return SPIFLASH_ERROR_ADDROUTOFRANGE
;
530 // Make sure that the supplied data is no larger than the page size
531 if (len
> W25Q16BV_PAGESIZE
)
533 return SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE
;
536 // Make sure that the data won't wrap around to the beginning of the sector
537 if ((address
% W25Q16BV_PAGESIZE
) + len
> W25Q16BV_PAGESIZE
)
539 // If you try to write to a page beyond the last byte, it will
540 // wrap around to the start of the page, almost certainly
541 // messing up your data
542 return SPIFLASH_ERROR_PAGEWRITEOVERFLOW
;
545 // Wait until the device is ready or a timeout occurs
546 if (w25q16bvWaitForReady())
547 return SPIFLASH_ERROR_TIMEOUT_READY
;
549 // Make sure the chip is write enabled
550 spiflashWriteEnable (TRUE
);
552 // Make sure the write enable latch is actually set
553 status
= w25q16bvGetStatus();
554 if (!(status
& W25Q16BV_STAT1_WRTEN
))
556 // Throw a write protection error (write enable latch not set)
557 return SPIFLASH_ERROR_PROTECTIONERR
;
560 // Send page write command (0x02) plus 24-bit address
562 w25q16bv_TransferByte(W25Q16BV_CMD_PAGEPROG
); // 0x02
563 w25q16bv_TransferByte((address
>> 16) & 0xFF); // address upper 8
564 w25q16bv_TransferByte((address
>> 8) & 0xFF); // address mid 8
567 // If len = 256 bytes, lower 8 bits must be 0 (see datasheet 11.2.17)
568 w25q16bv_TransferByte(0);
572 w25q16bv_TransferByte(address
& 0xFF); // address lower 8
575 for (i
= 0; i
< len
; i
++)
577 w25q16bv_TransferByte(buffer
[i
]);
579 // Write only occurs after the CS line is de-asserted
582 // Wait at least 3ms (max page program time according to datasheet)
585 // Wait until the device is ready or a timeout occurs
586 if (w25q16bvWaitForReady())
587 return SPIFLASH_ERROR_TIMEOUT_READY
;
589 return SPIFLASH_ERROR_OK
;
592 /**************************************************************************/
594 @brief Writes a continuous stream of data that will automatically
595 cross page boundaries.
597 @note Before writing data, make sure that the appropriate sectors
598 have been erased, otherwise the data will be meaningless.
601 The 24-bit address where the write will start.
603 Pointer to the buffer that will store the read results
605 Length of the buffer, within the limits of the starting
606 address and size of the flash device.
611 spiflashError_e error;
623 error = spiflashWrite (0, buffer, 8);
626 // Check what went wrong
629 case SPIFLASH_ERROR_ADDROUTOFRANGE:
630 // Specified starting address is out of range
632 case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
633 // Supplied data exceeds max page size
635 case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
636 // The data length plus the start address offset exceeeds page limits
638 case SPIFLASH_ERROR_TIMEOUT_READY:
639 // Timeout waiting for ready status (can be pre or post write)
641 case SPIFLASH_ERROR_PROTECTIONERR:
642 // Unable to set write latch
648 /**************************************************************************/
649 spiflashError_e
spiflashWrite (uint32_t address
, uint8_t *buffer
, uint32_t len
)
651 uint32_t bytestowrite
;
652 uint32_t bufferoffset
;
653 spiflashError_e error
;
655 // There's no point duplicating most error checks here since they will all be
656 // done in the underlying call to spiflashWritePage
658 // If the data is only on one page we can take a shortcut
659 if ((address
% W25Q16BV_PAGESIZE
) + len
<= W25Q16BV_PAGESIZE
)
661 // Only one page ... write and be done with it
662 return spiflashWritePage(address
, buffer
, len
);
665 // Block spans multiple pages
669 // Figure out how many bytes need to be written to this page
670 bytestowrite
= W25Q16BV_PAGESIZE
- (address
% W25Q16BV_PAGESIZE
);
671 // Write the current page
672 error
= spiflashWritePage(address
, buffer
+bufferoffset
, bytestowrite
);
673 // Abort if we returned an error
676 // Adjust address and len, and buffer offset
677 address
+= bytestowrite
;
679 bufferoffset
+=bytestowrite
;
680 // If the next page is the last one, write it and exit
681 // otherwise stay in the the loop and keep writing
682 if (len
<= W25Q16BV_PAGESIZE
)
684 // Write the last frame and then quit
685 error
= spiflashWritePage(address
, buffer
+bufferoffset
, len
);
686 // Abort if we returned an error
689 // set len to zero to gracefully exit loop
694 return SPIFLASH_ERROR_OK
;