2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
20 * Author: Dominic Clifton - Initial implementation and testing.
28 #if defined(USE_FLASH_W25Q128FV) && (defined(USE_QUADSPI) || defined(USE_OCTOSPI))
30 #define USE_FLASH_WRITES_USING_4LINES
31 #define USE_FLASH_READS_USING_4LINES
33 #include "build/debug.h"
34 #include "common/utils.h"
36 #include "drivers/time.h"
37 #include "drivers/flash.h"
38 #include "drivers/flash_impl.h"
39 #include "drivers/flash_w25q128fv.h"
40 #include "drivers/bus_quadspi.h"
41 #include "drivers/bus_octospi.h"
44 #define JEDEC_ID_WINBOND_W25Q128FV_SPI 0xEF4018
45 #define JEDEC_ID_WINBOND_W25Q128FV_QUADSPI 0xEF6018
46 #define JEDEC_ID_WINBOND_W25Q128JV_QUADSPI 0xEF7018
47 #define JEDEC_ID_WINBOND_W25Q16JV_SPI 0xEF4015
48 #define JEDEC_ID_WINBOND_W25Q16JV_DTR_SPI 0xEF7015
50 // Device size parameters
51 #define W25Q128FV_PAGE_SIZE 2048
52 #define W25Q128FV_PAGES_PER_BLOCK 64
53 #define W25Q128FV_BLOCKS_PER_DIE 1024
54 #define W25Q128FV_BLOCK_SIZE (W25Q128FV_PAGES_PER_BLOCK * W25Q128FV_PAGE_SIZE)
57 #define W25Q128FV_STATUS_REGISTER_BITS 8
58 #define W25Q128FV_ADDRESS_BITS 24
62 #define W25Q128FV_INSTRUCTION_RDID 0x9F
64 #define W25Q128FV_INSTRUCTION_ENABLE_RESET 0x66
65 #define W25Q128FV_INSTRUCTION_RESET_DEVICE 0x99
67 #define W25Q128FV_INSTRUCTION_READ_STATUS1_REG 0x05
68 #define W25Q128FV_INSTRUCTION_READ_STATUS2_REG 0x35
69 #define W25Q128FV_INSTRUCTION_READ_STATUS3_REG 0x15
71 #define W25Q128FV_INSTRUCTION_WRITE_STATUS1_REG 0x01
72 #define W25Q128FV_INSTRUCTION_WRITE_STATUS2_REG 0x31
73 #define W25Q128FV_INSTRUCTION_WRITE_STATUS3_REG 0x11
75 #define W25Q128FV_INSTRUCTION_WRITE_ENABLE 0x06
76 #define W25Q128FV_INSTRUCTION_VOLATILE_WRITE_ENABLE 0x50
77 #define W25Q128FV_INSTRUCTION_BLOCK_ERASE_64KB 0xD8
78 #define W25Q128FV_INSTRUCTION_CHIP_ERASE 0xC7
80 #define W25Q128FV_INSTRUCTION_ENTER_QPI_MODE 0x38
82 #define W25Q128FV_INSTRUCTION_FAST_READ 0x0B
83 #define W25Q128FV_INSTRUCTION_FAST_READ_QUAD_OUTPUT 0x6B
85 #define W25Q128FV_INSTRUCTION_PAGE_PROGRAM 0x02
86 #define W25Q128FV_INSTRUCTION_QUAD_PAGE_PROGRAM 0x32
88 #define W25Q128FV_SR1_BIT_WRITE_IN_PROGRESS (1 << 0)
89 #define W25Q128FV_SR1_BIT_WRITE_ENABLED (1 << 1)
91 #define W25Q128FV_SR2_BIT_QUAD_ENABLE (1 << 1)
94 //#define W25Q128FV_INSTRUCTION_WRITE_DISABLE 0x04
95 //#define W25Q128FV_INSTRUCTION_PAGE_PROGRAM 0x02
97 // Values from W25Q128FV Datasheet Rev L.
98 #define W25Q128FV_TIMEOUT_PAGE_READ_MS 1 // No minimum specified in datasheet
99 #define W25Q128FV_TIMEOUT_RESET_MS 1 // tRST = 30us
100 #define W25Q128FV_TIMEOUT_BLOCK_ERASE_64KB_MS 2000 // tBE2max = 2000ms, tBE2typ = 150ms
101 #define W25Q128FV_TIMEOUT_CHIP_ERASE_MS (200 * 1000) // tCEmax 200s, tCEtyp = 40s
103 #define W25Q128FV_TIMEOUT_PAGE_PROGRAM_MS 3 // tPPmax = 3ms, tPPtyp = 0.7ms
104 #define W25Q128FV_TIMEOUT_WRITE_ENABLE_MS 1
108 INITIAL_MODE_SPI
= 0,
109 INITIAL_MODE_QUADSPI
,
110 } w25q128fv_initialMode_e
;
112 typedef struct w25q128fvState_s
{
113 w25q128fv_initialMode_e initialMode
;
114 uint32_t currentWriteAddress
;
117 w25q128fvState_t w25q128fvState
= { 0 };
119 static bool w25q128fv_waitForReady(flashDevice_t
*fdevice
);
120 static void w25q128fv_waitForTimeout(flashDevice_t
*fdevice
);
122 MMFLASH_CODE
static void w25q128fv_setTimeout(flashDevice_t
*fdevice
, timeMs_t timeoutMillis
)
124 timeMs_t nowMs
= microsISR() / 1000;
125 fdevice
->timeoutAt
= nowMs
+ timeoutMillis
;
128 MMFLASH_CODE
static void w25q128fv_performOneByteCommand(flashDeviceIO_t
*io
, uint8_t command
)
130 #if defined(USE_QUADSPI)
131 QUADSPI_TypeDef
*quadSpi
= io
->handle
.quadSpi
;
132 quadSpiTransmit1LINE(quadSpi
, command
, 0, NULL
, 0);
133 #elif defined(USE_OCTOSPI)
134 OCTOSPI_TypeDef
*octoSpi
= io
->handle
.octoSpi
;
135 octoSpiTransmit1LINE(octoSpi
, command
, 0, NULL
, 0);
140 MMFLASH_CODE
static void w25q128fv_performCommandWithAddress(flashDeviceIO_t
*io
, uint8_t command
, uint32_t address
)
142 #if defined(USE_QUADSPI)
143 QUADSPI_TypeDef
*quadSpi
= io
->handle
.quadSpi
;
145 quadSpiInstructionWithAddress1LINE(quadSpi
, command
, 0, address
& 0xffffff, W25Q128FV_ADDRESS_BITS
);
146 #elif defined(USE_OCTOSPI)
147 OCTOSPI_TypeDef
*octoSpi
= io
->handle
.octoSpi
;
149 octoSpiInstructionWithAddress1LINE(octoSpi
, command
, 0, address
& 0xffffff, W25Q128FV_ADDRESS_BITS
);
153 MMFLASH_CODE
static void w25q128fv_writeEnable(flashDevice_t
*fdevice
)
155 w25q128fv_performOneByteCommand(&fdevice
->io
, W25Q128FV_INSTRUCTION_WRITE_ENABLE
);
158 MMFLASH_CODE
static uint8_t w25q128fv_readRegister(flashDeviceIO_t
*io
, uint8_t command
)
160 uint8_t in
[W25Q128FV_STATUS_REGISTER_BITS
/ 8] = { 0 };
161 #if defined(USE_QUADSPI)
162 QUADSPI_TypeDef
*quadSpi
= io
->handle
.quadSpi
;
164 quadSpiReceive1LINE(quadSpi
, command
, 0, in
, W25Q128FV_STATUS_REGISTER_BITS
/ 8);
165 #elif defined(USE_OCTOSPI)
166 OCTOSPI_TypeDef
*octoSpi
= io
->handle
.octoSpi
;
168 octoSpiReceive1LINE(octoSpi
, command
, 0, in
, W25Q128FV_STATUS_REGISTER_BITS
/ 8);
175 static void w25q128fv_writeRegister(flashDeviceIO_t
*io
, uint8_t command
, uint8_t data
)
177 #if defined(USE_QUADSPI)
178 QUADSPI_TypeDef
*quadSpi
= io
->handle
.quadSpi
;
180 quadSpiTransmit1LINE(quadSpi
, command
, 0, &data
, W25Q128FV_STATUS_REGISTER_BITS
/ 8);
181 #elif defined(USE_OCTOSPI)
182 OCTOSPI_TypeDef
*octoSpi
= io
->handle
.octoSpi
;
184 octoSpiTransmit1LINE(octoSpi
, command
, 0, &data
, W25Q128FV_STATUS_REGISTER_BITS
/ 8);
189 static void w25q128fv_deviceReset(flashDevice_t
*fdevice
)
191 flashDeviceIO_t
*io
= &fdevice
->io
;
193 w25q128fv_waitForReady(fdevice
);
194 w25q128fv_performOneByteCommand(io
, W25Q128FV_INSTRUCTION_ENABLE_RESET
);
195 w25q128fv_performOneByteCommand(io
, W25Q128FV_INSTRUCTION_RESET_DEVICE
);
197 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_RESET_MS
);
198 w25q128fv_waitForTimeout(fdevice
);
200 w25q128fv_waitForReady(fdevice
);
202 #ifdef DISABLE_NONVOLATILE_QE_MODE // Use this if you encounter a chip with it's QE bit enabled when it shouldn't be.
203 w25q128fv_performOneByteCommand(io
, W25Q128FV_INSTRUCTION_WRITE_ENABLE
);
204 w25q128fv_writeRegister(io
, W25Q128FV_INSTRUCTION_WRITE_STATUS2_REG
, 0x00);
208 #if defined(USE_FLASH_WRITES_USING_4LINES) || defined(USE_FLASH_READS_USING_4LINES)
209 uint8_t registerValue
= w25q128fv_readRegister(io
, W25Q128FV_INSTRUCTION_READ_STATUS2_REG
);
212 // WARNING: DO NOT ENABLE QE bit if IO2/IO3 are connected to GND or VCC.
214 // See datasheet https://www.winbond.com/resource-files/w25q128fv%20rev.m%2005132016%20kms.pdf
215 // W25Q128FV - Revision M - 7.1.10 Quad Enable
217 // There is no such warning for the W25Q128JV in the same documentation section
218 // See datasheet https://www.winbond.com/resource-files/w25q128jv%20revg%2004082019%20plus.pdf
219 // W25Q128JV - Revision G - 7.1.4 Quad Enable
222 if ((registerValue
& W25Q128FV_SR2_BIT_QUAD_ENABLE
) == 0) {
223 // Enable QUADSPI mode.
224 registerValue
= w25q128fv_readRegister(io
, W25Q128FV_INSTRUCTION_READ_STATUS2_REG
);
226 uint8_t newValue
= registerValue
;
227 newValue
|= W25Q128FV_SR2_BIT_QUAD_ENABLE
;
229 //w25q128fv_performOneByteCommand(io, W25Q128FV_INSTRUCTION_WRITE_ENABLE);
230 w25q128fv_performOneByteCommand(io
, W25Q128FV_INSTRUCTION_VOLATILE_WRITE_ENABLE
);
231 w25q128fv_writeRegister(io
, W25Q128FV_INSTRUCTION_WRITE_STATUS2_REG
, newValue
);
236 MMFLASH_CODE
bool w25q128fv_isReady(flashDevice_t
*fdevice
)
238 uint8_t status
= w25q128fv_readRegister(&fdevice
->io
, W25Q128FV_INSTRUCTION_READ_STATUS1_REG
);
240 bool busy
= (status
& W25Q128FV_SR1_BIT_WRITE_IN_PROGRESS
);
245 MMFLASH_CODE
static bool w25q128fv_isWritable(flashDevice_t
*fdevice
)
247 uint8_t status
= w25q128fv_readRegister(&fdevice
->io
, W25Q128FV_INSTRUCTION_READ_STATUS1_REG
);
249 bool writable
= (status
& W25Q128FV_SR1_BIT_WRITE_ENABLED
);
254 MMFLASH_CODE
bool w25q128fv_hasTimedOut(flashDevice_t
*fdevice
)
256 uint32_t nowMs
= microsISR() / 1000;
257 if (cmp32(nowMs
, fdevice
->timeoutAt
) >= 0) {
263 MMFLASH_CODE
void w25q128fv_waitForTimeout(flashDevice_t
*fdevice
)
265 while (!w25q128fv_hasTimedOut(fdevice
)) { }
267 fdevice
->timeoutAt
= 0;
270 MMFLASH_CODE
bool w25q128fv_waitForReady(flashDevice_t
*fdevice
)
273 while (!w25q128fv_isReady(fdevice
)) {
274 if (w25q128fv_hasTimedOut(fdevice
)) {
279 fdevice
->timeoutAt
= 0;
284 const flashVTable_t w25q128fv_vTable
;
286 static void w25q128fv_deviceInit(flashDevice_t
*flashdev
);
288 MMFLASH_CODE_NOINLINE
bool w25q128fv_identify(flashDevice_t
*fdevice
, uint32_t jedecID
)
291 case JEDEC_ID_WINBOND_W25Q128FV_SPI
:
292 case JEDEC_ID_WINBOND_W25Q128FV_QUADSPI
:
293 case JEDEC_ID_WINBOND_W25Q128JV_QUADSPI
:
294 fdevice
->geometry
.sectors
= 256;
295 fdevice
->geometry
.pagesPerSector
= 256;
296 fdevice
->geometry
.pageSize
= 256;
297 // = 16777216 128MBit 16MB
300 case JEDEC_ID_WINBOND_W25Q16JV_DTR_SPI
:
301 case JEDEC_ID_WINBOND_W25Q16JV_SPI
:
302 fdevice
->geometry
.sectors
= 32;
303 fdevice
->geometry
.pagesPerSector
= 256;
304 fdevice
->geometry
.pageSize
= 256;
305 // = 2097152 16MBit 2MB
310 fdevice
->geometry
.sectors
= 0;
311 fdevice
->geometry
.pagesPerSector
= 0;
312 fdevice
->geometry
.sectorSize
= 0;
313 fdevice
->geometry
.totalSize
= 0;
317 // use the chip id to determine the initial interface mode on cold-boot.
319 case JEDEC_ID_WINBOND_W25Q16JV_SPI
:
320 case JEDEC_ID_WINBOND_W25Q16JV_DTR_SPI
:
321 case JEDEC_ID_WINBOND_W25Q128FV_SPI
:
322 w25q128fvState
.initialMode
= INITIAL_MODE_SPI
;
325 case JEDEC_ID_WINBOND_W25Q128JV_QUADSPI
:
326 case JEDEC_ID_WINBOND_W25Q128FV_QUADSPI
:
327 w25q128fvState
.initialMode
= INITIAL_MODE_QUADSPI
;
334 fdevice
->geometry
.flashType
= FLASH_TYPE_NOR
;
335 fdevice
->geometry
.sectorSize
= fdevice
->geometry
.pagesPerSector
* fdevice
->geometry
.pageSize
;
336 fdevice
->geometry
.totalSize
= fdevice
->geometry
.sectorSize
* fdevice
->geometry
.sectors
;
338 fdevice
->vTable
= &w25q128fv_vTable
;
343 void w25q128fv_configure(flashDevice_t
*fdevice
, uint32_t configurationFlags
)
345 if (configurationFlags
& FLASH_CF_SYSTEM_IS_MEMORY_MAPPED
) {
349 w25q128fv_deviceReset(fdevice
);
351 w25q128fv_deviceInit(fdevice
);
354 MMFLASH_CODE
static void w25q128fv_eraseSector(flashDevice_t
*fdevice
, uint32_t address
)
356 w25q128fv_waitForReady(fdevice
);
358 w25q128fv_writeEnable(fdevice
);
360 w25q128fv_performCommandWithAddress(&fdevice
->io
, W25Q128FV_INSTRUCTION_BLOCK_ERASE_64KB
, address
);
362 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_BLOCK_ERASE_64KB_MS
);
365 static void w25q128fv_eraseCompletely(flashDevice_t
*fdevice
)
367 w25q128fv_waitForReady(fdevice
);
369 w25q128fv_writeEnable(fdevice
);
371 w25q128fv_performOneByteCommand(&fdevice
->io
, W25Q128FV_INSTRUCTION_CHIP_ERASE
);
373 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_CHIP_ERASE_MS
);
376 MMFLASH_CODE
static void w25q128fv_loadProgramData(flashDevice_t
*fdevice
, const uint8_t *data
, int length
)
378 w25q128fv_waitForReady(fdevice
);
380 #if defined(USE_QUADSPI)
381 QUADSPI_TypeDef
*quadSpi
= fdevice
->io
.handle
.quadSpi
;
383 #ifdef USE_FLASH_WRITES_USING_4LINES
384 quadSpiTransmitWithAddress4LINES(quadSpi
, W25Q128FV_INSTRUCTION_QUAD_PAGE_PROGRAM
, 0, w25q128fvState
.currentWriteAddress
, W25Q128FV_ADDRESS_BITS
, data
, length
);
386 quadSpiTransmitWithAddress1LINE(quadSpi
, W25Q128FV_INSTRUCTION_PAGE_PROGRAM
, 0, w25q128fvState
.currentWriteAddress
, W25Q128FV_ADDRESS_BITS
, data
, length
);
388 #elif defined(USE_OCTOSPI)
389 OCTOSPI_TypeDef
*octoSpi
= fdevice
->io
.handle
.octoSpi
;
391 #ifdef USE_FLASH_WRITES_USING_4LINES
392 octoSpiTransmitWithAddress4LINES(octoSpi
, W25Q128FV_INSTRUCTION_QUAD_PAGE_PROGRAM
, 0, w25q128fvState
.currentWriteAddress
, W25Q128FV_ADDRESS_BITS
, data
, length
);
394 octoSpiTransmitWithAddress1LINE(octoSpi
, W25Q128FV_INSTRUCTION_PAGE_PROGRAM
, 0, w25q128fvState
.currentWriteAddress
, W25Q128FV_ADDRESS_BITS
, data
, length
);
398 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_PAGE_PROGRAM_MS
);
400 w25q128fvState
.currentWriteAddress
+= length
;
403 MMFLASH_CODE
static void w25q128fv_pageProgramBegin(flashDevice_t
*fdevice
, uint32_t address
, void (*callback
)(uint32_t length
))
405 fdevice
->callback
= callback
;
406 w25q128fvState
.currentWriteAddress
= address
;
409 MMFLASH_CODE
static uint32_t w25q128fv_pageProgramContinue(flashDevice_t
*fdevice
, uint8_t const **buffers
, uint32_t *bufferSizes
, uint32_t bufferCount
)
411 for (uint32_t i
= 0; i
< bufferCount
; i
++) {
412 w25q128fv_waitForReady(fdevice
);
414 w25q128fv_writeEnable(fdevice
);
416 // verify write enable is set.
417 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_WRITE_ENABLE_MS
);
418 bool writable
= false;
420 writable
= w25q128fv_isWritable(fdevice
);
421 } while (!writable
&& w25q128fv_hasTimedOut(fdevice
));
424 return 0; // TODO report failure somehow.
427 w25q128fv_loadProgramData(fdevice
, buffers
[i
], bufferSizes
[i
]);
430 return fdevice
->callbackArg
;
433 MMFLASH_CODE
static void w25q128fv_pageProgramFinish(flashDevice_t
*fdevice
)
438 MMFLASH_CODE
static void w25q128fv_pageProgram(flashDevice_t
*fdevice
, uint32_t address
, const uint8_t *data
, uint32_t length
, void (*callback
)(uint32_t length
))
440 w25q128fv_pageProgramBegin(fdevice
, address
, callback
);
441 w25q128fv_pageProgramContinue(fdevice
, &data
, &length
, 1);
442 w25q128fv_pageProgramFinish(fdevice
);
445 MMFLASH_CODE
void w25q128fv_flush(flashDevice_t
*fdevice
)
450 MMFLASH_CODE
static int w25q128fv_readBytes(flashDevice_t
*fdevice
, uint32_t address
, uint8_t *buffer
, uint32_t length
)
452 if (!w25q128fv_waitForReady(fdevice
)) {
456 #if defined(USE_QUADSPI)
457 QUADSPI_TypeDef
*quadSpi
= fdevice
->io
.handle
.quadSpi
;
458 #ifdef USE_FLASH_READS_USING_4LINES
459 bool status
= quadSpiReceiveWithAddress4LINES(quadSpi
, W25Q128FV_INSTRUCTION_FAST_READ_QUAD_OUTPUT
, 8, address
, W25Q128FV_ADDRESS_BITS
, buffer
, length
);
461 bool status
= quadSpiReceiveWithAddress1LINE(quadSpi
, W25Q128FV_INSTRUCTION_FAST_READ
, 8, address
, W25Q128FV_ADDRESS_BITS
, buffer
, length
);
463 #elif defined(USE_OCTOSPI)
464 OCTOSPI_TypeDef
*octoSpi
= fdevice
->io
.handle
.octoSpi
;
465 #ifdef USE_FLASH_READS_USING_4LINES
466 bool status
= octoSpiReceiveWithAddress4LINES(octoSpi
, W25Q128FV_INSTRUCTION_FAST_READ_QUAD_OUTPUT
, 8, address
, W25Q128FV_ADDRESS_BITS
, buffer
, length
);
468 bool status
= octoSpiReceiveWithAddress1LINE(octoSpi
, W25Q128FV_INSTRUCTION_FAST_READ
, 8, address
, W25Q128FV_ADDRESS_BITS
, buffer
, length
);
472 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_PAGE_READ_MS
);
481 const flashGeometry_t
* w25q128fv_getGeometry(flashDevice_t
*fdevice
)
483 return &fdevice
->geometry
;
486 MMFLASH_DATA
const flashVTable_t w25q128fv_vTable
= {
487 .configure
= w25q128fv_configure
,
488 .isReady
= w25q128fv_isReady
,
489 .waitForReady
= w25q128fv_waitForReady
,
490 .eraseSector
= w25q128fv_eraseSector
,
491 .eraseCompletely
= w25q128fv_eraseCompletely
,
492 .pageProgramBegin
= w25q128fv_pageProgramBegin
,
493 .pageProgramContinue
= w25q128fv_pageProgramContinue
,
494 .pageProgramFinish
= w25q128fv_pageProgramFinish
,
495 .pageProgram
= w25q128fv_pageProgram
,
496 .flush
= w25q128fv_flush
,
497 .readBytes
= w25q128fv_readBytes
,
498 .getGeometry
= w25q128fv_getGeometry
,
501 static void w25q128fv_deviceInit(flashDevice_t
*flashdev
)