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)
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/flash.h"
37 #include "drivers/flash_impl.h"
38 #include "drivers/flash_w25q128fv.h"
39 #include "drivers/bus_quadspi.h"
42 #define JEDEC_ID_WINBOND_W25Q128FV_SPI 0xEF4018
43 #define JEDEC_ID_WINBOND_W25Q128FV_QUADSPI 0xEF6018
44 #define JEDEC_ID_WINBOND_W25Q128JV_QUADSPI 0xEF7018
46 // Device size parameters
47 #define W25Q128FV_PAGE_SIZE 2048
48 #define W25Q128FV_PAGES_PER_BLOCK 64
49 #define W25Q128FV_BLOCKS_PER_DIE 1024
50 #define W25Q128FV_BLOCK_SIZE (W25Q128FV_PAGES_PER_BLOCK * W25Q128FV_PAGE_SIZE)
53 #define W25Q128FV_STATUS_REGISTER_BITS 8
54 #define W25Q128FV_ADDRESS_BITS 24
58 #define W25Q128FV_INSTRUCTION_RDID 0x9F
60 #define W25Q128FV_INSTRUCTION_ENABLE_RESET 0x66
61 #define W25Q128FV_INSTRUCTION_RESET_DEVICE 0x99
63 #define W25Q128FV_INSTRUCTION_READ_STATUS1_REG 0x05
64 #define W25Q128FV_INSTRUCTION_READ_STATUS2_REG 0x35
65 #define W25Q128FV_INSTRUCTION_READ_STATUS3_REG 0x15
67 #define W25Q128FV_INSTRUCTION_WRITE_STATUS1_REG 0x01
68 #define W25Q128FV_INSTRUCTION_WRITE_STATUS2_REG 0x31
69 #define W25Q128FV_INSTRUCTION_WRITE_STATUS3_REG 0x11
71 #define W25Q128FV_INSTRUCTION_WRITE_ENABLE 0x06
72 #define W25Q128FV_INSTRUCTION_VOLATILE_WRITE_ENABLE 0x50
73 #define W25Q128FV_INSTRUCTION_BLOCK_ERASE_64KB 0xD8
74 #define W25Q128FV_INSTRUCTION_CHIP_ERASE 0xC7
76 #define W25Q128FV_INSTRUCTION_ENTER_QPI_MODE 0x38
78 #define W25Q128FV_INSTRUCTION_FAST_READ 0x0B
79 #define W25Q128FV_INSTRUCTION_FAST_READ_QUAD_OUTPUT 0x6B
81 #define W25Q128FV_INSTRUCTION_PAGE_PROGRAM 0x02
82 #define W25Q128FV_INSTRUCTION_QUAD_PAGE_PROGRAM 0x32
84 #define W25Q128FV_SR1_BIT_WRITE_IN_PROGRESS (1 << 0)
85 #define W25Q128FV_SR1_BIT_WRITE_ENABLED (1 << 1)
87 #define W25Q128FV_SR2_BIT_QUAD_ENABLE (1 << 1)
90 //#define W25Q128FV_INSTRUCTION_WRITE_DISABLE 0x04
91 //#define W25Q128FV_INSTRUCTION_PAGE_PROGRAM 0x02
93 // Timings (2ms minimum to avoid 1 tick advance in consecutive calls to HAL_GetTick).
94 #define W25Q128FV_TIMEOUT_PAGE_READ_MS 4
95 #define W25Q128FV_TIMEOUT_RESET_MS 2 // tRST = 30us
96 #define W25Q128FV_TIMEOUT_BLOCK_ERASE_64KB_MS 2000 // tBE2max = 2000ms, tBE2typ = 150ms
97 #define W25Q128FV_TIMEOUT_CHIP_ERASE_MS (200 * 1000) // tCEmax 200s, tCEtyp = 40s
99 #define W25Q128FV_TIMEOUT_PAGE_PROGRAM_MS 2 // tPPmax = 700us, tPPtyp = 250us
100 #define W25Q128FV_TIMEOUT_WRITE_ENABLE_MS 2
104 INITIAL_MODE_SPI
= 0,
105 INITIAL_MODE_QUADSPI
,
106 } w25q128fv_initialMode_e
;
108 typedef struct w25q128fvState_s
{
109 w25q128fv_initialMode_e initialMode
;
110 uint32_t currentWriteAddress
;
113 w25q128fvState_t w25q128fvState
= { 0 };
115 static bool w25q128fv_waitForReady(flashDevice_t
*fdevice
);
116 static void w25q128fv_waitForTimeout(flashDevice_t
*fdevice
);
118 static void w25q128fv_setTimeout(flashDevice_t
*fdevice
, uint32_t timeoutMillis
)
120 uint32_t now
= HAL_GetTick();
121 fdevice
->timeoutAt
= now
+ timeoutMillis
;
124 static void w25q128fv_performOneByteCommand(flashDeviceIO_t
*io
, uint8_t command
)
126 QUADSPI_TypeDef
*quadSpi
= io
->handle
.quadSpi
;
127 quadSpiTransmit1LINE(quadSpi
, command
, 0, NULL
, 0);
130 static void w25q128fv_performCommandWithAddress(flashDeviceIO_t
*io
, uint8_t command
, uint32_t address
)
132 QUADSPI_TypeDef
*quadSpi
= io
->handle
.quadSpi
;
134 quadSpiInstructionWithAddress1LINE(quadSpi
, command
, 0, address
& 0xffffff, W25Q128FV_ADDRESS_BITS
);
137 static void w25q128fv_writeEnable(flashDevice_t
*fdevice
)
139 w25q128fv_performOneByteCommand(&fdevice
->io
, W25Q128FV_INSTRUCTION_WRITE_ENABLE
);
142 static uint8_t w25q128fv_readRegister(flashDeviceIO_t
*io
, uint8_t command
)
144 QUADSPI_TypeDef
*quadSpi
= io
->handle
.quadSpi
;
147 quadSpiReceive1LINE(quadSpi
, command
, 0, in
, W25Q128FV_STATUS_REGISTER_BITS
/ 8);
152 static void w25q128fv_writeRegister(flashDeviceIO_t
*io
, uint8_t command
, uint8_t data
)
154 QUADSPI_TypeDef
*quadSpi
= io
->handle
.quadSpi
;
156 quadSpiTransmit1LINE(quadSpi
, command
, 0, &data
, W25Q128FV_STATUS_REGISTER_BITS
/ 8);
159 static void w25q128fv_deviceReset(flashDevice_t
*fdevice
)
161 flashDeviceIO_t
*io
= &fdevice
->io
;
163 w25q128fv_waitForReady(fdevice
);
164 w25q128fv_performOneByteCommand(io
, W25Q128FV_INSTRUCTION_ENABLE_RESET
);
165 w25q128fv_performOneByteCommand(io
, W25Q128FV_INSTRUCTION_RESET_DEVICE
);
167 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_RESET_MS
);
168 w25q128fv_waitForTimeout(fdevice
);
170 w25q128fv_waitForReady(fdevice
);
172 #ifdef DISABLE_NONVOLATILE_QE_MODE // Use this if you encounter a chip with it's QE bit enabled when it shouldn't be.
173 w25q128fv_performOneByteCommand(io
, W25Q128FV_INSTRUCTION_WRITE_ENABLE
);
174 w25q128fv_writeRegister(io
, W25Q128FV_INSTRUCTION_WRITE_STATUS2_REG
, 0x00);
178 #if defined(USE_FLASH_WRITES_USING_4LINES) || defined(USE_FLASH_READS_USING_4LINES)
179 uint8_t registerValue
= w25q128fv_readRegister(io
, W25Q128FV_INSTRUCTION_READ_STATUS2_REG
);
182 // WARNING: DO NOT ENABLE QE bit if IO2/IO3 are connected to GND or VCC.
184 // See datasheet https://www.winbond.com/resource-files/w25q128fv%20rev.m%2005132016%20kms.pdf
185 // W25Q128FV - Revision M - 7.1.10 Quad Enable
187 // There is no such warning for the W25Q128JV in the same documentation section
188 // See datasheet https://www.winbond.com/resource-files/w25q128jv%20revg%2004082019%20plus.pdf
189 // W25Q128JV - Revision G - 7.1.4 Quad Enable
192 if ((registerValue
& W25Q128FV_SR2_BIT_QUAD_ENABLE
) == 0) {
193 // Enable QUADSPI mode.
194 registerValue
= w25q128fv_readRegister(io
, W25Q128FV_INSTRUCTION_READ_STATUS2_REG
);
196 uint8_t newValue
= registerValue
;
197 newValue
|= W25Q128FV_SR2_BIT_QUAD_ENABLE
;
199 //w25q128fv_performOneByteCommand(io, W25Q128FV_INSTRUCTION_WRITE_ENABLE);
200 w25q128fv_performOneByteCommand(io
, W25Q128FV_INSTRUCTION_VOLATILE_WRITE_ENABLE
);
201 w25q128fv_writeRegister(io
, W25Q128FV_INSTRUCTION_WRITE_STATUS2_REG
, newValue
);
206 bool w25q128fv_isReady(flashDevice_t
*fdevice
)
208 uint8_t status
= w25q128fv_readRegister(&fdevice
->io
, W25Q128FV_INSTRUCTION_READ_STATUS1_REG
);
210 bool busy
= (status
& W25Q128FV_SR1_BIT_WRITE_IN_PROGRESS
);
215 static bool w25q128fv_isWritable(flashDevice_t
*fdevice
)
217 uint8_t status
= w25q128fv_readRegister(&fdevice
->io
, W25Q128FV_INSTRUCTION_READ_STATUS1_REG
);
219 bool writable
= (status
& W25Q128FV_SR1_BIT_WRITE_ENABLED
);
224 bool w25q128fv_hasTimedOut(flashDevice_t
*fdevice
)
226 uint32_t now
= HAL_GetTick();
227 if (cmp32(now
, fdevice
->timeoutAt
) >= 0) {
233 void w25q128fv_waitForTimeout(flashDevice_t
*fdevice
)
235 while (!w25q128fv_hasTimedOut(fdevice
)) { }
237 fdevice
->timeoutAt
= 0;
240 bool w25q128fv_waitForReady(flashDevice_t
*fdevice
)
243 while (!w25q128fv_isReady(fdevice
)) {
244 if (w25q128fv_hasTimedOut(fdevice
)) {
249 fdevice
->timeoutAt
= 0;
254 const flashVTable_t w25q128fv_vTable
;
256 static void w25q128fv_deviceInit(flashDevice_t
*flashdev
);
258 bool w25q128fv_detect(flashDevice_t
*fdevice
, uint32_t chipID
)
261 case JEDEC_ID_WINBOND_W25Q128FV_SPI
:
262 case JEDEC_ID_WINBOND_W25Q128FV_QUADSPI
:
263 case JEDEC_ID_WINBOND_W25Q128JV_QUADSPI
:
264 fdevice
->geometry
.sectors
= 256;
265 fdevice
->geometry
.pagesPerSector
= 256;
266 fdevice
->geometry
.pageSize
= 256;
271 fdevice
->geometry
.sectors
= 0;
272 fdevice
->geometry
.pagesPerSector
= 0;
273 fdevice
->geometry
.sectorSize
= 0;
274 fdevice
->geometry
.totalSize
= 0;
278 // use the chip id to determine the initial interface mode on cold-boot.
280 case JEDEC_ID_WINBOND_W25Q128FV_SPI
:
281 w25q128fvState
.initialMode
= INITIAL_MODE_SPI
;
284 case JEDEC_ID_WINBOND_W25Q128JV_QUADSPI
:
285 case JEDEC_ID_WINBOND_W25Q128FV_QUADSPI
:
286 w25q128fvState
.initialMode
= INITIAL_MODE_QUADSPI
;
293 fdevice
->geometry
.flashType
= FLASH_TYPE_NOR
;
294 fdevice
->geometry
.sectorSize
= fdevice
->geometry
.pagesPerSector
* fdevice
->geometry
.pageSize
;
295 fdevice
->geometry
.totalSize
= fdevice
->geometry
.sectorSize
* fdevice
->geometry
.sectors
;
297 w25q128fv_deviceReset(fdevice
);
299 w25q128fv_deviceInit(fdevice
);
301 fdevice
->vTable
= &w25q128fv_vTable
;
306 static void w25q128fv_eraseSector(flashDevice_t
*fdevice
, uint32_t address
)
309 w25q128fv_waitForReady(fdevice
);
311 w25q128fv_writeEnable(fdevice
);
313 w25q128fv_performCommandWithAddress(&fdevice
->io
, W25Q128FV_INSTRUCTION_BLOCK_ERASE_64KB
, address
);
315 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_BLOCK_ERASE_64KB_MS
);
318 static void w25q128fv_eraseCompletely(flashDevice_t
*fdevice
)
320 w25q128fv_waitForReady(fdevice
);
322 w25q128fv_writeEnable(fdevice
);
324 w25q128fv_performOneByteCommand(&fdevice
->io
, W25Q128FV_INSTRUCTION_CHIP_ERASE
);
326 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_CHIP_ERASE_MS
);
330 static void w25q128fv_loadProgramData(flashDevice_t
*fdevice
, const uint8_t *data
, int length
)
332 w25q128fv_waitForReady(fdevice
);
334 QUADSPI_TypeDef
*quadSpi
= fdevice
->io
.handle
.quadSpi
;
336 #ifdef USE_FLASH_WRITES_USING_4LINES
337 quadSpiTransmitWithAddress4LINES(quadSpi
, W25Q128FV_INSTRUCTION_QUAD_PAGE_PROGRAM
, 0, w25q128fvState
.currentWriteAddress
, W25Q128FV_ADDRESS_BITS
, data
, length
);
339 quadSpiTransmitWithAddress1LINE(quadSpi
, W25Q128FV_INSTRUCTION_PAGE_PROGRAM
, 0, w25q128fvState
.currentWriteAddress
, W25Q128FV_ADDRESS_BITS
, data
, length
);
342 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_PAGE_PROGRAM_MS
);
344 w25q128fvState
.currentWriteAddress
+= length
;
347 static void w25q128fv_pageProgramBegin(flashDevice_t
*fdevice
, uint32_t address
, void (*callback
)(uint32_t length
))
349 fdevice
->callback
= callback
;
350 w25q128fvState
.currentWriteAddress
= address
;
353 static uint32_t w25q128fv_pageProgramContinue(flashDevice_t
*fdevice
, uint8_t const **buffers
, uint32_t *bufferSizes
, uint32_t bufferCount
)
355 for (uint32_t i
= 0; i
< bufferCount
; i
++) {
356 w25q128fv_waitForReady(fdevice
);
358 w25q128fv_writeEnable(fdevice
);
360 // verify write enable is set.
361 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_WRITE_ENABLE_MS
);
362 bool writable
= false;
364 writable
= w25q128fv_isWritable(fdevice
);
365 } while (!writable
&& w25q128fv_hasTimedOut(fdevice
));
368 return 0; // TODO report failure somehow.
371 w25q128fv_loadProgramData(fdevice
, buffers
[i
], bufferSizes
[i
]);
374 return fdevice
->callbackArg
;
377 static void w25q128fv_pageProgramFinish(flashDevice_t
*fdevice
)
382 static void w25q128fv_pageProgram(flashDevice_t
*fdevice
, uint32_t address
, const uint8_t *data
, uint32_t length
, void (*callback
)(uint32_t length
))
384 w25q128fv_pageProgramBegin(fdevice
, address
, callback
);
385 w25q128fv_pageProgramContinue(fdevice
, &data
, &length
, 1);
386 w25q128fv_pageProgramFinish(fdevice
);
389 void w25q128fv_flush(flashDevice_t
*fdevice
)
394 static int w25q128fv_readBytes(flashDevice_t
*fdevice
, uint32_t address
, uint8_t *buffer
, uint32_t length
)
396 if (!w25q128fv_waitForReady(fdevice
)) {
400 QUADSPI_TypeDef
*quadSpi
= fdevice
->io
.handle
.quadSpi
;
401 #ifdef USE_FLASH_READS_USING_4LINES
402 bool status
= quadSpiReceiveWithAddress4LINES(quadSpi
, W25Q128FV_INSTRUCTION_FAST_READ_QUAD_OUTPUT
, 8, address
, W25Q128FV_ADDRESS_BITS
, buffer
, length
);
404 bool status
= quadSpiReceiveWithAddress1LINE(quadSpi
, W25Q128FV_INSTRUCTION_FAST_READ
, 8, address
, W25Q128FV_ADDRESS_BITS
, buffer
, length
);
406 w25q128fv_setTimeout(fdevice
, W25Q128FV_TIMEOUT_PAGE_READ_MS
);
417 const flashGeometry_t
* w25q128fv_getGeometry(flashDevice_t
*fdevice
)
419 return &fdevice
->geometry
;
422 const flashVTable_t w25q128fv_vTable
= {
423 .isReady
= w25q128fv_isReady
,
424 .waitForReady
= w25q128fv_waitForReady
,
425 .eraseSector
= w25q128fv_eraseSector
,
426 .eraseCompletely
= w25q128fv_eraseCompletely
,
427 .pageProgramBegin
= w25q128fv_pageProgramBegin
,
428 .pageProgramContinue
= w25q128fv_pageProgramContinue
,
429 .pageProgramFinish
= w25q128fv_pageProgramFinish
,
430 .pageProgram
= w25q128fv_pageProgram
,
431 .flush
= w25q128fv_flush
,
432 .readBytes
= w25q128fv_readBytes
,
433 .getGeometry
= w25q128fv_getGeometry
,
436 static void w25q128fv_deviceInit(flashDevice_t
*flashdev
)