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();
246 // ToDo: Put the WP pin in an appropriate state if required
249 w25q16bv_TransferByte(enable
? W25Q16BV_CMD_WRITEENABLE
: W25Q16BV_CMD_WRITEDISABLE
);
253 /**************************************************************************/
255 @brief Reads the specified number of bytes from the supplied address.
257 This function will read one or more bytes starting at the supplied
258 address. Please note that bufferLength is zero-based, meaning you
259 should supply '0' to read a single byte, '3' to read 4 bytes of data,
263 The 24-bit address where the read will start.
265 Pointer to the buffer that will store the read results
267 Length of the buffer.
273 spiflashError_e error;
274 error = spiflashReadBuffer (0, buffer, 64);
277 // Check what went wrong
280 case SPIFLASH_ERROR_ADDROUTOFRANGE:
281 // Specified starting address is out of range
283 case SPIFLASH_ERROR_TIMEOUT_READY:
284 // Timed out waiting for flash to return ready state
286 case SPIFLASH_ERROR_ADDROVERFLOW:
287 // Ran over the upper address during read
293 /**************************************************************************/
294 spiflashError_e
spiflashReadBuffer (uint32_t address
, uint8_t *buffer
, uint32_t len
)
296 if (!_w25q16bvInitialised
) spiflashInit();
301 // Make sure the address is valid
302 if (address
>= W25Q16BV_MAXADDRESS
)
304 return SPIFLASH_ERROR_ADDROUTOFRANGE
;
307 // Wait until the device is ready or a timeout occurs
308 if (w25q16bvWaitForReady())
309 return SPIFLASH_ERROR_TIMEOUT_READY
;
311 // Send the read data command
313 w25q16bv_TransferByte(W25Q16BV_CMD_READDATA
); // 0x03
314 w25q16bv_TransferByte((address
>> 16) & 0xFF); // address upper 8
315 w25q16bv_TransferByte((address
>> 8) & 0xFF); // address mid 8
316 w25q16bv_TransferByte(address
& 0xFF); // address lower 8
317 // Fill response buffer
318 for (a
= address
; a
< address
+ len
; a
++, i
++)
320 if (a
> W25Q16BV_MAXADDRESS
)
322 // Oops ... we're at the end of the flash memory
323 return SPIFLASH_ERROR_ADDROVERFLOW
;
325 buffer
[i
] = w25q16bv_TransferByte(0xFF);
329 return SPIFLASH_ERROR_OK
;
332 /**************************************************************************/
334 @brief Erases the contents of a single sector
336 @param[in] sectorNumber
337 The sector number to erase (zero-based).
342 spiflashError_e error;
343 error = spiflashEraseSector(0);
346 // Check what went wrong
349 case SPIFLASH_ERROR_ADDROUTOFRANGE:
350 // Specified starting address is out of range
352 case SPIFLASH_ERROR_PROTECTIONERR:
353 // Couldn't set the write enable bit
355 case SPIFLASH_ERROR_TIMEOUT_READY:
356 // Timed out waiting for flash to return ready state
362 /**************************************************************************/
363 spiflashError_e
spiflashEraseSector (uint32_t sectorNumber
)
365 if (!_w25q16bvInitialised
) spiflashInit();
367 // Make sure the address is valid
368 if (sectorNumber
>= W25Q16BV_SECTORS
)
370 return SPIFLASH_ERROR_ADDROUTOFRANGE
;
373 // Wait until the device is ready or a timeout occurs
374 if (w25q16bvWaitForReady())
375 return SPIFLASH_ERROR_TIMEOUT_READY
;
377 // Make sure the chip is write enabled
378 spiflashWriteEnable (TRUE
);
380 // Make sure the write enable latch is actually set
382 status
= w25q16bvGetStatus();
383 if (!(status
& W25Q16BV_STAT1_WRTEN
))
385 // Throw a write protection error (write enable latch not set)
386 return SPIFLASH_ERROR_PROTECTIONERR
;
389 // Send the erase sector command
390 uint32_t address
= sectorNumber
* W25Q16BV_SECTORSIZE
;
392 w25q16bv_TransferByte(W25Q16BV_CMD_SECTERASE4
);
393 w25q16bv_TransferByte((address
>> 16) & 0xFF); // address upper 8
394 w25q16bv_TransferByte((address
>> 8) & 0xFF); // address mid 8
395 w25q16bv_TransferByte(address
& 0xFF); // address lower 8
398 // Wait until the busy bit is cleared before exiting
399 // This can take up to 400ms according to the datasheet
400 while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY
);
402 return SPIFLASH_ERROR_OK
;
405 /**************************************************************************/
407 @brief Erases the entire flash chip
412 spiflashError_e error;
413 error = spiflashEraseChip();
416 // Check what went wrong
419 case SPIFLASH_ERROR_PROTECTIONERR:
420 // Couldn't set the write enable bit
422 case SPIFLASH_ERROR_TIMEOUT_READY:
423 // Timed out waiting for flash to return ready state
429 /**************************************************************************/
430 spiflashError_e
spiflashEraseChip (void)
432 if (!_w25q16bvInitialised
) spiflashInit();
434 // Wait until the device is ready or a timeout occurs
435 if (w25q16bvWaitForReady())
436 return SPIFLASH_ERROR_TIMEOUT_READY
;
438 // Make sure the chip is write enabled
439 spiflashWriteEnable (TRUE
);
441 // Make sure the write enable latch is actually set
443 status
= w25q16bvGetStatus();
444 if (!(status
& W25Q16BV_STAT1_WRTEN
))
446 // Throw a write protection error (write enable latch not set)
447 return SPIFLASH_ERROR_PROTECTIONERR
;
450 // Send the erase chip command
452 w25q16bv_TransferByte(W25Q16BV_CMD_CHIPERASE
);
455 // Wait until the busy bit is cleared before exiting
456 // This can take up to 10 seconds according to the datasheet!
457 while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY
);
459 return SPIFLASH_ERROR_OK
;
462 /**************************************************************************/
464 @brief Writes up to 256 bytes of data to the specified page.
466 @note Before writing data to a page, make sure that the 4K sector
467 containing the specific page has been erased, otherwise the
468 data will be meaningless.
471 The 24-bit address where the write will start.
473 Pointer to the buffer that will store the read results
475 Length of the buffer. Valid values are from 1 to 256,
476 within the limits of the starting address and page length.
481 spiflashError_e error;
493 error = spiflashWritePage (0, buffer, 8);
496 // Check what went wrong
499 case SPIFLASH_ERROR_ADDROUTOFRANGE:
500 // Specified starting address is out of range
502 case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
503 // Supplied data exceeds max page size
505 case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
506 // The data length plus the start address offset exceeeds page limits
508 case SPIFLASH_ERROR_TIMEOUT_READY:
509 // Timeout waiting for ready status (can be pre or post write)
511 case SPIFLASH_ERROR_PROTECTIONERR:
512 // Unable to set write latch
518 /**************************************************************************/
519 spiflashError_e
spiflashWritePage (uint32_t address
, uint8_t *buffer
, uint32_t len
)
522 uint32_t currentpage
, totalpages
;
523 uint32_t a
, i
, timeout
;
526 if (!_w25q16bvInitialised
) spiflashInit();
528 // Make sure the address is valid
529 if (address
>= W25Q16BV_MAXADDRESS
)
531 return SPIFLASH_ERROR_ADDROUTOFRANGE
;
534 // Make sure that the supplied data is no larger than the page size
535 if (len
> W25Q16BV_PAGESIZE
)
537 return SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE
;
540 // Make sure that the data won't wrap around to the beginning of the sector
541 if ((address
% W25Q16BV_PAGESIZE
) + len
> W25Q16BV_PAGESIZE
)
543 // If you try to write to a page beyond the last byte, it will
544 // wrap around to the start of the page, almost certainly
545 // messing up your data
546 return SPIFLASH_ERROR_PAGEWRITEOVERFLOW
;
549 // Wait until the device is ready or a timeout occurs
550 if (w25q16bvWaitForReady())
551 return SPIFLASH_ERROR_TIMEOUT_READY
;
553 // Make sure the chip is write enabled
554 spiflashWriteEnable (TRUE
);
556 // Make sure the write enable latch is actually set
557 status
= w25q16bvGetStatus();
558 if (!(status
& W25Q16BV_STAT1_WRTEN
))
560 // Throw a write protection error (write enable latch not set)
561 return SPIFLASH_ERROR_PROTECTIONERR
;
564 // Send page write command (0x02) plus 24-bit address
566 w25q16bv_TransferByte(W25Q16BV_CMD_PAGEPROG
); // 0x02
567 w25q16bv_TransferByte((address
>> 16) & 0xFF); // address upper 8
568 w25q16bv_TransferByte((address
>> 8) & 0xFF); // address mid 8
571 // If len = 256 bytes, lower 8 bits must be 0 (see datasheet 11.2.17)
572 w25q16bv_TransferByte(0);
576 w25q16bv_TransferByte(address
& 0xFF); // address lower 8
579 for (i
= 0; i
< len
; i
++)
581 w25q16bv_TransferByte(buffer
[i
]);
583 // Write only occurs after the CS line is de-asserted
586 // Wait at least 3ms (max page program time according to datasheet)
589 // Wait until the device is ready or a timeout occurs
590 if (w25q16bvWaitForReady())
591 return SPIFLASH_ERROR_TIMEOUT_READY
;
593 return SPIFLASH_ERROR_OK
;